When ovn-controller reconnects to the ovs-vswitchd, it deletes all the
OF flows in the switch. It doesn't install the flows again, leaving
the datapath broken unless ovn-controller is restarted or ovn-northd
updates the SB DB.

The reason for this is
  - lflow_reset_processing() is not called after the reconnection
  - the hmap "installed_flows" is not cleared, because of which
    ofctrl_put skips adding the flows to the switch.

This patch fixes the issue and also adds a test case to test
this scenario.

Signed-off-by: Numan Siddique <nusid...@redhat.com>
---
 ovn/controller/ofctrl.c |  7 ++++
 tests/ovn.at            | 95 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 102 insertions(+)

v1 -> v2
--------
 * Enhanced the test case to restart vswitchd and restore the flows


diff --git a/ovn/controller/ofctrl.c b/ovn/controller/ofctrl.c
index 9388cb8..26f85db 100644
--- a/ovn/controller/ofctrl.c
+++ b/ovn/controller/ofctrl.c
@@ -20,6 +20,7 @@
 #include "flow.h"
 #include "hash.h"
 #include "hindex.h"
+#include "lflow.h"
 #include "ofctrl.h"
 #include "openflow/openflow.h"
 #include "openvswitch/dynamic-string.h"
@@ -368,6 +369,7 @@ run_S_CLEAR_FLOWS(void)
 
     /* Clear installed_flows, to match the state of the switch. */
     ovn_flow_table_clear();
+    lflow_reset_processing();
 
     /* Clear existing groups, to match the state of the switch. */
     if (groups) {
@@ -812,6 +814,11 @@ ovn_flow_table_clear(void)
         hindex_remove(&uuid_flow_table, &f->uuid_hindex_node);
         ovn_flow_destroy(f);
     }
+
+    HMAP_FOR_EACH_SAFE (f, next, match_hmap_node, &installed_flows) {
+        hmap_remove(&installed_flows, &f->match_hmap_node);
+        ovn_flow_destroy(f);
+    }
 }
 
 static void
diff --git a/tests/ovn.at b/tests/ovn.at
index a95e0b2..7e3e25d 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -4072,3 +4072,98 @@ AT_CHECK([cat received2.packets], [0], [expout])
 OVN_CLEANUP([hv1])
 
 AT_CLEANUP
+
+AT_SETUP([ovn -- ovs-vswitchd restart])
+AT_KEYWORDS([vswitchd restart])
+AT_SKIP_IF([test $HAVE_PYTHON = no])
+ovn_start
+
+ovn-nbctl ls-add ls1
+
+ovn-nbctl lsp-add ls1 ls1-lp1 \
+-- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
+
+ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
+
+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 -- add-port br-int hv1-vif1 -- \
+    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
+    options:tx_pcap=hv1/vif1-tx.pcap \
+    options:rxq_pcap=hv1/vif1-rx.pcap \
+    ofport-request=1
+
+ovn_populate_arp
+sleep 2
+
+as hv1 ovs-vsctl show
+
+echo "---------------------"
+ovn-sbctl dump-flows
+echo "---------------------"
+
+echo "------ hv1 dump ----------"
+as hv1 ovs-ofctl dump-flows br-int
+total_flows=`as hv1 ovs-ofctl dump-flows br-int | wc -l`
+
+echo "Total flows before vswitchd restart = " $total_flows
+
+# Code taken from ovs-save utility
+save_flows () {
+    echo "ovs-ofctl add-flows br-int - << EOF" > restore_flows.sh
+    as hv1 ovs-ofctl dump-flows "br-int" | sed -e '/NXST_FLOW/d' \
+            -e 's/\(idle\|hard\)_age=[^,]*,//g' >> restore_flows.sh
+    echo "EOF" >> restore_flows.sh
+}
+
+restart_vswitchd () {
+    restore_flows=$1
+
+    if test $restore_flows = true; then
+        save_flows
+    fi
+
+    as hv1
+    OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
+
+    if test $restore_flows = true; then
+        as hv1
+        ovs-vsctl --no-wait set open_vswitch . 
other_config:flow-restore-wait="true"
+    fi
+
+    as hv1
+    start_daemon ovs-vswitchd --enable-dummy=system -vvconn -vofproto_dpif 
-vunixctl
+    ovs-ofctl dump-flows br-int
+
+    if test $restore_flows = true; then
+        sh ./restore_flows.sh
+        echo "Flows after restore"
+        as hv1
+        ovs-ofctl dump-flows br-int
+        ovs-vsctl --no-wait --if-exists remove open_vswitch . other_config \
+            flow-restore-wait="true"
+    fi
+}
+
+# Save the flows, restart vswitchd and restore the flows
+restart_vswitchd true
+sleep 2
+total_flows_after_restart=`as hv1 ovs-ofctl dump-flows br-int | wc -l`
+echo "Total flows after vswitchd restart = " $total_flows_after_restart
+
+AT_CHECK([test "${total_flows}" = "${total_flows_after_restart}"])
+
+# Restart vswitchd without restoring
+restart_vswitchd false
+sleep 2
+total_flows_after_restart=`as hv1 ovs-ofctl dump-flows br-int | wc -l`
+echo "Total flows after vswitchd restart = " $total_flows_after_restart
+
+AT_CHECK([test "${total_flows}" = "${total_flows_after_restart}"])
+
+OVN_CLEANUP([hv1])
+AT_CLEANUP
-- 
2.7.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to