Macro NS_CHECK_CONNECTIVITY is introduced to provide a more comprehensive
way to check connectivity between network namespaces. It takes source
namespace, destination namespace and destination IP as arguments, and
it verifies that source NS can reach destination NS on the provided IP.
Executed checks include:
  * simple ping
  * Exchange of multiple requests and replies over TCP
  * Exchange of multiple requests and replies over UDP

First usage of this macro is in
'DNAT and SNAT on distributed router - N/S' tests that were currently not
equipped to detect NAT failures after the initial connection was established.

Related macro NS_CHECK_CONNECTIVITY_V6 is provided with same
functionality, but expecitng IPv6 destination IP address.

Signed-off-by: Martin Kalcok <[email protected]>
---
 tests/system-common-macros.at |  71 ++++++++++++++++++
 tests/system-ovn.at           | 136 +++++++++-------------------------
 2 files changed, 105 insertions(+), 102 deletions(-)

diff --git a/tests/system-common-macros.at b/tests/system-common-macros.at
index 251a4c0b8..1f2b2b4eb 100644
--- a/tests/system-common-macros.at
+++ b/tests/system-common-macros.at
@@ -614,3 +614,74 @@ m4_define([OVN_NEIGH_EQUAL],
 m4_define([OVN_NEIGH_V6_EQUAL],
   [OVS_WAIT_UNTIL_EQUAL([ip -6 neigh show dev $1 $2 | sed -e 
's|[[[[:space:]]]]*$||g' | grep $3 | sort], [$4])
 ])
+
+# NS_CHECK_CONNECTIVITY__([NS_SRC], [NS_DST], [IP_ADDR], [SET_IF_V6])
+#
+# Ensures that network namespace NS_SRC can reach NS_DST on IP_ADDR. The check 
performs:
+#   * Ping
+#   * Exchange of multiple messages over TCP
+#   * Exchange of multiple messages over UDP
+#
+# If SET_IF_V6 argument is provided with any value, the IP_ADDR is treated as 
IPv6 address.
+m4_define([NS_CHECK_CONNECTIVITY__],
+[
+    ns_src="$1"
+    ns_dst="$2"
+    ip="$3"
+    is_v6="$4"
+
+    proto="-4"
+    if test -n "$is_v6"; then
+        proto="-6"
+    fi
+    # Start a simple TCP and UDP echo server that replies with "ack 
<received_msg>".
+    NETNS_DAEMONIZE($ns_dst, [nc $proto -l -p 1235 -d 0.1 -c '/bin/cat'], 
[nc-$ns_dst-$ip-tcp.pid])
+    NETNS_DAEMONIZE($ns_dst, [nc $proto -l -u -p 1234 -d 0.1 -c '/bin/cat'], 
[nc-$ns_dst-$ip-udp.pid])
+
+    # Ensure that the destination NS can be pinged on the specified IP
+    NS_CHECK_EXEC([$ns_src], [ping $proto -q -c 3 -i 0.3 -w 2 $ip | 
FORMAT_PING], \
+    [0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+    # Exchange multiple messages over TCP and UDP to verify connectivity
+    # Note(mkalcok): Server replies are printed to file, because STDOUT is 
captured by the nc.
+    :> ./tcp_data
+    :> ./udp_data
+
+    NETNS_DAEMONIZE($ns_src, [nc $proto $ip 1235 -d 0.1 -c 'for i in $(seq 1 
3); do echo "tcp_data $i"; read msg; echo "$msg" >>./tcp_data; done'], 
[nc_$ns_src-$ip-tcp.pid])
+    NETNS_DAEMONIZE($ns_src, [nc $proto -u $ip 1234 -d 0.1 -c 'for i in $(seq 
1 3); do echo "udp_data $i"; read msg; echo "$msg" >>./udp_data; done'], 
[nc_$ns_src-$ip-udp.pid])
+
+    OVS_WAIT_FOR_OUTPUT([cat ./tcp_data],  [0], [dnl
+tcp_data 1
+tcp_data 2
+tcp_data 3
+])
+    OVS_WAIT_FOR_OUTPUT([cat ./udp_data], [0], [dnl
+udp_data 1
+udp_data 2
+udp_data 3
+])
+
+    # cleanup echo processes
+    kill $(cat nc-$ns_dst-$ip-tcp.pid)
+    kill $(cat nc-$ns_dst-$ip-udp.pid)
+    kill $(cat nc_$ns_src-$ip-tcp.pid)
+    kill $(cat nc_$ns_src-$ip-udp.pid)
+])
+
+# NS_CHECK_CONNECTIVITY([NS_SRC], [NS_DST], [IPV4_ADDR])
+#
+# IPv4 version of NS_CHECK_CONNECTIVITY__.
+m4_define([NS_CHECK_CONNECTIVITY],
+[
+    NS_CHECK_CONNECTIVITY__([$1], [$2], [$3])
+])
+
+# NS_CHECK_CONNECTIVITY_V6([NS_SRC], [NS_DST], [IPV6_ADDR])
+#
+# IPv6 version of NS_CHECK_CONNECTIVITY__.
+m4_define([NS_CHECK_CONNECTIVITY_V6],
+[
+    NS_CHECK_CONNECTIVITY__([$1], [$2], [$3], [yes])
+])
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
index 8e356df6f..f84290594 100644
--- a/tests/system-ovn.at
+++ b/tests/system-ovn.at
@@ -3777,46 +3777,49 @@ AT_CHECK([ovn-nbctl lr-route-add R1 10.0.0.0/24 
172.16.1.2])
 check ovn-nbctl --wait=hv sync
 OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep 'nat(src=172.16.1.1)'])
 
-# North-South DNAT: 'alice1' pings 'foo1' using 172.16.1.3.
-NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.3 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
+# North-South DNAT: 'alice1' reaches 'foo1' on 172.16.1.3.
+NS_CHECK_CONNECTIVITY([alice1], [foo1], [172.16.1.3])
 
 # We verify that DNAT indeed happened via 'dump-conntrack' command.
 AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.3) | \
 sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
 
icmp,orig=(src=172.16.1.2,dst=172.16.1.3,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.2,id=<cleared>,type=0,code=0),zone=<cleared>
+tcp,orig=(src=172.16.1.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
+udp,orig=(src=172.16.1.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>
 ])
 
-# South-North SNAT: 'foo2' pings 'alice1'. But 'alice1' receives traffic
+# South-North SNAT: 'foo2' reaches 'alice1'. But 'alice1' receives traffic
 # from 172.16.1.4
-NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
+NS_CHECK_CONNECTIVITY([foo2], [alice1], 172.16.1.2)
 
 # We verify that SNAT indeed happened via 'dump-conntrack' command.
 AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.4) | \
 sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
 
icmp,orig=(src=192.168.1.3,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.4,id=<cleared>,type=0,code=0),zone=<cleared>
+tcp,orig=(src=192.168.1.3,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=172.16.1.4,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
+udp,orig=(src=192.168.1.3,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=172.16.1.4,sport=<cleared>,dport=<cleared>),zone=<cleared>
 ])
 
 AT_CHECK([ovs-appctl dpctl/flush-conntrack])
 
-# South-North SNAT: 'bar1' pings 'alice1'. But 'alice1' receives traffic
+# South-North SNAT: 'bar1' reaches 'alice1'. But 'alice1' receives traffic
 # from 172.16.1.1
-NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
+NS_CHECK_CONNECTIVITY([bar1], [alice1], 172.16.1.2)
 
 # We verify that SNAT indeed happened via 'dump-conntrack' command.
 AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) | \
 sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
 
icmp,orig=(src=192.168.2.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
+tcp,orig=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=172.16.1.1,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
+udp,orig=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=172.16.1.1,sport=<cleared>,dport=<cleared>),zone=<cleared>
 ])
 
+# North-South Direct (Bypassing DNAT): 'alice1' reaches 'foo1' using 
192.168.1.2
+NS_CHECK_CONNECTIVITY([alice1], [foo1], [192.168.1.2])
+
+# North-South Direct (Bypassing SNAT): 'alice1' reaches 'bar1' using 
192.168.2.2
+NS_CHECK_CONNECTIVITY([alice1], [bar1], [192.168.2.2])
+
 # Try to ping external network
 NETNS_START_TCPDUMP([ext-net], [-n -c 3 -i ext-veth dst 172.16.1.3 and icmp], 
[ext-net])
 AT_CHECK([ovn-nbctl lr-nat-del R1 snat])
@@ -3825,43 +3828,6 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 10.0.0.1 
| FORMAT_PING], \
 3 packets transmitted, 3 received, 0% packet loss, time 0ms
 ])
 
-# test_connectivity_from_ext takes parameters 'vm' and 'ip'. It tests
-# icmp, udp and tcp connectivity from external network to the 'vm' on
-# the specified 'ip'.
-test_connectivity_from_ext() {
-    local vm=$1; shift
-    local ip=$1; shift
-
-    # Start listening daemon TCP connections.
-    NETNS_DAEMONIZE($vm, [nc -l -k 1235], [nc-$vm-$ip-tcp.pid])
-
-    # Ensure that vm can be pinged on the specified IP
-    NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 $ip | FORMAT_PING], \
-    [0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
-
-    # Perform two consecutive UDP connections to the specified IP
-    NETNS_DAEMONIZE($vm, [nc -l -u 1234], [nc-$vm-$ip-udp.pid])
-    NS_CHECK_EXEC([alice1], [nc -u $ip 1234 -p 2000 -z])
-    kill $(cat nc-$vm-$ip-udp.pid)
-
-    NETNS_DAEMONIZE($vm, [nc -l -u 1234], [nc-$vm-$ip-udp.pid])
-    NS_CHECK_EXEC([alice1], [nc -u $ip 1234 -p 2000 -z])
-    kill $(cat nc-$vm-$ip-udp.pid)
-
-    # Send data over TCP connection to the specified IP
-    NS_CHECK_EXEC([alice1], [echo "TCP test" | nc --send-only $ip 1235])
-}
-
-# Test access from external network to the internal IP of a VM that
-# has also configured DNAT
-test_connectivity_from_ext foo1 192.168.1.2
-
-# Test access from external network to the internal IP of a VM that
-# does not have DNAT
-test_connectivity_from_ext bar1 192.168.2.2
-
 OVS_WAIT_UNTIL([
     total_pkts=$(cat ext-net.tcpdump | wc -l)
     test "${total_pkts}" = "3"
@@ -3980,26 +3946,22 @@ AT_CHECK([ovn-nbctl lr-nat-add R1 snat fd20::1 ::/0])
 check ovn-nbctl --wait=hv sync
 OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep 'nat(src=fd20::1)'])
 
-# North-South DNAT: 'alice1' pings 'foo1' using fd20::3
-NS_CHECK_EXEC([alice1], [ping6 -q -c 3 -i 0.3 -w 2 fd20::3 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
+# North-South DNAT: 'alice1' reaches 'foo1' using fd20::3
+NS_CHECK_CONNECTIVITY_V6([alice1], [foo1], [fd20::3])
 
 # We verify that DNAT indeed happened via 'dump-conntrack' command.
 AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::3) | \
 sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
 
icmpv6,orig=(src=fd20::2,dst=fd20::3,id=<cleared>,type=128,code=0),reply=(src=fd11::2,dst=fd20::2,id=<cleared>,type=129,code=0),zone=<cleared>
+tcp,orig=(src=fd20::2,dst=fd20::3,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd20::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
+udp,orig=(src=fd20::2,dst=fd20::3,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd20::2,sport=<cleared>,dport=<cleared>),zone=<cleared>
 ])
 
 AT_CHECK([ovs-appctl dpctl/flush-conntrack])
 
-# South-North SNAT: 'foo2' pings 'alice1'. But 'alice1' receives traffic
+# South-North SNAT: 'foo2' reaches 'alice1'. But 'alice1' receives traffic
 # from fd20::4
-NS_CHECK_EXEC([foo2], [ping6 -q -c 3 -i 0.3 -w 2 fd20::2 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
+NS_CHECK_CONNECTIVITY_V6([foo2], [alice1], fd20::2)
 
 ovs-appctl dpctl/dump-conntrack | grep icmpv6
 AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd11::3) | \
@@ -4010,59 +3972,29 @@ sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
 AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::4) | \
 sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
 
