Commit 40136a2f2c84 introduced the ability to directly reach networks behind
SNAT and DNAT_AND_SNAT on Distributed Routers, matching the behavior
of Gateway Routers. This was achieved by committing the incoming traffic into
the SNAT TC zone, which allowed the router to SNAT only traffic that originated
from inside the SNATed network.
An unintended consequence was that incoming traffic destined for the external
IP of a DNAT_AND_SNAT rule would also be committed to the SNAT CT zone,
resulting in an unnecessary entry, lingering in the table until it expired.
This change attempts to fix that by handling traffic matching DNAT_AND_SNAT
rule with slightly higher priority than the simple SNAT, and committing it to
DNAT CT zone instead.
Tests for the connectivity are also improved. Previously the system tests
'DNAT and SNAT on distributed router - N/S' used:
* 'ping' for ICMP traffic
* 'nc -u -z' for UDP traffic
* 'nc --send-only' for TCP traffic
It was especially the TCP traffic test that was problematic, because it would
not detect errors that occurred after the initial TCP handshake.
This patch proposes a new macro NS_CHECK_CONNECTIVITY that validates the
connectivity more thoroughly by exchanging multiple messages over the TCP
and UDP to make sure that the traffic can flow.
Fixes: 40136a2f2c84 ("northd: Fix direct access to SNAT network.")
Signed-off-by: Martin Kalcok <[email protected]>
---
northd/northd.c | 48 ++++++++----
tests/ovn-northd.at | 27 ++++---
tests/system-common-macros.at | 47 ++++++++++++
tests/system-ovn.at | 138 +++++++++-------------------------
4 files changed, 134 insertions(+), 126 deletions(-)
diff --git a/northd/northd.c b/northd/northd.c
index 8b5413ef3..6db6c7aed 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -16611,27 +16611,49 @@ build_lrouter_out_snat_flow(struct lflow_table
*lflows,
* properly tracked so we can decide whether to perform SNAT on traffic
* exiting the network. */
if (features->ct_commit_to_zone && features->ct_next_zone &&
- nat_entry->type == SNAT && !od->is_gw_router && !commit_all) {
- /* For traffic that comes from SNAT network, initiate CT state before
- * entering S_ROUTER_OUT_SNAT to allow matching on various CT states.
- */
- ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_UNDNAT, 70,
- ds_cstr(match), "ct_next(snat);",
+ !od->is_gw_router && !commit_all) {
+ const char *zone;
+ uint16_t prio_offset;
+ /* Traffic to/from hosts behind SNAT is tracked through the
+ * SNAT CT zone.*/
+ if (nat_entry->type == SNAT) {
+ zone = "snat";
+ prio_offset = 0;
+ /* Traffic to/from hosts behind DNAT_AND_SNAT is tracked through the
+ * DNAT CT zone with slightly higher priority flows.*/
+ } else {
+ zone = "dnat";
+ prio_offset = 5;
+ }
+
+ /* For traffic that comes from the SNAT network, initiate CT state
+ * from the correct zone, before entering S_ROUTER_OUT_SNAT to allow
+ * matching on various CT states.*/
+ ds_clear(actions);
+ ds_put_format(actions, "ct_next(%s);", zone);
+ ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_UNDNAT, 70 + prio_offset,
+ ds_cstr(match), ds_cstr(actions),
lflow_ref);
+ /* New traffic that goes into the SNAT network is committed to the
+ * correct CT zone to avoid SNAT-ing replies.*/
build_lrouter_out_snat_match(lflows, od, nat, match,
distributed_nat, cidr_bits, is_v6,
l3dgw_port, lflow_ref, true);
-
- /* New traffic that goes into SNAT network is committed to CT to avoid
- * SNAT-ing replies.*/
- ovn_lflow_add(lflows, od, S_ROUTER_OUT_SNAT, priority,
- ds_cstr(match), "ct_snat;",
+ size_t match_any_state_len = match->length;
+ ds_put_cstr(match, " && (!ct.trk || !ct.rpl)");
+ ds_clear(actions);
+ ds_put_format(actions, "ct_%s;", zone);
+ ovn_lflow_add(lflows, od, S_ROUTER_OUT_SNAT, priority + prio_offset,
+ ds_cstr(match), ds_cstr(actions),
lflow_ref);
+ ds_truncate(match, match_any_state_len);
ds_put_cstr(match, " && ct.new");
- ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_SNAT, priority,
- ds_cstr(match), "ct_commit_to_zone(snat);",
+ ds_clear(actions);
+ ds_put_format(actions, "ct_commit_to_zone(%s);", zone);
+ ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_SNAT,
+ priority + prio_offset, ds_cstr(match), ds_cstr(actions),
lflow_ref);
}
}
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index c9e998129..d99815dd6 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -1242,7 +1242,7 @@ AT_CAPTURE_FILE([crflows])
AT_CHECK([grep -e "lr_out_snat" drflows | ovn_strip_lflows], [0], [dnl
table=??(lr_out_snat ), priority=0 , match=(1), action=(next;)
table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;)
- table=??(lr_out_snat ), priority=161 , match=(ip && ip4.dst ==
50.0.0.11 && inport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.src ==
$allowed_range), action=(ct_snat;)
+ table=??(lr_out_snat ), priority=161 , match=(ip && ip4.dst ==
50.0.0.11 && inport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.src ==
$allowed_range && (!ct.trk || !ct.rpl)), action=(ct_snat;)
table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src ==
50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst
== $allowed_range && (!ct.trk || !ct.rpl)), action=(ct_snat(172.16.1.1);)
])
@@ -1281,7 +1281,7 @@ AT_CAPTURE_FILE([crflows2])
AT_CHECK([grep -e "lr_out_snat" drflows2 | ovn_strip_lflows], [0], [dnl
table=??(lr_out_snat ), priority=0 , match=(1), action=(next;)
table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;)
- table=??(lr_out_snat ), priority=161 , match=(ip && ip4.dst ==
50.0.0.11 && inport == "DR-S1" && is_chassis_resident("cr-DR-S1")),
action=(ct_snat;)
+ table=??(lr_out_snat ), priority=161 , match=(ip && ip4.dst ==
50.0.0.11 && inport == "DR-S1" && is_chassis_resident("cr-DR-S1") && (!ct.trk
|| !ct.rpl)), action=(ct_snat;)
table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src ==
50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && (!ct.trk
|| !ct.rpl)), action=(ct_snat(172.16.1.1);)
table=??(lr_out_snat ), priority=163 , match=(ip && ip4.src ==
50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst
== $disallowed_range), action=(next;)
])
@@ -1321,10 +1321,12 @@ AT_CHECK([grep -e "lr_out_snat" drflows3 |
ovn_strip_lflows], [0], [dnl
table=??(lr_out_snat ), priority=0 , match=(1), action=(next;)
table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;)
table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src ==
50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst
== $allowed_range && (!ct.trk || !ct.rpl)), action=(ct_snat(172.16.1.2);)
+ table=??(lr_out_snat ), priority=166 , match=(ip && ip4.dst ==
50.0.0.11 && inport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.src ==
$allowed_range && (!ct.trk || !ct.rpl)), action=(ct_dnat;)
])
AT_CHECK([grep -e "lr_out_post_snat" drflows3 | ovn_strip_lflows], [0], [dnl
table=??(lr_out_post_snat ), priority=0 , match=(1), action=(next;)
+ table=??(lr_out_post_snat ), priority=166 , match=(ip && ip4.dst ==
50.0.0.11 && inport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.src ==
$allowed_range && ct.new), action=(ct_commit_to_zone(dnat);)
])
AT_CHECK([grep -e "lr_out_snat" crflows3 | ovn_strip_lflows], [0], [dnl
@@ -1357,6 +1359,7 @@ AT_CHECK([grep -e "lr_out_snat" drflows4 |
ovn_strip_lflows], [0], [dnl
table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;)
table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src ==
50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && (!ct.trk
|| !ct.rpl)), action=(ct_snat(172.16.1.2);)
table=??(lr_out_snat ), priority=163 , match=(ip && ip4.src ==
50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst
== $disallowed_range), action=(next;)
+ table=??(lr_out_snat ), priority=166 , match=(ip && ip4.dst ==
50.0.0.11 && inport == "DR-S1" && is_chassis_resident("cr-DR-S1") && (!ct.trk
|| !ct.rpl)), action=(ct_dnat;)
])
AT_CHECK([grep -e "lr_out_snat" crflows4 | ovn_strip_lflows], [0], [dnl
@@ -5999,22 +6002,25 @@ AT_CHECK([grep "lr_out_post_undnat" lr0flows |
ovn_strip_lflows], [0], [dnl
table=??(lr_out_post_undnat ), priority=0 , match=(1), action=(next;)
table=??(lr_out_post_undnat ), priority=70 , match=(ip && ip4.src ==
10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")
&& (!ct.trk || !ct.rpl)), action=(ct_next(snat);)
table=??(lr_out_post_undnat ), priority=70 , match=(ip && ip4.src ==
10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") &&
(!ct.trk || !ct.rpl)), action=(ct_next(snat);)
+ table=??(lr_out_post_undnat ), priority=75 , match=(ip && ip4.src ==
10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") &&
(!ct.trk || !ct.rpl)), action=(ct_next(dnat);)
])
AT_CHECK([grep "lr_out_snat" lr0flows | ovn_strip_lflows], [0], [dnl
table=??(lr_out_snat ), priority=0 , match=(1), action=(next;)
table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;)
- table=??(lr_out_snat ), priority=153 , match=(ip && ip4.dst ==
10.0.0.0/24 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")),
action=(ct_snat;)
+ table=??(lr_out_snat ), priority=153 , match=(ip && ip4.dst ==
10.0.0.0/24 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")
&& (!ct.trk || !ct.rpl)), action=(ct_snat;)
table=??(lr_out_snat ), priority=153 , match=(ip && ip4.src ==
10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")
&& (!ct.trk || !ct.rpl)), action=(ct_snat(172.168.0.10);)
- table=??(lr_out_snat ), priority=161 , match=(ip && ip4.dst ==
10.0.0.10 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")),
action=(ct_snat;)
+ table=??(lr_out_snat ), priority=161 , match=(ip && ip4.dst ==
10.0.0.10 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public") &&
(!ct.trk || !ct.rpl)), action=(ct_snat;)
table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src ==
10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") &&
(!ct.trk || !ct.rpl)), action=(ct_snat(172.168.0.30);)
table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src ==
10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") &&
(!ct.trk || !ct.rpl)), action=(ct_snat(172.168.0.20);)
+ table=??(lr_out_snat ), priority=166 , match=(ip && ip4.dst ==
10.0.0.3 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public") &&
(!ct.trk || !ct.rpl)), action=(ct_dnat;)
])
AT_CHECK([grep "lr_out_post_snat" lr0flows | ovn_strip_lflows], [0], [dnl
table=??(lr_out_post_snat ), priority=0 , match=(1), action=(next;)
table=??(lr_out_post_snat ), priority=153 , match=(ip && ip4.dst ==
10.0.0.0/24 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")
&& ct.new), action=(ct_commit_to_zone(snat);)
table=??(lr_out_post_snat ), priority=161 , match=(ip && ip4.dst ==
10.0.0.10 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public") &&
ct.new), action=(ct_commit_to_zone(snat);)
+ table=??(lr_out_post_snat ), priority=166 , match=(ip && ip4.dst ==
10.0.0.3 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public") &&
ct.new), action=(ct_commit_to_zone(dnat);)
])
# Associate load balancer to lr0
@@ -6157,22 +6163,25 @@ AT_CHECK([grep "lr_out_post_undnat" lr0flows |
ovn_strip_lflows], [0], [dnl
table=??(lr_out_post_undnat ), priority=0 , match=(1), action=(next;)
table=??(lr_out_post_undnat ), priority=70 , match=(ip && ip4.src ==
10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")
&& (!ct.trk || !ct.rpl)), action=(ct_next(snat);)
table=??(lr_out_post_undnat ), priority=70 , match=(ip && ip4.src ==
10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") &&
(!ct.trk || !ct.rpl)), action=(ct_next(snat);)
+ table=??(lr_out_post_undnat ), priority=75 , match=(ip && ip4.src ==
10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") &&
(!ct.trk || !ct.rpl)), action=(ct_next(dnat);)
])
AT_CHECK([grep "lr_out_snat" lr0flows | ovn_strip_lflows], [0], [dnl
table=??(lr_out_snat ), priority=0 , match=(1), action=(next;)
table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;)
- table=??(lr_out_snat ), priority=153 , match=(ip && ip4.dst ==
10.0.0.0/24 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")),
action=(ct_snat;)
+ table=??(lr_out_snat ), priority=153 , match=(ip && ip4.dst ==
10.0.0.0/24 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")
&& (!ct.trk || !ct.rpl)), action=(ct_snat;)
table=??(lr_out_snat ), priority=153 , match=(ip && ip4.src ==
10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")
&& (!ct.trk || !ct.rpl)), action=(ct_snat(172.168.0.10);)
- table=??(lr_out_snat ), priority=161 , match=(ip && ip4.dst ==
10.0.0.10 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")),
action=(ct_snat;)
+ table=??(lr_out_snat ), priority=161 , match=(ip && ip4.dst ==
10.0.0.10 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public") &&
(!ct.trk || !ct.rpl)), action=(ct_snat;)
table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src ==
10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") &&
(!ct.trk || !ct.rpl)), action=(ct_snat(172.168.0.30);)
table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src ==
10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") &&
(!ct.trk || !ct.rpl)), action=(ct_snat(172.168.0.20);)
+ table=??(lr_out_snat ), priority=166 , match=(ip && ip4.dst ==
10.0.0.3 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public") &&
(!ct.trk || !ct.rpl)), action=(ct_dnat;)
])
AT_CHECK([grep "lr_out_post_snat" lr0flows | ovn_strip_lflows], [0], [dnl
table=??(lr_out_post_snat ), priority=0 , match=(1), action=(next;)
table=??(lr_out_post_snat ), priority=153 , match=(ip && ip4.dst ==
10.0.0.0/24 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")
&& ct.new), action=(ct_commit_to_zone(snat);)
table=??(lr_out_post_snat ), priority=161 , match=(ip && ip4.dst ==
10.0.0.10 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public") &&
ct.new), action=(ct_commit_to_zone(snat);)
+ table=??(lr_out_post_snat ), priority=166 , match=(ip && ip4.dst ==
10.0.0.3 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public") &&
ct.new), action=(ct_commit_to_zone(dnat);)
])
# Make the logical router as Gateway router
@@ -8389,9 +8398,9 @@ AT_CHECK([grep lr_in_unsnat lrflows | grep ct_snat |
ovn_strip_lflows], [0], [dn
])
AT_CHECK([grep lr_out_snat lrflows | grep ct_snat | ovn_strip_lflows], [0],
[dnl
- table=??(lr_out_snat ), priority=161 , match=(ip && ip4.dst ==
20.0.0.10 && inport == "DR-S1" && is_chassis_resident("cr-DR-S1")),
action=(ct_snat;)
- table=??(lr_out_snat ), priority=161 , match=(ip && ip4.dst ==
20.0.0.10 && inport == "DR-S2" && is_chassis_resident("cr-DR-S2")),
action=(ct_snat;)
- table=??(lr_out_snat ), priority=161 , match=(ip && ip4.dst ==
20.0.0.10 && inport == "DR-S3" && is_chassis_resident("cr-DR-S3")),
action=(ct_snat;)
+ table=??(lr_out_snat ), priority=161 , match=(ip && ip4.dst ==
20.0.0.10 && inport == "DR-S1" && is_chassis_resident("cr-DR-S1") && (!ct.trk
|| !ct.rpl)), action=(ct_snat;)
+ table=??(lr_out_snat ), priority=161 , match=(ip && ip4.dst ==
20.0.0.10 && inport == "DR-S2" && is_chassis_resident("cr-DR-S2") && (!ct.trk
|| !ct.rpl)), action=(ct_snat;)
+ table=??(lr_out_snat ), priority=161 , match=(ip && ip4.dst ==
20.0.0.10 && inport == "DR-S3" && is_chassis_resident("cr-DR-S3") && (!ct.trk
|| !ct.rpl)), action=(ct_snat;)
table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src ==
20.0.0.10 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && (!ct.trk
|| !ct.rpl)), action=(ct_snat(172.16.1.10);)
table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src ==
20.0.0.10 && outport == "DR-S2" && is_chassis_resident("cr-DR-S2") && (!ct.trk
|| !ct.rpl)), action=(ct_snat(10.0.0.10);)
table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src ==
20.0.0.10 && outport == "DR-S3" && is_chassis_resident("cr-DR-S3") && (!ct.trk
|| !ct.rpl)), action=(ct_snat(192.168.0.10);)
diff --git a/tests/system-common-macros.at b/tests/system-common-macros.at
index 251a4c0b8..1c6cefcd9 100644
--- a/tests/system-common-macros.at
+++ b/tests/system-common-macros.at
@@ -614,3 +614,50 @@ 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])
+#
+# 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
+m4_define([NS_CHECK_CONNECTIVITY],
+[
+ ns_src="$1"
+ ns_dst="$2"
+ ip="$3"
+ # Start a simple TCP and UDP echo server that replies with "ack
<received_msg>".
+ NETNS_DAEMONIZE($ns_dst, [nc -l -k -p 1235 -d 0.1 -c 'while read msg; do
echo "ack $msg"; done'], [nc-$ns_dst-$ip-tcp.pid])
+ NETNS_DAEMONIZE($ns_dst, [nc -l -u -k -p 1234 -d 0.1 -c 'read msg; echo
"ack $msg"'], [nc-$ns_dst-$ip-udp.pid])
+
+ # Ensure that the destination NS can be pinged on the specified IP
+ NS_CHECK_EXEC([$ns_src], [ping -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.
+ truncate --size 0 ./tcp_data
+ truncate --size 0 ./udp_data
+
+ NETNS_DAEMONIZE($ns_src, [nc $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 -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
+ack tcp_data 1
+ack tcp_data 2
+ack tcp_data 3
+])
+ OVS_WAIT_FOR_OUTPUT([cat ./udp_data], [0], [dnl
+ack udp_data 1
+ack udp_data 2
+ack 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)
+])
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
index 8e356df6f..0d01582a4 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([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([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([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([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([alice1], [bar1], [fd12::2])
OVN_CLEANUP_CONTROLLER([hv1])
@@ -4244,7 +4176,6 @@ NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2
172.16.1.4 | FORMAT_PING], \
AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(172.16.1.1)
| \
sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
icmp,orig=(src=172.16.1.1,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
-icmp,orig=(src=172.16.1.1,dst=192.168.2.2,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
icmp,orig=(src=192.168.1.3,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
])
@@ -4412,7 +4343,6 @@ NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 fd20::4 |
FORMAT_PING], \
AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::1) | \
sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
icmpv6,orig=(src=fd11::3,dst=fd20::4,id=<cleared>,type=128,code=0),reply=(src=fd20::4,dst=fd20::1,id=<cleared>,type=129,code=0),zone=<cleared>
-icmpv6,orig=(src=fd20::1,dst=fd12::2,id=<cleared>,type=128,code=0),reply=(src=fd12::2,dst=fd20::1,id=<cleared>,type=129,code=0),zone=<cleared>
icmpv6,orig=(src=fd20::1,dst=fd20::4,id=<cleared>,type=128,code=0),reply=(src=fd12::2,dst=fd20::1,id=<cleared>,type=129,code=0),zone=<cleared>
])
--
2.48.1
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev