[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