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

Reply via email to