On Mon, Sep 29, 2025 at 12:18:50PM +0100, Mairtin O'Loingsigh wrote:
> 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
> 

Recheck-request: github-robot-_ovn-kubernetes

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

Reply via email to