On 2/17/26 9:48 AM, Lorenzo Bianconi wrote:
> On Feb 17, Ilya Maximets wrote:
>> On 2/13/26 6:03 PM, Lorenzo Bianconi wrote:
>>> Do not forward non-{ip,arp} L2 multicast packets to routers ports in
>>> order to not exceed OVS recirculation limit if the logical switch is
>>> connected to multiple OVN routers since these packets will be discarded
>>> in the router pipeline.
>>>
>>> Reported-at: https://issues.redhat.com/browse/FDP-1908
>>> Signed-off-by: Lorenzo Bianconi <[email protected]>
>>> ---
>>> Changes in v3:
>>> - Convert system-test in unit-test
>>> - Use 71 priority for new added flow
>>> ---
>>> northd/northd.c | 26 +++++++++++-----
>>> northd/ovn-northd.8.xml | 8 ++++-
>>> tests/ovn-northd.at | 68 ++++++++++++++++++++++++++++++-----------
>>> tests/ovn.at | 49 +++++++++++++++++++++++++++++
>>> 4 files changed, 125 insertions(+), 26 deletions(-)
>>>
>>> diff --git a/northd/northd.c b/northd/northd.c
>>> index 4ecdd9c2d..10b328527 100644
>>> --- a/northd/northd.c
>>> +++ b/northd/northd.c
>>> @@ -10767,16 +10767,26 @@ build_lswitch_destination_lookup_bmcast(struct
>>> ovn_datapath *od,
>>> lflow_ref);
>>> }
>>>
>>> - if (!smap_get_bool(&od->nbs->other_config,
>>> - "broadcast-arps-to-all-routers", true)) {
>>> - ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 72,
>>> - "eth.mcast && (arp.op == 1 || nd_ns)",
>>> - "outport = \""MC_FLOOD_L2"\"; output;",
>>> - lflow_ref);
>>> - }
>>> + ds_clear(actions);
>>> + bool broadcast_arps_to_all_routers = smap_get_bool(
>>> + &od->nbs->other_config,
>>> + "broadcast-arps-to-all-routers",
>>> + true);
>>> + ds_put_format(actions, "outport = \"%s\"; output;",
>>> + broadcast_arps_to_all_routers ? MC_FLOOD : MC_FLOOD_L2);
>>> + ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 72,
>>> + "eth.mcast && (arp.op == 1 || nd_ns)",
>>> + ds_cstr(actions), lflow_ref);
>>
>> This code looks correct to me, though I'd still keep the original
>> prio 72 flow block and make the new prio 71 flow wider to catch
>> any arp, not only the replies. But it's just a style preference
>> at this point. Should be fine either way.
>
> maybe I am missing something here, but are we going to break
> "broadcast-arps-to-all-routers" option if we add a prio 71 flow that match
> even
> arp requests and set outport to MC_FLOOD?
For the broadcast-arps-to-all-routers=false with the current v3 we have:
priority=70 , match=(eth.mcast), action=(outport = "_MC_flood_l2"; output;)
priority=71 , match=(eth.mcast && (arp.op == 2 || ip)), action=(outport =
"_MC_flood"; output;)
priority=72 , match=(eth.mcast && (arp.op == 1 || nd_ns)), action=(outport =
"_MC_flood_l2"; output;)
Here all the ARP requests and NS traffic is only flooded to switch ports
and ARP replies and the rest of ND, together with IP traffic goes to all
ports including routers.
For the broadcast-arps-to-all-routers=true:
priority=70 , match=(eth.mcast), action=(outport = "_MC_flood_l2"; output;)
priority=71 , match=(eth.mcast && (arp.op == 2 || ip)), action=(outport =
"_MC_flood"; output;)
priority=72 , match=(eth.mcast && (arp.op == 1 || nd_ns)), action=(outport =
"_MC_flood"; output;)
Here all the ARP requests and NS are flooded to all ports including routers,
as all the IP traffic and ARP/ND replies as well.
--
What I suggested for broadcast-arps-to-all-routers=false:
priority=70 , match=(eth.mcast), action=(outport = "_MC_flood_l2"; output;)
priority=71 , match=(eth.mcast && (arp || ip)), action=(outport =
"_MC_flood"; output;)
priority=72 , match=(eth.mcast && (arp.op == 1 || nd_ns)), action=(outport =
"_MC_flood_l2"; output;)
Here all the ARP requests and NS traffic is only flooded to switch ports
and ARP replies and the rest of ND, together with IP traffic goes to all
ports including routers. It doesn't matter that we do not match on the
specific 'op' number, as the flow is lower priority. 'arp' is a superset
of 'arp.op == 1', the same as 'ip' is a superset of 'nd_ns'. The bahavior
is the same between this and the current v3.
For broadcast-arps-to-all-routers=true:
priority=70 , match=(eth.mcast), action=(outport = "_MC_flood_l2"; output;)
priority=71 , match=(eth.mcast && (arp || ip)), action=(outport =
"_MC_flood"; output;)
Here all the ARP and NS are flooded to all ports including routers, as all the
IP traffic as well. The same behavior as in this v3, but with one less flow.
We can do that because the prio 71 flow is less specific.
WDYT?
I'm not sure if we need a v4 for this tough. As I said, v3 is correct, just
a slightly different way to express the same logic. I'll leave it up to you
to decide. Or maybe Dumitru has a preference?
>
>>
>> There is a couple small nits for the test below. With these
>> addressed (can probbaly be addressed on commit) and with or without
>> the flow format change:
>
> I am fine to send a v4, just let me know.
>
> Regards,
> Lorenzo
>
>>
>> Acked-by: Ilya Maximets <[email protected]>
>>
>> Would be great if we can also have this backported as OVS logs are
>> filled with dropped packets on resubmit limit on many real world
>> setups, and these messages often distract from real issues that
>> people are dealing with.
>>
>>>
>>> - ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 70, "eth.mcast",
>>> + ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 71,
>>> + "eth.mcast && (arp.op == 2 || ip)",
>>> "outport = \""MC_FLOOD"\"; output;", lflow_ref);
>>> +
>>> + /* non-{arp,ip} L2 multicast traffic should not be sent to router
>>> + * ports since these packets will be discarded in the router pipeline.
>>> + */
>>> + ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 70, "eth.mcast",
>>> + "outport = \""MC_FLOOD_L2"\"; output;", lflow_ref);
>>> }
>>>
>>> /* Ingress table 30: destination lookup, multicast handling (priority 80).
>>> */
>>> diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
>>> index a17bc5f22..8ba68a4d0 100644
>>> --- a/northd/ovn-northd.8.xml
>>> +++ b/northd/ovn-northd.8.xml
>>> @@ -2420,9 +2420,15 @@ output;
>>> <code>other_config:broadcast-arps-to-all-routers=true</code>.
>>> </li>
>>>
>>> + <li>
>>> + A priority-71 flow that outputs all ARP replies or IP packets with
>>> an
>>> + Ethernet broadcast or multicast <code>eth.dst</code> to the <code>
>>> + MC_FLOOD</code> multicast group.
>>> + </li>
>>> +
>>> <li>
>>> A priority-70 flow that outputs all packets with an Ethernet
>>> broadcast
>>> - or multicast <code>eth.dst</code> to the <code>MC_FLOOD</code>
>>> + or multicast <code>eth.dst</code> to the <code>MC_FLOOD_L2</code>
>>> multicast group.
>>> </li>
>>>
>>> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
>>> index 36b3db6f6..8a37561a5 100644
>>> --- a/tests/ovn-northd.at
>>> +++ b/tests/ovn-northd.at
>>> @@ -5743,7 +5743,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows |
>>> ovn_strip_lflows], [0], [dnl
>>> table=??(ls_in_l2_lkup ), priority=110 , match=(eth.dst ==
>>> $svc_monitor_mac && (tcp || icmp || icmp6)),
>>> action=(handle_svc_check(inport);)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:01:02), action=(outport = "vm1"; output;)
>>> - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood_l2"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=71 , match=(eth.mcast &&
>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=72 , match=(eth.mcast &&
>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>> table=??(ls_in_l2_lkup ), priority=75 , match=(eth.src ==
>>> {00:00:00:00:01:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 ||
>>> rarp.op == 3 || nd_ns)), action=(outport = "_MC_flood_l2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> arp.op == 1 && arp.tpa == 192.168.1.1), action=(clone {outport = "ls1-ro1";
>>> output; }; outport = "_MC_flood_l2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> nd_ns && nd.target == fe80::200:ff:fe00:101), action=(clone {outport =
>>> "ls1-ro1"; output; }; outport = "_MC_flood_l2"; output;)
>>> @@ -5756,7 +5758,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows |
>>> ovn_strip_lflows], [0], [dnl
>>> table=??(ls_in_l2_lkup ), priority=110 , match=(eth.dst ==
>>> $svc_monitor_mac && (tcp || icmp || icmp6)),
>>> action=(handle_svc_check(inport);)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:02:01), action=(outport = "ls2-ro2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:02:02), action=(outport = "vm2"; output;)
>>> - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood_l2"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=71 , match=(eth.mcast &&
>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=72 , match=(eth.mcast &&
>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>> table=??(ls_in_l2_lkup ), priority=75 , match=(eth.src ==
>>> {00:00:00:00:02:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 ||
>>> rarp.op == 3 || nd_ns)), action=(outport = "_MC_flood_l2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> arp.op == 1 && arp.tpa == 192.168.2.1), action=(clone {outport = "ls2-ro2";
>>> output; }; outport = "_MC_flood_l2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> nd_ns && nd.target == fe80::200:ff:fe00:201), action=(clone {outport =
>>> "ls2-ro2"; output; }; outport = "_MC_flood_l2"; output;)
>>> @@ -5777,7 +5781,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows |
>>> ovn_strip_lflows], [0], [dnl
>>> table=??(ls_in_l2_lkup ), priority=110 , match=(eth.dst ==
>>> $svc_monitor_mac && (tcp || icmp || icmp6)),
>>> action=(handle_svc_check(inport);)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:01:02), action=(outport = "vm1"; output;)
>>> - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood_l2"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=71 , match=(eth.mcast &&
>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=72 , match=(eth.mcast &&
>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>> table=??(ls_in_l2_lkup ), priority=75 , match=(eth.src ==
>>> {00:00:00:00:01:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 ||
>>> rarp.op == 3 || nd_ns)), action=(outport = "_MC_flood_l2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> arp.op == 1 && arp.tpa == 10.0.0.100), action=(clone {outport = "ls1-ro1";
>>> output; }; outport = "_MC_flood_l2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> arp.op == 1 && arp.tpa == 10.0.0.200), action=(clone {outport = "ls1-ro1";
>>> output; }; outport = "_MC_flood_l2"; output;)
>>> @@ -5792,7 +5798,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows |
>>> ovn_strip_lflows], [0], [dnl
>>> table=??(ls_in_l2_lkup ), priority=110 , match=(eth.dst ==
>>> $svc_monitor_mac && (tcp || icmp || icmp6)),
>>> action=(handle_svc_check(inport);)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:02:01), action=(outport = "ls2-ro2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:02:02), action=(outport = "vm2"; output;)
>>> - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood_l2"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=71 , match=(eth.mcast &&
>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=72 , match=(eth.mcast &&
>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>> table=??(ls_in_l2_lkup ), priority=75 , match=(eth.src ==
>>> {00:00:00:00:02:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 ||
>>> rarp.op == 3 || nd_ns)), action=(outport = "_MC_flood_l2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> arp.op == 1 && arp.tpa == 192.168.2.1), action=(clone {outport = "ls2-ro2";
>>> output; }; outport = "_MC_flood_l2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> arp.op == 1 && arp.tpa == 20.0.0.100), action=(clone {outport = "ls2-ro2";
>>> output; }; outport = "_MC_flood_l2"; output;)
>>> @@ -5815,7 +5823,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows |
>>> ovn_strip_lflows], [0], [dnl
>>> table=??(ls_in_l2_lkup ), priority=110 , match=(eth.dst ==
>>> $svc_monitor_mac && (tcp || icmp || icmp6)),
>>> action=(handle_svc_check(inport);)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:01:02), action=(outport = "vm1"; output;)
>>> - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood_l2"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=71 , match=(eth.mcast &&
>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=72 , match=(eth.mcast &&
>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>> table=??(ls_in_l2_lkup ), priority=75 , match=(eth.src ==
>>> {00:00:00:00:01:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 ||
>>> rarp.op == 3 || nd_ns)), action=(outport = "_MC_flood_l2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> arp.op == 1 && arp.tpa == 10.0.0.100), action=(clone {outport = "ls1-ro1";
>>> output; }; outport = "_MC_flood_l2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> arp.op == 1 && arp.tpa == 10.0.0.200), action=(clone {outport = "ls1-ro1";
>>> output; }; outport = "_MC_flood_l2"; output;)
>>> @@ -5832,7 +5842,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows |
>>> ovn_strip_lflows], [0], [dnl
>>> table=??(ls_in_l2_lkup ), priority=110 , match=(eth.dst ==
>>> $svc_monitor_mac && (tcp || icmp || icmp6)),
>>> action=(handle_svc_check(inport);)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:02:01), action=(outport = "ls2-ro2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:02:02), action=(outport = "vm2"; output;)
>>> - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood_l2"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=71 , match=(eth.mcast &&
>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=72 , match=(eth.mcast &&
>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>> table=??(ls_in_l2_lkup ), priority=75 , match=(eth.src ==
>>> {00:00:00:00:02:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 ||
>>> rarp.op == 3 || nd_ns)), action=(outport = "_MC_flood_l2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> arp.op == 1 && arp.tpa == 192.168.2.1), action=(clone {outport = "ls2-ro2";
>>> output; }; outport = "_MC_flood_l2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> arp.op == 1 && arp.tpa == 20.0.0.100), action=(clone {outport = "ls2-ro2";
>>> output; }; outport = "_MC_flood_l2"; output;)
>>> @@ -5854,7 +5866,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows |
>>> ovn_strip_lflows], [0], [dnl
>>> table=??(ls_in_l2_lkup ), priority=110 , match=(eth.dst ==
>>> $svc_monitor_mac && (tcp || icmp || icmp6)),
>>> action=(handle_svc_check(inport);)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:01:02), action=(outport = "vm1"; output;)
>>> - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood_l2"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=71 , match=(eth.mcast &&
>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=72 , match=(eth.mcast &&
>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>> table=??(ls_in_l2_lkup ), priority=75 , match=(eth.src ==
>>> {00:00:00:00:01:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 ||
>>> rarp.op == 3 || nd_ns)), action=(outport = "_MC_flood_l2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> arp.op == 1 && arp.tpa == 10.0.0.100), action=(clone {outport = "ls1-ro1";
>>> output; }; outport = "_MC_flood_l2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> arp.op == 1 && arp.tpa == 10.0.0.200), action=(clone {outport = "ls1-ro1";
>>> output; }; outport = "_MC_flood_l2"; output;)
>>> @@ -5875,7 +5889,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows |
>>> ovn_strip_lflows], [0], [dnl
>>> table=??(ls_in_l2_lkup ), priority=110 , match=(eth.dst ==
>>> $svc_monitor_mac && (tcp || icmp || icmp6)),
>>> action=(handle_svc_check(inport);)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:01:02), action=(outport = "vm1"; output;)
>>> - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood_l2"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=71 , match=(eth.mcast &&
>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=72 , match=(eth.mcast &&
>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>> table=??(ls_in_l2_lkup ), priority=75 , match=(eth.src ==
>>> {00:00:00:00:01:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 ||
>>> rarp.op == 3 || nd_ns)), action=(outport = "_MC_flood_l2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> arp.op == 1 && arp.tpa == 10.0.0.100), action=(clone {outport = "ls1-ro1";
>>> output; }; outport = "_MC_flood_l2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> arp.op == 1 && arp.tpa == 10.0.0.200), action=(clone {outport = "ls1-ro1";
>>> output; }; outport = "_MC_flood_l2"; output;)
>>> @@ -5903,7 +5919,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows |
>>> ovn_strip_lflows], [0], [dnl
>>> table=??(ls_in_l2_lkup ), priority=110 , match=(eth.dst ==
>>> $svc_monitor_mac && (tcp || icmp || icmp6)),
>>> action=(handle_svc_check(inport);)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:01:01 && is_chassis_resident("cr-ro1-ls1")), action=(outport =
>>> "ls1-ro1"; output;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:01:02), action=(outport = "vm1"; output;)
>>> - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood_l2"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=71 , match=(eth.mcast &&
>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=72 , match=(eth.mcast &&
>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>> table=??(ls_in_l2_lkup ), priority=75 , match=(eth.src ==
>>> {00:00:00:00:01:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 ||
>>> rarp.op == 3 || nd_ns)), action=(outport = "_MC_flood_l2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> arp.op == 1 && arp.tpa == 10.0.0.100), action=(clone {outport = "ls1-ro1";
>>> output; }; outport = "_MC_flood_l2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> arp.op == 1 && arp.tpa == 10.0.0.200), action=(clone {outport = "ls1-ro1";
>>> output; }; outport = "_MC_flood_l2"; output;)
>>> @@ -9537,7 +9555,9 @@ ovn_strip_lflows ], [0], [dnl
>>> table=??(ls_in_l2_lkup ), priority=0 , match=(1),
>>> action=(outport = get_fdb(eth.dst); next;)
>>> table=??(ls_in_l2_lkup ), priority=100 , match=(reg8[[23]] == 1),
>>> action=(output;)
>>> table=??(ls_in_l2_lkup ), priority=110 , match=(eth.dst ==
>>> $svc_monitor_mac && (tcp || icmp || icmp6)),
>>> action=(handle_svc_check(inport);)
>>> - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood_l2"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=71 , match=(eth.mcast &&
>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=72 , match=(eth.mcast &&
>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>> table=??(ls_in_l2_unknown ), priority=0 , match=(1),
>>> action=(output;)
>>> table=??(ls_in_l2_unknown ), priority=50 , match=(outport ==
>>> "none"), action=(drop;)
>>> table=??(ls_out_apply_port_sec), priority=0 , match=(1),
>>> action=(output;)
>>> @@ -9572,7 +9592,9 @@ ovn_strip_lflows ], [0], [dnl
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:00:02), action=(outport = "sw0p2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:01:01), action=(outport = "sw0p1"; output;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:02:02), action=(outport = "sw0p2"; output;)
>>> - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood_l2"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=71 , match=(eth.mcast &&
>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=72 , match=(eth.mcast &&
>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>> table=??(ls_in_l2_unknown ), priority=0 , match=(1),
>>> action=(output;)
>>> table=??(ls_in_l2_unknown ), priority=50 , match=(outport ==
>>> "none"), action=(drop;)
>>> table=??(ls_out_apply_port_sec), priority=0 , match=(1),
>>> action=(output;)
>>> @@ -9606,7 +9628,9 @@ ovn_strip_lflows ], [0], [dnl
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:00:02), action=(outport = "sw0p2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:01:01), action=(outport = "sw0p1"; output;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:02:02), action=(outport = "sw0p2"; output;)
>>> - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood_l2"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=71 , match=(eth.mcast &&
>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=72 , match=(eth.mcast &&
>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>> table=??(ls_in_l2_unknown ), priority=0 , match=(1),
>>> action=(output;)
>>> table=??(ls_in_l2_unknown ), priority=50 , match=(outport ==
>>> "none"), action=(drop;)
>>> table=??(ls_out_apply_port_sec), priority=0 , match=(1),
>>> action=(output;)
>>> @@ -9641,7 +9665,9 @@ ovn_strip_lflows ], [0], [dnl
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:00:02), action=(outport = "sw0p2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:01:01), action=(drop;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:02:02), action=(outport = "sw0p2"; output;)
>>> - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood_l2"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=71 , match=(eth.mcast &&
>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=72 , match=(eth.mcast &&
>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>> table=??(ls_in_l2_unknown ), priority=0 , match=(1),
>>> action=(output;)
>>> table=??(ls_in_l2_unknown ), priority=50 , match=(outport ==
>>> "none"), action=(drop;)
>>> table=??(ls_in_l2_unknown ), priority=50 , match=(outport ==
>>> "sw0p1"), action=(drop;)
>>> @@ -9676,7 +9702,9 @@ ovn_strip_lflows ], [0], [dnl
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:00:02), action=(outport = "sw0p2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:01:01), action=(drop;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:02:02), action=(outport = "sw0p2"; output;)
>>> - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood_l2"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=71 , match=(eth.mcast &&
>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=72 , match=(eth.mcast &&
>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>> table=??(ls_in_l2_unknown ), priority=0 , match=(1),
>>> action=(output;)
>>> table=??(ls_in_l2_unknown ), priority=50 , match=(outport ==
>>> "none"), action=(drop;)
>>> table=??(ls_in_l2_unknown ), priority=50 , match=(outport ==
>>> "sw0p1"), action=(drop;)
>>> @@ -9715,7 +9743,9 @@ ovn_strip_lflows ], [0], [dnl
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:00:02), action=(outport = "sw0p2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:01:01), action=(outport = "sw0p1"; output;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:02:02), action=(outport = "sw0p2"; output;)
>>> - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood_l2"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=71 , match=(eth.mcast &&
>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=72 , match=(eth.mcast &&
>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>> table=??(ls_in_l2_unknown ), priority=0 , match=(1),
>>> action=(output;)
>>> table=??(ls_in_l2_unknown ), priority=50 , match=(outport ==
>>> "none"), action=(drop;)
>>> table=??(ls_out_apply_port_sec), priority=0 , match=(1),
>>> action=(output;)
>>> @@ -14054,7 +14084,9 @@ AT_CHECK([grep "ls_in_l2_lkup" publicflows |
>>> ovn_strip_lflows], [0], [dnl
>>> table=??(ls_in_l2_lkup ), priority=110 , match=(eth.dst ==
>>> $svc_monitor_mac && (tcp || icmp || icmp6)),
>>> action=(handle_svc_check(inport);)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:ff:02 && is_chassis_resident("cr-lr0-public")), action=(outport
>>> = "public-lr0"; output;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 30:54:00:00:00:03 && is_chassis_resident("sw0-port1")), action=(outport =
>>> "public-lr0"; output;)
>>> - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood_l2"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=71 , match=(eth.mcast &&
>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=72 , match=(eth.mcast &&
>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>> table=??(ls_in_l2_lkup ), priority=75 , match=(eth.src ==
>>> {00:00:00:00:ff:02, 30:54:00:00:00:03} && eth.dst == ff:ff:ff:ff:ff:ff &&
>>> (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport = "_MC_flood_l2";
>>> output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> arp.op == 1 && arp.tpa == 172.168.0.10), action=(clone {outport =
>>> "public-lr0"; output; }; outport = "_MC_flood_l2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> arp.op == 1 && arp.tpa == 172.168.0.100), action=(clone {outport =
>>> "public-lr0"; output; }; outport = "_MC_flood_l2"; output;)
>>> @@ -14231,7 +14263,9 @@ AT_CHECK([grep "ls_in_l2_lkup" publicflows |
>>> ovn_strip_lflows], [0], [dnl
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:ff:02 && !is_chassis_resident("cr-public-lr0")),
>>> action=(outport = "cr-public-lr0"; output;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 00:00:00:00:ff:02 && is_chassis_resident("cr-public-lr0")), action=(outport
>>> = "public-lr0"; output;)
>>> table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst ==
>>> 30:54:00:00:00:03 && is_chassis_resident("sw0-port1")), action=(outport =
>>> "public-lr0"; output;)
>>> - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast),
>>> action=(outport = "_MC_flood_l2"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=71 , match=(eth.mcast &&
>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>> + table=??(ls_in_l2_lkup ), priority=72 , match=(eth.mcast &&
>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>> table=??(ls_in_l2_lkup ), priority=75 , match=(eth.src ==
>>> {00:00:00:00:ff:02, 30:54:00:00:00:03} && eth.dst == ff:ff:ff:ff:ff:ff &&
>>> (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport = "_MC_flood_l2";
>>> output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> arp.op == 1 && arp.tpa == 172.168.0.10 &&
>>> !is_chassis_resident("cr-public-lr0")), action=(clone {outport =
>>> "cr-public-lr0"; output; }; outport = "_MC_flood_l2"; output;)
>>> table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 &&
>>> arp.op == 1 && arp.tpa == 172.168.0.10 &&
>>> is_chassis_resident("cr-public-lr0")), action=(clone {outport =
>>> "public-lr0"; output; }; outport = "_MC_flood_l2"; output;)
>>> diff --git a/tests/ovn.at b/tests/ovn.at
>>> index c6abd7b8b..2139c9fb1 100644
>>> --- a/tests/ovn.at
>>> +++ b/tests/ovn.at
>>> @@ -45652,3 +45652,52 @@ check_zone_flush ovn-controller-2.log 3
>>> OVN_CLEANUP([hv1])
>>> AT_CLEANUP
>>> ])
>>> +
>>> +OVN_FOR_EACH_NORTHD([
>>> +AT_SETUP([Drop unknown eth type on router ports])
>>> +AT_SKIP_IF([test $HAVE_SCAPY = no])
>>> +AT_SKIP_IF([test $HAVE_TCPDUMP = no])
>>
>> nit: This test doesn't use tcpdump, AFAICT.
>>
>>> +ovn_start
>>> +
>>> +net_add n1
>>> +
>>> +sim_add hv1
>>> +as hv1
>>> +check ovs-vsctl add-br br-phys
>>> +ovn_attach n1 br-phys 192.168.0.1
>>> +check ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>> + set interface hv1-vif1 external-ids:iface-id=sw0-p1 \
>>> + options:tx_pcap=hv1/vif1-tx.pcap \
>>> + options:rxq_pcap=hv1/vif1-rx.pcap
>>> +ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>
>> nit: Missing check.
>>
>>> + set interface hv1-vif2 external-ids:iface-id=sw0-p2 \
>>> + options:tx_pcap=hv1/vif2-tx.pcap \
>>> + options:rxq_pcap=hv1/vif2-rx.pcap
>>> +
>>> +check ovn-nbctl ls-add sw0
>>> +check ovn-nbctl lsp-add sw0 sw0-p1
>>> +check ovn-nbctl lsp-set-addresses sw0-p1 "50:54:10:00:00:01 10.0.0.1"
>>> +check ovn-nbctl lsp-add sw0 sw0-p2
>>> +check ovn-nbctl lsp-set-addresses sw0-p2 "50:54:20:00:00:01 10.0.0.2"
>>> +
>>> +check ovn-nbctl lr-add lr0
>>> +check ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.254/24
>>> +check ovn-nbctl lsp-add-router-port sw0 sw0-lr0 lr0-sw0
>>> +
>>> +# create an ACL to log traffic on the router port.
>>
>> nit: Capital letter.
>>
>>> +check ovn-nbctl --log --name='eth-unknown' acl-add sw0 to-lport 1000
>>> 'outport == "sw0-lr0" && eth.type == 0x5ff' allow
>>> +
>>> +OVN_POPULATE_ARP
>>> +wait_for_ports_up
>>> +check ovn-nbctl --wait=hv sync
>>> +
>>> +packet=$(fmt_pkt "Ether(dst='ff:ff:ff:ff:ff:ff', src='50:54:10:00:00:01',
>>> type=0x5ff)")
>>> +echo $packet > expected
>>> +check as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>> +OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>>> +
>>> +AT_CHECK([grep -q 'name="eth-unknown"' hv1/ovn-controller.log],[1])
>>
>> nit: Space after the comma.
>>
>> Note: Not sure if this would give false-negatives sometimes, i.e. if the log
>> is not written yet while we're checking, but actually will be at some point.
>> But I suppose the chances are very low as there are many other operations
>> between sending and the checking, and we also can't really wait for the event
>> that doesn't happen. So, it's probbaly fine.
>>
>> Best regards, Ilya Maximets.
>>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev