Signed-off-by: Darrell Ball <db...@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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev