Added commands to add, delete and list transit routers.
    $ ovn-ic-nbctl tr-add tr0
    $ ovn-ic-nbctl tr-del tr0
    $ ovn-ic-nbctl tr-list
Added commands to add and delete a transit router port.
    $ ovn-ic-nbctl trp-add tr0 tr0-p0 00:00:00:11:22:00 192.168.10.10/24
        192.168.10.20/24 chassis=ovn-chassis-1
    $ ovn-ic-nbctl trp-del tr0-p0

Reported-at: https://issues.redhat.com/browse/FDP-1477
Signed-off-by: Mairtin O'Loingsigh <[email protected]>
---
 utilities/ovn-ic-nbctl.c | 266 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 264 insertions(+), 2 deletions(-)

diff --git a/utilities/ovn-ic-nbctl.c b/utilities/ovn-ic-nbctl.c
index 5819192fe..740c75bf1 100644
--- a/utilities/ovn-ic-nbctl.c
+++ b/utilities/ovn-ic-nbctl.c
@@ -337,6 +337,14 @@ Transit switch commands:\n\
   ts-del SWITCH              delete SWITCH\n\
   ts-list                    print all transit switches\n\
 \n\
+Transit router commands:\n\
+  tr-add ROUTER              create a transit router named ROUTER\n\
+  tr-del ROUTER              delete ROUTER\n\
+  tr-list                    print all transit routers\n\
+  trp-add ROUTER PORT MAC [NETWORK]...[chassis=CHASSIS]\n\
+                             add a transit router PORT\n\
+  trp-del PORT               delete a transit router PORT\n\
+\n\
 Connection commands:\n\
   get-connection             print the connections\n\
   del-connection             delete the connections\n\
@@ -397,10 +405,20 @@ struct ic_nbctl_context {
 static struct cmd_show_table cmd_show_tables[] = {
     {&icnbrec_table_transit_switch,
      &icnbrec_transit_switch_col_name,
-     {NULL},
+     {NULL, NULL, NULL},
+     {NULL, NULL, NULL}},
+
+    {&icnbrec_table_transit_router,
+     &icnbrec_transit_router_col_name,
+     {NULL, NULL, NULL},
+     {NULL, NULL, NULL}},
+
+    {&icnbrec_table_transit_router_port,
+     &icnbrec_transit_router_port_col_name,
+     {&icnbrec_transit_router_port_col_nb_ic_uuid, NULL, NULL},
      {NULL, NULL, NULL}},
 
-    {NULL, NULL, {NULL, NULL, NULL}, {NULL, NULL, NULL}},
+    {NULL, NULL, {NULL, NULL, NULL}, {NULL, NULL, NULL}}
 };
 
 static void
@@ -507,6 +525,228 @@ ic_nbctl_ts_list(struct ctl_context *ctx)
     smap_destroy(&switches);
     free(nodes);
 }
