diff mbox series

[ovs-dev,v2] conntrack: Add a test for IPv4 UDP zero checksum

Message ID 20210317192819.3589092-1-aconole@redhat.com
State New
Headers show
Series [ovs-dev,v2] conntrack: Add a test for IPv4 UDP zero checksum | expand

Commit Message

Aaron Conole March 17, 2021, 7:28 p.m. UTC
Recently, during some conntrack testing a bug was uncovered in a DPDK
PMD, which doesn't support an IPv4 packet with a zero checksum value.
In order to show that the connection tracking code in userspace
supports IPv4 UDP with a zero checksum, add a test case to enforce
this behavior.

Reported-at: http://mails.dpdk.org/archives/dev/2021-January/198528.html
Reported-by: Paolo Valerio <pvalerio@redhat.com>
Signed-off-by: Aaron Conole <aconole@redhat.com>
---
Previous version:
https://mail.openvswitch.org/pipermail/ovs-dev/2021-February/380266.html

v1->v2: - Addressed most of the comments by Flavio & William Tu.
        - Added the 0xffff checksum case
        - Added a bad checksum case
        - For the single instance of "sleep 1," this needs to be retained
          due to the negative test case (we have no WAIT_UNTIL to rely on)
          but there are other instances of sleep 1 throughout the suite,
          so I guess it should be okay.

 tests/system-traffic.at | 64 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

Comments

Paolo Valerio March 22, 2021, 7:51 p.m. UTC | #1
Hi Aaron,

Aaron Conole <aconole@redhat.com> writes:

> Recently, during some conntrack testing a bug was uncovered in a DPDK
> PMD, which doesn't support an IPv4 packet with a zero checksum value.
> In order to show that the connection tracking code in userspace
> supports IPv4 UDP with a zero checksum, add a test case to enforce
> this behavior.
>
> Reported-at: http://mails.dpdk.org/archives/dev/2021-January/198528.html
> Reported-by: Paolo Valerio <pvalerio@redhat.com>
> Signed-off-by: Aaron Conole <aconole@redhat.com>
> ---
> Previous version:
> https://mail.openvswitch.org/pipermail/ovs-dev/2021-February/380266.html
>
> v1->v2: - Addressed most of the comments by Flavio & William Tu.
>         - Added the 0xffff checksum case
>         - Added a bad checksum case
>         - For the single instance of "sleep 1," this needs to be retained
>           due to the negative test case (we have no WAIT_UNTIL to rely on)
>           but there are other instances of sleep 1 throughout the suite,
>           so I guess it should be okay.
>
>  tests/system-traffic.at | 64 +++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 64 insertions(+)
>
> diff --git a/tests/system-traffic.at b/tests/system-traffic.at
> index fb5b9a36d2..5e51c24760 100644
> --- a/tests/system-traffic.at
> +++ b/tests/system-traffic.at
> @@ -5927,6 +5927,69 @@ ovs-appctl dpif/dump-flows br0
>  OVS_TRAFFIC_VSWITCHD_STOP
>  AT_CLEANUP
>  
> +
> +AT_SETUP([conntrack - IPv4 UDP zero checksum])

Don't know if this second new line up here was intentional (mixed style
in the file).
TBH, I have no strong preference about it, I pointed out just in case.

> +dnl This tracks sending zero checksum packets for udp over ipv4
> +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")
> +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24", "f0:00:00:01:01:02")
> +dnl setup ct flows
> +AT_DATA([flows.txt], [dnl
> +table=0,priority=10  ip,udp,ct_state=-trk action=ct(zone=1,table=1)
> +table=0,priority=0   action=drop
> +table=1,priority=10  ct_state=-est+trk+new,ip,ct_zone=1,in_port=1 action=ct(commit,table=2)
> +table=1,priority=10  ct_state=+est-new+trk,ct_zone=1,in_port=1 action=resubmit(,2)
> +table=1,priority=0   action=drop
> +table=2,priority=10  ct_state=+trk+new,in_port=1 action=2
> +table=2,priority=10  ct_state=+trk+est action=2
> +])
> +
> +AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
> +
> +# sending udp pkt with 0000 checksum
> +NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f0 00 00 01 01 02 f0 00 00 01 01 01 08 00 45 00 00 28 00 01 00 00 40 11 64 c0 0a 01 01 01 0a 01 01 02 04 d2 04 d2 00 14 00 00 aa aa aa aa aa aa aa aa aa aa aa aa > /dev/null])
> +
> +OVS_WAIT_UNTIL([ovs-appctl dpctl/dump-conntrack | grep "udp"])
> +
> +dnl ensure CT picked up the packet
> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1)], [0], [dnl
> +udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>)
> +])
> +
> +dnl clear CT tuples
> +AT_CHECK([ovs-appctl dpctl/flush-conntrack])
> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "udp"], [1])
> +
> +dnl send UDP with ffff checksum
> +NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f0 00 00 01 01 02 f0 00 00 01 01 01 08 00 45 00 00 40 00 01 00 00 40 11 64 a8 0a 01 01 01 0a 01 01 02 04 d2 04 d2 00 2c ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 df ed > /dev/null])
> +OVS_WAIT_UNTIL([ovs-appctl dpctl/dump-conntrack | grep "udp"])
> +
> +dnl ensure CT picked up the packet
> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1)], [0], [dnl
> +udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>)
> +])
> +
> +dnl clear CT tuples
> +AT_CHECK([ovs-appctl dpctl/flush-conntrack])
> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "udp"], [1])
> +
> +# sending udp pkt with bad checksum
> +NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f0 00 00 01 01 02 f0 00 00 01 01 01 08 00 45 00 00 28 00 01 00 00 40 11 64 c0 0a 01 01 01 0a 01 01 02 04 d2 04 d2 00 14 11 11 aa aa aa aa aa aa aa aa aa aa aa aa > /dev/null])
> +
> +dnl There isn't anything else to do here but call a sleep... we can't use a WAIT_UNTIL
> +dnl because there isn't a condition to check against - we just expect the packet to
> +dnl be dropped.
> +sleep 1
> +
> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "udp"], [1])
> +

what if we restrict a little the pattern here?

In case of kernel dp, considering the sleep, there's a chance an UDP
entry (e.g. a DNS query) gets created between the flush and the dump
with grep returning 0.


> +OVS_TRAFFIC_VSWITCHD_STOP
> +AT_CLEANUP
> +
>  AT_SETUP([conntrack - Multiple ICMP traverse])
>  dnl This tracks sending ICMP packets via conntrack multiple times for the
>  dnl same packet
> -- 
> 2.25.4
Aaron Conole March 23, 2021, 1:37 p.m. UTC | #2
Paolo Valerio <pvalerio@redhat.com> writes:

> Hi Aaron,
>
> Aaron Conole <aconole@redhat.com> writes:
>
>> Recently, during some conntrack testing a bug was uncovered in a DPDK
>> PMD, which doesn't support an IPv4 packet with a zero checksum value.
>> In order to show that the connection tracking code in userspace
>> supports IPv4 UDP with a zero checksum, add a test case to enforce
>> this behavior.
>>
>> Reported-at: http://mails.dpdk.org/archives/dev/2021-January/198528.html
>> Reported-by: Paolo Valerio <pvalerio@redhat.com>
>> Signed-off-by: Aaron Conole <aconole@redhat.com>
>> ---
>> Previous version:
>> https://mail.openvswitch.org/pipermail/ovs-dev/2021-February/380266.html
>>
>> v1->v2: - Addressed most of the comments by Flavio & William Tu.
>>         - Added the 0xffff checksum case
>>         - Added a bad checksum case
>>         - For the single instance of "sleep 1," this needs to be retained
>>           due to the negative test case (we have no WAIT_UNTIL to rely on)
>>           but there are other instances of sleep 1 throughout the suite,
>>           so I guess it should be okay.
>>
>>  tests/system-traffic.at | 64 +++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 64 insertions(+)
>>
>> diff --git a/tests/system-traffic.at b/tests/system-traffic.at
>> index fb5b9a36d2..5e51c24760 100644
>> --- a/tests/system-traffic.at
>> +++ b/tests/system-traffic.at
>> @@ -5927,6 +5927,69 @@ ovs-appctl dpif/dump-flows br0
>>  OVS_TRAFFIC_VSWITCHD_STOP
>>  AT_CLEANUP
>>  
>> +
>> +AT_SETUP([conntrack - IPv4 UDP zero checksum])
>
> Don't know if this second new line up here was intentional (mixed style
> in the file).
> TBH, I have no strong preference about it, I pointed out just in case.

Ugh... every time I rebase some stray new line makes it in.  It's like I
have a 4 year old in my lap...

>> +dnl This tracks sending zero checksum packets for udp over ipv4
>> +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")
>> +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24", "f0:00:00:01:01:02")
>> +dnl setup ct flows
>> +AT_DATA([flows.txt], [dnl
>> +table=0,priority=10  ip,udp,ct_state=-trk action=ct(zone=1,table=1)
>> +table=0,priority=0   action=drop
>> +table=1,priority=10  ct_state=-est+trk+new,ip,ct_zone=1,in_port=1 action=ct(commit,table=2)
>> +table=1,priority=10  ct_state=+est-new+trk,ct_zone=1,in_port=1 action=resubmit(,2)
>> +table=1,priority=0   action=drop
>> +table=2,priority=10  ct_state=+trk+new,in_port=1 action=2
>> +table=2,priority=10  ct_state=+trk+est action=2
>> +])
>> +
>> +AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
>> +
>> +# sending udp pkt with 0000 checksum
>> +NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f0 00 00 01
>> 01 02 f0 00 00 01 01 01 08 00 45 00 00 28 00 01 00 00 40 11 64 c0 0a
>> 01 01 01 0a 01 01 02 04 d2 04 d2 00 14 00 00 aa aa aa aa aa aa aa aa
>> aa aa aa aa > /dev/null])
>> +
>> +OVS_WAIT_UNTIL([ovs-appctl dpctl/dump-conntrack | grep "udp"])
>> +
>> +dnl ensure CT picked up the packet
>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1)], [0], [dnl
>> +udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>)
>> +])
>> +
>> +dnl clear CT tuples
>> +AT_CHECK([ovs-appctl dpctl/flush-conntrack])
>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "udp"], [1])
>> +
>> +dnl send UDP with ffff checksum
>> +NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f0 00 00 01
>> 01 02 f0 00 00 01 01 01 08 00 45 00 00 40 00 01 00 00 40 11 64 a8 0a
>> 01 01 01 0a 01 01 02 04 d2 04 d2 00 2c ff ff 00 00 00 00 00 00 00 00
>> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>> 00 00 00 df ed > /dev/null])
>> +OVS_WAIT_UNTIL([ovs-appctl dpctl/dump-conntrack | grep "udp"])
>> +
>> +dnl ensure CT picked up the packet
>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1)], [0], [dnl
>> +udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>)
>> +])
>> +
>> +dnl clear CT tuples
>> +AT_CHECK([ovs-appctl dpctl/flush-conntrack])
>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "udp"], [1])
>> +
>> +# sending udp pkt with bad checksum
>> +NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f0 00 00 01
>> 01 02 f0 00 00 01 01 01 08 00 45 00 00 28 00 01 00 00 40 11 64 c0 0a
>> 01 01 01 0a 01 01 02 04 d2 04 d2 00 14 11 11 aa aa aa aa aa aa aa aa
>> aa aa aa aa > /dev/null])
>> +
>> +dnl There isn't anything else to do here but call a sleep... we can't use a WAIT_UNTIL
>> +dnl because there isn't a condition to check against - we just expect the packet to
>> +dnl be dropped.
>> +sleep 1
>> +
>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "udp"], [1])
>> +
>
> what if we restrict a little the pattern here?

Sure, but I'm not sure how best to restrict it.  Something like:

  grep "udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=1234,dport=1234)"

I can do that - it makes the most sense to me.

> In case of kernel dp, considering the sleep, there's a chance an UDP
> entry (e.g. a DNS query) gets created between the flush and the dump
> with grep returning 0.

ACK

>
>> +OVS_TRAFFIC_VSWITCHD_STOP
>> +AT_CLEANUP
>> +
>>  AT_SETUP([conntrack - Multiple ICMP traverse])
>>  dnl This tracks sending ICMP packets via conntrack multiple times for the
>>  dnl same packet
>> -- 
>> 2.25.4
Paolo Valerio March 24, 2021, 10:47 a.m. UTC | #3
Aaron Conole <aconole@redhat.com> writes:

> Paolo Valerio <pvalerio@redhat.com> writes:
>
>> Hi Aaron,
>>
>> Aaron Conole <aconole@redhat.com> writes:
>>
>>> Recently, during some conntrack testing a bug was uncovered in a DPDK
>>> PMD, which doesn't support an IPv4 packet with a zero checksum value.
>>> In order to show that the connection tracking code in userspace
>>> supports IPv4 UDP with a zero checksum, add a test case to enforce
>>> this behavior.
>>>
>>> Reported-at: http://mails.dpdk.org/archives/dev/2021-January/198528.html
>>> Reported-by: Paolo Valerio <pvalerio@redhat.com>
>>> Signed-off-by: Aaron Conole <aconole@redhat.com>
>>> ---
>>> Previous version:
>>> https://mail.openvswitch.org/pipermail/ovs-dev/2021-February/380266.html
>>>
>>> v1->v2: - Addressed most of the comments by Flavio & William Tu.
>>>         - Added the 0xffff checksum case
>>>         - Added a bad checksum case
>>>         - For the single instance of "sleep 1," this needs to be retained
>>>           due to the negative test case (we have no WAIT_UNTIL to rely on)
>>>           but there are other instances of sleep 1 throughout the suite,
>>>           so I guess it should be okay.
>>>
>>>  tests/system-traffic.at | 64 +++++++++++++++++++++++++++++++++++++++++
>>>  1 file changed, 64 insertions(+)
>>>
>>> diff --git a/tests/system-traffic.at b/tests/system-traffic.at
>>> index fb5b9a36d2..5e51c24760 100644
>>> --- a/tests/system-traffic.at
>>> +++ b/tests/system-traffic.at
>>> @@ -5927,6 +5927,69 @@ ovs-appctl dpif/dump-flows br0
>>>  OVS_TRAFFIC_VSWITCHD_STOP
>>>  AT_CLEANUP
>>>  
>>> +
>>> +AT_SETUP([conntrack - IPv4 UDP zero checksum])
>>
>> Don't know if this second new line up here was intentional (mixed style
>> in the file).
>> TBH, I have no strong preference about it, I pointed out just in case.
>
> Ugh... every time I rebase some stray new line makes it in.  It's like I
> have a 4 year old in my lap...
>
>>> +dnl This tracks sending zero checksum packets for udp over ipv4
>>> +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")
>>> +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24", "f0:00:00:01:01:02")
>>> +dnl setup ct flows
>>> +AT_DATA([flows.txt], [dnl
>>> +table=0,priority=10  ip,udp,ct_state=-trk action=ct(zone=1,table=1)
>>> +table=0,priority=0   action=drop
>>> +table=1,priority=10  ct_state=-est+trk+new,ip,ct_zone=1,in_port=1 action=ct(commit,table=2)
>>> +table=1,priority=10  ct_state=+est-new+trk,ct_zone=1,in_port=1 action=resubmit(,2)
>>> +table=1,priority=0   action=drop
>>> +table=2,priority=10  ct_state=+trk+new,in_port=1 action=2
>>> +table=2,priority=10  ct_state=+trk+est action=2
>>> +])
>>> +
>>> +AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
>>> +
>>> +# sending udp pkt with 0000 checksum
>>> +NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f0 00 00 01
>>> 01 02 f0 00 00 01 01 01 08 00 45 00 00 28 00 01 00 00 40 11 64 c0 0a
>>> 01 01 01 0a 01 01 02 04 d2 04 d2 00 14 00 00 aa aa aa aa aa aa aa aa
>>> aa aa aa aa > /dev/null])
>>> +
>>> +OVS_WAIT_UNTIL([ovs-appctl dpctl/dump-conntrack | grep "udp"])
>>> +
>>> +dnl ensure CT picked up the packet
>>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1)], [0], [dnl
>>> +udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>)
>>> +])
>>> +
>>> +dnl clear CT tuples
>>> +AT_CHECK([ovs-appctl dpctl/flush-conntrack])
>>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "udp"], [1])
>>> +
>>> +dnl send UDP with ffff checksum
>>> +NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f0 00 00 01
>>> 01 02 f0 00 00 01 01 01 08 00 45 00 00 40 00 01 00 00 40 11 64 a8 0a
>>> 01 01 01 0a 01 01 02 04 d2 04 d2 00 2c ff ff 00 00 00 00 00 00 00 00
>>> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>>> 00 00 00 df ed > /dev/null])
>>> +OVS_WAIT_UNTIL([ovs-appctl dpctl/dump-conntrack | grep "udp"])
>>> +
>>> +dnl ensure CT picked up the packet
>>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1)], [0], [dnl
>>> +udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>)
>>> +])
>>> +
>>> +dnl clear CT tuples
>>> +AT_CHECK([ovs-appctl dpctl/flush-conntrack])
>>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "udp"], [1])
>>> +
>>> +# sending udp pkt with bad checksum
>>> +NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f0 00 00 01
>>> 01 02 f0 00 00 01 01 01 08 00 45 00 00 28 00 01 00 00 40 11 64 c0 0a
>>> 01 01 01 0a 01 01 02 04 d2 04 d2 00 14 11 11 aa aa aa aa aa aa aa aa
>>> aa aa aa aa > /dev/null])
>>> +
>>> +dnl There isn't anything else to do here but call a sleep... we can't use a WAIT_UNTIL
>>> +dnl because there isn't a condition to check against - we just expect the packet to
>>> +dnl be dropped.
>>> +sleep 1
>>> +
>>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "udp"], [1])
>>> +
>>
>> what if we restrict a little the pattern here?
>
> Sure, but I'm not sure how best to restrict it.  Something like:
>
>   grep "udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=1234,dport=1234)"
>
> I can do that - it makes the most sense to me.
>

