diff mbox series

[ovs-dev,3/3] system-traffic: Add conntrack floating IP test

Message ID 20171020182312.12888-4-e@erig.me
State Superseded
Headers show
Series Add dpif support for ct_clear action | expand

Commit Message

Eric Garver Oct. 20, 2017, 6:23 p.m. UTC
This test cases uses floating IP (FIP) addresses for each endpoint. If
the destination is a FIP, the packet will undergo a transformation of
the form (dst=FIP, src=non-FIP) --> (dst=non-FIP, src=FIP) before
egress. Otherwise the packet is untouched.

This exercises the ct_clear action in the datapath.

Signed-off-by: Eric Garver <e@erig.me>
---
 tests/system-traffic.at | 73 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)

Comments

William Tu Oct. 24, 2017, 7:46 p.m. UTC | #1
On Fri, Oct 20, 2017 at 11:23 AM, Eric Garver <e@erig.me> wrote:
> This test cases uses floating IP (FIP) addresses for each endpoint. If
> the destination is a FIP, the packet will undergo a transformation of
> the form (dst=FIP, src=non-FIP) --> (dst=non-FIP, src=FIP) before
> egress. Otherwise the packet is untouched.
>
> This exercises the ct_clear action in the datapath.
>
> Signed-off-by: Eric Garver <e@erig.me>
> ---
>  tests/system-traffic.at | 73 +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 73 insertions(+)
>
> diff --git a/tests/system-traffic.at b/tests/system-traffic.at
> index 522eaa615834..7cc1e1e21187 100644
> --- a/tests/system-traffic.at
> +++ b/tests/system-traffic.at
> @@ -3996,6 +3996,79 @@ ovs-ofctl -O OpenFlow15 dump-group-stats br0
>  OVS_TRAFFIC_VSWITCHD_STOP
>  AT_CLEANUP
>
> +AT_SETUP([conntrack - floating IP])
> +AT_SKIP_IF([test $HAVE_NC = no])
> +CHECK_CONNTRACK()
> +OVS_TRAFFIC_VSWITCHD_START()
> +OVS_CHECK_CT_CLEAR()
> +
> +ADD_NAMESPACES(at_ns0, at_ns1)
> +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24", "f0:00:00:01:01:01") dnl FIP 10.254.254.1
> +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24", "f0:00:00:01:01:02") dnl FIP 10.254.254.2
> +
> +dnl Static ARPs
> +NS_CHECK_EXEC([at_ns0], [ip neigh add 10.1.1.2 lladdr f0:00:00:01:01:02 dev p0])
> +NS_CHECK_EXEC([at_ns1], [ip neigh add 10.1.1.1 lladdr f0:00:00:01:01:01 dev p1])
> +
> +dnl Static ARP and route entries for the FIP "gateway"
> +NS_CHECK_EXEC([at_ns0], [ip neigh add 10.1.1.254 lladdr f0:00:00:01:01:FE dev p0])
> +NS_CHECK_EXEC([at_ns1], [ip neigh add 10.1.1.254 lladdr f0:00:00:01:01:FE dev p1])
> +NS_CHECK_EXEC([at_ns0], [ip route add default nexthop via 10.1.1.254])
> +NS_CHECK_EXEC([at_ns1], [ip route add default nexthop via 10.1.1.254])
> +
> +NETNS_DAEMONIZE([at_ns0], [nc -l -k > /dev/null], [nc0.pid])
> +
> +AT_DATA([flows.txt], [dnl
> +table=0,priority=10  ip action=ct(table=1)
> +table=0,priority=1   action=drop
> +dnl dst FIP
> +table=1,priority=20  ip,ct_state=+trk+est,nw_dst=10.254.254.0/24 action=goto_table:10
> +table=1,priority=20  ip,ct_state=+trk+new,nw_dst=10.254.254.0/24 action=ct(commit,table=10)
> +dnl dst local
> +table=1,priority=10  ip,ct_state=+trk+est action=goto_table:20
> +table=1,priority=10  ip,ct_state=+trk+new action=ct(commit,table=20)
> +table=1,priority=1   ip,ct_state=+trk+inv action=drop
> +dnl
> +dnl FIP translation (dst FIP, src local) --> (dst local, src FIP)
> +table=10             ip,nw_dst=10.254.254.1 action=set_field:10.1.1.1->nw_dst,goto_table:11
> +table=10             ip,nw_dst=10.254.254.2 action=set_field:10.1.1.2->nw_dst,goto_table:11
> +table=11             ip,nw_src=10.1.1.1 action=set_field:10.254.254.1->nw_src,goto_table:12
> +table=11             ip,nw_src=10.1.1.2 action=set_field:10.254.254.2->nw_src,goto_table:12
> +dnl clear conntrack and do another lookup since we changed the tuple
> +table=12,priority=10 ip action=ct_clear,ct(table=13)
> +table=12,priority=1  action=drop
> +table=13             ip,ct_state=+trk+est action=goto_table:20
> +table=13             ip,ct_state=+trk+new action=ct(commit,table=20)
> +table=13             ip,ct_state=+trk+inv action=drop
> +dnl
> +dnl Output
> +table=20             ip,nw_src=10.1.1.1 action=set_field:f0:00:00:01:01:01->eth_src,goto_table:21
> +table=20             ip,nw_src=10.1.1.2 action=set_field:f0:00:00:01:01:02->eth_src,goto_table:21
> +table=20             ip,nw_src=10.254.254.0/24 action=set_field:f0:00:00:01:01:FE->eth_src,goto_table:21
> +table=21             ip,nw_dst=10.1.1.1 action=set_field:f0:00:00:01:01:01->eth_dst,output:ovs-p0
> +table=21             ip,nw_dst=10.1.1.2 action=set_field:f0:00:00:01:01:02->eth_dst,output:ovs-p1
> +])
> +
> +AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
> +
> +dnl non-FIP case
> +NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.1.1.1])
> +OVS_WAIT_UNTIL([[ovs-appctl dpctl/dump-conntrack | sed -e 's/port=[0-9]*/port=<cleared>/g' -e 's/id=[0-9]*/id=<cleared>/g' |
> +grep "tcp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),protoinfo=(state=TIME_WAIT)"
> +]])
> +
> +dnl Check that the full session ends as expected (i.e. TIME_WAIT). Otherwise it
> +dnl means the datapath didn't process the ct_clear action. Ending in SYN_RECV
> +dnl (OVS maps to ESTABLISHED) means the initial frame was committed, but not a
> +dnl second time after the FIP translation (because ct_clear didn't occur).
> +NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.254.254.1])
> +OVS_WAIT_UNTIL([[ovs-appctl dpctl/dump-conntrack | sed -e 's/port=[0-9]*/port=<cleared>/g' -e 's/id=[0-9]*/id=<cleared>/g' |
> +grep "tcp,orig=(src=10.254.254.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.1,dst=10.254.254.2,sport=<cleared>,dport=<cleared>),protoinfo=(state=TIME_WAIT)"
> +]])
> +
> +OVS_TRAFFIC_VSWITCHD_STOP
> +AT_CLEANUP
> +
>  AT_BANNER([802.1ad])
>
>  AT_SETUP([802.1ad - vlan_limit])
> --