+
+static void
+ic_nbctl_tr_add(struct ctl_context *ctx)
+{
+    if (!ovsdb_idl_server_has_table(ctx->idl, &icnbrec_table_transit_router)) {
+        VLOG_WARN("icnbrec_table_transit_router missing");
+    }
+
+    const char *tr_name = ctx->argv[1];
+    bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
+
+    const struct icnbrec_transit_router *tr;
+    ICNBREC_TRANSIT_ROUTER_FOR_EACH (tr, ctx->idl) {
+        if (!strcmp(tr->name, tr_name)) {
+            if (may_exist) {
+                return;
+            }
+
+            ctl_error(ctx, "%s: a transit router with this name already "
+                      "exists", tr_name);
+            return;
+        }
+
+    }
+    tr = icnbrec_transit_router_insert(ctx->txn);
+
+    icnbrec_transit_router_set_name(tr, tr_name);
+}
+
+static char *
+tr_by_name_or_uuid(struct ctl_context *ctx, const char *id, bool must_exist,
+                   const struct icnbrec_transit_router **tr_p)
+{
+    const struct icnbrec_transit_router *tr = NULL;
+    *tr_p = NULL;
+
+    struct uuid tr_uuid;
+    bool is_uuid = uuid_from_string(&tr_uuid, id);
+    if (is_uuid) {
+        tr = icnbrec_transit_router_get_for_uuid(ctx->idl, &tr_uuid);
+    }
+
+    if (!tr) {
+        const struct icnbrec_transit_router *iter;
+
+        ICNBREC_TRANSIT_ROUTER_FOR_EACH (iter, ctx->idl) {
+            if (!strcmp(iter->name, id)) {
+                tr = iter;
+                break;
+            }
+        }
+    }
+
+    if (!tr && must_exist) {
+        return xasprintf("%s: router %s not found",
+                         id, is_uuid ? "UUID" : "name");
+    }
+
+    *tr_p = tr;
+    return NULL;
+}
+
+static void
+ic_nbctl_tr_del(struct ctl_context *ctx)
+{
+    bool must_exist = !shash_find(&ctx->options, "--if-exists");
+    const char *id = ctx->argv[1];
+    const struct icnbrec_transit_router *tr = NULL;
+
+    char *error = tr_by_name_or_uuid(ctx, id, must_exist, &tr);
+    if (error) {
+        ctx->error = error;
+        return;
+    }
+
+    if (!tr) {
+        return;
+    }
+
+    icnbrec_transit_router_delete(tr);
+}
+
+static void
+ic_nbctl_trp_del(struct ctl_context *ctx)
+{
+    const char *port = ctx->argv[1];
+    const struct icnbrec_transit_router_port *trp = NULL;
+
+    const struct icnbrec_transit_router_port *iter;
+
+    ICNBREC_TRANSIT_ROUTER_PORT_FOR_EACH (iter, ctx->idl) {
+        if (!strcmp(iter->name, port)) {
+            trp = iter;
+            break;
+        }
+
+    }
+
+    if (!trp) {
+        ctx->error = xasprintf("%s: router port not found", port);
+        return;
+    }
+
+    icnbrec_transit_router_port_delete(trp);
+}
+
+static void
+ic_nbctl_tr_list(struct ctl_context *ctx)
+{
+    const struct icnbrec_transit_router *tr;
+    struct smap routers;
+
+    smap_init(&routers);
+    ICNBREC_TRANSIT_ROUTER_FOR_EACH (tr, ctx->idl) {
+        smap_add_format(&routers, tr->name, UUID_FMT " (%s)",
+                        UUID_ARGS(&tr->header_.uuid), tr->name);
+    }
+    const struct smap_node **nodes = smap_sort(&routers);
+    for (size_t i = 0; i < smap_count(&routers); i++) {
+        const struct smap_node *node = nodes[i];
+        ds_put_format(&ctx->output, "%s\n", node->value);
+    }
+    smap_destroy(&routers);
+    free(nodes);
+}
+
+static void
+ic_nbctl_trp_add(struct ctl_context *ctx)
+{
+    const char *tr_name = ctx->argv[1];
+    const char *trp_name = ctx->argv[2];
+    const char *mac = ctx->argv[3];
+    const char **networks = (const char **) &ctx->argv[4];
+    bool found = false;
+    const struct icnbrec_transit_router *tr;
+    ICNBREC_TRANSIT_ROUTER_FOR_EACH (tr, ctx->idl) {
+        if (!strcmp(tr->name, tr_name)) {
+            found = true;
+            break;
+        }
+
+    }
+
+    if (!found) {
+        ctl_error(ctx, "%s: transit router does not exist.", tr_name);
+        return;
+    }
+
+    found = false;
+    const struct icnbrec_transit_router_port *trp;
+    ICNBREC_TRANSIT_ROUTER_PORT_FOR_EACH (trp, ctx->idl) {
+        if (!strcmp(trp->name, trp_name)) {
+            found = true;
+            break;
+        }
+
+    }
+
+    if (found) {
+        ctl_error(ctx, "%s: a transit router port with this name already "
+                  "exists.", trp_name);
+        return;
+
+    }
+
+    struct eth_addr ea;
+    if (!eth_addr_from_string(mac, &ea)) {
+        ctl_error(ctx, "%s: MAC address is invalid.", mac);
+        return;
+    }
+
+    /* Parse networks*/
+    int n_networks = ctx->argc - 4;
+    for (int i = 4; i < ctx->argc; i++) {
+        if (strchr(ctx->argv[i], '=')) {
+            n_networks = i - 4;
+            break;
+        }
+
+    }
+
+    char **settings = (char **) &ctx->argv[n_networks + 4];
+    int n_settings = ctx->argc - 4 - n_networks;
+
+    for (int i = 0; i < n_networks; i++) {
+        ovs_be32 ipv4;
+        unsigned int plen;
+        char *error;
+        error = ip_parse_cidr(networks[i], &ipv4, &plen);
+        if (error) {
+            free(error);
+            struct in6_addr ipv6;
+            error = ipv6_parse_cidr(networks[i], &ipv6, &plen);
+            if (error) {
+                free(error);
+                ctl_error(ctx, "%s: invalid network address: %s", trp_name,
+                          networks[i]);
+                return;
+            }
+
+        }
+
+    }
+
+    trp = icnbrec_transit_router_port_insert(ctx->txn);
+    icnbrec_transit_router_port_set_transit_router(trp, tr_name);
+    icnbrec_transit_router_port_set_name(trp, trp_name);
+    icnbrec_transit_router_port_set_mac(trp, mac);
+    icnbrec_transit_router_port_set_nb_ic_uuid(trp, tr->header_.uuid);
+    icnbrec_transit_router_port_set_networks(trp, networks, n_networks);
+
+    for (int i = 0; i < n_settings; i++) {
+        char *error = ctl_set_column("Transit_Router_Port", &trp->header_,
+                               settings[i], ctx->symtab);
+        if (error) {
+            ctx->error = error;
+            return;
+        }
+
+    }
+}
+
 static void
 verify_connections(struct ctl_context *ctx)
 {
@@ -714,6 +954,15 @@ cmd_set_ssl(struct ctl_context *ctx)
 static const struct ctl_table_class tables[ICNBREC_N_TABLES] = {
     [ICNBREC_TABLE_TRANSIT_SWITCH].row_ids[0] =
     {&icnbrec_transit_switch_col_name, NULL, NULL},
+
+    [ICNBREC_TABLE_TRANSIT_ROUTER].row_ids[0] =
+    {&icnbrec_transit_router_col_name, NULL, NULL},
+
+    [ICNBREC_TABLE_TRANSIT_ROUTER_PORT].row_ids =
+        {{&icnbrec_transit_router_port_col_name, NULL, NULL},
+        {&icnbrec_transit_router_port_col_nb_ic_uuid, NULL, NULL},
+        {&icnbrec_transit_router_port_col_mac, NULL, NULL},
+        {&icnbrec_transit_router_port_col_transit_router, NULL, NULL}},
 };
 
 
@@ -1010,11 +1259,24 @@ ic_nbctl_exit(int status)
 static const struct ctl_command_syntax ic_nbctl_commands[] = {
     { "init", 0, 0, "", NULL, ic_nbctl_init, NULL, "", RW },
     { "sync", 0, 0, "", ic_nbctl_pre_sync, NULL, NULL, "", RO },
+
     /* transit switch commands. */
     { "ts-add", 1, 1, "SWITCH", NULL, ic_nbctl_ts_add, NULL, "--may-exist", RW 
},
     { "ts-del", 1, 1, "SWITCH", NULL, ic_nbctl_ts_del, NULL, "--if-exists", RW 
},
     { "ts-list", 0, 0, "", NULL, ic_nbctl_ts_list, NULL, "", RO },
 
+    /* transit router commands. */
+    { "tr-add", 1, 1, "ROUTER", NULL, ic_nbctl_tr_add, NULL, "--may-exist",
+        RW },
+    { "tr-del", 1, 1, "ROUTER", NULL, ic_nbctl_tr_del, NULL, "--if-exists",
+        RW },
+    { "tr-list", 0, 0, "", NULL, ic_nbctl_tr_list, NULL, "", RO },
+    { "trp-add", 4, INT_MAX,
+        "ROUTER PORT MAC [NETWORK]...[COLUMN[:KEY]=VALUE]...",
+        NULL, ic_nbctl_trp_add, NULL, "--may-exist", RW },
+    { "trp-del", 1, 1, "PORT", NULL, ic_nbctl_trp_del, NULL, "--if-exists",
+        RW },
+
     /* Connection commands. */
     {"get-connection", 0, 0, "", pre_connection, cmd_get_connection, NULL, "",
         RO},
-- 
2.50.0

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to