On 2/23/22 19:58, Aaron Conole wrote:
> Ilya Maximets <[email protected]> writes:
> 
>> On 1/6/22 19:07, Aaron Conole wrote:
>>> This reverts commit c645550bb249 ("odp-util: Always report
>>> ODP_FIT_TOO_LITTLE for IGMP.")
>>>
>>> Always forcing a slow path action can result in some over-broad
>>> flows which swallow all traffic and force them to userspace, as reported
>>> in the thread at
>>> https://mail.openvswitch.org/pipermail/ovs-dev/2021-September/387706.html
>>> and at
>>> https://mail.openvswitch.org/pipermail/ovs-dev/2021-September/387689.html
>>>
>>> Revert the ODP_FIT_TOO_LITTLE return for IGMP specifically.
>>> Additionally, remove the userspace wc mask to prevent revalidator from
>>> cycling flows.
>>>
>>> Fixes: c645550bb249 ("odp-util: Always report ODP_FIT_TOO_LITTLE for IGMP.")
>>> Signed-off-by: Aaron Conole <[email protected]>
>>> Acked-by: Eelco Chaudron <[email protected]>
>>> ---
>>> v1->v2: Add unit test for coverage of mcast traffic when not doing snooping
>>> v2->v3: Add a unit test for the non-dummy datapaths as well to demonstrate 
>>> the
>>>         matching issue.
>>> v3->v4: Fix up the unit tests to be consistent when reporting dp flows.  
>>> Split
>>>         IGMP unit test into two different tests.  Use a multicast eth addr 
>>> for
>>>         the FLOOD under NORMAL action case.
>>>
>>>  lib/odp-util.c               |  5 ---
>>>  ofproto/ofproto-dpif-xlate.c |  1 -
>>>  tests/mcast-snooping.at      | 68 ++++++++++++++++++++++++++++++
>>>  tests/ofproto-macros.at      | 15 +++++++
>>>  tests/system-traffic.at      | 80 ++++++++++++++++++++++++++++++++++++
>>>  5 files changed, 163 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/lib/odp-util.c b/lib/odp-util.c
>>> index fbdfc7ad83..0f21ffe639 100644
>>> --- a/lib/odp-util.c
>>> +++ b/lib/odp-util.c
>>> @@ -7132,11 +7132,6 @@ parse_l2_5_onward(const struct nlattr 
>>> *attrs[OVS_KEY_ATTR_MAX + 1],
>>>                  }
>>>              }
>>>          }
>>> -    } else if (src_flow->nw_proto == IPPROTO_IGMP
>>> -               && src_flow->dl_type == htons(ETH_TYPE_IP)) {
>>> -        /* OVS userspace parses the IGMP type, code, and group, but its
>>> -         * datapaths do not, so there is always missing information. */
>>> -        return ODP_FIT_TOO_LITTLE;
>>>      }
>>>      if (is_mask && expected_bit != OVS_KEY_ATTR_UNSPEC) {
>>>          if ((flow->tp_src || flow->tp_dst) && flow->nw_proto != 0xff) {
>>> diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
>>> index cafcd014ad..29d26cf9ac 100644
>>> --- a/ofproto/ofproto-dpif-xlate.c
>>> +++ b/ofproto/ofproto-dpif-xlate.c
>>> @@ -3048,7 +3048,6 @@ xlate_normal(struct xlate_ctx *ctx)
>>>               */
>>>              ctx->xout->slow |= SLOW_ACTION;
>>>  
>>> -            memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src);
>>>              if (mcast_snooping_is_membership(flow->tp_src) ||
>>>                  mcast_snooping_is_query(flow->tp_src)) {
>>>                  if (ctx->xin->allow_side_effects && ctx->xin->packet) {
>>> diff --git a/tests/mcast-snooping.at b/tests/mcast-snooping.at
>>> index 757cf7186e..e24f293a0c 100644
>>> --- a/tests/mcast-snooping.at
>>> +++ b/tests/mcast-snooping.at
>>> @@ -216,3 +216,70 @@ AT_CHECK([ovs-appctl mdb/show br0], [0], [dnl
>>>  ])
>>>  
>>>  AT_CLEANUP
>>> +
>>> +
>>> +AT_SETUP([mcast - igmp flood for non-snoop enabled])
>>> +OVS_VSWITCHD_START([])
>>> +
>>> +AT_CHECK([
>>> +    ovs-vsctl set bridge br0 \
>>> +    datapath_type=dummy], [0])
>>> +
>>> +add_of_ports br0 1 2
>>> +
>>> +AT_CHECK([ovs-ofctl add-flow br0 action=normal])
>>> +
>>> +ovs-appctl time/stop
>>> +
>>> +dnl Basic scenario - needs to flood for IGMP followed by unicast ICMP
>>> +dnl in reverse direction
>>> +AT_CHECK([ovs-appctl netdev-dummy/receive p1 \
>>> +    
>>> '0101000c29a0aa55aa550001080046c00028000040000102d3494565eb4ae0000016940400002200f9020000000104000000e00000fb000000000000'])
>>> +AT_CHECK([ovs-appctl netdev-dummy/receive p2 \
>>> +    
>>> 'aa55aa5500010101000c29a008004500001c00010000400164dc0a0101010a0101020800f7ffffffffff'])
>>> +
>>> +
>>> +AT_CHECK([ovs-appctl dpctl/dump-flows | grep -e .*ipv4 | sort | dnl
>>> +          strip_stats | strip_used | strip_recirc | dnl
>>> +          sed -e 's/,packet_type(ns=[[0-9]]*,id=[[0-9]]*),/,/'],
>>> +                     [0], [dnl
>>> +recirc_id(<recirc>),in_port(1),eth(src=aa:55:aa:55:00:01,dst=01:01:00:0c:29:a0),eth_type(0x0800),ipv4(frag=no),
>>>  packets:0, bytes:0, used:never, actions:100,2
>>> +recirc_id(<recirc>),in_port(2),eth(src=01:01:00:0c:29:a0,dst=aa:55:aa:55:00:01),eth_type(0x0800),ipv4(frag=no),
>>>  packets:0, bytes:0, used:never, actions:1
>>> +])
>>> +
>>> +ovs-appctl time/warp 100000
>>> +
>>> +dnl Next we should clear the flows and install a complex case
>>> +AT_CHECK([ovs-ofctl del-flows br0])
>>> +
>>> +AT_DATA([flows.txt], [dnl
>>> +table=0, arp actions=NORMAL
>>> +table=0, ip,in_port=1 actions=ct(table=1,zone=64000)
>>> +table=0, in_port=2 actions=output:1
>>> +table=1, ip,ct_state=+trk+inv actions=drop
>>> +table=1  ip,in_port=1,icmp,ct_state=+trk+new actions=output:2
>>> +table=1, in_port=1,ip,ct_state=+trk+new 
>>> actions=controller(userdata=00.de.ad.be.ef.ca.fe.01)
>>> +table=1, in_port=1,ip,ct_state=+trk+est actions=output:2
>>> +])
>>> +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
>>> +
>>> +ovs-appctl time/warp 100000
>>> +
>>> +dnl Send the IGMP, followed by a unicast ICMP - ensure we won't black hole
>>> +AT_CHECK([ovs-appctl netdev-dummy/receive p1 \
>>> +    
>>> '0101000c29a0aa55aa550001080046c00028000040000102d3494565eb4ae0000016940400002200f9020000000104000000e00000fb000000000000'])
>>> +AT_CHECK([ovs-appctl netdev-dummy/receive p1 \
>>> +    
>>> 'aa55aa550001aa55aa55000208004500001c00010000400164dc0a0101010a0101020800f7ffffffffff'])
>>> +
>>> +
>>> +AT_CHECK([ovs-appctl dpctl/dump-flows | grep -e .*ipv4 | sort | dnl
>>> +          strip_stats | strip_used | strip_recirc | dnl
>>> +          sed 's/pid=[[0-9]]*,//
>>> +               s/,packet_type(ns=[[0-9]]*,id=[[0-9]]*),/,/'],
>>> +                     [0], [dnl
>>> +ct_state(+new-inv+trk),recirc_id(<recirc>),in_port(1),eth_type(0x0800),ipv4(proto=1,frag=no),
>>>  packets:0, bytes:0, used:never, actions:2
>>> +ct_state(+new-inv+trk),recirc_id(<recirc>),in_port(1),eth_type(0x0800),ipv4(proto=2,frag=no),
>>>  packets:0, bytes:0, used:never, 
>>> actions:userspace(controller(reason=1,dont_send=0,continuation=0,recirc_id=<recirc>,rule_cookie=0,controller_id=0,max_len=65535))
>>> +recirc_id(<recirc>),in_port(1),eth_type(0x0800),ipv4(frag=no), packets:0, 
>>> bytes:0, used:0.0s, actions:ct(zone=64000),recirc(<recirc>)
>>> +])
>>
>> I tried to backport the patch to earlier branches, but this test fails
>> on 2.14 and 2.13 (works on 2.15+) with the following result:
>>
>> --- -        2022-01-26 21:33:15.713282778 +0000
>> +++
>> /home/runner/work/ovs/ovs/openvswitch-2.13.7/_build/sub/tests/testsuite.dir/at-groups/2302/stdout
>> 2022-01-26 21:33:15.708679313 +0000
>> @@ -1,4 +1,4 @@
>> +ct_state(+inv+trk),recirc_id(<recirc>),in_port(1),eth_type(0x0800),ipv4(frag=no),
>> packets:0, bytes:0, used:never, actions:drop
>>  
>> ct_state(+new-inv+trk),recirc_id(<recirc>),in_port(1),eth_type(0x0800),ipv4(proto=1,frag=no),
>> packets:0, bytes:0, used:never, actions:2
>> -ct_state(+new-inv+trk),recirc_id(<recirc>),in_port(1),eth_type(0x0800),ipv4(proto=2,frag=no),
>> packets:0, bytes:0, used:never,
>> actions:userspace(controller(reason=1,dont_send=0,continuation=0,recirc_id=<recirc>,rule_cookie=0,controller_id=0,max_len=65535))
>>  recirc_id(<recirc>),in_port(1),eth_type(0x0800),ipv4(frag=no),
>> packets:0, bytes:0, used:0.0s, actions:ct(zone=64000),recirc(<recirc>)
>>
>> Packets seems to be marked +inv by conntrack.  Is it some kind
>> of conntrack issue that got fixed in 2.15 that we should backport?
>> Can we modify the test somehow to make it work on 2.13 ?
> 
> I'll look into it.  Thanks.
> 
>>> +
>>> +AT_CLEANUP
>>> diff --git a/tests/ofproto-macros.at b/tests/ofproto-macros.at
>>> index 736d9809cb..f906b5c3b5 100644
>>> --- a/tests/ofproto-macros.at
>>> +++ b/tests/ofproto-macros.at
>>> @@ -134,6 +134,21 @@ strip_ufid () {
>>>      sed 's/mega_ufid:[[-0-9a-f]]* //
>>>      s/ufid:[[-0-9a-f]]* //'
>>>  }
>>> +
>>> +# Strips packets: and bytes: from output
>>> +strip_stats () {
>>> +    sed 's/packets:[[0-9]]*/packets:0/
>>> +    s/bytes:[[0-9]]*/bytes:0/'
>>> +}
>>> +
>>> +# Changes all 'recirc(...)' and 'recirc=...' to say 'recirc(<recirc_id>)' 
>>> and
>>> +# 'recirc=<recirc_id>' respectively.  This should make output easier to
>>> +# compare.
>>> +strip_recirc() {
>>> +   sed 's/recirc_id([[x0-9]]*)/recirc_id(<recirc>)/
>>> +        s/recirc_id=[[x0-9]]*/recirc_id=<recirc>/
>>> +        s/recirc([[x0-9]]*)/recirc(<recirc>)/'
>>> +}
>>>  m4_divert_pop([PREPARE_TESTS])
>>>  
>>>  m4_define([TESTABLE_LOG], [-vPATTERN:ANY:'%c|%p|%m'])
>>> diff --git a/tests/system-traffic.at b/tests/system-traffic.at
>>> index d79753a99a..5d9449fada 100644
>>> --- a/tests/system-traffic.at
>>> +++ b/tests/system-traffic.at
>>> @@ -6287,6 +6287,86 @@ AT_CHECK([ovs-ofctl dump-flows br0 | grep table=2, | 
>>> OFPROTO_CLEAR_DURATION_IDLE
>>>  OVS_TRAFFIC_VSWITCHD_STOP
>>>  AT_CLEANUP
>>>  
>>> +AT_BANNER([IGMP])
>>> +
>>> +AT_SETUP([IGMP - flood under normal action])
>>> +
>>> +OVS_TRAFFIC_VSWITCHD_START()
>>> +ADD_NAMESPACES(at_ns0, at_ns1)
>>> +
>>> +ADD_VETH(p1, at_ns0, br0, "10.1.1.1/24", "f0:00:00:01:01:01")
>>> +ADD_VETH(p2, at_ns1, br0, "10.1.1.2/24", "f0:00:00:01:01:02")
>>> +
>>> +AT_CHECK([ovs-ofctl add-flow br0 "actions=NORMAL"])
>>> +
>>> +NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p1 01 00 5e 01 01 03 
>>> dnl
>>> +f0 00 00 01 01 01 08 00 46 c0 00 28 00 00 40 00 01 02 d3 49 45 65 eb 4a e0 
>>> dnl
>>> +00 00 16 94 04 00 00 22 00 f9 02 00 00 00 01 04 00 00 00 e0 00 00 fb 00 00 
>>> dnl
>>> +00 00 00 00 > /dev/null])
>>> +
>>> +AT_CHECK([ovs-appctl dpif/show | grep -v missed:], [0], [dnl
>>> +  br0:
>>> +    br0 65534/1: (internal)
>>
>> This line is failing the system-userspace testsuite, because userspace
>> datapath reports 'tap' instead of 'internal'.  Suggesting a following
>> change:
>>
>> diff --git a/tests/system-traffic.at b/tests/system-traffic.at
>> index 1ba28f7ee..7711f14b0 100644
>> --- a/tests/system-traffic.at
>> +++ b/tests/system-traffic.at
>> @@ -6681,18 +6681,11 @@ f0 00 00 01 01 01 08 00 46 c0 00 28 00 00 40 00 01 
>> 02 d3 49 45 65 eb 4a e0 dnl
>>  00 00 16 94 04 00 00 22 00 f9 02 00 00 00 01 04 00 00 00 e0 00 00 fb 00 00 
>> dnl
>>  00 00 00 00 > /dev/null])
>>  
>> -AT_CHECK([ovs-appctl dpif/show | grep -v missed:], [0], [dnl
>> -  br0:
>> -    br0 65534/1: (internal)
>> -    ovs-p1 1/2: (system)
>> -    ovs-p2 2/3: (system)
>> -])
>> -
>> -AT_CHECK([ovs-appctl dpctl/dump-flows | grep -e .*ipv4 | sort | dnl
>> +AT_CHECK([ovs-appctl dpctl/dump-flows --names | grep -e .*ipv4 | sort | dnl
>>            strip_stats | strip_used | strip_recirc | dnl
>>            sed 's/,packet_type(ns=[[0-9]]*,id=[[0-9]]*),/,/'],
>>                       [0], [dnl
>> -recirc_id(<recirc>),in_port(2),eth(src=f0:00:00:01:01:01,dst=01:00:5e:01:01:03),eth_type(0x0800),ipv4(frag=no),
>>  packets:0, bytes:0, used:never, actions:1,3
>> +recirc_id(<recirc>),in_port(ovs-p1),eth(src=f0:00:00:01:01:01,dst=01:00:5e:01:01:03),eth_type(0x0800),ipv4(frag=no),
>>  packets:0, bytes:0, used:never, actions:br0,ovs-p2
>>  ])
>>  OVS_TRAFFIC_VSWITCHD_STOP
>>  AT_CLEANUP
>> ---
>>
>> What do you think?
> 
> ACK - I'll pull that in.
> 
>>
>>> +    ovs-p1 1/2: (system)
>>> +    ovs-p2 2/3: (system)
>>> +])
>>> +
>>> +AT_CHECK([ovs-appctl dpctl/dump-flows | grep -e .*ipv4 | sort | dnl
>>> +          strip_stats | strip_used | strip_recirc | dnl
>>> +          sed 's/,packet_type(ns=[[0-9]]*,id=[[0-9]]*),/,/'],
>>> +                     [0], [dnl
>>> +recirc_id(<recirc>),in_port(2),eth(src=f0:00:00:01:01:01,dst=01:00:5e:01:01:03),eth_type(0x0800),ipv4(frag=no),
>>> packets:0, bytes:0, used:never, actions:1,3
>>> +])
>>> +OVS_TRAFFIC_VSWITCHD_STOP
>>> +AT_CLEANUP
>>> +
>>> +AT_SETUP([IGMP - forward with ICMP])
>>> +
>>> +OVS_TRAFFIC_VSWITCHD_START()
>>> +ADD_NAMESPACES(at_ns0, at_ns1)
>>> +
>>> +ADD_VETH(p1, at_ns0, br0, "10.1.1.1/24", "f0:00:00:01:01:01")
>>> +ADD_VETH(p2, at_ns1, br0, "10.1.1.2/24", "f0:00:00:01:01:02")
>>> +
>>> +AT_DATA([flows.txt], [dnl
>>> +table=0, arp actions=NORMAL
>>> +table=0, ip,in_port=1 actions=ct(table=1,zone=64000)
>>> +table=0, in_port=2 actions=output:1
>>> +table=1, ip,ct_state=+trk+inv actions=drop
>>> +table=1  ip,in_port=1,icmp,ct_state=+trk+new actions=output:2
>>> +table=1, in_port=1,ip,ct_state=+trk+new 
>>> actions=controller(userdata=00.de.ad.be.ef.ca.fe.01)
>>> +table=1, in_port=1,ip,ct_state=+trk+est actions=output:2
>>> +])
>>> +AT_CHECK([ovs-ofctl del-flows br0])
>>> +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
>>> +
>>> +dnl Send the IGMP, followed by a unicast ICMP - ensure we won't black hole
>>> +
>>> +NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p1 f0 00 00 01 01 02 
>>> dnl
>>> +f0 00 00 01 01 01 08 00 46 c0 00 28 00 00 40 00 01 02 d3 49 45 65 eb 4a e0 
>>> dnl
>>> +00 00 16 94 04 00 00 22 00 f9 02 00 00 00 01 04 00 00 00 e0 00 00 fb 00 00 
>>> dnl
>>> +00 00 00 00 > /dev/null])
>>> +
>>> +NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p1 f0 00 00 01 01 02 
>>> dnl
>>> +f0 00 00 01 01 01 08 00 45 00 00 1c 00 01 00 00 40 01 64 dc 0a 01 01 01 0a 
>>> dnl
>>> +01 01 02 08 00 f7 ff ff ff ff ff > /dev/null])
>>> +
>>> +sleep 1
>>> +
>>> +AT_CHECK([ovs-ofctl dump-flows br0 | grep -v NXST | dnl
>>> +          strip_duration | grep -v arp | grep -v n_packets=0 | dnl
>>> +          grep -v 'in_port=2 actions=output:1' | dnl
>>> +          sed 's/n_bytes=[[0-9]]*/n_bytes=0/
>>> +               s/idle_age=[[0-9]]*/idle_age=0/
>>> +               s/n_packets=[[1-9]]/n_packets=0/' | sort], [0], [dnl
>>> + cookie=0x0, table=0, n_packets=0, n_bytes=0, idle_age=0,
>>> ip,in_port=1 actions=ct(table=1,zone=64000)
>>> + cookie=0x0, table=1, n_packets=0, n_bytes=0, idle_age=0,
>>> ct_state=+new+trk,icmp,in_port=1 actions=output:2
>>> + cookie=0x0, table=1, n_packets=0, n_bytes=0, idle_age=0,
>>> ct_state=+new+trk,ip,in_port=1
>>> actions=controller(userdata=00.de.ad.be.ef.ca.fe.01)
>>> +])
>>
>> These are OpenFlow rules.  Shouldn't we dump datapath flows, or
>> am I missing something?
> 
> IIRC, we use the openflow rules because they are wildly different
> datapath rules between the two, so we rely on these rules being hit.
> Additionally, in the kernel DP case, if ipv6 is enabled then some ND
> will occur and that will tamper with n_packets/n_bytes counters (which
> is why I clear it before doing the comparison).
> 
> I will look at the datapath flows again, but I believe the datapath
> action set is different because of the way controller() is implemented
> between the two (in the userspace DP, it can be a direct call, but in
> the kerneldp it needs to be a userspace call first).
> 
> So I guess I will look at this, but expect to keep it as-is.

OK.  I guess, the main check here is n_packets=[[1-9]].  Is that correct?
Maybe just a comment would be enough in that case.  It's not clear what
exactly we're testing here otherwise.

Best regards, Ilya Maximets.
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to