I'm using
~/ovs# make check-system-userspace TESTSUITEFLAGS='83'
but fails due to the nc $NC_EOF_OPT.
I suggest we explicitly add network port number, ex: 1234 below

--- a/tests/system-traffic.at
+++ b/tests/system-traffic.at
@@ -4016,7 +4016,7 @@ NS_CHECK_EXEC([at_ns1], [ip neigh add 10.1.1.254
lladdr f0:00:00:01:01:FE dev p1
 NS_CHECK_EXEC([at_ns0], [ip route add default nexthop via 10.1.1.254])
 NS_CHECK_EXEC([at_ns1], [ip route add default nexthop via 10.1.1.254])

-NETNS_DAEMONIZE([at_ns0], [nc -l -k > /dev/null], [nc0.pid])
+NETNS_DAEMONIZE([at_ns0], [nc -l -k 1234 > /dev/null], [nc0.pid])

 AT_DATA([flows.txt], [dnl
 table=0,priority=10  ip action=ct(table=1)
@@ -4052,7 +4052,7 @@ table=21             ip,nw_dst=10.1.1.2
action=set_field:f0:00:00:01:01:02->eth_
 AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])

 dnl non-FIP case
-NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.1.1.1])
+NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.1.1.1 1234])
 OVS_WAIT_UNTIL([[ovs-appctl dpctl/dump-conntrack | sed -e
's/port=[0-9]*/port=<cleared>/g' -e 's/id=[0-9]*/id=<cleared>/g' |
 grep "tcp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),protoinfo=(state=TIME_WAIT)"
 ]])
@@ -4061,7 +4061,7 @@ dnl Check that the full session ends as expected
(i.e. TIME_WAIT). Otherwise it
 dnl means the datapath didn't process the ct_clear action. Ending in SYN_RECV
 dnl (OVS maps to ESTABLISHED) means the initial frame was committed, but not a
 dnl second time after the FIP translation (because ct_clear didn't occur).
-NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.254.254.1])
+NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.254.254.1 1234])
Eric Garver Oct. 24, 2017, 8:44 p.m. UTC | #2
On Tue, Oct 24, 2017 at 12:46:46PM -0700, William Tu wrote:
> On Fri, Oct 20, 2017 at 11:23 AM, Eric Garver <e@erig.me> wrote:
> > This test cases uses floating IP (FIP) addresses for each endpoint. If
> > the destination is a FIP, the packet will undergo a transformation of
> > the form (dst=FIP, src=non-FIP) --> (dst=non-FIP, src=FIP) before
> > egress. Otherwise the packet is untouched.
> >
> > This exercises the ct_clear action in the datapath.
> >
> > Signed-off-by: Eric Garver <e@erig.me>
> > ---
> >  tests/system-traffic.at | 73 +++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 73 insertions(+)
> >
> > diff --git a/tests/system-traffic.at b/tests/system-traffic.at
> > index 522eaa615834..7cc1e1e21187 100644
> > --- a/tests/system-traffic.at
> > +++ b/tests/system-traffic.at
> > @@ -3996,6 +3996,79 @@ ovs-ofctl -O OpenFlow15 dump-group-stats br0
> >  OVS_TRAFFIC_VSWITCHD_STOP
> >  AT_CLEANUP
> >
> > +AT_SETUP([conntrack - floating IP])
> > +AT_SKIP_IF([test $HAVE_NC = no])
> > +CHECK_CONNTRACK()
> > +OVS_TRAFFIC_VSWITCHD_START()
> > +OVS_CHECK_CT_CLEAR()
> > +
> > +ADD_NAMESPACES(at_ns0, at_ns1)
> > +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24", "f0:00:00:01:01:01") dnl FIP 10.254.254.1
> > +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24", "f0:00:00:01:01:02") dnl FIP 10.254.254.2
> > +
> > +dnl Static ARPs
> > +NS_CHECK_EXEC([at_ns0], [ip neigh add 10.1.1.2 lladdr f0:00:00:01:01:02 dev p0])
> > +NS_CHECK_EXEC([at_ns1], [ip neigh add 10.1.1.1 lladdr f0:00:00:01:01:01 dev p1])
> > +
> > +dnl Static ARP and route entries for the FIP "gateway"
> > +NS_CHECK_EXEC([at_ns0], [ip neigh add 10.1.1.254 lladdr f0:00:00:01:01:FE dev p0])
> > +NS_CHECK_EXEC([at_ns1], [ip neigh add 10.1.1.254 lladdr f0:00:00:01:01:FE dev p1])
> > +NS_CHECK_EXEC([at_ns0], [ip route add default nexthop via 10.1.1.254])
> > +NS_CHECK_EXEC([at_ns1], [ip route add default nexthop via 10.1.1.254])
> > +
> > +NETNS_DAEMONIZE([at_ns0], [nc -l -k > /dev/null], [nc0.pid])
> > +
> > +AT_DATA([flows.txt], [dnl
> > +table=0,priority=10  ip action=ct(table=1)
> > +table=0,priority=1   action=drop
> > +dnl dst FIP
> > +table=1,priority=20  ip,ct_state=+trk+est,nw_dst=10.254.254.0/24 action=goto_table:10
> > +table=1,priority=20  ip,ct_state=+trk+new,nw_dst=10.254.254.0/24 action=ct(commit,table=10)
> > +dnl dst local
> > +table=1,priority=10  ip,ct_state=+trk+est action=goto_table:20
> > +table=1,priority=10  ip,ct_state=+trk+new action=ct(commit,table=20)
> > +table=1,priority=1   ip,ct_state=+trk+inv action=drop
> > +dnl
> > +dnl FIP translation (dst FIP, src local) --> (dst local, src FIP)
> > +table=10             ip,nw_dst=10.254.254.1 action=set_field:10.1.1.1->nw_dst,goto_table:11
> > +table=10             ip,nw_dst=10.254.254.2 action=set_field:10.1.1.2->nw_dst,goto_table:11
> > +table=11             ip,nw_src=10.1.1.1 action=set_field:10.254.254.1->nw_src,goto_table:12
> > +table=11             ip,nw_src=10.1.1.2 action=set_field:10.254.254.2->nw_src,goto_table:12
> > +dnl clear conntrack and do another lookup since we changed the tuple
> > +table=12,priority=10 ip action=ct_clear,ct(table=13)
> > +table=12,priority=1  action=drop
> > +table=13             ip,ct_state=+trk+est action=goto_table:20
> > +table=13             ip,ct_state=+trk+new action=ct(commit,table=20)
> > +table=13             ip,ct_state=+trk+inv action=drop
> > +dnl
> > +dnl Output
> > +table=20             ip,nw_src=10.1.1.1 action=set_field:f0:00:00:01:01:01->eth_src,goto_table:21
> > +table=20             ip,nw_src=10.1.1.2 action=set_field:f0:00:00:01:01:02->eth_src,goto_table:21
> > +table=20             ip,nw_src=10.254.254.0/24 action=set_field:f0:00:00:01:01:FE->eth_src,goto_table:21
> > +table=21             ip,nw_dst=10.1.1.1 action=set_field:f0:00:00:01:01:01->eth_dst,output:ovs-p0
> > +table=21             ip,nw_dst=10.1.1.2 action=set_field:f0:00:00:01:01:02->eth_dst,output:ovs-p1
> > +])
> > +
> > +AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
> > +
> > +dnl non-FIP case
> > +NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.1.1.1])
> > +OVS_WAIT_UNTIL([[ovs-appctl dpctl/dump-conntrack | sed -e 's/port=[0-9]*/port=<cleared>/g' -e 's/id=[0-9]*/id=<cleared>/g' |
> > +grep "tcp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),protoinfo=(state=TIME_WAIT)"
> > +]])
> > +
> > +dnl Check that the full session ends as expected (i.e. TIME_WAIT). Otherwise it
> > +dnl means the datapath didn't process the ct_clear action. Ending in SYN_RECV
> > +dnl (OVS maps to ESTABLISHED) means the initial frame was committed, but not a
> > +dnl second time after the FIP translation (because ct_clear didn't occur).
> > +NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.254.254.1])
> > +OVS_WAIT_UNTIL([[ovs-appctl dpctl/dump-conntrack | sed -e 's/port=[0-9]*/port=<cleared>/g' -e 's/id=[0-9]*/id=<cleared>/g' |
> > +grep "tcp,orig=(src=10.254.254.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.1,dst=10.254.254.2,sport=<cleared>,dport=<cleared>),protoinfo=(state=TIME_WAIT)"
> > +]])
> > +
> > +OVS_TRAFFIC_VSWITCHD_STOP
> > +AT_CLEANUP
> > +
> >  AT_BANNER([802.1ad])
> >
> >  AT_SETUP([802.1ad - vlan_limit])
> > --
> 
> I'm using
> ~/ovs# make check-system-userspace TESTSUITEFLAGS='83'
> but fails due to the nc $NC_EOF_OPT.
> I suggest we explicitly add network port number, ex: 1234 below
> 
> --- a/tests/system-traffic.at
> +++ b/tests/system-traffic.at
> @@ -4016,7 +4016,7 @@ NS_CHECK_EXEC([at_ns1], [ip neigh add 10.1.1.254
> lladdr f0:00:00:01:01:FE dev p1
>  NS_CHECK_EXEC([at_ns0], [ip route add default nexthop via 10.1.1.254])
>  NS_CHECK_EXEC([at_ns1], [ip route add default nexthop via 10.1.1.254])
> 
> -NETNS_DAEMONIZE([at_ns0], [nc -l -k > /dev/null], [nc0.pid])
> +NETNS_DAEMONIZE([at_ns0], [nc -l -k 1234 > /dev/null], [nc0.pid])
> 
>  AT_DATA([flows.txt], [dnl
>  table=0,priority=10  ip action=ct(table=1)
> @@ -4052,7 +4052,7 @@ table=21             ip,nw_dst=10.1.1.2
> action=set_field:f0:00:00:01:01:02->eth_
>  AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
> 
>  dnl non-FIP case
> -NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.1.1.1])
> +NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.1.1.1 1234])
>  OVS_WAIT_UNTIL([[ovs-appctl dpctl/dump-conntrack | sed -e
> 's/port=[0-9]*/port=<cleared>/g' -e 's/id=[0-9]*/id=<cleared>/g' |
>  grep "tcp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),protoinfo=(state=TIME_WAIT)"
>  ]])
> @@ -4061,7 +4061,7 @@ dnl Check that the full session ends as expected
> (i.e. TIME_WAIT). Otherwise it
>  dnl means the datapath didn't process the ct_clear action. Ending in SYN_RECV
>  dnl (OVS maps to ESTABLISHED) means the initial frame was committed, but not a
>  dnl second time after the FIP translation (because ct_clear didn't occur).
> -NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.254.254.1])
> +NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.254.254.1 1234])

