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
