[ovs-dev] [PATCH v3] vtep: add logical router related commands.

Wenyu Zhang wenyuz at vmware.com
Fri Jan 29 10:22:16 UTC 2016


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 at vmware.com>
---
 vtep/vtep-ctl.8.in |  25 +++++++++
 vtep/vtep-ctl.c    | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 180 insertions(+)

diff --git a/vtep/vtep-ctl.8.in b/vtep/vtep-ctl.8.in
index 21fb6db..129c7ed 100644
--- a/vtep/vtep-ctl.8.in
+++ b/vtep/vtep-ctl.8.in
@@ -195,6 +195,31 @@ combination on the physical switch \fIpswitch\fR.
 List the logical switch bindings for \fIport\fR on the physical switch
 \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"
 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
diff --git a/vtep/vtep-ctl.c b/vtep/vtep-ctl.c
index e46c73d..11e30db 100644
--- a/vtep/vtep-ctl.c
+++ b/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 *,
                                              const char *name,
                                              bool must_exist);
+static struct vtep_ctl_lrouter *find_lrouter(struct vtep_ctl_context *,
+                                             const char *name,
+                                             bool must_exist);
 
 int
 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\
   list-bindings PS PORT       list bindings for PORT on PS\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\
   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\
@@ -437,6 +446,8 @@ struct vtep_ctl_context {
                              * struct vtep_ctl_lswitch. */
     struct shash plocs;     /* Maps from "<encap>+<dst_ip>" to
                              * struct vteprec_physical_locator. */
+    struct shash lrouters; /* Maps from logical router name to
+                             * struct vtep_ctl_lswitch. */
 };
 
 /* 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 vtep_ctl_lrouter {
+    const struct vteprec_logical_router *lr_cfg;
+    char *name;
+};
+
 struct vtep_ctl_mcast_mac {
     const struct vteprec_mcast_macs_local *local_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);
 }
 
+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 *
 find_ploc(struct vtep_ctl_context *vtepctl_ctx, const char *encap,
           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->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
@@ -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_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_locator);
     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);
     const struct vteprec_global *vtep_global = vtepctl_ctx->vtep_global;
     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_remote *ucast_remote_cfg;
     const struct vteprec_mcast_macs_local *mcast_local_cfg;
     const struct vteprec_mcast_macs_remote *mcast_remote_cfg;
     const struct vteprec_tunnel *tunnel_cfg;
     struct sset pswitches, ports, lswitches;
+    struct sset lrouters;
     size_t i;
 
     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->lswitches);
     shash_init(&vtepctl_ctx->plocs);
+    shash_init(&vtepctl_ctx->lrouters);
 
     sset_init(&pswitches);
     sset_init(&ports);
@@ -902,6 +952,17 @@ vtep_ctl_context_populate_cache(struct ctl_context *ctx)
     }
     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) {
         struct vtep_ctl_lswitch *ls;
 
@@ -1463,6 +1524,94 @@ cmd_unbind_ls(struct ctl_context *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 switch %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
 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},
     {"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. */
     {"add-ucast-local", 3, 4, NULL, pre_get_info, cmd_add_ucast_local, NULL,
      "", RW},
-- 
2.1.4




More information about the dev mailing list