Are you saying it works for you with the explicit port?
If not, can you show the error?

FWIW, nmap-ncat defaults to 31337. I guess other nc implementations may
be different.
William Tu Oct. 24, 2017, 9:10 p.m. UTC | #3
On Tue, Oct 24, 2017 at 1:44 PM, Eric Garver <e@erig.me> wrote:
> On Tue, Oct 24, 2017 at 12:46:46PM -0700, William Tu wrote:
>> On Fri, Oct 20, 2017 at 11:23 AM, Eric Garver <e@erig.me> wrote:
>> > This test cases uses floating IP (FIP) addresses for each endpoint. If
>> > the destination is a FIP, the packet will undergo a transformation of
>> > the form (dst=FIP, src=non-FIP) --> (dst=non-FIP, src=FIP) before
>> > egress. Otherwise the packet is untouched.
>> >
>> > This exercises the ct_clear action in the datapath.
>> >
>> > Signed-off-by: Eric Garver <e@erig.me>
>> > ---
>> >  tests/system-traffic.at | 73 +++++++++++++++++++++++++++++++++++++++++++++++++
>> >  1 file changed, 73 insertions(+)
>> >
>> > diff --git a/tests/system-traffic.at b/tests/system-traffic.at
>> > index 522eaa615834..7cc1e1e21187 100644
>> > --- a/tests/system-traffic.at
>> > +++ b/tests/system-traffic.at
>> > @@ -3996,6 +3996,79 @@ ovs-ofctl -O OpenFlow15 dump-group-stats br0
>> >  OVS_TRAFFIC_VSWITCHD_STOP
>> >  AT_CLEANUP
>> >
>> > +AT_SETUP([conntrack - floating IP])
>> > +AT_SKIP_IF([test $HAVE_NC = no])
>> > +CHECK_CONNTRACK()
>> > +OVS_TRAFFIC_VSWITCHD_START()
>> > +OVS_CHECK_CT_CLEAR()
>> > +
>> > +ADD_NAMESPACES(at_ns0, at_ns1)
>> > +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24", "f0:00:00:01:01:01") dnl FIP 10.254.254.1
>> > +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24", "f0:00:00:01:01:02") dnl FIP 10.254.254.2
>> > +
>> > +dnl Static ARPs
>> > +NS_CHECK_EXEC([at_ns0], [ip neigh add 10.1.1.2 lladdr f0:00:00:01:01:02 dev p0])
>> > +NS_CHECK_EXEC([at_ns1], [ip neigh add 10.1.1.1 lladdr f0:00:00:01:01:01 dev p1])
>> > +
>> > +dnl Static ARP and route entries for the FIP "gateway"
>> > +NS_CHECK_EXEC([at_ns0], [ip neigh add 10.1.1.254 lladdr f0:00:00:01:01:FE dev p0])
>> > +NS_CHECK_EXEC([at_ns1], [ip neigh add 10.1.1.254 lladdr f0:00:00:01:01:FE dev p1])
>> > +NS_CHECK_EXEC([at_ns0], [ip route add default nexthop via 10.1.1.254])
>> > +NS_CHECK_EXEC([at_ns1], [ip route add default nexthop via 10.1.1.254])
>> > +
>> > +NETNS_DAEMONIZE([at_ns0], [nc -l -k > /dev/null], [nc0.pid])
>> > +
>> > +AT_DATA([flows.txt], [dnl
>> > +table=0,priority=10  ip action=ct(table=1)
>> > +table=0,priority=1   action=drop
>> > +dnl dst FIP
>> > +table=1,priority=20  ip,ct_state=+trk+est,nw_dst=10.254.254.0/24 action=goto_table:10
>> > +table=1,priority=20  ip,ct_state=+trk+new,nw_dst=10.254.254.0/24 action=ct(commit,table=10)
>> > +dnl dst local
>> > +table=1,priority=10  ip,ct_state=+trk+est action=goto_table:20
>> > +table=1,priority=10  ip,ct_state=+trk+new action=ct(commit,table=20)
>> > +table=1,priority=1   ip,ct_state=+trk+inv action=drop
>> > +dnl
>> > +dnl FIP translation (dst FIP, src local) --> (dst local, src FIP)
>> > +table=10             ip,nw_dst=10.254.254.1 action=set_field:10.1.1.1->nw_dst,goto_table:11
>> > +table=10             ip,nw_dst=10.254.254.2 action=set_field:10.1.1.2->nw_dst,goto_table:11
>> > +table=11             ip,nw_src=10.1.1.1 action=set_field:10.254.254.1->nw_src,goto_table:12
>> > +table=11             ip,nw_src=10.1.1.2 action=set_field:10.254.254.2->nw_src,goto_table:12
>> > +dnl clear conntrack and do another lookup since we changed the tuple
>> > +table=12,priority=10 ip action=ct_clear,ct(table=13)
>> > +table=12,priority=1  action=drop
>> > +table=13             ip,ct_state=+trk+est action=goto_table:20
>> > +table=13             ip,ct_state=+trk+new action=ct(commit,table=20)
>> > +table=13             ip,ct_state=+trk+inv action=drop
>> > +dnl
>> > +dnl Output
>> > +table=20             ip,nw_src=10.1.1.1 action=set_field:f0:00:00:01:01:01->eth_src,goto_table:21
>> > +table=20             ip,nw_src=10.1.1.2 action=set_field:f0:00:00:01:01:02->eth_src,goto_table:21
>> > +table=20             ip,nw_src=10.254.254.0/24 action=set_field:f0:00:00:01:01:FE->eth_src,goto_table:21
>> > +table=21             ip,nw_dst=10.1.1.1 action=set_field:f0:00:00:01:01:01->eth_dst,output:ovs-p0
>> > +table=21             ip,nw_dst=10.1.1.2 action=set_field:f0:00:00:01:01:02->eth_dst,output:ovs-p1
>> > +])
>> > +
>> > +AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
>> > +
>> > +dnl non-FIP case
>> > +NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.1.1.1])
>> > +OVS_WAIT_UNTIL([[ovs-appctl dpctl/dump-conntrack | sed -e 's/port=[0-9]*/port=<cleared>/g' -e 's/id=[0-9]*/id=<cleared>/g' |
>> > +grep "tcp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),protoinfo=(state=TIME_WAIT)"
>> > +]])
>> > +
>> > +dnl Check that the full session ends as expected (i.e. TIME_WAIT). Otherwise it
>> > +dnl means the datapath didn't process the ct_clear action. Ending in SYN_RECV
>> > +dnl (OVS maps to ESTABLISHED) means the initial frame was committed, but not a
>> > +dnl second time after the FIP translation (because ct_clear didn't occur).
>> > +NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.254.254.1])
>> > +OVS_WAIT_UNTIL([[ovs-appctl dpctl/dump-conntrack | sed -e 's/port=[0-9]*/port=<cleared>/g' -e 's/id=[0-9]*/id=<cleared>/g' |
>> > +grep "tcp,orig=(src=10.254.254.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.1,dst=10.254.254.2,sport=<cleared>,dport=<cleared>),protoinfo=(state=TIME_WAIT)"
>> > +]])
>> > +
>> > +OVS_TRAFFIC_VSWITCHD_STOP
>> > +AT_CLEANUP
>> > +
>> >  AT_BANNER([802.1ad])
>> >
>> >  AT_SETUP([802.1ad - vlan_limit])
>> > --
>>
>> I'm using
>> ~/ovs# make check-system-userspace TESTSUITEFLAGS='83'
>> but fails due to the nc $NC_EOF_OPT.
>> I suggest we explicitly add network port number, ex: 1234 below
>>
>> --- a/tests/system-traffic.at
>> +++ b/tests/system-traffic.at
>> @@ -4016,7 +4016,7 @@ NS_CHECK_EXEC([at_ns1], [ip neigh add 10.1.1.254
>> lladdr f0:00:00:01:01:FE dev p1
>>  NS_CHECK_EXEC([at_ns0], [ip route add default nexthop via 10.1.1.254])
>>  NS_CHECK_EXEC([at_ns1], [ip route add default nexthop via 10.1.1.254])
>>
>> -NETNS_DAEMONIZE([at_ns0], [nc -l -k > /dev/null], [nc0.pid])
>> +NETNS_DAEMONIZE([at_ns0], [nc -l -k 1234 > /dev/null], [nc0.pid])
>>
>>  AT_DATA([flows.txt], [dnl
>>  table=0,priority=10  ip action=ct(table=1)
>> @@ -4052,7 +4052,7 @@ table=21             ip,nw_dst=10.1.1.2
>> action=set_field:f0:00:00:01:01:02->eth_
>>  AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
>>
>>  dnl non-FIP case
>> -NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.1.1.1])
>> +NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.1.1.1 1234])
>>  OVS_WAIT_UNTIL([[ovs-appctl dpctl/dump-conntrack | sed -e
>> 's/port=[0-9]*/port=<cleared>/g' -e 's/id=[0-9]*/id=<cleared>/g' |
>>  grep "tcp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),protoinfo=(state=TIME_WAIT)"
>>  ]])
>> @@ -4061,7 +4061,7 @@ dnl Check that the full session ends as expected
>> (i.e. TIME_WAIT). Otherwise it
>>  dnl means the datapath didn't process the ct_clear action. Ending in SYN_RECV
>>  dnl (OVS maps to ESTABLISHED) means the initial frame was committed, but not a
>>  dnl second time after the FIP translation (because ct_clear didn't occur).
>> -NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.254.254.1])
>> +NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.254.254.1 1234])
>
> Are you saying it works for you with the explicit port?
> If not, can you show the error?
>
> FWIW, nmap-ncat defaults to 31337. I guess other nc implementations may
> be different.

