The regex for loaded connections is matching on \d as a first symbol,
expecting an IP address.  But that doesn't work for IPv6 addresses
as there are likely hex symbols and not just digits.  This is causing
ovs-monitor-ipsec daemon to periodically remove established IPv6
connections thinking they are not properly loaded:

  851 | INFO | ovn-e629de-0-in-1 is half-loaded, removing
  853 | INFO | ovn-e629de-0-out-1 is half-loaded, removing
  855 | INFO | Adding ipsec connection ovn-e629de-0-in-1
  857 | INFO | Starting ipsec connection ovn-e629de-0-out-1

Fix the regex to include all the hex characters.  This is still not
great that we rely on string parsing for this, but there is currently
no better interface.

Fixes: 25a301822e0d ("ipsec: libreswan: Reconcile missing connections 
periodically.")
Reported-at: https://issues.redhat.com/browse/FDP-1328
Signed-off-by: Ilya Maximets <i.maxim...@ovn.org>
---
 ipsec/ovs-monitor-ipsec.in |   3 +-
 tests/system-ipsec.at      | 137 +++++++++++++++++++++++++++++++++++++
 2 files changed, 139 insertions(+), 1 deletion(-)

diff --git a/ipsec/ovs-monitor-ipsec.in b/ipsec/ovs-monitor-ipsec.in
index f451fb84a..7309bdf3c 100755
--- a/ipsec/ovs-monitor-ipsec.in
+++ b/ipsec/ovs-monitor-ipsec.in
@@ -789,7 +789,8 @@ conn prevent_unencrypted_vxlan
         return self.get_conns_from_status(r"#\d+: .*\"(.*)\".*")
 
     def get_loaded_conns(self):
-        return self.get_conns_from_status(r"\"(.*)\": \d+.*(===|\.\.\.).*")
+        return self.get_conns_from_status(
+            r"\"(.*)\": [0-9a-f]+.*(===|\.\.\.).*")
 
     def get_conn_names(self, monitor, ifname):
         conns = []
diff --git a/tests/system-ipsec.at b/tests/system-ipsec.at
index 298b14feb..de3ecd361 100644
--- a/tests/system-ipsec.at
+++ b/tests/system-ipsec.at
@@ -132,6 +132,15 @@ m4_define([CHECK_LIBRESWAN],
       dnl https://github.com/libreswan/libreswan/issues/428
       AT_SKIP_IF([test "${#ovs_base}" -gt "90" ])])
 
+dnl IPSEC_SA_LIST([namespace], [output-file])
+dnl
+dnl Get numbers of all the currently active SAs.
+m4_define([IPSEC_SA_LIST], [
+    AT_CHECK([ipsec --rundir $ovs_base/$1 status > $2.status])
+    AT_CHECK([grep -oE '#[0-9]+:' $2.status | sort -u], [0], [stdout])
+    AT_CHECK([mv stdout $2])
+])
+
 dnl IPSEC_STATUS_LOADED([])
 dnl
 dnl Get number of loaded connections from ipsec status
@@ -526,6 +535,134 @@ AT_CHECK([grep -q -E "(ike|ikev2|esp)=" 
$ovs_base/right/custom.conf], [1])
 OVS_TRAFFIC_VSWITCHD_STOP()
 AT_CLEANUP
 
+AT_SETUP([IPsec -- Libreswan - established conns survive new additions - ipv4])
+AT_KEYWORDS([ipsec libreswan ipv4 geneve psk persistence])
+dnl Note: Geneve test may not work on older kernels due to CVE-2020-25645
+dnl https://bugzilla.redhat.com/show_bug.cgi?id=1883988
+
+CHECK_LIBRESWAN()
+OVS_TRAFFIC_VSWITCHD_START()
+IPSEC_SETUP_UNDERLAY()
+
+dnl Set up hosts.
+IPSEC_ADD_NODE_LEFT([10.1.1.1], [10.1.1.254])
+IPSEC_ADD_NODE_RIGHT([10.1.1.2], [10.1.1.254])
+
+m4_define([PSK_OPTIONS], [options:remote_ip=$1 options:psk=swordfish])
+
+dnl Set up IPsec tunnel on a 'left' host.
+IPSEC_ADD_TUNNEL_LEFT([geneve], PSK_OPTIONS([10.1.1.2]))
+dnl Set up IPsec tunnel on a 'right' host.
+IPSEC_ADD_TUNNEL_RIGHT([geneve], PSK_OPTIONS([10.1.1.1]))
+
+CHECK_ESP_TRAFFIC
+
+dnl Get the numbers of all the current SAs.
+IPSEC_SA_LIST([left], [left/sa.before])
+IPSEC_SA_LIST([right], [right/sa.before])
+
+dnl Add a third host and wire it up only to the left to avoid creating a loop.
+IPSEC_ADD_NODE([third], [p3], [10.1.1.3], [10.1.1.254])
+IPSEC_ADD_TUNNEL([third], [geneve], PSK_OPTIONS([10.1.1.1]))
+OVS_VSCTL([left], add-port br-ipsec tun3 \
+                   -- set Interface tun3 type=geneve PSK_OPTIONS([10.1.1.3]))
+dnl Wait for all the expected connections to be loaded into Libreswan.
+dnl 2 tunnels == 4 connections.
+OVS_WAIT_UNTIL([test $(IPSEC_STATUS_LOADED(left)) -eq 4])
+
+dnl Wait for tunnels to become active.
+OVS_WAIT_UNTIL([test $(IPSEC_STATUS_LOADED(left)) \
+                 -eq $(IPSEC_STATUS_ACTIVE(left))])
+OVS_WAIT_UNTIL([test $(IPSEC_STATUS_LOADED(third)) \
+                 -eq $(IPSEC_STATUS_ACTIVE(third))])
+
+dnl Check that the original left-right tunnel still works.
+NS_CHECK_EXEC([left], [ping -q -c 3 -i 0.1 -W 2 192.0.0.2 | FORMAT_PING], [0],
+              [3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+NS_CHECK_EXEC([right], [ping -q -c 3 -i 0.1 -W 2 192.0.0.1 | FORMAT_PING], [0],
+              [3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+dnl Check that ovs-monitor-ipsec didn't touch the original tunnel.
+IPSEC_SA_LIST([left], [left/sa.after])
+IPSEC_SA_LIST([right], [right/sa.after])
+
+dnl Right SAs should not change at all.
+AT_CHECK([diff -u right/sa.before right/sa.after])
+
+dnl Left SAs should be the same, but there will be new ones for the third conn.
+AT_CHECK([test $(grep -c ':' left/sa.after) -gt $(grep -c ':' left/sa.before)])
+AT_CHECK([head -n $(grep -c ':' left/sa.before) left/sa.after \
+            | diff -u - left/sa.before])
+
+OVS_TRAFFIC_VSWITCHD_STOP()
+AT_CLEANUP
+
+AT_SETUP([IPsec -- Libreswan - established conns survive new additions - ipv6])
+AT_KEYWORDS([ipsec libreswan ipv6 geneve psk persistence])
+dnl Note: Geneve test may not work on older kernels due to CVE-2020-25645
+dnl https://bugzilla.redhat.com/show_bug.cgi?id=1883988
+
+CHECK_LIBRESWAN()
+OVS_TRAFFIC_VSWITCHD_START()
+IPSEC_SETUP_UNDERLAY()
+
+dnl Set up hosts.
+IPSEC_ADD_NODE_LEFT([fd01::101], [fd01::254])
+IPSEC_ADD_NODE_RIGHT([fd01::102], [fd01::254])
+
+m4_define([PSK_OPTIONS], [options:remote_ip=$1 options:psk=swordfish])
+
+dnl Set up IPsec tunnel on a 'left' host.
+IPSEC_ADD_TUNNEL_LEFT([geneve], PSK_OPTIONS([fd01::102]))
+dnl Set up IPsec tunnel on a 'right' host.
+IPSEC_ADD_TUNNEL_RIGHT([geneve], PSK_OPTIONS([fd01::101]))
+
+CHECK_ESP_TRAFFIC
+
+dnl Get the numbers of all the current SAs.
+IPSEC_SA_LIST([left], [left/sa.before])
+IPSEC_SA_LIST([right], [right/sa.before])
+
+dnl Add a third host and wire it up only to the left to avoid creating a loop.
+IPSEC_ADD_NODE([third], [p3], [fd01::103], [fd01::254])
+IPSEC_ADD_TUNNEL([third], [geneve], PSK_OPTIONS([fd01::101]))
+OVS_VSCTL([left], add-port br-ipsec tun3 \
+                   -- set Interface tun3 type=geneve PSK_OPTIONS([fd01::103]))
+dnl Wait for all the expected connections to be loaded into Libreswan.
+dnl 2 tunnels == 4 connections.
+OVS_WAIT_UNTIL([test `IPSEC_STATUS_LOADED(left)` -eq 4])
+
+dnl Wait for tunnels to become active.
+OVS_WAIT_UNTIL([test $(IPSEC_STATUS_LOADED(left)) \
+                 -eq $(IPSEC_STATUS_ACTIVE(left))])
+OVS_WAIT_UNTIL([test $(IPSEC_STATUS_LOADED(third)) \
+                 -eq $(IPSEC_STATUS_ACTIVE(third))])
+
+dnl Check that the original left-right tunnel still works.
+NS_CHECK_EXEC([left], [ping -q -c 3 -i 0.1 -W 2 192.0.0.2 | FORMAT_PING], [0],
+              [3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+NS_CHECK_EXEC([right], [ping -q -c 3 -i 0.1 -W 2 192.0.0.1 | FORMAT_PING], [0],
+              [3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+dnl Check that ovs-monitor-ipsec didn't touch the original tunnel.
+IPSEC_SA_LIST([left], [left/sa.after])
+IPSEC_SA_LIST([right], [right/sa.after])
+
+dnl Right SAs should not change at all.
+AT_CHECK([diff -u right/sa.before right/sa.after])
+
+dnl Left SAs should be the same, but there will be new ones for the third conn.
+AT_CHECK([test $(grep -c ':' left/sa.after) -gt $(grep -c ':' left/sa.before)])
+AT_CHECK([head -n $(grep -c ':' left/sa.before) left/sa.after \
+            | diff -u - left/sa.before])
+
+OVS_TRAFFIC_VSWITCHD_STOP()
+AT_CLEANUP
+
 AT_SETUP([IPsec -- Libreswan NxN geneve tunnels + reconciliation])
 AT_KEYWORDS([ipsec libreswan scale reconciliation])
 dnl Note: Geneve test may not work on older kernels due to CVE-2020-25645
-- 
2.49.0

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

Reply via email to