On 1/23/26 12:53 PM, Ilya Maximets wrote:
> On 1/23/26 11:38 AM, Dumitru Ceara wrote:
>> Hi all,
>>
>> Thanks for the patch and discussion! I'll add my own opinion below.
>>
>> On 1/23/26 7:30 AM, Ales Musil wrote:
>>> On Thu, Jan 22, 2026 at 7:40 PM Mark Michelson <[email protected]> wrote:
>>>
>>>> In the commit title and description, "compliant" is misspelled as
>>>> "complaint". It is spelled correctly in the code, though.
>>>>
>>>> I have comments below, both regarding the code submission and to
>>>> respond to Ilya's remarks.
>>>>
>>>> On Thu, Jan 22, 2026 at 12:18 PM Ilya Maximets <[email protected]> wrote:
>>>>>
>>>>> On 1/22/26 3:27 PM, Ales Musil via dev wrote:
>>>>>> The RFC defines a Virtual Router Redundancy Protocol [0], in order
>>>>>> for that protocol to work the workload might "spoof" MAC address
>>>>>> within ARP or ND request/response. This wasn't allowed as the port
>>>>>> security is specifically designed against spoofing and checks if
>>>>>> the port security MAC address is the same for source of ARP/ND
>>>>>> and the inner source/target address. To make the port security
>>>>>> complaint add an option which when enabled will add extra flows
>>>>>> that match on the MAC address range specified by the RFC.
>>>>>>
>>>>>> [0] https://datatracker.ietf.org/doc/html/rfc5798
>>>>>> Reported-at: https://issues.redhat.com/browse/FDP-2979
>>>>>> Signed-off-by: Ales Musil <[email protected]>
>>>>>> ---
>>>>>> NEWS | 2 +
>>>>>> controller/lflow.c | 67 ++++++++++++++++++++
>>>>>> ovn-nb.xml | 9 +++
>>>>>> tests/ovn.at | 149
>>>> +++++++++++++++++++++++++++++++++++++++++++++
>>>>>> 4 files changed, 227 insertions(+)
>>>>>>
>>>>>> diff --git a/NEWS b/NEWS
>>>>>> index dc9d28f2c..e58f8ee1e 100644
>>>>>> --- a/NEWS
>>>>>> +++ b/NEWS
>>>>>> @@ -87,6 +87,8 @@ Post v25.09.0
>>>>>> other_config column.
>>>>>> - Introduce the capability to specify multiple ips for
>>>> ovn-evpn-local-ip
>>>>>> option.
>>>>>> + - Add an LSP option called "port-security-rfc5798-compliant", this
>>>>>> + allows VRRP v3 (RFC 5798) to work with port security enabled.
>>>>>
>>>>> Hi, Ales.
>>>>>
>>>>> This option name seems a bit misleading, as someone seeing it may assume
>>>>> that just enbaling it will allow the port to participate in VRRPv3. But
>>>>> it's not the case as port security will drop all the actual VRRP traffic,
>>>>> unless the virtual router mac address is also added to the port security,
>>>>> as all the actual VRRP packets with have this address as a source. As
>>>> per
>>>>> RFC itself:
>>>>>
>>>>> Note: VRRP packets are transmitted with the virtual router MAC
>>>>> address as the source MAC address to ensure that learning bridges
>>>>> correctly determine the LAN segment the virtual router is
>>>>> attached to.
>>>>>
>>>>> We should either add explicit indication that this option only affects
>>>>> ARP/ND packets, which would still be a bit confusing and will make the
>>>>> name even longer, or just have one knob like port-security-allow-vrrpv3
>>>>> that also allows all the actual VRRP traffic, so users don't have to
>>>>> add all the possible router IDs into port security. This option may
>>>>> potentially accept a list of allowed router IDs or "yes" for all, but
>>>>> that can be added later if necessary.
>>>>
>>>> If this is the case, then does this mean that non-ARP and non-ND VRRP
>>>> traffic will still be dropped by port security flows when this option
>>>> is enabled? If so, then it seems like allowing the ARPs and NDs is
>>>> only getting rid of the surface issue. The ARPs/NDs will be allowed
>>>> through, but then other VRRP traffic will still be dropped. Is that
>>>> OK? It seems like we're going to immediately get a complaint about
>>>> this patch not actually fixing the problem if that's the case. I think
>>>> Ilya is on the right track by suggesting that we allow all VRRP
>>>> traffic with this option, not just the ARP/ND packets.
>>>>
>>
>> The bug report was about ARP replies not being allowed. VRRP ARP
>> replies for the virtual IP are special:
>>
>> https://datatracker.ietf.org/doc/html/rfc5798#section-8.1.2
>>
>> When a host sends an ARP request for one of the virtual router IPv4
>> addresses, the Virtual Router Master MUST respond to the ARP request
>> with an ARP response that indicates the virtual MAC address for the
>> virtual router. Note that the source address of the Ethernet frame
>> of this ARP response is the physical MAC address of the physical
>> router.
>>
>> The traffic the virtual router actually forwards, IP traffic, is sent
>> using the _virtual_ MAC as source, i.e., from 00-00-5E-00-01-{VRID} (for
>> IPv4).
>>
>> But as the RFC states, the ARP replies are sent from with eth.src ==
>> _physical_ MAC of the VRRP member and arp.sha == 00-00-5E-00-01-{VRID}.
>>
>> Actual VRRP protocol packets are multicast and use the _physical_ MAC
>> address as source.
>
> I suppose, you meant "virtual" here. See the note at the end of
> https://datatracker.ietf.org/doc/html/rfc5798#section-7.2 that I
> cited before.
>
You're right, it should be "virtual". But that doesn't my argument
above much.
>>
>> So, in order for ALL this to work, the CMS must _anyway_ configure two
>> MACs (physical and 00-00-5E-00-01-{VRID}) in the port_security field of
>> the LSP.
>
> That is true. But why not save users from extra configuration and
> just allow the new knob to allow both the ARP/ND and the VRRP and
> the routed traffic? AFAIU, anyone setting the option will always
> have to set the MACs in the port_security column as well. There is
> no point in setting the option and not adding virtual MAC to the
> port_security list as well. So I'm not sure why we're forcing users
> to do that when we already adding a special vrrp knob.
>
Your suggestion was:
>>>>> We should either add explicit indication that this option
>>>>> only affects ARP/ND packets, which would still be a bit
>>>>> confusing and will make the name even longer, or just have
>>>>> one knob like port-security-allow-vrrpv3 that also allows
>>>>> all the actual VRRP traffic, so users don't have to add all
>>>>> the possible router IDs into port security. This option may
>>>>> potentially accept a list of allowed router IDs or "yes" for
>>>>> all, but that can be added later if necessary.
I read it as:
1. for now support "yes/no" for this option.
2. if "yes" then the user needs to configure the physical MAC in the
port_security field.
In that case OVN will allow:
- all traffic from/to the physical MAC, including VRRP ARPs with arp.sha
== VRRP-MAC (all VRIDs)
but also
- all traffic from/to any VRRP VID mac, i.e, any 00-00-5E-00-01-{VRID}
This is less "secure" than the additional knob added by Ales in this
patch which, in combination with explicitly adding the user VRID MAC to
port_security along with the physical MAC, would allow routed IP traffic
only if it's routed by that explicitly configured VRRP VRID.
Now, if we assume in the future we allow a list of VRRP MACs instead of
"yes" as value to the option, the user still needs to configure:
- port_security=[<physical-MAC>]
- port-security-allow-vrrpv3=[<VRRP-MAC1>, <VRRP-MAC2>]
While that's one config less, it does mean that we're not as restrictive
as we could be in 26.03 (or until we backport the extended config support).
>>
>> The problem is that port security semantics in OVN are too strict and
>> don't allow the mismatch between physical MAC and inner VRRP MAC for
>> ARPs/ND.
>>
>> So the knob is _only_ about arp/nd VRRP RFC 5798 compliance, in my opinion.
>>
>>>
>>> It is specifically said in the documentation that this applies
>>> only to ARP/ND, the user is expected to configure all MACs they
>>> want to allow in port security as usual. We can change the name of
>>> the option to make it more explicit. Also the regular traffic doesn't
>>> have any issues if it's configured properly, this option is there for
>>> the only part that cannot be configured in any way now.
>>>
>>
>> Maybe "port-security-rfc5798-arp-nd-compliant"? It's long but it's
>> explicit enough. We could also do "port-security-vrrp-arp-nd-compliant"
>> I guess.
>>
>> Regards,
>> Dumitru
>>
>>>
>>>>>
>>>>> I didn't read too deep into the code, but see a few comments inline.
>>>>>
>>>>> Best rgeards, Ilya Maximets.
>>>>>
>>>>>>
>>>>>> OVN v25.09.0 - xxx xx xxxx
>>>>>> --------------------------
>>>>>> diff --git a/controller/lflow.c b/controller/lflow.c
>>>>>> index b0998e605..93d9d090e 100644
>>>>>> --- a/controller/lflow.c
>>>>>> +++ b/controller/lflow.c
>>>>>> @@ -2551,6 +2551,11 @@ build_in_port_sec_arp_flows(const struct
>>>> sbrec_port_binding *pb,
>>>>>> return;
>>>>>> }
>>>>>>
>>>>>> + bool vrrp_compliant =
>>>>>> + smap_get_bool(&pb->options,
>>>> "port-security-rfc5798-compliant", false);
>>>>>> + const struct eth_addr vrrp_mac = ETH_ADDR_C(00,00,5e,00,01,00);
>>>>
>>>> Nit: This and all the other const eth_addrs should be "static" as well.
>>>>
>>>>>> + const struct eth_addr vrrp_mask = ETH_ADDR_C(ff,ff,ff,ff,ff,00);
>>>>>> +
>>>>>> build_port_sec_allow_action(ofpacts);
>>>>>>
>>>>>> if (!ps_addr->n_ipv4_addrs) {
>>>>>> @@ -2561,6 +2566,9 @@ build_in_port_sec_arp_flows(const struct
>>>> sbrec_port_binding *pb,
>>>>>> * match - "inport == pb->port && eth.src == ps_addr.ea &&
>>>>>> * arp && arp.sha == ps_addr.ea"
>>>>>> * action - "port_sec_failed = 0;"
>>>>>> + * If port security is configured to be VRRP (RFC5798)
>>>> compliant add
>>>>>
>>>>> Just the ARP flows do not make it RFC-compliant.
>>>>>
>>>>>> + * an extra flow to match on
>>>>>> + * arp.sha == 00:00:5e:00:01:00/ff:ff:ff:ff:ff:00
>>>>>> */
>>>>>> reset_match_for_port_sec_flows(pb, MFF_LOG_INPORT, m);
>>>>>> match_set_dl_src(m, ps_addr->ea);
>>>>>> @@ -2569,6 +2577,13 @@ build_in_port_sec_arp_flows(const struct
>>>> sbrec_port_binding *pb,
>>>>>> ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND, 90,
>>>>>> pb->header_.uuid.parts[0], m, ofpacts,
>>>>>> &pb->header_.uuid);
>>>>>> +
>>>>>> + if (vrrp_compliant) {
>>>>>> + match_set_arp_sha_masked(m, vrrp_mac, vrrp_mask);
>>>>>> + ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND,
>>>> 90,
>>>>>> + pb->header_.uuid.parts[0], m, ofpacts,
>>>>>> + &pb->header_.uuid);
>>>>>> + }
>>>>>> }
>>>>>>
>>>>>> /* Add the below logical flow equivalent OF rules in
>>>> 'in_port_sec_nd'
>>>>>> @@ -2577,6 +2592,9 @@ build_in_port_sec_arp_flows(const struct
>>>> sbrec_port_binding *pb,
>>>>>> * match - "inport == pb->port && eth.src == ps_addr.ea &&
>>>>>> * arp && arp.sha == ps_addr.ea && arp.spa ==
>>>> {ps_addr.ipv4_addrs}"
>>>>>> * action - "port_sec_failed = 0;"
>>>>>> + * If port security is configured to be VRRP (RFC5798) compliant
>>>> add
>>>>>> + * an extra flow to match on
>>>>>> + * arp.sha == 00:00:5e:00:01:00/ff:ff:ff:ff:ff:00
>>>>>> */
>>>>>> for (size_t j = 0; j < ps_addr->n_ipv4_addrs; j++) {
>>>>>> reset_match_for_port_sec_flows(pb, MFF_LOG_INPORT, m);
>>>>>> @@ -2594,6 +2612,13 @@ build_in_port_sec_arp_flows(const struct
>>>> sbrec_port_binding *pb,
>>>>>> ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND, 90,
>>>>>> pb->header_.uuid.parts[0], m, ofpacts,
>>>>>> &pb->header_.uuid);
>>>>>> +
>>>>>> + if (vrrp_compliant) {
>>>>>> + match_set_arp_sha_masked(m, vrrp_mac, vrrp_mask);
>>>>>> + ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND,
>>>> 90,
>>>>>> + pb->header_.uuid.parts[0], m, ofpacts,
>>>>>> + &pb->header_.uuid);
>>>>>> + }
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> @@ -2701,6 +2726,11 @@ build_in_port_sec_nd_flows(const struct
>>>> sbrec_port_binding *pb,
>>>>>> struct match *m, struct ofpbuf *ofpacts,
>>>>>> struct ovn_desired_flow_table *flow_table)
>>>>>> {
>>>>>> + bool vrrp_compliant =
>>>>>> + smap_get_bool(&pb->options,
>>>> "port-security-rfc5798-compliant", false);
>>>>>> + const struct eth_addr vrrp_mac = ETH_ADDR_C(00,00,5e,00,02,00);
>>>>>> + const struct eth_addr vrrp_mask = ETH_ADDR_C(ff,ff,ff,ff,ff,00);
>>>>>> +
>>>>>> build_port_sec_allow_action(ofpacts);
>>>>>>
>>>>>> /* Add the below logical flow equivalent OF rules in
>>>> 'in_port_sec_nd'
>>>>>> @@ -2710,6 +2740,9 @@ build_in_port_sec_nd_flows(const struct
>>>> sbrec_port_binding *pb,
>>>>>> * icmp6 && icmp6.code == 135 && icmp6.type == 0 &&
>>>>>> * ip6.tll == 255 && nd.sll == {00:00:00:00:00:00,
>>>> ps_addr.ea}"
>>>>>> * action - "port_sec_failed = 0;"
>>>>>> + * If port security is configured to be VRRP (RFC5798) compliant
>>>> add
>>>>>> + * an extra flow to match on
>>>>>> + * nd.sll == 00:00:5e:00:02:00/ff:ff:ff:ff:ff:00
>>>>>> */
>>>>>> reset_match_for_port_sec_flows(pb, MFF_LOG_INPORT, m);
>>>>>> match_set_dl_type(m, htons(ETH_TYPE_IPV6));
>>>>>> @@ -2728,6 +2761,13 @@ build_in_port_sec_nd_flows(const struct
>>>> sbrec_port_binding *pb,
>>>>>> pb->header_.uuid.parts[0], m, ofpacts,
>>>>>> &pb->header_.uuid);
>>>>>>
>>>>>> + if (vrrp_compliant) {
>>>>>> + match_set_arp_sha_masked(m, vrrp_mac, vrrp_mask);
>>>>>> + ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND, 90,
>>>>>> + pb->header_.uuid.parts[0], m, ofpacts,
>>>>>> + &pb->header_.uuid);
>>>>>> + }
>>>>>> +
>>>>>> match_set_icmp_type(m, 136);
>>>>>> match_set_icmp_code(m, 0);
>>>>>> if (ps_addr->n_ipv6_addrs) {
>>>>>> @@ -2739,6 +2779,9 @@ build_in_port_sec_nd_flows(const struct
>>>> sbrec_port_binding *pb,
>>>>>> * nd.tll == {00:00:00:00:00:00, ps_addr.ea} &&
>>>>>> * nd.target == {ps_addr.ipv6_addrs, lla}"
>>>>>> * action - "port_sec_failed = 0;"
>>>>>> + * If port security is configured to be VRRP (RFC5798)
>>>> compliant add
>>>>>> + * an extra flow to match on
>>>>>> + * nd.tll == 00:00:5e:00:02:00/ff:ff:ff:ff:ff:00
>>>>>> */
>>>>>> struct in6_addr lla;
>>>>>> in6_generate_lla(ps_addr->ea, &lla);
>>>>>> @@ -2754,6 +2797,13 @@ build_in_port_sec_nd_flows(const struct
>>>> sbrec_port_binding *pb,
>>>>>> pb->header_.uuid.parts[0], m, ofpacts,
>>>>>> &pb->header_.uuid);
>>>>>>
>>>>>> + if (vrrp_compliant) {
>>>>>> + match_set_arp_tha_masked(m, vrrp_mac, vrrp_mask);
>>>>>> + ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND,
>>>> 90,
>>>>>> + pb->header_.uuid.parts[0], m, ofpacts,
>>>>>> + &pb->header_.uuid);
>>>>>> + }
>>>>>> +
>>>>>> for (size_t j = 0; j < ps_addr->n_ipv6_addrs; j++) {
>>>>>> reset_match_for_port_sec_flows(pb, MFF_LOG_INPORT, m);
>>>>>> match_set_dl_src(m, ps_addr->ea);
>>>>>> @@ -2781,6 +2831,13 @@ build_in_port_sec_nd_flows(const struct
>>>> sbrec_port_binding *pb,
>>>>>> ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND,
>>>> 90,
>>>>>> pb->header_.uuid.parts[0], m, ofpacts,
>>>>>> &pb->header_.uuid);
>>>>>> +
>>>>>> + if (vrrp_compliant) {
>>>>>> + match_set_arp_tha_masked(m, vrrp_mac, vrrp_mask);
>>>>>> + ofctrl_add_flow(flow_table,
>>>> OFTABLE_CHK_IN_PORT_SEC_ND, 90,
>>>>>> + pb->header_.uuid.parts[0], m, ofpacts,
>>>>>> + &pb->header_.uuid);
>>>>>> + }
>>>>>> }
>>>>>> } else {
>>>>>> /* Add the below logical flow equivalent OF rules in
>>>> 'in_port_sec_nd'
>>>>>> @@ -2790,6 +2847,9 @@ build_in_port_sec_nd_flows(const struct
>>>> sbrec_port_binding *pb,
>>>>>> * icmp6.code == 136 && icmp6.type == 0 && ip6.tll
>>>> == 255 &&
>>>>>> * nd.tll == {00:00:00:00:00:00, ps_addr.ea}"
>>>>>> * action - "port_sec_failed = 0;"
>>>>>> + * If port security is configured to be VRRP (RFC5798)
>>>> compliant add
>>>>>> + * extra an flow to match on
>>>>>> + * nd.tll == 00:00:5e:00:02:00/ff:ff:ff:ff:ff:00
>>>>>> */
>>>>>> match_set_arp_tha(m, eth_addr_zero);
>>>>>> ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND, 90,
>>>>>> @@ -2800,6 +2860,13 @@ build_in_port_sec_nd_flows(const struct
>>>> sbrec_port_binding *pb,
>>>>>> ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND, 90,
>>>>>> pb->header_.uuid.parts[0], m, ofpacts,
>>>>>> &pb->header_.uuid);
>>>>>> +
>>>>>> + if (vrrp_compliant) {
>>>>>> + match_set_arp_tha_masked(m, vrrp_mac, vrrp_mask);
>>>>>> + ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND,
>>>> 90,
>>>>>> + pb->header_.uuid.parts[0], m, ofpacts,
>>>>>> + &pb->header_.uuid);
>>>>>> + }
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> diff --git a/ovn-nb.xml b/ovn-nb.xml
>>>>>> index e74c0d010..4e95a13b6 100644
>>>>>> --- a/ovn-nb.xml
>>>>>> +++ b/ovn-nb.xml
>>>>>> @@ -1674,6 +1674,15 @@
>>>>>> <ref table="Interface" db="vswitch"/> table. This in
>>>> turn will
>>>>>> make OVS vswitchd update the MTU of the linked interface.
>>>>>> </column>
>>>>>> +
>>>>>> + <column name="options" key="port-security-rfc5798-compliant"
>>>>>> + type='{"type": "boolean"}'>
>>>>>> + Allows the inner ARP SHA or ND TLL/SLL to be within the
>>>> range of
>>>>>> + MAC addresses specified by RFC 5798. The result is a
>>>> masked match
>>>>>> + that allows the whole range of MAC addresses to pass
>>>> through.
>>>>>> + This option is only applicable if <ref
>>>> column="port_security"/>
>>>>>> + is populated.
>>>>>> + </column>
>>>>>> </group>
>>>>>> </group>
>>>>>>
>>>>>> diff --git a/tests/ovn.at b/tests/ovn.at
>>>>>> index d5ee90e17..4455b7580 100644
>>>>>> --- a/tests/ovn.at
>>>>>> +++ b/tests/ovn.at
>>>>>> @@ -44181,3 +44181,152 @@ check ovn-nbctl --wait=hv lsp-set-type
>>>> down_ext localnet
>>>>>> OVN_CLEANUP([hv1],[hv2])
>>>>>> AT_CLEANUP
>>>>>> ])
>>>>>> +
>>>>>> +OVN_FOR_EACH_NORTHD([
>>>>>> +AT_SETUP([Port security - RFC 5798])
>>>>>> +AT_SKIP_IF([test $HAVE_SCAPY = no])
>>>>>> +ovn_start
>>>>>> +net_add n1
>>>>>> +sim_add hv1
>>>>>> +as hv1
>>>>>> +ovs-vsctl add-br br-phys
>>>>>
>>>>> check
>>>>>
>>>>>> +ovn_attach n1 br-phys 192.168.0.1
>>>>>> +
>>>>>> +check ovn-nbctl ls-add ls
>>>>>> +
>>>>>> +check ovn-nbctl lsp-add ls lsp1
>>>>>> +check ovn-nbctl lsp-set-addresses lsp1 "00:00:00:00:10:01
>>>> 192.168.10.1 fd10::1"
>>>>>> +
>>>>>> +check ovn-nbctl lsp-add ls lsp2
>>>>>> +check ovn-nbctl lsp-set-addresses lsp2 "00:00:00:00:10:02
>>>> 192.168.10.2 fd10::2"
>>>>>> +
>>>>>> +check ovs-vsctl -- add-port br-int vif1 -- \
>>>>>> + set interface vif1 external-ids:iface-id=lsp1 \
>>>>>> + options:tx_pcap=hv1/vif1-tx.pcap \
>>>>>> + options:rxq_pcap=hv1/vif1-rx.pcap
>>>>>> +
>>>>>> +check ovs-vsctl -- add-port br-int vif2 -- \
>>>>>> + set interface vif2 external-ids:iface-id=lsp2 \
>>>>>> + options:tx_pcap=hv1/vif2-tx.pcap \
>>>>>> + options:rxq_pcap=hv1/vif2-rx.pcap
>>>>>> +
>>>>>> +wait_for_ports_up
>>>>>> +
>>>>>> +test_arp() {
>>>>>> + local dropped=$1
>>>>>> +
>>>>>> + packet=$(fmt_pkt "
>>>>>> + Ether(dst='ff:ff:ff:ff:ff:ff', src='00:00:00:00:10:01') /
>>>>>> + ARP(op=1, hwsrc='00:00:5e:00:01:05',
>>>> hwdst='ff:ff:ff:ff:ff:ff', psrc='192.168.10.1', pdst='192.168.10.2')
>>>>>> + ")
>>>>>> + as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
>>>>>
>>>>> Need to check that this actually worked.
>>>>>
>>>>>> +
>>>>>> + packet=$(fmt_pkt "
>>>>>> + Ether(dst='ff:ff:ff:ff:ff:ff', src='00:00:00:00:10:01') /
>>>>>> + ARP(op=2, hwsrc='00:00:5e:00:01:05',
>>>> hwdst='ff:ff:ff:ff:ff:ff', psrc='192.168.10.1', pdst='192.168.10.1')
>>>>>> + ")
>>>>>
>>>>> Indentation is different here for some reason.
>>>>>
>>>>>> + as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
>>>>>
>>>>> check
>>>>>
>>>>>> +
>>>>>> + if [[ "$dropped" != "yes" ]]; then
>>>>>> + echo $packet >> vif2.expected
>>>>>
>>>>> Why are we sending two packets, but expecting only the second one?
>>>>
>>>> The first ARP has pdst not equal to lsp1's IP address, so it's
>>>> expected to be dropped by port security, even if VRRP compliance is
>>>> enabled. It's a control to ensure that a packet that should always be
>>>> dropped is not slipping through when VRRP compliance is enabled. The
>>>> second ARP has pdst equal to lsp1's IP address, so it is expected to
>>>> be dropped only if VRRP compliance is disabled.
>>>>
>>>
>>> We are sending ARP and gARP, ARP will be replied by LS lflows
>>> so it will never arrive to the second port, gARP will go through
>>> that's why we expected one packet for each port. One ARP reply
>>> and second gARP. The same happens with ND packets.
>>>
>>>
>>>>
>>>>>
>>>>>> + packet=$(fmt_pkt "
>>>>>> + Ether(dst='00:00:00:00:10:01', src='00:00:00:00:10:02') /
>>>>>> + ARP(op=2, hwsrc='00:00:00:00:10:02',
>>>> hwdst='00:00:5e:00:01:05', psrc='192.168.10.2', pdst='192.168.10.1')
>>>>>> + ")
>>>>>> + echo $packet >> vif1.expected
>>>>>> + fi
>>>>>> +}
>>>>>> +test_nd() {
>>>>>> + local dropped=$1
>>>>>> +
>>>>>> + packet=$(fmt_pkt "
>>>>>> + Ether(dst='33:33:ff:ff:ff:ff', src='00:00:00:00:10:01') /
>>>>>
>>>>> This is not a correct IPv6 multicast address.
>>>>>
>>>>>> + IPv6(src='fd10::1', dst='ff02::1:ff00:2') /
>>>>>> + ICMPv6ND_NS(tgt='fd10::2') /
>>>>>> + ICMPv6NDOptSrcLLAddr(lladdr='00:00:5e:00:02:05')
>>>>>> + ")
>>>>>> + as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
>>>>>
>>>>> check
>>>>>
>>>>>> +
>>>>>> + packet=$(fmt_pkt "
>>>>>> + Ether(dst='ff:ff:ff:ff:ff:ff', src='00:00:00:00:10:01') /
>>>>>
>>>>> Address.
>>>>>
>>>>>> + IPv6(src='fd10::1', dst='ff01::1') /
>>>>>> + ICMPv6ND_NA(tgt='fd10::1') /
>>>>>> + ICMPv6NDOptDstLLAddr(lladdr='00:00:5e:00:02:05')
>>>>>> + ")
>>>>>> + as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
>>>>>
>>>>> check
>>>>>
>>>>>> +
>>>>>> + if [[ "$dropped" != "yes" ]]; then
>>>>>> + echo $packet >> vif2.expected
>>>>>> +
>>>>>> + packet=$(fmt_pkt "
>>>>>> + Ether(dst='00:00:00:00:10:01',
>>>> src='00:00:00:00:10:02') /
>>>>>> + IPv6(src='fd10::2', dst='fd10::1') /
>>>>>> + ICMPv6ND_NA(tgt='fd10::2', R=0, S=1, O=1) /
>>>>>> + ICMPv6NDOptDstLLAddr(lladdr='00:00:00:00:10:02')
>>>>>> + ")
>>>>>> + echo $packet >> vif1.expected
>>>>>> + fi
>>>>>> +}
>>>>>> +
>>>>>> +reset_pcap_and_expected() {
>>>>>> + reset_pcap_file vif1 hv1/vif1
>>>>>> + reset_pcap_file vif2 hv1/vif2
>>>>>> +
>>>>>> + : > vif1.expected
>>>>>> + : > vif2.expected
>>>>>> +}
>>>>>> +
>>>>>> +AS_BOX([Without port security])
>>>>>> +reset_pcap_and_expected
>>>>>> +
>>>>>> +test_arp no
>>>>>> +test_nd no
>>>>>> +
>>>>>> +OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
>>>>>> +OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [vif2.expected])
>>>>>> +
>>>>>> +AS_BOX([With MAC only port security])
>>>>>> +reset_pcap_and_expected
>>>>>> +check ovn-nbctl --wait=hv lsp-set-port-security lsp1
>>>> "00:00:00:00:10:01"
>>>>>> +
>>>>>> +test_arp yes
>>>>>> +test_nd yes
>>>>>> +
>>>>>> +OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
>>>>>> +OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [vif2.expected])
>>>>>> +
>>>>>> +AS_BOX([With MAC + IP port security])
>>>>>> +reset_pcap_and_expected
>>>>>> +check ovn-nbctl --wait=hv lsp-set-port-security lsp1
>>>> "00:00:00:00:10:01 192.168.10.1 fd10::1"
>>>>>> +
>>>>>> +test_arp yes
>>>>>> +test_nd yes
>>>>>> +
>>>>>> +OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
>>>>>> +OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [vif2.expected])
>>>>>> +
>>>>>> +AS_BOX([With MAC only port security, compatibility enabled])
>>>>>> +reset_pcap_and_expected
>>>>>> +check ovn-nbctl lsp-set-options lsp1
>>>> port-security-rfc5798-compliant=true
>>>>>> +check ovn-nbctl --wait=hv lsp-set-port-security lsp1
>>>> "00:00:00:00:10:01"
>>>>>> +
>>>>>> +test_arp no
>>>>>> +test_nd no
>>>>>> +
>>>>>> +OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
>>>>>> +OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [vif2.expected])
>>>>>> +
>>>>>> +AS_BOX([With MAC + IP port security, compatibility enabled])
>>>>>> +reset_pcap_and_expected
>>>>>> +check ovn-nbctl --wait=hv lsp-set-port-security lsp1
>>>> "00:00:00:00:10:01 192.168.10.1 fd10::1"
>>>>>> +
>>>>>> +test_arp no
>>>>>> +test_nd no
>>>>>> +
>>>>>> +OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
>>>>>> +OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [vif2.expected])
>>>>>> +
>>>>>> +OVN_CLEANUP([hv1])
>>>>>> +
>>>>>> +AT_CLEANUP
>>>>>> +])
>>>>>
>>>>> _______________________________________________
>>>>> dev mailing list
>>>>> [email protected]
>>>>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>>>>>
>>>>
>>>>
>>>
>>
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev