[ovs-dev] [PATCH 3/4] Update sbctl to support OVN SB physical endpoint table usage and associated changes in the port binding table

Darrell Ball dlu998 at gmail.com
Tue Mar 1 18:39:18 UTC 2016


Signed-off-by: Darrell Ball <dball at vmware.com>
---
 ovn/utilities/ovn-sbctl.c | 263 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 259 insertions(+), 4 deletions(-)

diff --git a/ovn/utilities/ovn-sbctl.c b/ovn/utilities/ovn-sbctl.c
index b9e3c10..aba7e01 100644
--- a/ovn/utilities/ovn-sbctl.c
+++ b/ovn/utilities/ovn-sbctl.c
@@ -311,11 +311,24 @@ Chassis commands:\n\
                                            and ENCAP-IP\n\
   chassis-del CHASSIS         delete CHASSIS and all of its encaps\n\
                               and gateway_ports\n\
+Physical Endpoint commands:\n\
+  phys-endpt-add PHYS-ENDPT CHASSIS PORT TYPE ING-ENC EGR-ENC\n\
+                                 create a new phys endpt named\n\
+                                 PHYS-ENDPT on CHASSIS/PORT\n\
+                                 with TYPE encap\n\
+                                 and encap values ING-ENC EGR-ENC\n\
+  phys-endpt-del PHYS-ENDPT      delete PHYS-ENDPT \n\
 \n\
 Port binding commands:\n\
   lport-bind LPORT CHASSIS    bind logical port LPORT to CHASSIS\n\
   lport-unbind LPORT          reset the port binding of logical port LPORT\n\
 \n\
+Port binding Phys Endpt commands:\n\
+  lport-bind-phys-endpt LPORT PHYS-ENDPT\n\
+                             bind logical port LPORT to PHYS-ENDPT\n\
+  lport-unbind-phys-endpt LPORT\n\
+                          reset the binding of LPORT to PHYS-ENDPT\n\
+\n\
 Logical flow commands:\n\
   lflow-list [DATAPATH]       List logical flows for all or a single datapath\n\
   dump-flows [DATAPATH]       Alias for lflow-list\n\
@@ -357,6 +370,9 @@ struct sbctl_context {
     struct shash chassis;
     /* Maps from lport name to struct sbctl_port_binding. */
     struct shash port_bindings;
+
+    /* Maps from phys_endpt name to struct sbctl_physical_endpoint. */
+    struct shash phys_endpts_name_to_rec;
 };
 
 /* Casts 'base' into 'struct sbctl_context'. */
@@ -374,6 +390,10 @@ struct sbctl_port_binding {
     const struct sbrec_port_binding *bd_cfg;
 };
 
+struct sbctl_physical_endpoint {
+    const struct sbrec_physical_endpoint *phys_endpt_db_rec;
+};
+
 static void
 sbctl_context_invalidate_cache(struct ctl_context *ctx)
 {
@@ -382,9 +402,12 @@ sbctl_context_invalidate_cache(struct ctl_context *ctx)
     if (!sbctl_ctx->cache_valid) {
         return;
     }
-    sbctl_ctx->cache_valid = false;
+
     shash_destroy_free_data(&sbctl_ctx->chassis);
     shash_destroy_free_data(&sbctl_ctx->port_bindings);
+
+    shash_destroy_free_data(&sbctl_ctx->phys_endpts_name_to_rec);
+    sbctl_ctx->cache_valid = false;
 }
 
 static void
@@ -393,7 +416,8 @@ sbctl_context_populate_cache(struct ctl_context *ctx)
     struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
     const struct sbrec_chassis *chassis_rec;
     const struct sbrec_port_binding *port_binding_rec;
-    struct sset chassis, port_bindings;
+    const struct sbrec_physical_endpoint *phys_endpt_db_rec;
+    struct sset chassis, port_bindings, physical_endpoints_set;
 
     if (sbctl_ctx->cache_valid) {
         /* Cache is already populated. */
@@ -402,6 +426,8 @@ sbctl_context_populate_cache(struct ctl_context *ctx)
     sbctl_ctx->cache_valid = true;
     shash_init(&sbctl_ctx->chassis);
     shash_init(&sbctl_ctx->port_bindings);
+    shash_init(&sbctl_ctx->phys_endpts_name_to_rec);
+
     sset_init(&chassis);
     SBREC_CHASSIS_FOR_EACH(chassis_rec, ctx->idl) {
         struct sbctl_chassis *ch;
@@ -435,10 +461,30 @@ sbctl_context_populate_cache(struct ctl_context *ctx)
                   bd);
     }
     sset_destroy(&port_bindings);
+
+    sset_init(&physical_endpoints_set);
+    SBREC_PHYSICAL_ENDPOINT_FOR_EACH(phys_endpt_db_rec, ctx->idl) {
+        struct sbctl_physical_endpoint *phys_endpt_lrec;
+
+        if (!sset_add(&physical_endpoints_set, phys_endpt_db_rec->name)) {
+            VLOG_WARN("database contains duplicate physical endpoint record "
+                      "for name (%s)",
+					  phys_endpt_db_rec->name);
+            continue;
+        }
+
+        phys_endpt_lrec
+		     = xmalloc(sizeof *phys_endpt_lrec);
+        phys_endpt_lrec->phys_endpt_db_rec = phys_endpt_db_rec;
+        shash_add(&sbctl_ctx->phys_endpts_name_to_rec,
+                  phys_endpt_db_rec->name, phys_endpt_lrec);
+    }
+    sset_destroy(&physical_endpoints_set);
+
 }
 
 static void
-check_conflicts(struct sbctl_context *sbctl_ctx, const char *name,
+chassis_check_conflict(struct sbctl_context *sbctl_ctx, const char *name,
                 char *msg)
 {
     if (shash_find(&sbctl_ctx->chassis, name)) {
@@ -448,6 +494,18 @@ check_conflicts(struct sbctl_context *sbctl_ctx, const char *name,
     free(msg);
 }
 
+static void
+physical_endpoint_check_conflict(
+          struct sbctl_context *sbctl_ctx, const char *name,
+          char *msg)
+{
+    if (shash_find(&sbctl_ctx->phys_endpts_name_to_rec, name)) {
+        ctl_fatal("%s because a physical endpoint named %s already exists",
+                    msg, name);
+    }
+    free(msg);
+}
+
 static struct sbctl_chassis *
 find_chassis(struct sbctl_context *sbctl_ctx, const char *name,
              bool must_exist)
@@ -480,6 +538,23 @@ find_port_binding(struct sbctl_context *sbctl_ctx, const char *name,
     return bd;
 }
 
+static struct sbctl_physical_endpoint *
+find_phys_endpt(struct sbctl_context *sbctl_ctx, const char *name,
+                  bool must_exist)
+{
+    struct sbctl_physical_endpoint *phys_endpt_lrec;
+
+    ovs_assert(sbctl_ctx->cache_valid);
+
+    phys_endpt_lrec =
+        shash_find_data(&sbctl_ctx->phys_endpts_name_to_rec, name);
+    if (must_exist && !phys_endpt_lrec) {
+        ctl_fatal("no physical endpoint named %s", name);
+    }
+
+    return phys_endpt_lrec;
+}
+
 static void
 pre_get_info(struct ctl_context *ctx)
 {
@@ -489,8 +564,16 @@ pre_get_info(struct ctl_context *ctx)
     ovsdb_idl_add_column(ctx->idl, &sbrec_encap_col_type);
     ovsdb_idl_add_column(ctx->idl, &sbrec_encap_col_ip);
 
+    ovsdb_idl_add_column(ctx->idl, &sbrec_physical_endpoint_col_name);
+    ovsdb_idl_add_column(ctx->idl, &sbrec_physical_endpoint_col_chassis);
+    ovsdb_idl_add_column(ctx->idl, &sbrec_physical_endpoint_col_chassis_port);
+    ovsdb_idl_add_column(ctx->idl, &sbrec_physical_endpoint_col_type);
+    ovsdb_idl_add_column(ctx->idl, &sbrec_physical_endpoint_col_ingress_encap);
+    ovsdb_idl_add_column(ctx->idl, &sbrec_physical_endpoint_col_egress_encap);
+
     ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_logical_port);
     ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_chassis);
+    ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_phys_endpt);
 
     ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_logical_datapath);
     ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_pipeline);
@@ -518,6 +601,9 @@ static struct cmd_show_table cmd_show_tables[] = {
       NULL},
      {NULL, NULL, NULL}},
 
+	 /* Consider adding Physical Endpoint table with
+	  * port binding table reference */
+
     {NULL, NULL, {NULL, NULL, NULL}, {NULL, NULL, NULL}},
 };
 
@@ -541,7 +627,7 @@ cmd_chassis_add(struct ctl_context *ctx)
             return;
         }
     }
