When generating SB records that have tunnel_keys (e.g., Datapath,
Port_Binding, Multicast_Group) ovn-northd tries to reuse the
tunnel_key value from the original SB record, if any available.

However, there's no check for tunnel_keys that would conflict with
newly allocated keys for new records. In order to avoid that,
we first check that the tunnel_key value in the SB record doesn't
match a key already allocated by northd in the current run.
If there's a conflict, ovn-north will generate a new key for the SB
record.

Two potential scenarios that might trigger this issue are:
a. ovn-northd is started and pointed to instances of NB and SB databases
   that have inconsistent contents.
b. NB/SB databases are running in clustered mode and bugs in ovsdb-server
   cause the NB/SB instance ovn-northd reconnects to to be in an inconsistent
   state.

Reported-by: Dan Williams <d...@redhat.com>
Reported-at: https://bugzilla.redhat.com/1828637
Signed-off-by: Dumitru Ceara <dce...@redhat.com>
---
 northd/ovn-northd.c |   27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index ed8fba4..df9f1a7 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -1068,7 +1068,13 @@ build_datapaths(struct northd_context *ctx, struct hmap 
*datapaths,
     struct ovn_datapath *od, *next;
     if (!ovs_list_is_empty(&nb_only) || !ovs_list_is_empty(&both)) {
         LIST_FOR_EACH (od, list, &both) {
-            ovn_add_tnlid(&dp_tnlids, od->sb->tunnel_key);
+            if (!ovn_tnlid_in_use(&dp_tnlids, od->sb->tunnel_key)) {
+                ovn_add_tnlid(&dp_tnlids, od->sb->tunnel_key);
+            } else {
+                uint32_t dp_key = ovn_datapath_allocate_key(&dp_tnlids);
+
+                sbrec_datapath_binding_set_tunnel_key(od->sb, dp_key);
+            }
         }
     }
 
@@ -3462,7 +3468,12 @@ build_ports(struct northd_context *ctx,
     /* For logical ports that are in both databases, index the in-use
      * tunnel_keys. */
     LIST_FOR_EACH (op, list, &both) {
-        ovn_add_tnlid(&op->od->port_tnlids, op->sb->tunnel_key);
+        if (!ovn_tnlid_in_use(&op->od->port_tnlids, op->sb->tunnel_key)) {
+            ovn_add_tnlid(&op->od->port_tnlids, op->sb->tunnel_key);
+        } else {
+            sbrec_port_binding_set_tunnel_key(op->sb,
+                                              ovn_port_allocate_key(op->od));
+        }
         if (op->sb->tunnel_key > op->od->port_key_hint) {
             op->od->port_key_hint = op->sb->tunnel_key;
         }
@@ -3722,8 +3733,16 @@ ovn_igmp_group_add(struct northd_context *ctx, struct 
hmap *igmp_groups,
         igmp_group->address = *address;
         if (mcgroup) {
             igmp_group->mcgroup.key = mcgroup->tunnel_key;
-            ovn_add_tnlid(&datapath->mcast_info.group_tnlids,
-                          mcgroup->tunnel_key);
+            if (!ovn_tnlid_in_use(&datapath->mcast_info.group_tnlids,
+                                  mcgroup->tunnel_key)) {
+                ovn_add_tnlid(&datapath->mcast_info.group_tnlids,
+                              mcgroup->tunnel_key);
+            } else {
+                uint32_t group_key =
+                    ovn_mcast_group_allocate_key(&datapath->mcast_info);
+
+                sbrec_multicast_group_set_tunnel_key(mcgroup, group_key);
+            }
         } else {
             igmp_group->mcgroup.key = 0;
         }

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

Reply via email to