[ovs-dev,v2,1/2] system-ovn.at: Add a OVN NAT test using OVN gateway.
diff mbox

Message ID 1468393460-6153-1-git-send-email-guru@ovn.org
State Accepted
Headers show

Commit Message

Guru Shetty July 13, 2016, 7:04 a.m. UTC
This unit test adds a basic OVN NAT test that tests north-south
DNAT, south-north SNAT and east-west DNAT and SNAT. It uses network
namespaces connected to br-int using veth pairs to act as logical
ports. This test does not cover multi-host scenarios, so there is
a gap. But userspace OVN tests do multi-host scenarios (without NAT
testing), so it should still be a decent coverage.

Signed-off-by: Gurucharan Shetty <guru@ovn.org>
---
 tests/automake.mk                   |   2 +
 tests/system-kmod-testsuite.at      |   1 +
 tests/system-ovn.at                 | 169 ++++++++++++++++++++++++++++++++++++
 tests/system-userspace-testsuite.at |   1 +
 4 files changed, 173 insertions(+)
 create mode 100644 tests/system-ovn.at

Comments

Joe Stringer July 15, 2016, 10:05 p.m. UTC | #1
On 13 July 2016 at 00:04, Gurucharan Shetty <guru@ovn.org> wrote:
> This unit test adds a basic OVN NAT test that tests north-south
> DNAT, south-north SNAT and east-west DNAT and SNAT. It uses network
> namespaces connected to br-int using veth pairs to act as logical
> ports. This test does not cover multi-host scenarios, so there is
> a gap. But userspace OVN tests do multi-host scenarios (without NAT
> testing), so it should still be a decent coverage.
>
> Signed-off-by: Gurucharan Shetty <guru@ovn.org>

