Same as for tunnel ports, controllers should not touch OVN patch ports that don't belong to their active integration bridge (except when those are peers to corresponding patch ports).
Signed-off-by: Ihar Hrachyshka <[email protected]> --- controller/ovn-controller.c | 5 +++- controller/patch.c | 36 +++++++++++++++++++++++-- controller/patch.h | 2 +- tests/ovn.at | 52 +++++++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 4 deletions(-) diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index 16d9e1030..351cf1c5b 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -3999,6 +3999,9 @@ main(int argc, char *argv[]) struct ovsdb_idl_index *ovsrec_port_by_interfaces = ovsdb_idl_index_create1(ovs_idl_loop.idl, &ovsrec_port_col_interfaces); + struct ovsdb_idl_index *ovsrec_port_by_name + = ovsdb_idl_index_create1(ovs_idl_loop.idl, + &ovsrec_port_col_name); ovsdb_idl_get_initial_snapshot(ovs_idl_loop.idl); @@ -4647,7 +4650,7 @@ main(int argc, char *argv[]) sbrec_port_binding_by_type, ovsrec_bridge_table_get(ovs_idl_loop.idl), ovsrec_open_vswitch_table_get(ovs_idl_loop.idl), - ovsrec_port_table_get(ovs_idl_loop.idl), + ovsrec_port_by_name, br_int, chassis, &runtime_data->local_datapaths); stopwatch_stop(PATCH_RUN_STOPWATCH_NAME, time_msec()); if (vif_plug_provider_has_providers() && ovs_idl_txn) { diff --git a/controller/patch.c b/controller/patch.c index af4e8911f..c1cd5060d 100644 --- a/controller/patch.c +++ b/controller/patch.c @@ -271,12 +271,26 @@ add_bridge_mappings(struct ovsdb_idl_txn *ovs_idl_txn, shash_destroy(&bridge_mappings); } +static const struct ovsrec_port * +get_port(struct ovsdb_idl_index *ovsrec_port_by_name, const char *name) +{ + struct ovsrec_port *target = + ovsrec_port_index_init_row(ovsrec_port_by_name); + ovsrec_port_index_set_name(target, name); + + const struct ovsrec_port *port = NULL; + OVSREC_PORT_FOR_EACH_EQUAL (port, target, ovsrec_port_by_name) { + } + ovsrec_port_index_destroy_row(target); + return port; +} + void patch_run(struct ovsdb_idl_txn *ovs_idl_txn, struct ovsdb_idl_index *sbrec_port_binding_by_type, const struct ovsrec_bridge_table *bridge_table, const struct ovsrec_open_vswitch_table *ovs_table, - const struct ovsrec_port_table *port_table, + struct ovsdb_idl_index *ovsrec_port_by_name, const struct ovsrec_bridge *br_int, const struct sbrec_chassis *chassis, const struct hmap *local_datapaths) @@ -293,7 +307,8 @@ patch_run(struct ovsdb_idl_txn *ovs_idl_txn, * leaving useless ports on upgrade. */ struct shash existing_ports = SHASH_INITIALIZER(&existing_ports); const struct ovsrec_port *port; - OVSREC_PORT_TABLE_FOR_EACH (port, port_table) { + for (size_t i = 0; i < br_int->n_ports; i++) { + port = br_int->ports[i]; if (smap_get(&port->external_ids, "ovn-localnet-port") || smap_get(&port->external_ids, "ovn-l2gateway-port") || smap_get(&port->external_ids, "ovn-l3gateway-port") @@ -321,6 +336,23 @@ patch_run(struct ovsdb_idl_txn *ovs_idl_txn, * ovn-controller. Otherwise it may cause unncessary dataplane * interruption during restart/upgrade. */ if (!daemon_started_recently()) { + /* delete peer patch port first */ + for (size_t i = 0; i < port->n_interfaces; i++) { + struct ovsrec_interface *iface = port->interfaces[i]; + if (strcmp(iface->type, "patch")) { + continue; + } + const char *iface_peer = smap_get(&iface->options, "peer"); + if (iface_peer) { + const struct ovsrec_port *peer_port = + get_port(ovsrec_port_by_name, iface_peer); + if (peer_port) { + remove_port(bridge_table, peer_port); + } + } + } + + /* now delete integration bridge patch port */ remove_port(bridge_table, port); } } diff --git a/controller/patch.h b/controller/patch.h index 208b8d3ee..db4a888e6 100644 --- a/controller/patch.h +++ b/controller/patch.h @@ -40,7 +40,7 @@ void patch_run(struct ovsdb_idl_txn *ovs_idl_txn, struct ovsdb_idl_index *sbrec_port_binding_by_type, const struct ovsrec_bridge_table *, const struct ovsrec_open_vswitch_table *, - const struct ovsrec_port_table *, + struct ovsdb_idl_index *ovsrec_port_by_name, const struct ovsrec_bridge *br_int, const struct sbrec_chassis *, const struct hmap *local_datapaths); diff --git a/tests/ovn.at b/tests/ovn.at index 6b55fb33e..0c7cb7ab3 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -34479,3 +34479,55 @@ OVS_WAIT_UNTIL([ OVN_CLEANUP([hv1]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([ovn-controller deletes OVN patch ports for its integration bridge only]) +ovn_start +net_add n1 + +sim_add hv1 +as hv1 + +# prepare OVN patch ports on both "integration" bridges +ovs-vsctl add-br br-phys +ovs-vsctl add-br br-int +ovs-vsctl -- add-port br-int fake-int-to-phys -- \ + set port fake-int-to-phys external-ids:ovn-localnet-port=fake-port -- \ + set interface fake-int-to-phys options:peer=fake-phys-to-int type=patch +ovs-vsctl -- add-port br-phys fake-phys-to-int -- \ + set port fake-phys-to-int external-ids:ovn-localnet-port=fake-port -- \ + set interface fake-phys-to-int options:peer=fake-int-to-phys type=patch + +ovs-vsctl add-br br-phys-2 +ovs-vsctl add-br br-int-2 +ovs-vsctl -- add-port br-int-2 fake-int-2-to-phys-2 -- \ + set port fake-int-2-to-phys-2 external-ids:ovn-localnet-port=fake-port-2 -- \ + set interface fake-int-2-to-phys-2 options:peer=fake-phys-2-to-int-2 type=patch +ovs-vsctl -- add-port br-phys-2 fake-phys-2-to-int-2 -- \ + set port fake-phys-2-to-int-2 external-ids:ovn-localnet-port=fake-port-2 -- \ + set interface fake-phys-2-to-int-2 options:peer=fake-int-2-to-phys-2 type=patch + +ovn_attach n1 br-phys 192.168.1.1 24 + +# allow controller to immediately clean patch ports up +check ovn-appctl -t ovn-controller debug/ignore-startup-delay + +# check that patch port on br-int is cleaned up (and also its peer) +OVS_WAIT_UNTIL([ + test 0 = $(ovs-vsctl --columns _uuid --bare find Port name=fake-int-to-phys | wc -l) +]) +OVS_WAIT_UNTIL([ + test 0 = $(ovs-vsctl --columns _uuid --bare find Port name=fake-phys-to-int | wc -l) +]) + +# check that patch port on a different bridge is not touched +OVS_WAIT_UNTIL([ + test 1 = $(ovs-vsctl --columns _uuid --bare find Port name=fake-int-2-to-phys-2 | wc -l) +]) +OVS_WAIT_UNTIL([ + test 1 = $(ovs-vsctl --columns _uuid --bare find Port name=fake-phys-2-to-int-2 | wc -l) +]) + +OVN_CLEANUP([hv1]) +AT_CLEANUP +]) -- 2.38.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