-    check_conflicts(sbctl_ctx, ch_name,
+    chassis_check_conflict(sbctl_ctx, ch_name,
                     xasprintf("cannot create a chassis named %s", ch_name));
 
     char *tokstr = xstrdup(encap_types);
@@ -598,6 +684,100 @@ cmd_chassis_del(struct ctl_context *ctx)
 }
 
 static void
+cmd_phys_endpt_add(struct ctl_context *ctx)
+{
+    struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
+    bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
+    const char *phys_endpt_name, *chassis_name, *chassis_port_name;
+    const char *type_name, *ing_encap, *egr_encap;
+    struct sbctl_chassis *sbctl_ch;
+    int v;
+
+    phys_endpt_name = ctx->argv[1];
+    chassis_name = ctx->argv[2];
+    chassis_port_name = ctx->argv[3];
+    type_name = ctx->argv[4];
+    ing_encap = ctx->argv[5];
+    egr_encap = ctx->argv[6];
+
+    sbctl_context_populate_cache(ctx);
+    if (may_exist) {
+        struct sbctl_physical_endpoint
+            *phys_endpt_lrec =
+               find_phys_endpt(
+                    sbctl_ctx, phys_endpt_name, false);
+        if (phys_endpt_lrec) {
+            return;
+        }
+    }
+    physical_endpoint_check_conflict(
+        sbctl_ctx, phys_endpt_name,
+        xasprintf("cannot create physical endpoint %s",
+                  phys_endpt_name));
+
+    /* Reminder: Splice out a encap verify function.
+       Presently only supporting single vlan with same
+       value for ingress and egress */
+    if ( (strcmp(type_name, "vlan")) ||
+        (!str_to_int(ing_encap, 10, &v) || v < 0 || v > 4095) ||
+        (!str_to_int(egr_encap, 10, &v) || v < 0 || v > 4095) ||
+        (strcmp(ing_encap, egr_encap))) {
+        ctl_fatal("phys endpt (%s) unsupported encap ",
+                  phys_endpt_name);
+    }
+
+    struct sbrec_physical_endpoint *phys_endpt_db_rec =
+       sbrec_physical_endpoint_insert(ctx->txn);
+
+    sbrec_physical_endpoint_set_name(
+            phys_endpt_db_rec,
+            phys_endpt_name);
+
+    sbctl_ch = find_chassis(sbctl_ctx, chassis_name, true);
+    sbrec_physical_endpoint_set_chassis(
+            phys_endpt_db_rec,
+			sbctl_ch->ch_cfg);
+
+    sbrec_physical_endpoint_set_chassis_port(
+            phys_endpt_db_rec,
+			chassis_port_name);
+    sbrec_physical_endpoint_set_type(
+            phys_endpt_db_rec,
+            type_name);
+    sbrec_physical_endpoint_set_ingress_encap(
+            phys_endpt_db_rec,
+			ing_encap);
+    sbrec_physical_endpoint_set_egress_encap(
+            phys_endpt_db_rec,
+            egr_encap);
+
+    sbctl_context_invalidate_cache(ctx);
+}
+
+static void
+cmd_phys_endpt_del(struct ctl_context *ctx)
+{
+    struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
+    bool must_exist = !shash_find(&ctx->options, "--if-exists");
+    struct sbctl_physical_endpoint *phys_endpt_lrec;
+
+    sbctl_context_populate_cache(ctx);
+    phys_endpt_lrec = find_phys_endpt(
+            sbctl_ctx, ctx->argv[1], must_exist);
+    if (phys_endpt_lrec) {
+        if (phys_endpt_lrec->phys_endpt_db_rec) {
+
+            sbrec_physical_endpoint_delete(
+                phys_endpt_lrec->phys_endpt_db_rec);
+        }
+        shash_find_and_delete(
+                     &sbctl_ctx->phys_endpts_name_to_rec,
+                     ctx->argv[1]);
+        free(phys_endpt_lrec);
+    }
+}
+
+static void
 cmd_lport_bind(struct ctl_context *ctx)
 {
     struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
@@ -642,6 +822,63 @@ cmd_lport_unbind(struct ctl_context *ctx)
     }
 }
 
+static void
+cmd_lport_bind_phys_endpt(struct ctl_context *ctx)
+{
+    struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
+    bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
+    struct sbctl_port_binding *sbctl_bd;
+    struct sbctl_physical_endpoint *phys_endpt_lrec;
+    char *lport_name, *phys_endpt_name;
+
+    /* port_binding must exist, chassis must exist! */
+    lport_name = ctx->argv[1];
+    phys_endpt_name = ctx->argv[2];
+
+    sbctl_context_populate_cache(ctx);
+    sbctl_bd = find_port_binding(sbctl_ctx, lport_name, true);
+    phys_endpt_lrec =
+         find_phys_endpt(sbctl_ctx, phys_endpt_name, true);
+
+
+    if ((strcmp(sbctl_bd->bd_cfg->type, "localnet")) &&
+        (strcmp(sbctl_bd->bd_cfg->type, "vtep"))) {
+        ctl_fatal("lport (%s) type must be localnet or vtep ",
+                  lport_name);
+    }
+    if (sbctl_bd->bd_cfg->phys_endpt) {
+        if (may_exist &&
+            sbctl_bd->bd_cfg->phys_endpt ==
+              phys_endpt_lrec->phys_endpt_db_rec) {
+            return;
+        } else {
+            ctl_fatal("lport (%s) already bound to phys_endpt (%s)",
+                      lport_name,
+                      phys_endpt_lrec->phys_endpt_db_rec->name);
+        }
+    }
+    sbrec_port_binding_set_phys_endpt(
+        sbctl_bd->bd_cfg,
+		phys_endpt_lrec->phys_endpt_db_rec);
+    sbctl_context_invalidate_cache(ctx);
+}
+
+static void
+cmd_lport_unbind_phys_endpt(struct ctl_context *ctx)
+{
+    struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
+    bool must_exist = !shash_find(&ctx->options, "--if-exists");
+    struct sbctl_port_binding *sbctl_bd;
+    char *lport_name;
+
+    lport_name = ctx->argv[1];
+    sbctl_context_populate_cache(ctx);
+    sbctl_bd = find_port_binding(sbctl_ctx, lport_name, must_exist);
+    if (sbctl_bd) {
+        sbrec_port_binding_set_phys_endpt(sbctl_bd->bd_cfg, NULL);
+    }
+}
+
 enum {
     PL_INGRESS,
     PL_EGRESS,
@@ -771,6 +1008,11 @@ static const struct ctl_table_class tables[] = {
      {{&sbrec_table_port_binding, &sbrec_port_binding_col_logical_port, NULL},
       {NULL, NULL, NULL}}},
 
+    {&sbrec_table_physical_endpoint,
+     {{&sbrec_table_physical_endpoint,
+       &sbrec_physical_endpoint_col_name, NULL},
+      {NULL, NULL, NULL}}},
+
     {NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
 };
 
@@ -1007,17 +1249,30 @@ sbctl_exit(int status)
 
 static const struct ctl_command_syntax sbctl_commands[] = {
     /* Chassis commands. */
+
     {"chassis-add", 3, 3, "CHASSIS ENCAP-TYPE ENCAP-IP", pre_get_info,
      cmd_chassis_add, NULL, "--may-exist", RW},
     {"chassis-del", 1, 1, "CHASSIS", pre_get_info, cmd_chassis_del, NULL,
      "--if-exists", RW},
 
+	/* Physical Endpoint commands */
+	{"phys-endpt-add", 6, 6, "PHYS-ENDPT CHASSIS PORT TYPE ING-ENC EGR-ENC",
+     pre_get_info, cmd_phys_endpt_add, NULL, "--may-exist", RW},
+	{"phys-endpt-del", 1, 1, "PHYS-ENDPT",
+     pre_get_info, cmd_phys_endpt_del, NULL, "--if-exists", RW},
+
     /* Port binding commands. */
     {"lport-bind", 2, 2, "LPORT CHASSIS", pre_get_info, cmd_lport_bind, NULL,
      "--may-exist", RW},
     {"lport-unbind", 1, 1, "LPORT", pre_get_info, cmd_lport_unbind, NULL,
      "--if-exists", RW},
 
+	/* Port to physical endpoint binding */
+    {"lport-bind-phys-endpt", 2, 2, "LPORT PHYS-ENDPT", pre_get_info,
+     cmd_lport_bind_phys_endpt, NULL, "--may-exist", RW},
+    {"lport-unbind-phys-endpt", 1, 1, "LPORT", pre_get_info,
+     cmd_lport_unbind_phys_endpt, NULL, "--if-exists", RW},
+
     /* Logical flow commands */
     {"lflow-list", 0, 1, "[DATAPATH]", pre_get_info, cmd_lflow_list, NULL,
      "", RO},
-- 
1.9.1




More information about the dev mailing list