It's a little clearer to see what's going on with these latest changes
(or maybe it's just from reviewing it the first time ;) ), thanks.

Acked-by: Joe Stringer <joe@ovn.org>

Patch
diff mbox

diff --git a/tests/automake.mk b/tests/automake.mk
index bdf6828..bad68d9 100644
--- a/tests/automake.mk
+++ b/tests/automake.mk
@@ -102,10 +102,12 @@  SYSTEM_KMOD_TESTSUITE_AT = \
 
 SYSTEM_USERSPACE_TESTSUITE_AT = \
 	tests/system-userspace-testsuite.at \
+	tests/system-ovn.at \
 	tests/system-userspace-macros.at
 
 SYSTEM_TESTSUITE_AT = \
 	tests/system-common-macros.at \
+	tests/system-ovn.at \
 	tests/system-traffic.at
 
 TESTSUITE = $(srcdir)/tests/testsuite
diff --git a/tests/system-kmod-testsuite.at b/tests/system-kmod-testsuite.at
index fc71a48..bdf57c8 100644
--- a/tests/system-kmod-testsuite.at
+++ b/tests/system-kmod-testsuite.at
@@ -23,3 +23,4 @@  m4_include([tests/system-common-macros.at])
 m4_include([tests/system-kmod-macros.at])
 
 m4_include([tests/system-traffic.at])
+m4_include([tests/system-ovn.at])
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
new file mode 100644
index 0000000..b4cbc85
--- /dev/null
+++ b/tests/system-ovn.at
@@ -0,0 +1,169 @@ 
+AT_SETUP([ovn -- 2 LRs connected via LS, gateway router, NAT])
+AT_KEYWORDS([ovnnat])
+
+CHECK_CONNTRACK()
+ovn_start
+OVS_TRAFFIC_VSWITCHD_START()
+ADD_BR([br-int])
+
+# Set external-ids in br-int needed for ovn-controller
+ovs-vsctl \
+        -- set Open_vSwitch . external-ids:system-id=hv1 \
+        -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
+        -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
+        -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \
+        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
+
+# Start ovn-controller
+start_daemon ovn-controller
+
+# Logical network:
+# Two LRs - R1 and R2 that are connected to each other via LS "join"
+# in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24) and
+# bar (192.168.2.0/24) connected to it. R2 has alice (172.16.1.0/24) connected
+# to it.  R2 is a gateway router on which we add NAT rules.
+#
+#    foo -- R1 -- join - R2 -- alice
+#           |
+#    bar ----
+
+ovn-nbctl create Logical_Router name=R1
+ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
+
+ovn-nbctl ls-add foo
+ovn-nbctl ls-add bar
+ovn-nbctl ls-add alice
+ovn-nbctl ls-add join
+
+# Connect foo to R1
+ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
+ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
+    type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
+
+# Connect bar to R1
+ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
+ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
+    type=router options:router-port=bar addresses=\"00:00:01:01:02:04\"
+
+# Connect alice to R2
+ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
+ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
+    type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
+
+# Connect R1 to join
+ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
+ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
+    type=router options:router-port=R1_join addresses='"00:00:04:01:02:03"'
+
+# Connect R2 to join
+ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
+ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
+    type=router options:router-port=R2_join addresses='"00:00:04:01:02:04"'
+
+# Static routes.
+ovn-nbctl lr-route-add R1 172.16.1.0/24 20.0.0.2
+ovn-nbctl lr-route-add R2 192.168.0.0/16 20.0.0.1
+
+# Logical port 'foo1' in switch 'foo'.
+ADD_NAMESPACES(foo1)
+ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
+         "192.168.1.1")
+ovn-nbctl lsp-add foo foo1 \
+-- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
+
+# Logical port 'alice1' in switch 'alice'.
+ADD_NAMESPACES(alice1)
+ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24", "f0:00:00:01:02:04", \
+         "172.16.1.1")
+ovn-nbctl lsp-add alice alice1 \
+-- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
+
+# Logical port 'bar1' in switch 'bar'.
+ADD_NAMESPACES(bar1)
+ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24", "f0:00:00:01:02:05", \
+"192.168.2.1")
+ovn-nbctl lsp-add bar bar1 \
+-- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
+
+# Add a DNAT rule.
+ovn-nbctl -- --id=@nat create nat type="dnat" logical_ip=192.168.1.2 \
+    external_ip=30.0.0.2 -- add logical_router R2 nat @nat
+
+# Add a SNAT rule
+ovn-nbctl -- --id=@nat create nat type="snat" logical_ip=192.168.2.2 \
+    external_ip=30.0.0.1 -- add logical_router R2 nat @nat
+
+# wait for ovn-controller to catch up.
+OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep ct\( | grep nat])
+
+# 'alice1' should be able to ping 'foo1' directly.
+NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 192.168.1.2 | FORMAT_PING], \
+[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+# North-South DNAT: 'alice1' should also be able to ping 'foo1' via 30.0.0.2
+NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.2 | FORMAT_PING], \
+[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+# Check conntrack entries.
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.2) | \
+sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
+icmp,orig=(src=172.16.1.2,dst=30.0.0.2,id=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,id=<cleared>),zone=<cleared>
+])
+
+# South-North SNAT: 'bar1' pings 'alice1'. But 'alice1' receives traffic
+# from 30.0.0.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
+])
+
+# We verify that SNAT indeed happened via 'dump-conntrack' command.
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.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>),reply=(src=172.16.1.2,dst=30.0.0.1,id=<cleared>),zone=<cleared>
+])
+
+# Add static routes to handle east-west NAT.
+ovn-nbctl lr-route-add R1 30.0.0.0/24 20.0.0.2
+
+# Flush conntrack entries for easier output parsing of next test.
+AT_CHECK([ovs-appctl dpctl/flush-conntrack])
+
+# East-west DNAT and SNAT: 'bar1' pings 30.0.0.2. 'foo1' receives it.
+NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.2 | FORMAT_PING], \
+[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+# As we have a static route that sends all packets with destination
+# 30.0.0.2 to R2, it hits the DNAT rule and converts 30.0.0.2 to 192.168.1.2
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | \
+sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
+icmp,orig=(src=192.168.2.2,dst=30.0.0.2,id=<cleared>),reply=(src=192.168.1.2,dst=192.168.2.2,id=<cleared>),zone=<cleared>
+])
+
+# As we have a SNAT rule that converts 192.168.2.2 to 30.0.0.1, the source is
+# SNATted and 'foo1' receives it.
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
+sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
+icmp,orig=(src=192.168.2.2,dst=192.168.1.2,id=<cleared>),reply=(src=192.168.1.2,dst=30.0.0.1,id=<cleared>),zone=<cleared>
+])
+
+OVS_APP_EXIT_AND_WAIT([ovn-controller])
+
+as ovn-sb
+OVS_APP_EXIT_AND_WAIT([ovsdb-server])
+
+as ovn-nb
+OVS_APP_EXIT_AND_WAIT([ovsdb-server])
+
+as northd
+OVS_APP_EXIT_AND_WAIT([ovn-northd])
+
+as
+OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d"])
+AT_CLEANUP
diff --git a/tests/system-userspace-testsuite.at b/tests/system-userspace-testsuite.at
index 3e03256..c99e512 100644
--- a/tests/system-userspace-testsuite.at
+++ b/tests/system-userspace-testsuite.at
@@ -23,3 +23,4 @@  m4_include([tests/system-userspace-macros.at])
 m4_include([tests/system-common-macros.at])
 
 m4_include([tests/system-traffic.at])
+m4_include([tests/system-ovn.at])