The error message:

 83: conntrack - floating IP                         FAILED
(system-traffic.at:4055)
+This is nc from the netcat-openbsd package. An alternative nc is available
+in the netcat-traditional package.
+usage: nc [-46bCDdhjklnrStUuvZz] [-I length] [-i interval] [-O length]
+         [-P proxy_username] [-p source_port] [-q seconds] [-s source]
+         [-T toskeyword] [-V rtable] [-w timeout] [-X proxy_protocol]
+         [-x proxy_address[:port]] [destination] [port]
./system-traffic.at:4055: exit code was 1, expected 0

on my system (ubuntu 1604), it is using the BSD
tests/atlocal.in:    NC_EOF_OPT="-q 1 -w 5"

Thanks
William
Eric Garver Oct. 25, 2017, 4:38 p.m. UTC | #4
On Tue, Oct 24, 2017 at 02:10:47PM -0700, William Tu wrote:
> On Tue, Oct 24, 2017 at 1:44 PM, Eric Garver <e@erig.me> wrote:
> > On Tue, Oct 24, 2017 at 12:46:46PM -0700, William Tu wrote:
> >> On Fri, Oct 20, 2017 at 11:23 AM, Eric Garver <e@erig.me> wrote:
> >> > This test cases uses floating IP (FIP) addresses for each endpoint. If
> >> > the destination is a FIP, the packet will undergo a transformation of
> >> > the form (dst=FIP, src=non-FIP) --> (dst=non-FIP, src=FIP) before
> >> > egress. Otherwise the packet is untouched.
> >> >
> >> > This exercises the ct_clear action in the datapath.
> >> >
> >> > Signed-off-by: Eric Garver <e@erig.me>
> >> > ---
> >> >  tests/system-traffic.at | 73 +++++++++++++++++++++++++++++++++++++++++++++++++
> >> >  1 file changed, 73 insertions(+)
> >> >
> >> > diff --git a/tests/system-traffic.at b/tests/system-traffic.at
> >> > index 522eaa615834..7cc1e1e21187 100644
> >> > --- a/tests/system-traffic.at
> >> > +++ b/tests/system-traffic.at
> >> > @@ -3996,6 +3996,79 @@ ovs-ofctl -O OpenFlow15 dump-group-stats br0
> >> >  OVS_TRAFFIC_VSWITCHD_STOP
> >> >  AT_CLEANUP
> >> >
> >> > +AT_SETUP([conntrack - floating IP])
> >> > +AT_SKIP_IF([test $HAVE_NC = no])
> >> > +CHECK_CONNTRACK()
> >> > +OVS_TRAFFIC_VSWITCHD_START()
> >> > +OVS_CHECK_CT_CLEAR()
> >> > +
> >> > +ADD_NAMESPACES(at_ns0, at_ns1)
> >> > +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24", "f0:00:00:01:01:01") dnl FIP 10.254.254.1
> >> > +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24", "f0:00:00:01:01:02") dnl FIP 10.254.254.2
> >> > +
> >> > +dnl Static ARPs
> >> > +NS_CHECK_EXEC([at_ns0], [ip neigh add 10.1.1.2 lladdr f0:00:00:01:01:02 dev p0])
> >> > +NS_CHECK_EXEC([at_ns1], [ip neigh add 10.1.1.1 lladdr f0:00:00:01:01:01 dev p1])
> >> > +
> >> > +dnl Static ARP and route entries for the FIP "gateway"
> >> > +NS_CHECK_EXEC([at_ns0], [ip neigh add 10.1.1.254 lladdr f0:00:00:01:01:FE dev p0])
> >> > +NS_CHECK_EXEC([at_ns1], [ip neigh add 10.1.1.254 lladdr f0:00:00:01:01:FE dev p1])
> >> > +NS_CHECK_EXEC([at_ns0], [ip route add default nexthop via 10.1.1.254])
> >> > +NS_CHECK_EXEC([at_ns1], [ip route add default nexthop via 10.1.1.254])
> >> > +
> >> > +NETNS_DAEMONIZE([at_ns0], [nc -l -k > /dev/null], [nc0.pid])
> >> > +
> >> > +AT_DATA([flows.txt], [dnl
> >> > +table=0,priority=10  ip action=ct(table=1)
> >> > +table=0,priority=1   action=drop
> >> > +dnl dst FIP
> >> > +table=1,priority=20  ip,ct_state=+trk+est,nw_dst=10.254.254.0/24 action=goto_table:10
> >> > +table=1,priority=20  ip,ct_state=+trk+new,nw_dst=10.254.254.0/24 action=ct(commit,table=10)
> >> > +dnl dst local
> >> > +table=1,priority=10  ip,ct_state=+trk+est action=goto_table:20
> >> > +table=1,priority=10  ip,ct_state=+trk+new action=ct(commit,table=20)
> >> > +table=1,priority=1   ip,ct_state=+trk+inv action=drop
> >> > +dnl
> >> > +dnl FIP translation (dst FIP, src local) --> (dst local, src FIP)
> >> > +table=10             ip,nw_dst=10.254.254.1 action=set_field:10.1.1.1->nw_dst,goto_table:11
> >> > +table=10             ip,nw_dst=10.254.254.2 action=set_field:10.1.1.2->nw_dst,goto_table:11
> >> > +table=11             ip,nw_src=10.1.1.1 action=set_field:10.254.254.1->nw_src,goto_table:12
> >> > +table=11             ip,nw_src=10.1.1.2 action=set_field:10.254.254.2->nw_src,goto_table:12
> >> > +dnl clear conntrack and do another lookup since we changed the tuple
> >> > +table=12,priority=10 ip action=ct_clear,ct(table=13)
> >> > +table=12,priority=1  action=drop
> >> > +table=13             ip,ct_state=+trk+est action=goto_table:20
> >> > +table=13             ip,ct_state=+trk+new action=ct(commit,table=20)
> >> > +table=13             ip,ct_state=+trk+inv action=drop
> >> > +dnl
> >> > +dnl Output
> >> > +table=20             ip,nw_src=10.1.1.1 action=set_field:f0:00:00:01:01:01->eth_src,goto_table:21
> >> > +table=20             ip,nw_src=10.1.1.2 action=set_field:f0:00:00:01:01:02->eth_src,goto_table:21
> >> > +table=20             ip,nw_src=10.254.254.0/24 action=set_field:f0:00:00:01:01:FE->eth_src,goto_table:21
> >> > +table=21             ip,nw_dst=10.1.1.1 action=set_field:f0:00:00:01:01:01->eth_dst,output:ovs-p0
> >> > +table=21             ip,nw_dst=10.1.1.2 action=set_field:f0:00:00:01:01:02->eth_dst,output:ovs-p1
> >> > +])
> >> > +
> >> > +AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
> >> > +
> >> > +dnl non-FIP case
> >> > +NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.1.1.1])
> >> > +OVS_WAIT_UNTIL([[ovs-appctl dpctl/dump-conntrack | sed -e 's/port=[0-9]*/port=<cleared>/g' -e 's/id=[0-9]*/id=<cleared>/g' |
> >> > +grep "tcp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),protoinfo=(state=TIME_WAIT)"
> >> > +]])
> >> > +
> >> > +dnl Check that the full session ends as expected (i.e. TIME_WAIT). Otherwise it
> >> > +dnl means the datapath didn't process the ct_clear action. Ending in SYN_RECV
> >> > +dnl (OVS maps to ESTABLISHED) means the initial frame was committed, but not a
> >> > +dnl second time after the FIP translation (because ct_clear didn't occur).
> >> > +NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.254.254.1])
> >> > +OVS_WAIT_UNTIL([[ovs-appctl dpctl/dump-conntrack | sed -e 's/port=[0-9]*/port=<cleared>/g' -e 's/id=[0-9]*/id=<cleared>/g' |
> >> > +grep "tcp,orig=(src=10.254.254.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.1,dst=10.254.254.2,sport=<cleared>,dport=<cleared>),protoinfo=(state=TIME_WAIT)"
> >> > +]])
> >> > +
> >> > +OVS_TRAFFIC_VSWITCHD_STOP
> >> > +AT_CLEANUP
> >> > +
> >> >  AT_BANNER([802.1ad])
> >> >
> >> >  AT_SETUP([802.1ad - vlan_limit])
> >> > --
> >>
> >> I'm using
> >> ~/ovs# make check-system-userspace TESTSUITEFLAGS='83'
> >> but fails due to the nc $NC_EOF_OPT.
> >> I suggest we explicitly add network port number, ex: 1234 below
> >>
> >> --- a/tests/system-traffic.at
> >> +++ b/tests/system-traffic.at
> >> @@ -4016,7 +4016,7 @@ NS_CHECK_EXEC([at_ns1], [ip neigh add 10.1.1.254
> >> lladdr f0:00:00:01:01:FE dev p1
> >>  NS_CHECK_EXEC([at_ns0], [ip route add default nexthop via 10.1.1.254])
> >>  NS_CHECK_EXEC([at_ns1], [ip route add default nexthop via 10.1.1.254])
> >>
> >> -NETNS_DAEMONIZE([at_ns0], [nc -l -k > /dev/null], [nc0.pid])
> >> +NETNS_DAEMONIZE([at_ns0], [nc -l -k 1234 > /dev/null], [nc0.pid])
> >>
> >>  AT_DATA([flows.txt], [dnl
> >>  table=0,priority=10  ip action=ct(table=1)
> >> @@ -4052,7 +4052,7 @@ table=21             ip,nw_dst=10.1.1.2
> >> action=set_field:f0:00:00:01:01:02->eth_
> >>  AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
> >>
> >>  dnl non-FIP case
> >> -NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.1.1.1])
> >> +NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.1.1.1 1234])
> >>  OVS_WAIT_UNTIL([[ovs-appctl dpctl/dump-conntrack | sed -e
> >> 's/port=[0-9]*/port=<cleared>/g' -e 's/id=[0-9]*/id=<cleared>/g' |
> >>  grep "tcp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),protoinfo=(state=TIME_WAIT)"
> >>  ]])
> >> @@ -4061,7 +4061,7 @@ dnl Check that the full session ends as expected
> >> (i.e. TIME_WAIT). Otherwise it
> >>  dnl means the datapath didn't process the ct_clear action. Ending in SYN_RECV
> >>  dnl (OVS maps to ESTABLISHED) means the initial frame was committed, but not a
> >>  dnl second time after the FIP translation (because ct_clear didn't occur).
> >> -NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.254.254.1])
> >> +NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.254.254.1 1234])
> >
> > Are you saying it works for you with the explicit port?
> > If not, can you show the error?
> >
> > FWIW, nmap-ncat defaults to 31337. I guess other nc implementations may
> > be different.
> 
> The error message:
> 
>  83: conntrack - floating IP                         FAILED
> (system-traffic.at:4055)
> +This is nc from the netcat-openbsd package. An alternative nc is available
> +in the netcat-traditional package.
> +usage: nc [-46bCDdhjklnrStUuvZz] [-I length] [-i interval] [-O length]
> +         [-P proxy_username] [-p source_port] [-q seconds] [-s source]
> +         [-T toskeyword] [-V rtable] [-w timeout] [-X proxy_protocol]
> +         [-x proxy_address[:port]] [destination] [port]
> ./system-traffic.at:4055: exit code was 1, expected 0
> 
> on my system (ubuntu 1604), it is using the BSD
> tests/atlocal.in:    NC_EOF_OPT="-q 1 -w 5"

