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.

> 
> 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.

> 
> 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

Reply via email to