I was going to suggest the src or dst ip, that's even better.

Do you think it's a good idea to do something similar in every
place we have a command sequence like:

AT_CHECK([ovs-appctl dpctl/flush-conntrack])
AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "udp"], [1])

>> In case of kernel dp, considering the sleep, there's a chance an UDP
>> entry (e.g. a DNS query) gets created between the flush and the dump
>> with grep returning 0.
>
> ACK
>
>>
>>> +OVS_TRAFFIC_VSWITCHD_STOP
>>> +AT_CLEANUP
>>> +
>>>  AT_SETUP([conntrack - Multiple ICMP traverse])
>>>  dnl This tracks sending ICMP packets via conntrack multiple times for the
>>>  dnl same packet
>>> -- 
>>> 2.25.4
diff mbox series

Patch

diff --git a/tests/system-traffic.at b/tests/system-traffic.at
index fb5b9a36d2..5e51c24760 100644
--- a/tests/system-traffic.at
+++ b/tests/system-traffic.at
@@ -5927,6 +5927,69 @@  ovs-appctl dpif/dump-flows br0
 OVS_TRAFFIC_VSWITCHD_STOP
 AT_CLEANUP
 
+
+AT_SETUP([conntrack - IPv4 UDP zero checksum])
+dnl This tracks sending zero checksum packets for udp over ipv4
+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")
+ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24", "f0:00:00:01:01:02")
+dnl setup ct flows
+AT_DATA([flows.txt], [dnl
+table=0,priority=10  ip,udp,ct_state=-trk action=ct(zone=1,table=1)
+table=0,priority=0   action=drop
+table=1,priority=10  ct_state=-est+trk+new,ip,ct_zone=1,in_port=1 action=ct(commit,table=2)
+table=1,priority=10  ct_state=+est-new+trk,ct_zone=1,in_port=1 action=resubmit(,2)
+table=1,priority=0   action=drop
+table=2,priority=10  ct_state=+trk+new,in_port=1 action=2
+table=2,priority=10  ct_state=+trk+est action=2
+])
+
+AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
+
+# sending udp pkt with 0000 checksum
+NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f0 00 00 01 01 02 f0 00 00 01 01 01 08 00 45 00 00 28 00 01 00 00 40 11 64 c0 0a 01 01 01 0a 01 01 02 04 d2 04 d2 00 14 00 00 aa aa aa aa aa aa aa aa aa aa aa aa > /dev/null])
+
+OVS_WAIT_UNTIL([ovs-appctl dpctl/dump-conntrack | grep "udp"])
+
+dnl ensure CT picked up the packet
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1)], [0], [dnl
+udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>)
+])
+
+dnl clear CT tuples
+AT_CHECK([ovs-appctl dpctl/flush-conntrack])
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "udp"], [1])
+
+dnl send UDP with ffff checksum
+NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f0 00 00 01 01 02 f0 00 00 01 01 01 08 00 45 00 00 40 00 01 00 00 40 11 64 a8 0a 01 01 01 0a 01 01 02 04 d2 04 d2 00 2c ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 df ed > /dev/null])
+OVS_WAIT_UNTIL([ovs-appctl dpctl/dump-conntrack | grep "udp"])
+
+dnl ensure CT picked up the packet
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1)], [0], [dnl
+udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>)
+])
+
+dnl clear CT tuples
+AT_CHECK([ovs-appctl dpctl/flush-conntrack])
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "udp"], [1])
+
+# sending udp pkt with bad checksum
+NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f0 00 00 01 01 02 f0 00 00 01 01 01 08 00 45 00 00 28 00 01 00 00 40 11 64 c0 0a 01 01 01 0a 01 01 02 04 d2 04 d2 00 14 11 11 aa aa aa aa aa aa aa aa aa aa aa aa > /dev/null])
+
+dnl There isn't anything else to do here but call a sleep... we can't use a WAIT_UNTIL
+dnl because there isn't a condition to check against - we just expect the packet to
+dnl be dropped.
+sleep 1
+
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "udp"], [1])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_SETUP([conntrack - Multiple ICMP traverse])
 dnl This tracks sending ICMP packets via conntrack multiple times for the
 dnl same packet