Signed-off-by: Gavin McKee <gavmcke...@googlemail.com>
---
 controller/ovn-controller.8.xml |  5 +++
 controller/ovn-controller.c     |  1 -
 controller/patch.c              | 44 +++++++++++++++++---
 tests/ovn-controller.at         | 72 +++++++++++++++++++++++++++++++++
 4 files changed, 115 insertions(+), 7 deletions(-)

diff --git a/controller/ovn-controller.8.xml b/controller/ovn-controller.8.xml
index 5007f5f80..422eb2cf7 100644
--- a/controller/ovn-controller.8.xml
+++ b/controller/ovn-controller.8.xml
@@ -554,6 +554,11 @@
           bridge, with the same <code>external_ids:ovn-localnet-port</code>
           value.
         </p>
+        <p>
+          When a <code>localnet</code> port has additional values in its
+          <code>external_ids</code> column, these key-value pairs are copied to
+          the corresponding patch ports.
+        </p>
       </dd>
 
       <dt>
diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index 7940091da..8c8d47fe3 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -5857,7 +5857,6 @@ main(int argc, char *argv[])
 
     ovsdb_idl_omit(ovnsb_idl_loop.idl, &sbrec_sb_global_col_external_ids);
     ovsdb_idl_omit(ovnsb_idl_loop.idl, &sbrec_logical_flow_col_external_ids);
-    ovsdb_idl_omit(ovnsb_idl_loop.idl, &sbrec_port_binding_col_external_ids);
     ovsdb_idl_omit(ovnsb_idl_loop.idl, &sbrec_ssl_col_external_ids);
     ovsdb_idl_omit(ovnsb_idl_loop.idl,
                    &sbrec_gateway_chassis_col_external_ids);
diff --git a/controller/patch.c b/controller/patch.c
index 4fed6e375..5ba1466e0 100644
--- a/controller/patch.c
+++ b/controller/patch.c
@@ -73,18 +73,38 @@ match_patch_port(const struct ovsrec_port *port, const char 
*peer)
  * 'dst_name' in bridge 'dst'.  Initializes the patch port's external-ids:'key'
  * to 'key'.
  *
- * If such a patch port already exists, removes it from 'existing_ports'. */
+ * If such a patch port already exists, removes it from 'existing_ports'.  Any
+ * key-value pairs in 'extra_ids' are merged into the port's external IDs.  If
+ * the port already exists, its external IDs are updated accordingly.
+ */
 static void
 create_patch_port(struct ovsdb_idl_txn *ovs_idl_txn,
                   const char *key, const char *value,
                   const struct ovsrec_bridge *src, const char *src_name,
                   const struct ovsrec_bridge *dst, const char *dst_name,
-                  struct shash *existing_ports)
+                  struct shash *existing_ports,
+                  const struct smap *extra_ids)
 {
     for (size_t i = 0; i < src->n_ports; i++) {
         if (match_patch_port(src->ports[i], dst_name)) {
             /* Patch port already exists on 'src'. */
-            shash_find_and_delete(existing_ports, src->ports[i]->name);
+            const struct ovsrec_port *port = src->ports[i];
+            shash_find_and_delete(existing_ports, port->name);
+            if (extra_ids) {
+                const struct smap *ids = &port->external_ids;
+                struct smap merged = SMAP_INITIALIZER(&merged);
+                smap_clone(&merged, ids);
+                struct smap_node *node;
+                SMAP_FOR_EACH (node, extra_ids) {
+                    const char *cur = smap_get(&merged, node->key);
+                    if (!cur || strcmp(cur, node->value)) {
+                        ovsrec_port_update_external_ids_setkey(port,
+                                                              node->key,
+                                                              node->value);
+                    }
+                }
+                smap_destroy(&merged);
+            }
             return;
         }
     }
@@ -94,9 +114,16 @@ create_patch_port(struct ovsdb_idl_txn *ovs_idl_txn,
             src_name, src->name, dst->name);
 
     const struct smap if_options = SMAP_CONST1(&if_options, "peer", dst_name);
-    const struct smap port_ids = SMAP_CONST1(&port_ids, key, value);
+
+    struct smap port_ids = SMAP_INITIALIZER(&port_ids);
+    if (extra_ids) {
+        smap_clone(&port_ids, extra_ids);
+    }
+    smap_replace(&port_ids, key, value);
+
     ovsport_create(ovs_idl_txn, src, src_name, "patch", &port_ids, NULL,
                    &if_options, 0);
+    smap_destroy(&port_ids);
 }
 
 static void
@@ -223,12 +250,17 @@ add_bridge_mappings_by_type(struct ovsdb_idl_txn 
*ovs_idl_txn,
         sset_find_and_delete(&missed_bridges, msg_key);
         free(msg_key);
 
+        const struct smap *extra_ids =
+            !strcmp(pb_type, "localnet") ? &binding->external_ids : NULL;
+
         char *name1 = patch_port_name(br_int->name, binding->logical_port);
         char *name2 = patch_port_name(binding->logical_port, br_int->name);
         create_patch_port(ovs_idl_txn, patch_port_id, binding->logical_port,
-                          br_int, name1, br_ln, name2, existing_ports);
+                          br_int, name1, br_ln, name2, existing_ports,
+                          extra_ids);
         create_patch_port(ovs_idl_txn, patch_port_id, binding->logical_port,
-                          br_ln, name2, br_int, name1, existing_ports);
+                          br_ln, name2, br_int, name1, existing_ports,
+                          extra_ids);
         free(name1);
         free(name2);
     }
diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at
index ae7eb6f31..6ae97e87d 100644
--- a/tests/ovn-controller.at
+++ b/tests/ovn-controller.at
@@ -139,6 +139,7 @@ check_patches \
     'br-int  patch-br-int-to-localnet2 patch-localnet2-to-br-int' \
     'br-eth0 patch-localnet2-to-br-int patch-br-int-to-localnet2'
 
+
 # Add logical patch ports to connect new logical datapath.
 #
 # OVN no longer uses OVS patch ports to implement logical patch ports, so
@@ -174,6 +175,77 @@ OVS_APP_EXIT_AND_WAIT([ovsdb-server])
 AT_CLEANUP
 ])
 
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([Localnet port external ids])
+AT_KEYWORDS([lb])
+ovn_start
+
+check ovn-nbctl ls-add sw0
+check ovn-nbctl lsp-add sw0 sw0-port1
+check ovn-nbctl lsp-set-addresses sw0-port1 "50:54:00:00:00:01 10.0.0.3 
1000::3"
+check ovn-nbctl lsp-add sw0 sw0-port2
+check ovn-nbctl lsp-set-addresses sw0-port2 "50:54:00:00:00:02 10.0.0.4 
1000::4"
+
+check ovn-nbctl lr-add lr0
+check ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24 1000::1/64
+check ovn-nbctl lsp-add sw0 sw0-lr0
+check ovn-nbctl lsp-set-type sw0-lr0 router
+check ovn-nbctl lsp-set-addresses sw0-lr0 router
+check ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0
+
+check ovn-nbctl ls-add public
+check ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 172.168.0.100/24 
2000::1/64
+check ovn-nbctl lsp-add public public-lr0
+check ovn-nbctl lsp-set-type public-lr0 router
+check ovn-nbctl lsp-set-addresses public-lr0 router
+check ovn-nbctl lsp-set-options public-lr0 router-port=lr0-public
+
+# localnet port
+check ovn-nbctl lsp-add public ln-public
+check ovn-nbctl lsp-set-type ln-public localnet
+check ovn-nbctl lsp-set-addresses ln-public unknown
+check ovn-nbctl lsp-set-options ln-public network_name=phys
+
+check ovn-nbctl lrp-set-gateway-chassis lr0-public hv1 20
+
+net_add n1
+
+sim_add hv1
+as hv1
+ovs-vsctl add-br br-phys
+ovn_attach n1 br-phys 192.168.0.1
+ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
+ovs-vsctl -- add-port br-int hv1-vif1 -- \
+    set interface hv1-vif1 external-ids:iface-id=sw0-port1 \
+    options:tx_pcap=hv1/vif1-tx.pcap \
+    options:rxq_pcap=hv1/vif1-rx.pcap \
+    ofport-request=1
+
+check ovn-nbctl --wait=hv set logical_switch_port ln-public 
external_ids:foo=bar
+wait_column "foo=bar" Port_Binding external_ids logical_port=ln-public
+
+AT_CHECK([as hv1 ovs-vsctl get port patch-br-int-to-ln-public 
external_ids:foo], [0], [dnl
+bar
+])
+
+AT_CHECK([as hv1 ovs-vsctl get port patch-ln-public-to-br-int 
external_ids:foo], [0], [dnl
+bar
+])
+
+check ovn-nbctl --wait=hv set logical_switch_port ln-public 
external_ids:foo=foobar
+wait_column "foo=foobar" Port_Binding external_ids logical_port=ln-public
+
+AT_CHECK([as hv1 ovs-vsctl get port patch-br-int-to-ln-public 
external_ids:foo], [0], [dnl
+foobar
+])
+
+AT_CHECK([as hv1 ovs-vsctl get port patch-ln-public-to-br-int 
external_ids:foo], [0], [dnl
+foobar
+])
+
+AT_CLEANUP
+])
+
 # Checks that ovn-controller populates datapath-type and iface-types
 # correctly in the Chassis other_config column.
 OVN_FOR_EACH_NORTHD([
-- 
2.34.1

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to