mirror of
https://github.com/openvswitch/ovs
synced 2025-08-31 22:35:15 +00:00
vtep: add logical router related commands.
Add logical router related vtep-ctl commands: vtep-ctl add-lr LR vtep-ctl del-lr LR vtep-ctl list-lr vtep-ctl lr-exists LR Signed-off-by: Wenyu Zhang <wenyuz@vmware.com> Signed-off-by: Gurucharan Shetty <guru@ovn.org>
This commit is contained in:
committed by
Gurucharan Shetty
parent
5a4bee8a02
commit
993225bd48
@@ -195,6 +195,31 @@ combination on the physical switch \fIpswitch\fR.
|
|||||||
List the logical switch bindings for \fIport\fR on the physical switch
|
List the logical switch bindings for \fIport\fR on the physical switch
|
||||||
\fIpswitch\fR.
|
\fIpswitch\fR.
|
||||||
.
|
.
|
||||||
|
.SS "Logical Router Commands"
|
||||||
|
These commands examine and manipulate logical routers.
|
||||||
|
.
|
||||||
|
.IP "[\fB\-\-may\-exist\fR] \fBadd\-lr \fIlrouter\fR"
|
||||||
|
Creates a new logical router named \fIlrouter\fR.
|
||||||
|
.IP
|
||||||
|
Without \fB\-\-may\-exist\fR, attempting to create a router that
|
||||||
|
exists is an error. With \fB\-\-may\-exist\fR, this command does
|
||||||
|
nothing if \fIlrouter\fR already exists.
|
||||||
|
.
|
||||||
|
.IP "[\fB\-\-if\-exists\fR] \fBdel\-lr \fIlrouter\fR"
|
||||||
|
Deletes \fIlrouter\fR.
|
||||||
|
.IP
|
||||||
|
Without \fB\-\-if\-exists\fR, attempting to delete a router that does
|
||||||
|
not exist is an error. With \fB\-\-if\-exists\fR, attempting to
|
||||||
|
delete a router that does not exist has no effect.
|
||||||
|
.
|
||||||
|
.IP "\fBlist\-lr\fR"
|
||||||
|
Lists all existing logical routers on standard output, one per line.
|
||||||
|
.
|
||||||
|
.IP "\fBlr\-exists \fIlrouter\fR"
|
||||||
|
Tests whether \fIlrouter\fR exists. If so, \fBvtep\-ctl\fR exits
|
||||||
|
successfully with exit code 0. If not, \fBvtep\-ctl\fR exits
|
||||||
|
unsuccessfully with exit code 2.
|
||||||
|
|
||||||
.SS "Local MAC Binding Commands"
|
.SS "Local MAC Binding Commands"
|
||||||
These commands examine and manipulate local MAC bindings for the logical
|
These commands examine and manipulate local MAC bindings for the logical
|
||||||
switch. The local maps are written by the VTEP to refer to MACs it has
|
switch. The local maps are written by the VTEP to refer to MACs it has
|
||||||
|
155
vtep/vtep-ctl.c
155
vtep/vtep-ctl.c
@@ -87,6 +87,9 @@ static void do_vtep_ctl(const char *args, struct ctl_command *, size_t n,
|
|||||||
static struct vtep_ctl_lswitch *find_lswitch(struct vtep_ctl_context *,
|
static struct vtep_ctl_lswitch *find_lswitch(struct vtep_ctl_context *,
|
||||||
const char *name,
|
const char *name,
|
||||||
bool must_exist);
|
bool must_exist);
|
||||||
|
static struct vtep_ctl_lrouter *find_lrouter(struct vtep_ctl_context *,
|
||||||
|
const char *name,
|
||||||
|
bool must_exist);
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
@@ -334,6 +337,12 @@ Logical Switch commands:\n\
|
|||||||
unbind-ls PS PORT VLAN unbind logical switch on VLAN from PORT\n\
|
unbind-ls PS PORT VLAN unbind logical switch on VLAN from PORT\n\
|
||||||
list-bindings PS PORT list bindings for PORT on PS\n\
|
list-bindings PS PORT list bindings for PORT on PS\n\
|
||||||
\n\
|
\n\
|
||||||
|
Logical Router commands:\n\
|
||||||
|
add-lr LR create a new logical router named LR\n\
|
||||||
|
del-lr LR delete LR\n\
|
||||||
|
list-lr print the names of all the logical routers\n\
|
||||||
|
lr-exists LR exit 2 if LR does not exist\n\
|
||||||
|
\n\
|
||||||
MAC binding commands:\n\
|
MAC binding commands:\n\
|
||||||
add-ucast-local LS MAC [ENCAP] IP add ucast local entry in LS\n\
|
add-ucast-local LS MAC [ENCAP] IP add ucast local entry in LS\n\
|
||||||
del-ucast-local LS MAC del ucast local entry from LS\n\
|
del-ucast-local LS MAC del ucast local entry from LS\n\
|
||||||
@@ -437,6 +446,8 @@ struct vtep_ctl_context {
|
|||||||
* struct vtep_ctl_lswitch. */
|
* struct vtep_ctl_lswitch. */
|
||||||
struct shash plocs; /* Maps from "<encap>+<dst_ip>" to
|
struct shash plocs; /* Maps from "<encap>+<dst_ip>" to
|
||||||
* struct vteprec_physical_locator. */
|
* struct vteprec_physical_locator. */
|
||||||
|
struct shash lrouters; /* Maps from logical router name to
|
||||||
|
* struct vtep_ctl_lrouter. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Casts 'base' into 'struct vtep_ctl_context'. */
|
/* Casts 'base' into 'struct vtep_ctl_context'. */
|
||||||
@@ -468,6 +479,11 @@ struct vtep_ctl_lswitch {
|
|||||||
struct shash mcast_remote; /* Maps from mac to vtep_ctl_mcast_mac. */
|
struct shash mcast_remote; /* Maps from mac to vtep_ctl_mcast_mac. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct vtep_ctl_lrouter {
|
||||||
|
const struct vteprec_logical_router *lr_cfg;
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
|
||||||
struct vtep_ctl_mcast_mac {
|
struct vtep_ctl_mcast_mac {
|
||||||
const struct vteprec_mcast_macs_local *local_cfg;
|
const struct vteprec_mcast_macs_local *local_cfg;
|
||||||
const struct vteprec_mcast_macs_remote *remote_cfg;
|
const struct vteprec_mcast_macs_remote *remote_cfg;
|
||||||
@@ -648,6 +664,28 @@ del_cached_ls_binding(struct vtep_ctl_port *port, const char *vlan)
|
|||||||
shash_find_and_delete(&port->bindings, vlan);
|
shash_find_and_delete(&port->bindings, vlan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct vtep_ctl_lrouter *
|
||||||
|
add_lrouter_to_cache(struct vtep_ctl_context *vtepctl_ctx,
|
||||||
|
const struct vteprec_logical_router *lr_cfg)
|
||||||
|
{
|
||||||
|
struct vtep_ctl_lrouter *lr = xmalloc(sizeof *lr);
|
||||||
|
lr->lr_cfg = lr_cfg;
|
||||||
|
lr->name = xstrdup(lr_cfg->name);
|
||||||
|
shash_add(&vtepctl_ctx->lrouters, lr->name, lr);
|
||||||
|
return lr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
del_cached_lrouter(struct vtep_ctl_context *ctx, struct vtep_ctl_lrouter *lr)
|
||||||
|
{
|
||||||
|
if (lr->lr_cfg) {
|
||||||
|
vteprec_logical_router_delete(lr->lr_cfg);
|
||||||
|
}
|
||||||
|
shash_find_and_delete(&ctx->lrouters, lr->name);
|
||||||
|
free(lr->name);
|
||||||
|
free(lr);
|
||||||
|
}
|
||||||
|
|
||||||
static struct vteprec_physical_locator *
|
static struct vteprec_physical_locator *
|
||||||
find_ploc(struct vtep_ctl_context *vtepctl_ctx, const char *encap,
|
find_ploc(struct vtep_ctl_context *vtepctl_ctx, const char *encap,
|
||||||
const char *dst_ip)
|
const char *dst_ip)
|
||||||
@@ -792,6 +830,13 @@ vtep_ctl_context_invalidate_cache(struct ctl_context *ctx)
|
|||||||
}
|
}
|
||||||
shash_destroy(&vtepctl_ctx->lswitches);
|
shash_destroy(&vtepctl_ctx->lswitches);
|
||||||
shash_destroy(&vtepctl_ctx->plocs);
|
shash_destroy(&vtepctl_ctx->plocs);
|
||||||
|
|
||||||
|
SHASH_FOR_EACH (node, &vtepctl_ctx->lrouters) {
|
||||||
|
struct vtep_ctl_lrouter *lr = node->data;
|
||||||
|
free(lr->name);
|
||||||
|
free(lr);
|
||||||
|
}
|
||||||
|
shash_destroy(&vtepctl_ctx->lrouters);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -808,6 +853,8 @@ pre_get_info(struct ctl_context *ctx)
|
|||||||
|
|
||||||
ovsdb_idl_add_column(ctx->idl, &vteprec_logical_switch_col_name);
|
ovsdb_idl_add_column(ctx->idl, &vteprec_logical_switch_col_name);
|
||||||
|
|
||||||
|
ovsdb_idl_add_column(ctx->idl, &vteprec_logical_router_col_name);
|
||||||
|
|
||||||
ovsdb_idl_add_column(ctx->idl, &vteprec_ucast_macs_local_col_MAC);
|
ovsdb_idl_add_column(ctx->idl, &vteprec_ucast_macs_local_col_MAC);
|
||||||
ovsdb_idl_add_column(ctx->idl, &vteprec_ucast_macs_local_col_locator);
|
ovsdb_idl_add_column(ctx->idl, &vteprec_ucast_macs_local_col_locator);
|
||||||
ovsdb_idl_add_column(ctx->idl,
|
ovsdb_idl_add_column(ctx->idl,
|
||||||
@@ -848,12 +895,14 @@ vtep_ctl_context_populate_cache(struct ctl_context *ctx)
|
|||||||
struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
|
struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
|
||||||
const struct vteprec_global *vtep_global = vtepctl_ctx->vtep_global;
|
const struct vteprec_global *vtep_global = vtepctl_ctx->vtep_global;
|
||||||
const struct vteprec_logical_switch *ls_cfg;
|
const struct vteprec_logical_switch *ls_cfg;
|
||||||
|
const struct vteprec_logical_router *lr_cfg;
|
||||||
const struct vteprec_ucast_macs_local *ucast_local_cfg;
|
const struct vteprec_ucast_macs_local *ucast_local_cfg;
|
||||||
const struct vteprec_ucast_macs_remote *ucast_remote_cfg;
|
const struct vteprec_ucast_macs_remote *ucast_remote_cfg;
|
||||||
const struct vteprec_mcast_macs_local *mcast_local_cfg;
|
const struct vteprec_mcast_macs_local *mcast_local_cfg;
|
||||||
const struct vteprec_mcast_macs_remote *mcast_remote_cfg;
|
const struct vteprec_mcast_macs_remote *mcast_remote_cfg;
|
||||||
const struct vteprec_tunnel *tunnel_cfg;
|
const struct vteprec_tunnel *tunnel_cfg;
|
||||||
struct sset pswitches, ports, lswitches;
|
struct sset pswitches, ports, lswitches;
|
||||||
|
struct sset lrouters;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if (vtepctl_ctx->cache_valid) {
|
if (vtepctl_ctx->cache_valid) {
|
||||||
@@ -865,6 +914,7 @@ vtep_ctl_context_populate_cache(struct ctl_context *ctx)
|
|||||||
shash_init(&vtepctl_ctx->ports);
|
shash_init(&vtepctl_ctx->ports);
|
||||||
shash_init(&vtepctl_ctx->lswitches);
|
shash_init(&vtepctl_ctx->lswitches);
|
||||||
shash_init(&vtepctl_ctx->plocs);
|
shash_init(&vtepctl_ctx->plocs);
|
||||||
|
shash_init(&vtepctl_ctx->lrouters);
|
||||||
|
|
||||||
sset_init(&pswitches);
|
sset_init(&pswitches);
|
||||||
sset_init(&ports);
|
sset_init(&ports);
|
||||||
@@ -902,6 +952,17 @@ vtep_ctl_context_populate_cache(struct ctl_context *ctx)
|
|||||||
}
|
}
|
||||||
sset_destroy(&lswitches);
|
sset_destroy(&lswitches);
|
||||||
|
|
||||||
|
sset_init(&lrouters);
|
||||||
|
VTEPREC_LOGICAL_ROUTER_FOR_EACH (lr_cfg, ctx->idl) {
|
||||||
|
if (!sset_add(&lrouters, lr_cfg->name)) {
|
||||||
|
VLOG_WARN("%s: database contains duplicate logical router name",
|
||||||
|
lr_cfg->name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
add_lrouter_to_cache(vtepctl_ctx, lr_cfg);
|
||||||
|
}
|
||||||
|
sset_destroy(&lrouters);
|
||||||
|
|
||||||
VTEPREC_UCAST_MACS_LOCAL_FOR_EACH (ucast_local_cfg, ctx->idl) {
|
VTEPREC_UCAST_MACS_LOCAL_FOR_EACH (ucast_local_cfg, ctx->idl) {
|
||||||
struct vtep_ctl_lswitch *ls;
|
struct vtep_ctl_lswitch *ls;
|
||||||
|
|
||||||
@@ -1463,6 +1524,94 @@ cmd_unbind_ls(struct ctl_context *ctx)
|
|||||||
vtep_ctl_context_invalidate_cache(ctx);
|
vtep_ctl_context_invalidate_cache(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct vtep_ctl_lrouter *
|
||||||
|
find_lrouter(struct vtep_ctl_context *vtepctl_ctx,
|
||||||
|
const char *name, bool must_exist)
|
||||||
|
{
|
||||||
|
struct vtep_ctl_lrouter *lr;
|
||||||
|
|
||||||
|
ovs_assert(vtepctl_ctx->cache_valid);
|
||||||
|
|
||||||
|
lr = shash_find_data(&vtepctl_ctx->lrouters, name);
|
||||||
|
if (must_exist && !lr) {
|
||||||
|
ctl_fatal("no logical router named %s", name);
|
||||||
|
}
|
||||||
|
return lr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_add_lr(struct ctl_context *ctx)
|
||||||
|
{
|
||||||
|
struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
|
||||||
|
const char *lr_name = ctx->argv[1];
|
||||||
|
bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
|
||||||
|
struct vteprec_logical_router *lr;
|
||||||
|
|
||||||
|
vtep_ctl_context_populate_cache(ctx);
|
||||||
|
if (find_lrouter(vtepctl_ctx, lr_name, false)) {
|
||||||
|
if (!may_exist) {
|
||||||
|
ctl_fatal("cannot create logical router %s because it "
|
||||||
|
"already exists", lr_name);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lr = vteprec_logical_router_insert(ctx->txn);
|
||||||
|
vteprec_logical_router_set_name(lr, lr_name);
|
||||||
|
|
||||||
|
vtep_ctl_context_invalidate_cache(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
del_lrouter(struct vtep_ctl_context *vtepctl_ctx, struct vtep_ctl_lrouter *lr)
|
||||||
|
{
|
||||||
|
del_cached_lrouter(vtepctl_ctx, lr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_del_lr(struct ctl_context *ctx)
|
||||||
|
{
|
||||||
|
struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
|
||||||
|
bool must_exist = !shash_find(&ctx->options, "--if-exists");
|
||||||
|
struct vtep_ctl_lrouter *lr;
|
||||||
|
|
||||||
|
vtep_ctl_context_populate_cache(ctx);
|
||||||
|
lr = find_lrouter(vtepctl_ctx, ctx->argv[1], must_exist);
|
||||||
|
if (lr) {
|
||||||
|
del_lrouter(vtepctl_ctx, lr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_list_lr(struct ctl_context *ctx)
|
||||||
|
{
|
||||||
|
struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
|
||||||
|
struct shash_node *node;
|
||||||
|
struct svec lrouters;
|
||||||
|
|
||||||
|
vtep_ctl_context_populate_cache(ctx);
|
||||||
|
|
||||||
|
svec_init(&lrouters);
|
||||||
|
SHASH_FOR_EACH (node, &vtepctl_ctx->lrouters) {
|
||||||
|
struct vtep_ctl_lrouter *lr = node->data;
|
||||||
|
|
||||||
|
svec_add(&lrouters, lr->name);
|
||||||
|
}
|
||||||
|
output_sorted(&lrouters, &ctx->output);
|
||||||
|
svec_destroy(&lrouters);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_lr_exists(struct ctl_context *ctx)
|
||||||
|
{
|
||||||
|
struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
|
||||||
|
|
||||||
|
vtep_ctl_context_populate_cache(ctx);
|
||||||
|
if (!find_lrouter(vtepctl_ctx, ctx->argv[1], false)) {
|
||||||
|
vtep_ctl_exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_ucast_entry(struct ctl_context *ctx, bool local)
|
add_ucast_entry(struct ctl_context *ctx, bool local)
|
||||||
{
|
{
|
||||||
@@ -2312,6 +2461,12 @@ static const struct ctl_command_syntax vtep_commands[] = {
|
|||||||
{"bind-ls", 4, 4, NULL, pre_get_info, cmd_bind_ls, NULL, "", RO},
|
{"bind-ls", 4, 4, NULL, pre_get_info, cmd_bind_ls, NULL, "", RO},
|
||||||
{"unbind-ls", 3, 3, NULL, pre_get_info, cmd_unbind_ls, NULL, "", RO},
|
{"unbind-ls", 3, 3, NULL, pre_get_info, cmd_unbind_ls, NULL, "", RO},
|
||||||
|
|
||||||
|
/* Logical Router commands. */
|
||||||
|
{"add-lr", 1, 1, NULL, pre_get_info, cmd_add_lr, NULL, "--may-exist", RW},
|
||||||
|
{"del-lr", 1, 1, NULL, pre_get_info, cmd_del_lr, NULL, "--if-exists", RW},
|
||||||
|
{"list-lr", 0, 0, NULL, pre_get_info, cmd_list_lr, NULL, "", RO},
|
||||||
|
{"lr-exists", 1, 1, NULL, pre_get_info, cmd_lr_exists, NULL, "", RO},
|
||||||
|
|
||||||
/* MAC binding commands. */
|
/* MAC binding commands. */
|
||||||
{"add-ucast-local", 3, 4, NULL, pre_get_info, cmd_add_ucast_local, NULL,
|
{"add-ucast-local", 3, 4, NULL, pre_get_info, cmd_add_ucast_local, NULL,
|
||||||
"", RW},
|
"", RW},
|
||||||
|
Reference in New Issue
Block a user