icmpv6,orig=(src=fd11::3,dst=fd20::2,id=<cleared>,type=128,code=0),reply=(src=fd20::2,dst=fd20::4,id=<cleared>,type=129,code=0),zone=<cleared>
+tcp,orig=(src=fd11::3,dst=fd20::2,sport=<cleared>,dport=<cleared>),reply=(src=fd20::2,dst=fd20::4,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
+udp,orig=(src=fd11::3,dst=fd20::2,sport=<cleared>,dport=<cleared>),reply=(src=fd20::2,dst=fd20::4,sport=<cleared>,dport=<cleared>),zone=<cleared>
 ])
 
 AT_CHECK([ovs-appctl dpctl/flush-conntrack])
 
-# South-North SNAT: 'bar1' pings 'alice1'. But 'alice1' receives traffic
+# South-North SNAT: 'bar1' reaches 'alice1'. But 'alice1' receives traffic
 # from fd20::1
-NS_CHECK_EXEC([bar1], [ping6 -q -c 3 -i 0.3 -w 2 fd20::2 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
+NS_CHECK_CONNECTIVITY_V6([bar1], [alice1], fd20::2)
 
 # We verify that SNAT indeed happened via 'dump-conntrack' command.
 AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::1) | \
 sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
 
icmpv6,orig=(src=fd12::2,dst=fd20::2,id=<cleared>,type=128,code=0),reply=(src=fd20::2,dst=fd20::1,id=<cleared>,type=129,code=0),zone=<cleared>
+tcp,orig=(src=fd12::2,dst=fd20::2,sport=<cleared>,dport=<cleared>),reply=(src=fd20::2,dst=fd20::1,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
+udp,orig=(src=fd12::2,dst=fd20::2,sport=<cleared>,dport=<cleared>),reply=(src=fd20::2,dst=fd20::1,sport=<cleared>,dport=<cleared>),zone=<cleared>
 ])
 
-# test_connectivity_from_ext takes parameters 'vm' and 'ip'. It tests
-# icmp, udp and tcp connectivity from external network to the 'vm' on
-# the specified 'ip'.
-test_connectivity_from_ext() {
-    local vm=$1; shift
-    local ip=$1; shift
-
-    # Start listening daemon for TCP connections.
-    NETNS_DAEMONIZE($vm, [nc -6 -l -k 1235], [nc-$vm-$ip-tcp.pid])
-
-    # Ensure that vm can be pinged on the specified IP
-    NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 $ip | FORMAT_PING], \
-    [0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
-
-    # Perform two consecutive UDP connections to the specified IP
-    NETNS_DAEMONIZE($vm, [nc -6 -l -u 1234], [nc-$vm-$ip-udp.pid])
-    NS_CHECK_EXEC([alice1], [nc -u $ip 1234 -p 2000 -z])
-    kill $(cat nc-$vm-$ip-udp.pid)
-
-    NETNS_DAEMONIZE($vm, [nc -6 -l -u 1234], [nc-$vm-$ip-udp.pid])
-    NS_CHECK_EXEC([alice1], [nc -u $ip 1234 -p 2000 -z])
-    kill $(cat nc-$vm-$ip-udp.pid)
-
-    # Send data over TCP connection to the specified IP
-    NS_CHECK_EXEC([alice1], [echo "TCP test" | nc --send-only $ip 1235])
-}
-
-# Test access from external network to the internal IP of a VM that
-# has also configured DNAT
-test_connectivity_from_ext foo1 fd11::2
+# North-South Direct (Bypassing DNAT): 'alice1' reaches 'foo1' using fd11::2
+NS_CHECK_CONNECTIVITY_V6([alice1], [foo1], [fd11::2])
 
-# Test access from external network to the internal IP of a VM that
-# does not have DNAT
-test_connectivity_from_ext bar1 fd12::2
+# North-South Direct (Bypassing SNAT): 'alice1' reaches 'bar1' using fd12::2
+NS_CHECK_CONNECTIVITY_V6([alice1], [bar1], [fd12::2])
 
 OVN_CLEANUP_CONTROLLER([hv1])
 
-- 
2.48.1

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to