There are other test cases that use NC_EOF_OPT, so I expect those are
failing for you as well. Can you verify?

Indeed, OpenBSD nc(1) man page does not list the -q option. Nor do the
other BSDs. I don't know why that option is being used. The first
evidence of it's usage seems to be 9ac0aadab9f9 ("conntrack: Add support
for NAT.").

I'll look into this and possibly avoid using NC_EOF_OPT entirely.
William Tu Oct. 26, 2017, 1:06 p.m. UTC | #5
Hi Eric,
Thanks for the reply.

>> >>  dnl means the datapath didn't process the ct_clear action. Ending in SYN_RECV
>> >>  dnl (OVS maps to ESTABLISHED) means the initial frame was committed, but not a
>> >>  dnl second time after the FIP translation (because ct_clear didn't occur).
>> >> -NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.254.254.1])
>> >> +NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.254.254.1 1234])
>> >
>> > Are you saying it works for you with the explicit port?
Yes, it works for me with explicit port (sorry I didn't answer this question)

>> > If not, can you show the error?
>> >
>> > FWIW, nmap-ncat defaults to 31337. I guess other nc implementations may
>> > be different.
>>
>> The error message:
>>
>>  83: conntrack - floating IP                         FAILED
>> (system-traffic.at:4055)
>> +This is nc from the netcat-openbsd package. An alternative nc is available
>> +in the netcat-traditional package.
>> +usage: nc [-46bCDdhjklnrStUuvZz] [-I length] [-i interval] [-O length]
>> +         [-P proxy_username] [-p source_port] [-q seconds] [-s source]
>> +         [-T toskeyword] [-V rtable] [-w timeout] [-X proxy_protocol]
>> +         [-x proxy_address[:port]] [destination] [port]
>> ./system-traffic.at:4055: exit code was 1, expected 0
>>
>> on my system (ubuntu 1604), it is using the BSD
>> tests/atlocal.in:    NC_EOF_OPT="-q 1 -w 5"
>
> There are other test cases that use NC_EOF_OPT, so I expect those are
> failing for you as well. Can you verify?
>
So my other test cases work OK since it has explicit port number.

> Indeed, OpenBSD nc(1) man page does not list the -q option. Nor do the
> other BSDs. I don't know why that option is being used. The first

Actually my BSD nc (netcat-traditional package) has -q options.

> evidence of it's usage seems to be 9ac0aadab9f9 ("conntrack: Add support
> for NAT.").

I think "-q 1" is mentioned at b54971f72ec ("system-traffic: use
appropriate nc options for installed version")

William
Eric Garver Oct. 26, 2017, 1:54 p.m. UTC | #6
On Thu, Oct 26, 2017 at 06:06:15AM -0700, William Tu wrote:
> Hi Eric,
> Thanks for the reply.
> 
> >> >>  dnl means the datapath didn't process the ct_clear action. Ending in SYN_RECV
> >> >>  dnl (OVS maps to ESTABLISHED) means the initial frame was committed, but not a
> >> >>  dnl second time after the FIP translation (because ct_clear didn't occur).
> >> >> -NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.254.254.1])
> >> >> +NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.254.254.1 1234])
> >> >
> >> > Are you saying it works for you with the explicit port?
> Yes, it works for me with explicit port (sorry I didn't answer this question)

Perfect.
I'll send a v2 with only this change.
diff mbox series

Patch

diff --git a/tests/system-traffic.at b/tests/system-traffic.at
index 522eaa615834..7cc1e1e21187 100644
--- a/tests/system-traffic.at
+++ b/tests/system-traffic.at
@@ -3996,6 +3996,79 @@  ovs-ofctl -O OpenFlow15 dump-group-stats br0
 OVS_TRAFFIC_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([conntrack - floating IP])
+AT_SKIP_IF([test $HAVE_NC = no])
+CHECK_CONNTRACK()
+OVS_TRAFFIC_VSWITCHD_START()
+OVS_CHECK_CT_CLEAR()
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24", "f0:00:00:01:01:01") dnl FIP 10.254.254.1
+ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24", "f0:00:00:01:01:02") dnl FIP 10.254.254.2
+
+dnl Static ARPs
+NS_CHECK_EXEC([at_ns0], [ip neigh add 10.1.1.2 lladdr f0:00:00:01:01:02 dev p0])
+NS_CHECK_EXEC([at_ns1], [ip neigh add 10.1.1.1 lladdr f0:00:00:01:01:01 dev p1])
+
+dnl Static ARP and route entries for the FIP "gateway"
+NS_CHECK_EXEC([at_ns0], [ip neigh add 10.1.1.254 lladdr f0:00:00:01:01:FE dev p0])
+NS_CHECK_EXEC([at_ns1], [ip neigh add 10.1.1.254 lladdr f0:00:00:01:01:FE dev p1])
+NS_CHECK_EXEC([at_ns0], [ip route add default nexthop via 10.1.1.254])
+NS_CHECK_EXEC([at_ns1], [ip route add default nexthop via 10.1.1.254])
+
+NETNS_DAEMONIZE([at_ns0], [nc -l -k > /dev/null], [nc0.pid])
+
+AT_DATA([flows.txt], [dnl
+table=0,priority=10  ip action=ct(table=1)
+table=0,priority=1   action=drop
+dnl dst FIP
+table=1,priority=20  ip,ct_state=+trk+est,nw_dst=10.254.254.0/24 action=goto_table:10
+table=1,priority=20  ip,ct_state=+trk+new,nw_dst=10.254.254.0/24 action=ct(commit,table=10)
+dnl dst local
+table=1,priority=10  ip,ct_state=+trk+est action=goto_table:20
+table=1,priority=10  ip,ct_state=+trk+new action=ct(commit,table=20)
+table=1,priority=1   ip,ct_state=+trk+inv action=drop
+dnl
+dnl FIP translation (dst FIP, src local) --> (dst local, src FIP)
+table=10             ip,nw_dst=10.254.254.1 action=set_field:10.1.1.1->nw_dst,goto_table:11
+table=10             ip,nw_dst=10.254.254.2 action=set_field:10.1.1.2->nw_dst,goto_table:11
+table=11             ip,nw_src=10.1.1.1 action=set_field:10.254.254.1->nw_src,goto_table:12
+table=11             ip,nw_src=10.1.1.2 action=set_field:10.254.254.2->nw_src,goto_table:12
+dnl clear conntrack and do another lookup since we changed the tuple
+table=12,priority=10 ip action=ct_clear,ct(table=13)
+table=12,priority=1  action=drop
+table=13             ip,ct_state=+trk+est action=goto_table:20
+table=13             ip,ct_state=+trk+new action=ct(commit,table=20)
+table=13             ip,ct_state=+trk+inv action=drop
+dnl
+dnl Output
+table=20             ip,nw_src=10.1.1.1 action=set_field:f0:00:00:01:01:01->eth_src,goto_table:21
+table=20             ip,nw_src=10.1.1.2 action=set_field:f0:00:00:01:01:02->eth_src,goto_table:21
+table=20             ip,nw_src=10.254.254.0/24 action=set_field:f0:00:00:01:01:FE->eth_src,goto_table:21
+table=21             ip,nw_dst=10.1.1.1 action=set_field:f0:00:00:01:01:01->eth_dst,output:ovs-p0
+table=21             ip,nw_dst=10.1.1.2 action=set_field:f0:00:00:01:01:02->eth_dst,output:ovs-p1
+])
+
+AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
+
+dnl non-FIP case
+NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.1.1.1])
+OVS_WAIT_UNTIL([[ovs-appctl dpctl/dump-conntrack | sed -e 's/port=[0-9]*/port=<cleared>/g' -e 's/id=[0-9]*/id=<cleared>/g' |
+grep "tcp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),protoinfo=(state=TIME_WAIT)"
+]])
+
+dnl Check that the full session ends as expected (i.e. TIME_WAIT). Otherwise it
+dnl means the datapath didn't process the ct_clear action. Ending in SYN_RECV
+dnl (OVS maps to ESTABLISHED) means the initial frame was committed, but not a
+dnl second time after the FIP translation (because ct_clear didn't occur).
+NS_CHECK_EXEC([at_ns1], [echo "foobar" |nc $NC_EOF_OPT 10.254.254.1])
+OVS_WAIT_UNTIL([[ovs-appctl dpctl/dump-conntrack | sed -e 's/port=[0-9]*/port=<cleared>/g' -e 's/id=[0-9]*/id=<cleared>/g' |
+grep "tcp,orig=(src=10.254.254.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.1,dst=10.254.254.2,sport=<cleared>,dport=<cleared>),protoinfo=(state=TIME_WAIT)"
+]])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_BANNER([802.1ad])
 
 AT_SETUP([802.1ad - vlan_limit])