summaryrefslogtreecommitdiff
path: root/ovn
diff options
context:
space:
mode:
Diffstat (limited to 'ovn')
-rw-r--r--ovn/utilities/ovn-nbctl.8.xml23
-rw-r--r--ovn/utilities/ovn-nbctl.c186
2 files changed, 209 insertions, 0 deletions
diff --git a/ovn/utilities/ovn-nbctl.8.xml b/ovn/utilities/ovn-nbctl.8.xml
index 15012af6b..f4fc6cfa6 100644
--- a/ovn/utilities/ovn-nbctl.8.xml
+++ b/ovn/utilities/ovn-nbctl.8.xml
@@ -389,6 +389,29 @@
Prints the administrative state of <var>port</var>, either
<code>enabled</code> or <code>disabled</code>.
</dd>
+
+ <dt><code>lrp-set-gateway-chassis</code> <var>port</var>
+ <var>chassis</var> [<var>priority</var>]</dt>
+ <dd>
+ Set gateway chassis for <var>port</var>. <var>chassis</var>
+ is the name of the chassis. This creates a gateway chassis entry
+ in Gateway_Chassis table. It won't check if chassis really exists
+ in OVN_Southbound database. Priority will be set to 0
+ if <var>priority</var> is not provided by user. <var>priority</var>
+ must be between <code>0</code> and <code>32767</code>, inclusive.
+ </dd>
+ <dt><code>lrp-del-gateway-chassis</code> <var>port</var>
+ <var>chassis</var></dt>
+ <dd>
+ Deletes gateway chassis from <var>port</var>. It is an error if
+ gateway chassis with <var>chassis</var> for <var>port</var> does
+ not exist.
+ </dd>
+ <dt><code>lrp-get-gateway-chassis</code> <var>port</var></dt>
+ <dd>
+ Lists all the gateway chassis with priority within <var>port</var> on
+ standard output, one per line, ordered based on priority.
+ </dd>
</dl>
<h1>Logical Router Static Route Commands</h1>
diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c
index 0488318c4..ce692acb3 100644
--- a/ovn/utilities/ovn-nbctl.c
+++ b/ovn/utilities/ovn-nbctl.c
@@ -376,6 +376,13 @@ Logical router commands:\n\
Logical router port commands:\n\
lrp-add ROUTER PORT MAC NETWORK... [peer=PEER]\n\
add logical port PORT on ROUTER\n\
+ lrp-set-gateway-chassis PORT CHASSIS [PRIORITY]\n\
+ set gateway chassis for port PORT\n\
+ lrp-del-gateway-chassis PORT CHASSIS\n\
+ delete gateway chassis from port PORT\n\
+ lrp-get-gateway-chassis PORT\n\
+ print the names of all gateway chassis on PORT\n\
+ with PRIORITY\n\
lrp-del PORT delete PORT from its attached router\n\
lrp-list ROUTER print the names of all ports on ROUTER\n\
lrp-set-enabled PORT STATE\n\
@@ -2528,6 +2535,178 @@ lr_get_name(const struct nbrec_logical_router *lr, char uuid_s[UUID_LEN + 1],
return uuid_s;
}
+static const struct nbrec_gateway_chassis *
+gc_by_name_or_uuid(struct ctl_context *ctx, const char *id, bool must_exist)
+{
+ const struct nbrec_gateway_chassis *gc = NULL;
+
+ struct uuid gc_uuid;
+ bool is_uuid = uuid_from_string(&gc_uuid, id);
+ if (is_uuid) {
+ gc = nbrec_gateway_chassis_get_for_uuid(ctx->idl, &gc_uuid);
+ }
+
+ if (!gc) {
+ NBREC_GATEWAY_CHASSIS_FOR_EACH (gc, ctx->idl) {
+ if (!strcmp(gc->name, id)) {
+ break;
+ }
+ }
+ }
+
+ if (!gc && must_exist) {
+ ctl_fatal("%s: gateway chassis %s not found", id,
+ is_uuid ? "UUID" : "name");
+ }
+
+ return gc;
+}
+
+static void
+nbctl_lrp_set_gateway_chassis(struct ctl_context *ctx)
+{
+ char *gc_name;
+ int64_t priority = 0;
+ const char *lrp_name = ctx->argv[1];
+ const struct nbrec_logical_router_port *lrp;
+ lrp = lrp_by_name_or_uuid(ctx, lrp_name, true);
+ if (!lrp) {
+ ctl_fatal("router port %s is required", lrp_name);
+ return;
+ }
+
+ const char *chassis_name = ctx->argv[2];
+ if (ctx->argv[3]) {
+ priority = parse_priority(ctx->argv[3]);
+ }
+
+ gc_name = xasprintf("%s-%s", lrp_name, chassis_name);
+ const struct nbrec_gateway_chassis *existing_gc;
+ existing_gc = gc_by_name_or_uuid(ctx, gc_name, false);
+ if (existing_gc) {
+ nbrec_gateway_chassis_set_priority(existing_gc, priority);
+ free(gc_name);
+ return;
+ }
+
+ /* Create the logical gateway chassis. */
+ struct nbrec_gateway_chassis *gc
+ = nbrec_gateway_chassis_insert(ctx->txn);
+ nbrec_gateway_chassis_set_name(gc, gc_name);
+ nbrec_gateway_chassis_set_chassis_name(gc, chassis_name);
+ nbrec_gateway_chassis_set_priority(gc, priority);
+
+ /* Insert the logical gateway chassis into the logical router port. */
+ nbrec_logical_router_port_verify_gateway_chassis(lrp);
+ struct nbrec_gateway_chassis **new_gc = xmalloc(
+ sizeof *new_gc * (lrp->n_gateway_chassis + 1));
+ nullable_memcpy(new_gc, lrp->gateway_chassis,
+ sizeof *new_gc * lrp->n_gateway_chassis);
+ new_gc[lrp->n_gateway_chassis] = gc;
+ nbrec_logical_router_port_set_gateway_chassis(
+ lrp, new_gc, lrp->n_gateway_chassis + 1);
+ free(new_gc);
+ free(gc_name);
+}
+
+/* Removes logical router port 'lrp->gateway_chassis[idx]'. */
+static void
+remove_gc(const struct nbrec_logical_router_port *lrp, size_t idx)
+{
+ const struct nbrec_gateway_chassis *gc = lrp->gateway_chassis[idx];
+
+ if (lrp->n_gateway_chassis == 1) {
+ nbrec_logical_router_port_set_gateway_chassis(lrp, NULL, 0);
+ } else {
+ /* First remove 'gc' from the array of gateway_chassis. This is what
+ * will actually cause the gateway chassis to be deleted when the
+ * transaction is sent to the database server (due to garbage
+ * collection). */
+ struct nbrec_gateway_chassis **new_gc
+ = xmemdup(lrp->gateway_chassis,
+ sizeof *new_gc * lrp->n_gateway_chassis);
+ new_gc[idx] = new_gc[lrp->n_gateway_chassis - 1];
+ nbrec_logical_router_port_verify_gateway_chassis(lrp);
+ nbrec_logical_router_port_set_gateway_chassis(
+ lrp, new_gc, lrp->n_gateway_chassis - 1);
+ free(new_gc);
+ }
+
+ /* Delete 'gc' from the IDL. This won't have a real effect on
+ * the database server (the IDL will suppress it in fact) but it
+ * means that it won't show up when we iterate with
+ * NBREC_GATEWAY_CHASSIS_FOR_EACH later. */
+ nbrec_gateway_chassis_delete(gc);
+}
+
+static void
+nbctl_lrp_del_gateway_chassis(struct ctl_context *ctx)
+{
+ const struct nbrec_logical_router_port *lrp;
+ lrp = lrp_by_name_or_uuid(ctx, ctx->argv[1], true);
+ if (!lrp) {
+ return;
+ }
+ /* Find the lrp that contains 'gc', then delete it. */
+ const char *chassis_name = ctx->argv[2];
+ for (size_t i = 0; i < lrp->n_gateway_chassis; i++) {
+ if (!strncmp(lrp->gateway_chassis[i]->chassis_name,
+ chassis_name,
+ strlen(lrp->gateway_chassis[i]->chassis_name))) {
+ remove_gc(lrp, i);
+ return;
+ }
+ }
+
+ /* Can't happen because of the database schema. */
+ ctl_fatal("chassis %s is not added to logical port %s",
+ chassis_name, ctx->argv[1]);
+}
+
+/* gateway_chassis ordering
+ * */
+static int
+compare_chassis_prio_(const void *gc1_, const void *gc2_)
+{
+ const struct nbrec_gateway_chassis *const *gc1p = gc1_;
+ const struct nbrec_gateway_chassis *const *gc2p = gc2_;
+ const struct nbrec_gateway_chassis *gc1 = *gc1p;
+ const struct nbrec_gateway_chassis *gc2 = *gc2p;
+
+ int prio_diff = gc2->priority - gc1->priority;
+ if (!prio_diff) {
+ return strcmp(gc2->name, gc1->name);
+ }
+ return prio_diff;
+}
+
+/* Print a list of gateway chassis. */
+static void
+nbctl_lrp_get_gateway_chassis(struct ctl_context *ctx)
+{
+ const char *id = ctx->argv[1];
+ const struct nbrec_logical_router_port *lrp;
+ const struct nbrec_gateway_chassis **gcs;
+ size_t i;
+
+ lrp = lrp_by_name_or_uuid(ctx, id, true);
+
+ gcs = xmalloc(sizeof *gcs * lrp->n_gateway_chassis);
+ for (i = 0; i < lrp->n_gateway_chassis; i++) {
+ gcs[i] = lrp->gateway_chassis[i];
+ }
+
+ qsort(gcs, lrp->n_gateway_chassis, sizeof *gcs, compare_chassis_prio_);
+
+ for (i = 0; i < lrp->n_gateway_chassis; i++) {
+ const struct nbrec_gateway_chassis *gc = gcs[i];
+ ds_put_format(&ctx->output, "%s %5"PRId64"\n",
+ gc->name, gc->priority);
+ }
+
+ free(gcs);
+}
+
static void
nbctl_lrp_add(struct ctl_context *ctx)
{
@@ -3413,6 +3592,13 @@ static const struct ctl_command_syntax nbctl_commands[] = {
{ "lrp-add", 4, INT_MAX,
"ROUTER PORT MAC NETWORK... [COLUMN[:KEY]=VALUE]...",
NULL, nbctl_lrp_add, NULL, "--may-exist", RW },
+ { "lrp-set-gateway-chassis", 2, 3,
+ "PORT CHASSIS [PRIORITY]",
+ NULL, nbctl_lrp_set_gateway_chassis, NULL, "--may-exist", RW },
+ { "lrp-del-gateway-chassis", 2, 2, "PORT CHASSIS", NULL,
+ nbctl_lrp_del_gateway_chassis, NULL, "", RW },
+ { "lrp-get-gateway-chassis", 1, 1, "PORT", NULL,
+ nbctl_lrp_get_gateway_chassis, NULL, "", RO },
{ "lrp-del", 1, 1, "PORT", NULL, nbctl_lrp_del, NULL, "--if-exists", RW },
{ "lrp-list", 1, 1, "ROUTER", NULL, nbctl_lrp_list, NULL, "", RO },
{ "lrp-set-enabled", 2, 2, "PORT STATE", NULL, nbctl_lrp_set_enabled,