[ovs-dev] [PATCH v2] ovn: Delete stale MAC_Bindings that result in Referential Integrity Violation

Chandra S Vejendla csvejend at us.ibm.com
Thu Aug 25 19:04:13 UTC 2016


The MAC_Bindings have a strong reference to the Datapath_Binding. However the
MAC_Bindings are never deleted anywhere, and when the Datapath (associated
with a MAC_Binding) is deleted, the ovsdb-server returns Referential
Integrity Violation. This prevents newer operations initiated from the CMS
from being committed to the Southbound DB.

The patch fixes this  by deleting the MAC_Binding entry when the
logical_port referred in the mac_binding entry is deleted.

Signed-off-by: Chandra Sekhar Vejendla <csvejend at us.ibm.com>
---
v1->v2:
 Call cleanup_mac_bindings only when ports are deleted

 ovn/northd/ovn-northd.c | 27 +++++++++++++++++++++++++++
 tests/ovn.at            | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+)

diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index 0874a9c..19f3fb1 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -1219,6 +1219,19 @@ ovn_port_update_sbrec(const struct ovn_port *op)
     }
 }
 
+/* Remove mac_binding entries that refer to logical_ports which are
+ * deleted. */
+static void
+cleanup_mac_bindings(struct northd_context *ctx, struct hmap *ports)
+{
+    const struct sbrec_mac_binding *b, *n;
+    SBREC_MAC_BINDING_FOR_EACH_SAFE (b, n, ctx->ovnsb_idl) {
+        if (!ovn_port_find(ports, b->logical_port)) {
+            sbrec_mac_binding_delete(b);
+        }
+    }
+}
+
 /* Updates the southbound Port_Binding table so that it contains the logical
  * switch ports specified by the northbound database.
  *
@@ -1259,12 +1272,20 @@ build_ports(struct northd_context *ctx, struct hmap *datapaths,
         sbrec_port_binding_set_tunnel_key(op->sb, tunnel_key);
     }
 
+    bool remove_mac_bindings = false;
+    if (!ovs_list_is_empty(&sb_only)) {
+        remove_mac_bindings = true;
+    }
+
     /* Delete southbound records without northbound matches. */
     LIST_FOR_EACH_SAFE(op, next, list, &sb_only) {
         ovs_list_remove(&op->list);
         sbrec_port_binding_delete(op->sb);
         ovn_port_destroy(ports, op);
     }
+    if (remove_mac_bindings) {
+        cleanup_mac_bindings(ctx, ports);
+    }
 }
 
 #define OVN_MIN_MULTICAST 32768
@@ -4347,6 +4368,12 @@ main(int argc, char *argv[])
     add_column_noalert(ovnsb_idl_loop.idl, &sbrec_port_binding_col_options);
     add_column_noalert(ovnsb_idl_loop.idl, &sbrec_port_binding_col_mac);
     ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_port_binding_col_chassis);
+    ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_mac_binding);
+    add_column_noalert(ovnsb_idl_loop.idl, &sbrec_mac_binding_col_datapath);
+    add_column_noalert(ovnsb_idl_loop.idl, &sbrec_mac_binding_col_ip);
+    add_column_noalert(ovnsb_idl_loop.idl, &sbrec_mac_binding_col_mac);
+    add_column_noalert(ovnsb_idl_loop.idl,
+                       &sbrec_mac_binding_col_logical_port);
     ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_dhcp_options);
     add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dhcp_options_col_code);
     add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dhcp_options_col_type);
diff --git a/tests/ovn.at b/tests/ovn.at
index 828beb7..2fa5d0b 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -4965,3 +4965,36 @@ cat packets
 OVN_CLEANUP([hv1])
 
 AT_CLEANUP
+
+AT_SETUP([ovn -- delete mac bindings])
+AT_KEYWORDS([ovn])
+ovn_start
+net_add n1
+sim_add hv1
+as hv1
+ovs-vsctl -- add-br br-phys
+ovn_attach n1 br-phys 192.168.0.1
+# Create logical switch ls0
+ovn-nbctl ls-add ls0
+# Create ports lp0, lp1 in ls0
+ovn-nbctl lsp-add ls0 lp0
+ovn-nbctl lsp-add ls0 lp1
+ovn-nbctl lsp-set-addresses lp0 "f0:00:00:00:00:01 192.168.0.1"
+ovn-nbctl lsp-set-addresses lp1 "f0:00:00:00:00:02 192.168.0.2"
+dp_uuid=`ovn-sbctl find datapath | grep uuid | cut -f2 -d ":" | cut -f2 -d " "`
+ovn-sbctl create MAC_Binding ip=10.0.0.1 datapath=$dp_uuid logical_port=lp0 mac="mac1"
+ovn-sbctl create MAC_Binding ip=10.0.0.1 datapath=$dp_uuid logical_port=lp1 mac="mac2"
+ovn-sbctl find MAC_Binding
+#Delete port lp0
+ovn-nbctl lsp-del lp0
+ovn-sbctl find MAC_Binding
+AT_CHECK([ovn-sbctl find MAC_Binding logical_port=lp0], [0], [])
+#Delete ls0. This will verify that the mac_bindings are cleaned up when a
+#datapath is deleted without explicitly removing the the logical ports
+ovn-nbctl ls-del ls0
+ovn-sbctl find MAC_Binding
+AT_CHECK([ovn-sbctl find MAC_Binding], [0], [])
+
+OVN_CLEANUP([hv1])
+
+AT_CLEANUP
-- 
1.9.1




More information about the dev mailing list