On Mon, Jun 22, 2026 at 10:49 AM Mairtin O'Loingsigh <[email protected]>
wrote:

> On Mon, Jun 22, 2026 at 09:46:17AM +0200, Ales Musil wrote:
> > On Fri, Jun 19, 2026 at 2:32 PM Mairtin O'Loingsigh <[email protected]
> >
> > wrote:
> >
> > > Enable the creation and management of transit switch ports, when
> > > created, these ports are available across multiple AZs and may share
> > > port binding depending on configuration. This patch also includes tests
> > > and a multinode test.
> > >
> > > Commands to add, set address and delete port
> > >     ovn-ic-nbctl tsp-add ts0 ts0-p0 chassis=chassis
> > >     ovn-ic-nbctl tsp-set-addr ts0-p0 "00:11:22:11:22:34
> > >         192.168.10.11/24"
> > >     ovn-ic-nbctl tsp-del ts0-p0
> > >
> > > Reported-at: https://issues.redhat.com/browse/FDP-2878
> > > Signed-off-by: Mairtin O'Loingsigh <[email protected]>
> > > ---
> > >
> >
> > Hi Mairtin,
> >
> > thank you for the v8. I think this still requires a few changes.
> > I suggest the following diff, if you agree I will apply it
> > with the diff to main:
> >
> > diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c
> > index e9ad422c6..f07e74866 100644
> > --- a/ic/ovn-ic.c
> > +++ b/ic/ovn-ic.c
> > @@ -826,17 +826,18 @@ update_isb_pb_external_ids(struct ic_context *ctx,
> >
> >  /* Sync a local port's fields from TSP INB->ISB. */
> >  static void
> > -sync_tsp_port(struct ic_context *ctx,
> > -              const struct icnbrec_transit_switch_port *tsp,
> > -              const struct icsbrec_port_binding *isb_pb,
> > -              const struct nbrec_logical_switch_port *lsp)
> > +sync_tsp_pb(const struct icnbrec_transit_switch_port *tsp,
> > +            const struct icsbrec_port_binding *isb_pb)
> >  {
> > +    if (!isb_pb) {
> > +        return;
> > +    }
> > +
> >      /* Sync address to ISB. */
> > -    if (!tsp->n_addresses) {
> > -        if (isb_pb->address[0]) {
> > -            icsbrec_port_binding_set_address(isb_pb, "");
> > -        }
> > -    } else if (strcmp(tsp->addresses[0], isb_pb->address)) {
> > +    if (!tsp->n_addresses && isb_pb->address[0]) {
> > +        icsbrec_port_binding_set_address(isb_pb, "");
> > +    } else if (tsp->n_addresses &&
> > +               strcmp(tsp->addresses[0], isb_pb->address)) {
> >          icsbrec_port_binding_set_address(isb_pb, tsp->addresses[0]);
> >      }
> >
> > @@ -844,49 +845,6 @@ sync_tsp_port(struct ic_context *ctx,
> >      if (strcmp(tsp->chassis, isb_pb->gateway)) {
> >          icsbrec_port_binding_set_gateway(isb_pb, tsp->chassis);
> >      }
> > -
> > -    /* Sync router-id information to ISB. */
> > -    struct uuid uuid;
> > -    if (!strcmp(tsp->type, "router")) {
> > -        if (tsp->peer[0]) {
> > -            const struct nbrec_logical_router *lr = NULL;
> > -            const struct nbrec_logical_router *iter = NULL;
> > -            NBREC_LOGICAL_ROUTER_FOR_EACH (iter, ctx->ovnnb_idl) {
> > -                for (size_t i = 0; i < iter->n_ports; i++) {
> > -                    if (!strcmp(tsp->peer, iter->ports[i]->name)) {
> > -                        lr = iter;
> > -                        break;
> > -                    }
> > -                }
> > -                if (lr) {
> > -                    break;
> > -                }
> > -            }
> > -
> > -            if (lr) {
> > -                if (!smap_get_uuid(&isb_pb->external_ids, "router-id",
> > &uuid)
> > -                    || !uuid_equals(&lr->header_.uuid, &uuid)) {
> > -                    char *uuid_s =
> > -                        xasprintf(UUID_FMT,
> UUID_ARGS(&lr->header_.uuid));
> > -                    icsbrec_port_binding_update_external_ids_setkey(
> > -                        isb_pb, "router-id", uuid_s);
> > -                    free(uuid_s);
> > -                }
> > -            } else {
> > -                if (smap_get_uuid(&isb_pb->external_ids, "router-id",
> > &uuid)) {
> > -                    icsbrec_port_binding_update_external_ids_delkey(
> > -                        isb_pb, "router-id");
> > -                }
> > -            }
> > -        }
> > -    } else {
> > -        if (smap_get_uuid(&isb_pb->external_ids, "router-id", &uuid)) {
> > -            icsbrec_port_binding_update_external_ids_delkey(isb_pb,
> > -
> "router-id");
> > -        }
> > -    }
> > -
> > -    sync_lsp_tnl_key(lsp, isb_pb->tunnel_key);
> >  }
> >
> >  /* For each local port:
> > @@ -937,26 +895,52 @@ sync_local_port(struct ic_context *ctx,
> >      sync_lsp_tnl_key(lsp, isb_pb->tunnel_key);
> >  }
> >
> > +static void
> > +sync_tsp_router_peer(const struct icnbrec_transit_switch_port *tsp,
> > +                     const struct nbrec_logical_switch_port *lsp)
> > +{
> > +    /* Clear the peer for router port type. */
> > +    if (lsp->peer && lsp->peer[0]) {
> > +        nbrec_logical_switch_port_set_peer(lsp, NULL);
> > +    }
> > +
> > +    if (tsp->peer[0]) {
> > +        const char *rp = smap_get(&lsp->options, "router-port");
> > +        if (!rp || strcmp(rp, tsp->peer)) {
> > +            nbrec_logical_switch_port_update_options_setkey(
> > +                lsp, "router-port", tsp->peer);
> > +        }
> > +    } else if (smap_get(&lsp->options, "router-port")) {
> > +        nbrec_logical_switch_port_update_options_delkey(lsp,
> > "router-port");
> > +    }
> > +}
> > +
> > +static void
> > +sync_tsp_non_router_peer(const struct icnbrec_transit_switch_port *tsp,
> > +                         const struct nbrec_logical_switch_port *lsp)
> > +{
> > +    /* Clear router-port setting for non-routers. */
> > +    if (smap_get(&lsp->options, "router-port")) {
> > +        nbrec_logical_switch_port_update_options_delkey(lsp,
> > "router-port");
> > +    }
> > +
> > +    if (tsp->peer[0]) {
> > +        if (!lsp->peer || strcmp(lsp->peer, tsp->peer)) {
> > +            nbrec_logical_switch_port_set_peer(lsp, tsp->peer);
> > +        }
> > +    } else if (lsp->peer && lsp->peer[0]) {
> > +        nbrec_logical_switch_port_set_peer(lsp, NULL);
> > +    }
> > +}
> > +
> >  static void
> >  sync_tsp_common(const struct icnbrec_transit_switch_port *tsp,
> >                  const struct icsbrec_port_binding *isb_pb,
> >                  const struct nbrec_logical_switch_port *lsp)
> >  {
> >      /* Sync addresses from TSP to NB. */
> > -    if (!tsp->n_addresses) {
> > -        if (lsp->n_addresses) {
> > -            nbrec_logical_switch_port_set_addresses(lsp, NULL, 0);
> > -        }
> > -    } else if (lsp->n_addresses) {
> > -        if (strcmp(lsp->addresses[0], tsp->addresses[0])) {
> > -            nbrec_logical_switch_port_set_addresses(
> > -                lsp, (const char **) &tsp->addresses[0],
> > -                tsp->n_addresses);
> > -        }
> > -    } else {
> > -        nbrec_logical_switch_port_set_addresses(
> > -            lsp, (const char **) &tsp->addresses[0], 1);
> > -    }
> > +    nbrec_logical_switch_port_set_addresses(
> > +        lsp, (const char **) tsp->addresses, tsp->n_addresses);
> >
> >      if (tsp->chassis[0]) {
> >          const char *current = smap_get(&lsp->options,
> "requested-chassis");
> > @@ -973,30 +957,9 @@ sync_tsp_common(const struct
> > icnbrec_transit_switch_port *tsp,
> >      sync_lsp_tnl_key(lsp, isb_pb->tunnel_key);
> >
> >      if (!strcmp(tsp->type, "router")) {
> > -        const char *rp = smap_get(&lsp->options, "router-port");
> > -        if (!rp || strcmp(rp, tsp->peer)) {
> > -            nbrec_logical_switch_port_update_options_setkey(
> > -                lsp, "router-port", tsp->peer);
> > -        }
> > -    }
> > -
> > -    if (strcmp(tsp->type, "router")) {
> > -        if (tsp->peer[0]) {
> > -            if (!lsp->peer || strcmp(lsp->peer, tsp->peer)) {
> > -                nbrec_logical_switch_port_set_peer(lsp, tsp->peer);
> > -            }
> > -        } else if (lsp->peer && lsp->peer[0]) {
> > -            nbrec_logical_switch_port_set_peer(lsp, NULL);
> > -        }
> > -        /* Clear router-port setting for non-routers. */
> > -        if (smap_get(&lsp->options, "router-port")) {
> > -            nbrec_logical_switch_port_update_options_delkey(lsp,
> > -
> "router-port");
> > -        }
> > +        sync_tsp_router_peer(tsp, lsp);
> >      } else {
> > -        if (lsp->peer && lsp->peer[0]) {
> > -            nbrec_logical_switch_port_set_peer(lsp, NULL);
> > -        }
> > +        sync_tsp_non_router_peer(tsp, lsp);
> >      }
> >  }
> >
> > @@ -1246,7 +1209,7 @@ lsp_create(struct ic_context *ctx, const struct
> > nbrec_logical_switch *ls,
> >          nbrec_logical_switch_port_insert(ctx->ovnnb_txn);
> >      nbrec_logical_switch_port_set_name(lsp, tsp->name);
> >
> > -    nbrec_logical_switch_port_update_options_setkey(lsp, "interconn-ts",
> > +    nbrec_logical_switch_port_update_options_setkey(lsp,
> "interconn-tsp",
> >                                                      tsp->name);
> >      nbrec_logical_switch_update_ports_addvalue(ls, lsp);
> >      return lsp;
> > @@ -1303,7 +1266,7 @@ port_binding_run(struct ic_context *ctx)
> >
> >          for (size_t i = 0; i < ls->n_ports; i++) {
> >              const struct nbrec_logical_switch_port *lsp = ls->ports[i];
> > -            if (smap_get(&lsp->options, "interconn-ts")) {
> > +            if (smap_get(&lsp->options, "interconn-tsp")) {
> >                  shash_add(&nb_ports, lsp->name, lsp);
> >              } else {
> >                  shash_add(&old_nb_ports, lsp->name, lsp);
> > @@ -1328,7 +1291,6 @@ port_binding_run(struct ic_context *ctx)
> >
> >          for (size_t i = 0; i < ts->n_ports; i++) {
> >              struct icnbrec_transit_switch_port *tsp = ts->ports[i];
> > -            bool is_owner = false;
> >
> >              if (!tsp->chassis[0]) {
> >                  isb_pb = shash_find_and_delete(&local_pbs, tsp->name);
> > @@ -1343,7 +1305,7 @@ port_binding_run(struct ic_context *ctx)
> >                              ts->name, &ts->header_.uuid,
> > "transit-switch-port",
> >                              &pb_tnlids);
> >                      }
> > -                    is_owner = true;
> > +                    sync_tsp_pb(tsp, isb_pb);
> >                  }
> >              } else if (!chassis_is_remote(ctx, tsp->chassis)) {
> >                  /* Create ISB port_binding as its chassis is local. */
> > @@ -1354,7 +1316,7 @@ port_binding_run(struct ic_context *ctx)
> >                                             ts->name, &ts->header_.uuid,
> >                                             "transit-switch-port",
> > &pb_tnlids);
> >                  }
> > -                is_owner = true;
> > +                sync_tsp_pb(tsp, isb_pb);
> >              } else {
> >                  isb_pb = shash_find_and_delete(&remote_pbs, tsp->name);
> >              }
> > @@ -1369,10 +1331,6 @@ port_binding_run(struct ic_context *ctx)
> >                  lsp = lsp_create(ctx, ls, tsp);
> >              }
> >
> > -            if (is_owner) {
> > -                sync_tsp_port(ctx, tsp, isb_pb, lsp);
> > -            }
> > -
> >              if (!tsp->chassis[0] || !chassis_is_remote(ctx,
> tsp->chassis))
> > {
> >                  sync_tsp_local(tsp, isb_pb, lsp);
> >              } else {
> > diff --git a/lib/ovn-util.h b/lib/ovn-util.h
> > index caf5d2cf4..b911a59b0 100644
> > --- a/lib/ovn-util.h
> > +++ b/lib/ovn-util.h
> > @@ -796,7 +796,7 @@ char *normalize_addr_str(const char *orig_addr);
> >
> >  bool port_contains_duplicate_ip(struct lport_addresses *laddrs1,
> >                                  struct lport_addresses *laddrs2,
> > -                                const char *name, char **error_str);
> > +                                const char *port_name, char
> **error_str);
> >
> >  #define NEIGH_REDISTRIBUTE_MODES    \
> >      NEIGH_REDISTRIBUTE_MODE(FDB, 0) \
> > diff --git a/ovn-ic-nb.xml b/ovn-ic-nb.xml
> > index 669f9f7aa..f6110324c 100644
> > --- a/ovn-ic-nb.xml
> > +++ b/ovn-ic-nb.xml
> > @@ -222,8 +222,7 @@
> >      </column>
> >
> >      <column name="addresses">
> > -      The addresses associated with this port.  Used when
> > -      <ref column="type"/> is not <code>router</code>.
> > +      The addresses associated with this port.
> >      </column>
> >
> >      <group title="Common Columns">
> > diff --git a/tests/ovn-ic-nbctl.at b/tests/ovn-ic-nbctl.at
> > index eb333edec..4615f73f4 100644
> > --- a/tests/ovn-ic-nbctl.at
> > +++ b/tests/ovn-ic-nbctl.at
> > @@ -108,6 +108,26 @@ AT_CHECK([ovn-ic-nbctl tsp-del ts0-p0], [1], [],
> >  ])
> >  AT_CHECK([ovn-ic-nbctl --if-exists trp-del tr0-p0])
> >
> > +dnl tsp-del --if-exists on nonexistent port should succeed silently
> > +AT_CHECK([ovn-ic-nbctl --if-exists tsp-del nonexistent-port])
> > +
> > +dnl tsp-add to nonexistent transit switch should fail
> > +AT_CHECK([ovn-ic-nbctl tsp-add no-such-ts port1], [1], [],
> > +  [ovn-ic-nbctl: no-such-ts: switch name not found
> > +])
> > +
> > +dnl tsp-set-addr with invalid address format
> > +AT_CHECK([ovn-ic-nbctl tsp-add ts0 ts0-p1])
> > +AT_CHECK([ovn-ic-nbctl tsp-set-addr ts0-p1 "not-a-valid-address"], [1],
> [],
> > +  [ovn-ic-nbctl: not-a-valid-address: Invalid address format. See
> > ovn-ic-nb(5). Hint: An Ethernet address must be listed before an IP
> > address, together as a single argument.
> > +])
> > +
> > +dnl tsp-set-addr with multiple address arguments
> > +AT_CHECK([ovn-ic-nbctl tsp-set-addr ts0-p1 "aa:bb:cc:dd:ee:f1 10.0.0.1"
> > "aa:bb:cc:dd:ee:f2 10.0.0.2"])
> > +check_column "aa:bb:cc:dd:ee:f1 10.0.0.1 aa:bb:cc:dd:ee:f2 10.0.0.2"
> > ic-nb:transit_switch_port addresses name=ts0-p1
> > +
> > +AT_CHECK([ovn-ic-nbctl tsp-del ts0-p1])
> > +
> >  OVN_IC_NBCTL_TEST_STOP
> >  AT_CLEANUP
> >
> > diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at
> > index 260346a48..cf42a5cd0 100644
> > --- a/tests/ovn-ic.at
> > +++ b/tests/ovn-ic.at
> > @@ -210,10 +210,7 @@ wait_row_count Datapath_Binding 1
> > external_ids:interconn-ts=ts1
> >  check ovn-ic-nbctl --wait=sb sync
> >  check_column "router" nb:Logical_Switch_Port type name=tsp1
> >  check_column "" nb:Logical_Switch_Port peer name=tsp1
> > -check_column "interconn-ts=tsp1 router-port=lrp1
> requested-chassis=gw-az1
> > requested-tnl-key=1" nb:Logical_Switch_Port options name=tsp1
> > -
> > -ROUTER_UUID=$(ovn-nbctl --bare --columns=_uuid find Logical_Router
> > name=lr1)
> > -check_column "router-id=$ROUTER_UUID" ic-sb:port_binding external-ids
> > logical_port=tsp1
> > +check_column "interconn-tsp=tsp1 router-port=lrp1
> requested-chassis=gw-az1
> > requested-tnl-key=1" nb:Logical_Switch_Port options name=tsp1
> >
> >  AT_CHECK([ovn-ic-sbctl show | grep -A2 tsp1], [0], [dnl
> >          port tsp1
> > @@ -221,9 +218,53 @@ AT_CHECK([ovn-ic-sbctl show | grep -A2 tsp1], [0],
> [dnl
> >              address: [["00:00:00:00:00:02 10.0.1.2/24"]]
> >  ])
> >
> > -# remove transit switch and check if port_binding is deleted
> > -check ovn-ic-nbctl --wait=sb ts-del ts1
> > +dnl Verify ISB metadata fields
> > +check_column "transit-switch-port" ic-sb:port_binding type
> > logical_port=tsp1
> > +check_column "gw-az1" ic-sb:port_binding gateway logical_port=tsp1
> > +
> > +dnl Add a second TSP on az2 to test individual tsp-del
> > +check ovn-ic-nbctl tsp-add ts1 tsp2 chassis=gw-az2
> > +check ovn-ic-nbctl tsp-set-addr tsp2 "00:00:00:00:00:03 10.0.2.3/24"
> > +check ovn-ic-nbctl --wait=sb sync
> > +
> > +ovn_as az2
> > +wait_row_count nb:Logical_Switch_Port 1 name=tsp2
> > +check_column "" nb:Logical_Switch_Port type name=tsp2
> > +check_row_count ic-sb:Port_Binding 1 logical_port=tsp2
> > +check_column "transit-switch-port" ic-sb:port_binding type
> > logical_port=tsp2
> > +check_column "gw-az2" ic-sb:port_binding gateway logical_port=tsp2
> > +
> > +dnl Delete tsp1 via tsp-del (not ts-del) and verify orphan cleanup
> > +ovn_as az1
> > +check ovn-ic-nbctl tsp-del tsp1
> > +check ovn-ic-nbctl --wait=sb sync
> > +
> > +dnl ISB port_binding for tsp1 should be gone
> >  check_row_count ic-sb:Port_Binding 0 logical_port=tsp1
> > +
> > +dnl NB LSP for tsp1 should be cleaned up (orphan removal)
> > +wait_row_count nb:Logical_Switch_Port 0 name=tsp1
> > +ovn_as az2
> > +wait_row_count nb:Logical_Switch_Port 0 name=tsp1
> > +
> > +dnl tsp2 should still be intact
> > +check_row_count ic-sb:Port_Binding 1 logical_port=tsp2
> > +wait_row_count nb:Logical_Switch_Port 1 name=tsp2
> > +
> > +dnl The TS itself should still exist
> > +check_row_count ic-sb:Datapath_Binding 1 transit_switch=ts1
> > +
> > +dnl Now delete tsp2 as well
> > +ovn_as az1
> > +check ovn-ic-nbctl tsp-del tsp2
> > +check ovn-ic-nbctl --wait=sb sync
> > +check_row_count ic-sb:Port_Binding 0 logical_port=tsp2
> > +wait_row_count nb:Logical_Switch_Port 0 name=tsp2
> > +
> > +dnl TS still exists after all ports are deleted
> > +check_row_count ic-sb:Datapath_Binding 1 transit_switch=ts1
> > +
> > +check ovn-ic-nbctl --wait=sb ts-del ts1
> >  for i in 1 2; do
> >      az=az$i
> >      ovn_as $az
> > @@ -266,8 +307,6 @@ wait_row_count Datapath_Binding 1
> > external_ids:interconn-ts=ts1
> >  # Sync ic-sb DB to see the TS changes.
> >  check ovn-ic-nbctl --wait=sb sync
> >
> > -ROUTER_UUID=$(ovn-nbctl --bare --columns=_uuid find Logical_Router
> > name=lr1)
> > -check_column "router-id=$ROUTER_UUID" ic-sb:port_binding external-ids
> > logical_port=tsp1
> >  AT_CHECK([ovn-ic-sbctl show | grep -A2 tsp1], [0], [dnl
> >          port tsp1
> >              transit switch: ts1
> > @@ -287,9 +326,8 @@ check ovn-ic-nbctl set Transit_Switch_Port $PORT_UUID
> > 'type=""'
> >  check ovn-ic-nbctl --wait=sb sync
> >  check_column "" nb:Logical_Switch_Port type name=tsp1
> >  check_row_count nb:Logical_Switch_Port 1 name=tsp1 peer=lrp1
> > -check_column "interconn-ts=tsp1 requested-chassis=gw-az1
> > requested-tnl-key=1" nb:Logical_Switch_Port options name=tsp1
> > +check_column "interconn-tsp=tsp1 requested-chassis=gw-az1
> > requested-tnl-key=1" nb:Logical_Switch_Port options name=tsp1
> >
> > -check_row_count ic-sb:Port_Binding 0 logical_port=tsp1
> > 'external_ids:router-id!=""'
> >  AT_CHECK([ovn-ic-sbctl show | grep -A2 tsp1], [0], [dnl
> >          port tsp1
> >              transit switch: ts1
> > @@ -306,15 +344,51 @@ PORT_UUID=$(ovn-ic-nbctl --bare --columns=_uuid
> find
> > Transit_Switch_Port name=ts
> >  check ovn-ic-nbctl set Transit_Switch_Port $PORT_UUID 'type="router"'
> >  check ovn-ic-nbctl --wait=sb sync
> >  check_column "router" nb:Logical_Switch_Port type name=tsp1
> > -check_column "interconn-ts=tsp1 router-port=lrp1
> requested-chassis=gw-az1
> > requested-tnl-key=1" nb:Logical_Switch_Port options name=tsp1
> > +check_column "interconn-tsp=tsp1 router-port=lrp1
> requested-chassis=gw-az1
> > requested-tnl-key=1" nb:Logical_Switch_Port options name=tsp1
> >
> > -check_column "router-id=$ROUTER_UUID" ic-sb:port_binding external-ids
> > logical_port=tsp1
> >  AT_CHECK([ovn-ic-sbctl show | grep -A2 tsp1], [0], [dnl
> >          port tsp1
> >              transit switch: ts1
> >              address: [["00:00:00:00:00:02 10.0.1.2/24"]]
> >  ])
> >
> > +dnl Verify remote AZ NB LSP details beyond just type="remote"
> > +ovn_as az2
> > +wait_row_count nb:Logical_Switch_Port 1 name=tsp1
> > +check_column "remote" nb:Logical_Switch_Port type name=tsp1
> > +check_column "00:00:00:00:00:02 10.0.1.2/24" nb:Logical_Switch_Port
> > addresses name=tsp1
> > +check_column "" nb:Logical_Switch_Port peer name=tsp1
> > +ovn_as az1
> > +
> > +dnl Test address change after initial sync
> > +check ovn-ic-nbctl tsp-set-addr tsp1 "aa:bb:cc:dd:ee:ff 192.168.1.1/24"
> > +check ovn-ic-nbctl --wait=sb sync
> > +
> > +dnl Verify NB LSP address updated in owning AZ
> > +check_column "aa:bb:cc:dd:ee:ff 192.168.1.1/24" nb:Logical_Switch_Port
> > addresses name=tsp1
> > +
> > +dnl Verify ISB address updated
> > +AT_CHECK([ovn-ic-sbctl show | grep -A2 tsp1], [0], [dnl
> > +        port tsp1
> > +            transit switch: ts1
> > +            address: [["aa:bb:cc:dd:ee:ff 192.168.1.1/24"]]
> > +])
> > +
> > +dnl Verify remote AZ reflects the new address
> > +ovn_as az2
> > +check_column "aa:bb:cc:dd:ee:ff 192.168.1.1/24" nb:Logical_Switch_Port
> > addresses name=tsp1
> > +ovn_as az1
> > +
> > +dnl Clear address and verify propagation
> > +check ovn-ic-nbctl tsp-set-addr tsp1
> > +check ovn-ic-nbctl --wait=sb sync
> > +check_column "" nb:Logical_Switch_Port addresses name=tsp1
> > +
> > +dnl Set address again to verify recovery
> > +check ovn-ic-nbctl tsp-set-addr tsp1 "00:00:00:00:00:02 10.0.1.2/24"
> > +check ovn-ic-nbctl --wait=sb sync
> > +check_column "00:00:00:00:00:02 10.0.1.2/24" nb:Logical_Switch_Port
> > addresses name=tsp1
> > +
> >  # remove transit switch and check if port_binding is deleted
> >  check ovn-ic-nbctl --wait=sb ts-del ts1
> >  check_row_count ic-sb:Port_Binding 0 logical_port=tsp1
> > @@ -422,17 +496,22 @@ check ovn-ic-nbctl tsp-add ts1 tsp1
> >  check ovn-ic-nbctl tsp-set-addr tsp1 "00:00:00:00:00:02 10.0.0.2"
> >  check ovn-ic-nbctl --wait=sb sync
> >
> > -# Leader AZ should have the NB LSP
> > +dnl Leader AZ should have the NB LSP with correct address
> >  wait_row_count nb:Logical_Switch_Port 1 name=tsp1
> >  check_column "" nb:Logical_Switch_Port type name=tsp1
> > +check_column "00:00:00:00:00:02 10.0.0.2" nb:Logical_Switch_Port
> addresses
> > name=tsp1
> >
> > -# Non-leader AZ should also have it (found via index lookup)
> > +dnl Non-leader AZ should also have it with address
> >  ovn_as az2
> >  check ovn-ic-nbctl --wait=sb sync
> >  wait_row_count nb:Logical_Switch_Port 1 name=tsp1
> > +check_column "" nb:Logical_Switch_Port type name=tsp1
> > +check_column "00:00:00:00:00:02 10.0.0.2" nb:Logical_Switch_Port
> addresses
> > name=tsp1
> >
> > -# Verify ISB port binding exists
> > +dnl Verify ISB port binding exists with correct metadata
> >  check_row_count ic-sb:Port_Binding 1 logical_port=tsp1
> > +check_column "transit-switch-port" ic-sb:port_binding type
> > logical_port=tsp1
> > +check_column "" ic-sb:port_binding gateway logical_port=tsp1
> >
> >  # Cleanup
> >  ovn_as az1
> > @@ -473,28 +552,31 @@ check ovn-ic-nbctl tsp-add ts1 tsp1 chassis=gw-az1
> >  check ovn-ic-nbctl tsp-set-addr tsp1 "00:00:00:00:00:01 10.0.0.1"
> >  check ovn-ic-nbctl --wait=sb sync
> >
> > -# az1 owns it
> > +dnl az1 owns it, verify ISB gateway
> >  wait_row_count nb:Logical_Switch_Port 1 name=tsp1
> >  check_column "" nb:Logical_Switch_Port type name=tsp1
> > +check_column "gw-az1" ic-sb:port_binding gateway logical_port=tsp1
> >
> > -# az2 sees it as remote
> > +dnl az2 sees it as remote with synced address
> >  ovn_as az2
> >  wait_row_count nb:Logical_Switch_Port 1 name=tsp1
> >  check_column "remote" nb:Logical_Switch_Port type name=tsp1
> > +check_column "00:00:00:00:00:01 10.0.0.1" nb:Logical_Switch_Port
> addresses
> > name=tsp1
> >
> > -# Reassign chassis to gw-az2
> > +dnl Reassign chassis to gw-az2
> >  ovn_as az1
> >  PORT_UUID=$(ovn-ic-nbctl --bare --columns=_uuid find Transit_Switch_Port
> > name=tsp1)
> >  check ovn-ic-nbctl set Transit_Switch_Port $PORT_UUID chassis=gw-az2
> >  check ovn-ic-nbctl --wait=sb sync
> >
> > -# az1 now sees it as remote
> > +dnl az1 now sees it as remote
> >  wait_column "remote" nb:Logical_Switch_Port type name=tsp1
> >
> > -# az2 now owns it
> > +dnl az2 now owns it, ISB gateway updated
> >  ovn_as az2
> >  check ovn-ic-nbctl --wait=sb sync
> >  wait_column "" nb:Logical_Switch_Port type name=tsp1
> > +check_column "gw-az2" ic-sb:port_binding gateway logical_port=tsp1
> >
> >  # Change type to router with peer on az2
> >  check ovn-nbctl lr-add lr1
> > @@ -794,6 +876,44 @@ switch <0> (ts1)
> >  check ovn-nbctl lsp-del lsp-ts1-lr1
> >  OVS_WAIT_WHILE([ovn_as az2 ovn-nbctl show | grep lsp-ts1-lr1])
> >
> > +dnl Test mixed legacy + TSP coexistence on the same TS.
> > +dnl Re-create the legacy port
> > +check ovn-nbctl lrp-add lr1 lrp-lr1-ts1 aa:aa:aa:aa:aa:01
> 169.254.100.1/24
> > +check ovn-nbctl lrp-set-gateway-chassis lrp-lr1-ts1 gw1
> > +check ovn-nbctl --wait=hv lsp-add-router-port ts1 lsp-ts1-lr1
> lrp-lr1-ts1
> > +OVS_WAIT_UNTIL([ovn_as az2 ovn-nbctl show | grep -q lsp-ts1-lr1])
> > +
> > +dnl Add a TSP alongside the legacy port
> > +check ovn-ic-nbctl tsp-add ts1 tsp-mixed chassis=gw1
> > +check ovn-ic-nbctl tsp-set-addr tsp-mixed "bb:bb:bb:bb:bb:01 10.0.0.50"
> > +check ovn-ic-nbctl --wait=sb sync
> > +
> > +dnl Both ports should exist in NB
> > +ovn_as az1
> > +wait_row_count nb:Logical_Switch_Port 1 name=lsp-ts1-lr1
> > +wait_row_count nb:Logical_Switch_Port 1 name=tsp-mixed
> > +
> > +dnl Legacy port should NOT have interconn-tsp option
> > +AT_CHECK([ovn-nbctl --bare --columns=options find Logical_Switch_Port
> > name=lsp-ts1-lr1 | grep -q interconn-tsp], [1])
> > +
> > +dnl TSP port SHOULD have interconn-tsp option
> > +AT_CHECK([ovn-nbctl --bare --columns=options find Logical_Switch_Port
> > name=tsp-mixed | grep -q interconn-tsp])
> > +
> > +dnl Both should have ISB port bindings
> > +check_row_count ic-sb:Port_Binding 1 logical_port=lsp-ts1-lr1
> > +check_row_count ic-sb:Port_Binding 1 logical_port=tsp-mixed
> > +
> > +dnl Delete the TSP - legacy port should be unaffected
> > +check ovn-ic-nbctl tsp-del tsp-mixed
> > +check ovn-ic-nbctl --wait=sb sync
> > +wait_row_count nb:Logical_Switch_Port 0 name=tsp-mixed
> > +wait_row_count nb:Logical_Switch_Port 1 name=lsp-ts1-lr1
> > +check_row_count ic-sb:Port_Binding 1 logical_port=lsp-ts1-lr1
> > +
> > +dnl Delete the legacy port - should clean up normally
> > +check ovn-nbctl lsp-del lsp-ts1-lr1
> > +OVS_WAIT_WHILE([ovn_as az2 ovn-nbctl show | grep -q lsp-ts1-lr1])
> > +
> >  # ts1 should not be local datapath since lsp-ts1-lr1 has been deleted.
> >  OVN_CLEANUP_SBOX(gw1, [], [], [ts1,lr1])
> >  OVN_CLEANUP_IC([az1], [az2])
> > diff --git a/utilities/ovn-ic-nbctl.c b/utilities/ovn-ic-nbctl.c
> > index 4bf922212..6f5bc0826 100644
> > --- a/utilities/ovn-ic-nbctl.c
> > +++ b/utilities/ovn-ic-nbctl.c
> > @@ -1023,7 +1023,7 @@ ic_nbctl_tsp_set_addr(struct ctl_context *ctx)
> >              && !ovs_scan(ctx->argv[i], "dynamic "IPV6_SCAN_FMT, ipv6_s)
> >              && !ovs_scan(ctx->argv[i], "dynamic "IP_SCAN_FMT,
> >                           IP_SCAN_ARGS(&ip))) {
> > -            ctl_error(ctx, "%s: Invalid address format. See ovn-nb(5). "
> > +            ctl_error(ctx, "%s: Invalid address format. See
> ovn-ic-nb(5). "
> >                        "Hint: An Ethernet address must be "
> >                        "listed before an IP address, together as a
> single "
> >                        "argument.", ctx->argv[i]);
> >
> >
> >
> > > [...]
> >
> >
> > Regards,
> > Ales
>
> Looks good to me.
>
> Thanks Ales!
>
>
Thank you Mairtin,

with that applied to main.

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

Reply via email to