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
compliant add an special literal which when specified will allow
user to add any/all MAC addresses defined by VRRPv3. The traffic
from and to those additional MAC addresses will be allowed as
well as permutations of ARP/ND inner MACs combined with the
physical MAC as a source.

[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               |   3 +
 controller/lflow.c | 823 ++++++++++++++++++++++++++++-----------------
 ovn-nb.xml         |  33 ++
 tests/ovn.at       | 751 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 1302 insertions(+), 308 deletions(-)

diff --git a/NEWS b/NEWS
index b7268c835..5276f2c29 100644
--- a/NEWS
+++ b/NEWS
@@ -93,6 +93,9 @@ Post v25.09.0
      other_config column.
    - Introduce the capability to specify multiple ips for ovn-evpn-local-ip
      option.
+   - Add support for special port_security prefix "VRRPv3". This prefix allows
+     CMS to specify one physical MAC and multiple VRRPv3 MAC addresses.
+     The VRRPv3 MAC also accepts masked format.
 
 OVN v25.09.0 - xxx xx xxxx
 --------------------------
diff --git a/controller/lflow.c b/controller/lflow.c
index 94fd8807c..6b87727b5 100644
--- a/controller/lflow.c
+++ b/controller/lflow.c
@@ -2340,6 +2340,125 @@ add_port_sec_flows(const struct shash *binding_lports,
     }
 }
 
+struct masked_ip4_addr {
+    ovs_be32 addr;
+    ovs_be32 mask;
+    ovs_be32 bcast;
+};
+
+struct masked_ip6_addr {
+    struct in6_addr addr;
+    struct in6_addr mask;
+};
+
+struct masked_eth_addr {
+    struct eth_addr addr;
+    struct eth_addr mask;
+};
+
+struct port_security_addresses {
+    struct eth_addr phys_addr;
+    /* Vector of 'struct masked_eth_addr'. */
+    struct vector vrrp4;
+    /* Vector of 'struct masked_eth_addr'. */
+    struct vector vrrp6;
+    /* Vector of 'struct masked_ip4_addr' .*/
+    struct vector ip4;
+    /* Vector of 'struct masked_ip6_addr' .*/
+    struct vector ip6;
+};
+
+static const struct masked_eth_addr maddr_any_vrrp4 = {
+    .addr = ETH_ADDR_C(00,00,5e,00,01,00),
+    .mask = ETH_ADDR_C(ff,ff,ff,ff,ff,00)
+};
+static const struct masked_eth_addr maddr_any_vrrp6 = {
+    .addr = ETH_ADDR_C(00,00,5e,00,02,00),
+    .mask = ETH_ADDR_C(ff,ff,ff,ff,ff,00)
+};
+
+static bool
+port_security_addresses_add_vrrp_mac(struct port_security_addresses *ps_addr,
+                                     struct eth_addr mac, unsigned int plen)
+{
+    /* Only the last byte contains ID for VRRPv3. */
+    if (plen < 40) {
+        return false;
+    }
+
+    /* If the masked portion is non-zero, the host can only use
+     * the specified MAC address.  If zero, the host is allowed
+     * to use any MAC address within the mask.
+     */
+    struct eth_addr mask = eth_addr_create_mask(plen);
+    struct masked_eth_addr maddr = (struct masked_eth_addr) {
+        .addr = mac,
+        .mask = (eth_addr_to_uint64(mac) & ~eth_addr_to_uint64(mask))
+            ? eth_addr_exact : mask,
+    };
+
+    /* The exact match on VRRPv3 MAC ending with zero is not allowed, the
+     * id is starting from 1. */
+    if (plen == 48 && (eth_addr_equals(mac, maddr_any_vrrp4.addr) ||
+        eth_addr_equals(mac, maddr_any_vrrp6.addr))) {
+        return false;
+    }
+
+    if (eth_addr_equal_except(maddr_any_vrrp4.addr, mac,
+                              maddr_any_vrrp4.mask)) {
+        vector_push(&ps_addr->vrrp4, &maddr);
+        return true;
+    }
+
+    if (eth_addr_equal_except(maddr_any_vrrp6.addr, mac,
+                              maddr_any_vrrp6.mask)) {
+        vector_push(&ps_addr->vrrp6, &maddr);
+        return true;
+    }
+
+    return false;
+}
+
+static bool
+port_security_addresses_add_ip(struct port_security_addresses *ps_addr,
+                               struct in6_addr ip, unsigned int plen)
+{
+    /* When the netmask is applied, if the host portion is
+     * non-zero, the host can only use the specified
+     * address.  If zero, the host is allowed to use any
+     * address in the subnet. Also add broadcast in the special case
+     * of matching only the specified address.
+     */
+    if (IN6_IS_ADDR_V4MAPPED(&ip)) {
+        if (plen > 32) {
+            return false;
+        }
+
+        ovs_be32 addr = in6_addr_get_mapped_ipv4(&ip);
+        ovs_be32 mask = be32_prefix_mask(plen);
+
+        struct masked_ip4_addr maddr = (struct masked_ip4_addr) {
+            .addr = addr,
+            .mask = (addr & ~mask) ? OVS_BE32_MAX : mask,
+            .bcast = (addr & ~mask) ? addr | ~mask : htonl(0),
+        };
+        vector_push(&ps_addr->ip4, &maddr);
+    } else {
+        if (plen > 128) {
+            return false;
+        }
+
+        struct in6_addr mask = ipv6_create_mask(plen);
+        struct masked_ip6_addr maddr = (struct masked_ip6_addr) {
+            .addr = ip,
+            .mask = !ipv6_addr_is_host_zero(&ip, &mask) ? in6addr_exact : mask,
+        };
+        vector_push(&ps_addr->ip6, &maddr);
+    }
+
+    return true;
+}
+
 static void
 reset_match_for_port_sec_flows(const struct sbrec_port_binding *pb,
                                enum mf_field_id reg_id, struct match *match)
@@ -2446,24 +2565,39 @@ build_in_port_sec_default_flows(const struct 
sbrec_port_binding *pb,
                     &pb->header_.uuid);
 }
 
+static void
+build_out_port_sec_default_flows(const struct sbrec_port_binding *pb,
+                                struct match *m, struct ofpbuf *ofpacts,
+                                struct ovn_desired_flow_table *flow_table)
+{
+    /* Add the below logical flow equivalent OF rules in 'out_port_sec_nd'
+     * table.
+     * priority: 80
+     * match - "outport == pb->logical_port"
+     * action - "port_sec_failed = 1;"
+     * descrption: "Drop all traffic"
+     */
+    reset_match_for_port_sec_flows(pb, MFF_LOG_OUTPORT, m);
+    build_port_sec_deny_action(ofpacts);
+    ofctrl_add_flow(flow_table, OFTABLE_CHK_OUT_PORT_SEC, 80,
+                    pb->header_.uuid.parts[0], m, ofpacts,
+                    &pb->header_.uuid);
+}
+
 static void
 build_in_port_sec_no_ip_flows(const struct sbrec_port_binding *pb,
-                              struct lport_addresses *ps_addr,
+                              struct eth_addr mac, struct eth_addr mask,
                               struct match *m, struct ofpbuf *ofpacts,
                               struct ovn_desired_flow_table *flow_table)
 {
-    if (ps_addr->n_ipv4_addrs || ps_addr->n_ipv6_addrs) {
-        return;
-    }
-
     /* Add the below logical flow equivalent OF rules in 'in_port_sec' table.
      * priority: 90
-     * match - "inport == pb->logical_port && eth.src == ps_addr.ea"
+     * match - "inport == pb->logical_port && eth.src == mac/mask"
      * action - "next;"
      * description: "Advance the packet for ARP/ND check"
      */
     reset_match_for_port_sec_flows(pb, MFF_LOG_INPORT, m);
-    match_set_dl_src(m, ps_addr->ea);
+    match_set_dl_src_masked(m, mac, mask);
     build_port_sec_adv_nd_check(ofpacts);
     ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC, 90,
                     pb->header_.uuid.parts[0], m, ofpacts,
@@ -2472,43 +2606,26 @@ build_in_port_sec_no_ip_flows(const struct 
sbrec_port_binding *pb,
 
 static void
 build_in_port_sec_ip4_flows(const struct sbrec_port_binding *pb,
-                           struct lport_addresses *ps_addr,
-                           struct match *m, struct ofpbuf *ofpacts,
-                           struct ovn_desired_flow_table *flow_table)
+                            struct eth_addr mac, struct eth_addr mask,
+                            const struct vector *ip4_addrs,
+                            struct match *m, struct ofpbuf *ofpacts,
+                            struct ovn_desired_flow_table *flow_table)
 {
-    if (!ps_addr->n_ipv4_addrs) {
-        /* If no IPv4 addresses, then 'pb' is not allowed to send IPv4 traffic.
-         * build_in_port_sec_default_flows() takes care of this scenario. */
-        return;
-    }
-
     /* Advance all traffic from the port security eth address for ND check. */
     build_port_sec_allow_action(ofpacts);
+    reset_match_for_port_sec_flows(pb, MFF_LOG_INPORT, m);
+    match_set_dl_src_masked(m, mac, mask);
+    match_set_dl_type(m, htons(ETH_TYPE_IP));
 
     /* Add the below logical flow equivalent OF rules in in_port_sec.
      * priority: 90
-     * match - "inport == pb->port && eth.src == ps_addr.ea &&
-     *         ip4.src == {ps_addr.ipv4_addrs}"
+     * match - "inport == pb->port && eth.src == mac/mask &&
+     *         ip4.src == {ip4}"
      * action - "port_sec_failed = 0;"
      */
-    for (size_t j = 0; j < ps_addr->n_ipv4_addrs; j++) {
-        reset_match_for_port_sec_flows(pb, MFF_LOG_INPORT, m);
-        match_set_dl_src(m, ps_addr->ea);
-        match_set_dl_type(m, htons(ETH_TYPE_IP));
-
-        ovs_be32 mask = ps_addr->ipv4_addrs[j].mask;
-        /* When the netmask is applied, if the host portion is
-         * non-zero, the host can only use the specified
-         * address.  If zero, the host is allowed to use any
-         * address in the subnet.
-         */
-        if (ps_addr->ipv4_addrs[j].plen == 32 ||
-                ps_addr->ipv4_addrs[j].addr & ~mask) {
-            match_set_nw_src(m, ps_addr->ipv4_addrs[j].addr);
-        } else {
-            match_set_nw_src_masked(m, ps_addr->ipv4_addrs[j].addr, mask);
-        }
-
+    const struct masked_ip4_addr *ip;
+    VECTOR_FOR_EACH_PTR (ip4_addrs, ip) {
+        match_set_nw_src_masked(m, ip->addr, ip->mask);
         ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC, 90,
                         pb->header_.uuid.parts[0], m, ofpacts,
                         &pb->header_.uuid);
@@ -2516,20 +2633,14 @@ build_in_port_sec_ip4_flows(const struct 
sbrec_port_binding *pb,
 
     /* Add the below logical flow equivalent OF rules in in_port_sec.
      * priority: 90
-     * match - "inport == pb->port && eth.src == ps_addr.ea &&
+     * match - "inport == pb->port && eth.src == mac/mask &&
      *          ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 &&
      *          udp.src == 67 && udp.dst == 68"
      * action - "port_sec_failed = 0;"
      * description: "Allow the DHCP requests."
      */
-    reset_match_for_port_sec_flows(pb, MFF_LOG_INPORT, m);
-    match_set_dl_src(m, ps_addr->ea);
-    match_set_dl_type(m, htons(ETH_TYPE_IP));
-
-    ovs_be32 ip4 = htonl(0);
-    match_set_nw_src(m, ip4);
-    ip4 = htonl(0xffffffff);
-    match_set_nw_dst(m, ip4);
+    match_set_nw_src(m, htonl(0));
+    match_set_nw_dst(m, htonl(0xffffffff));
     match_set_nw_proto(m, IPPROTO_UDP);
     match_set_tp_src(m, htons(68));
     match_set_tp_dst(m, htons(67));
@@ -2542,33 +2653,39 @@ build_in_port_sec_ip4_flows(const struct 
sbrec_port_binding *pb,
 /* Adds the OF rules to allow ARP packets in 'in_port_sec_nd' table. */
 static void
 build_in_port_sec_arp_flows(const struct sbrec_port_binding *pb,
-                           struct lport_addresses *ps_addr,
-                           struct match *m, struct ofpbuf *ofpacts,
-                           struct ovn_desired_flow_table *flow_table)
+                            struct eth_addr phys_mac,
+                            const struct vector *ip4_addrs,
+                            const struct vector *vrrp4_addrs,
+                            struct match *m, struct ofpbuf *ofpacts,
+                            struct ovn_desired_flow_table *flow_table)
 {
-    if (!ps_addr->n_ipv4_addrs && ps_addr->n_ipv6_addrs) {
-        /* No ARP is allowed as only IPv6 addresses are configured. */
-        return;
-    }
-
     build_port_sec_allow_action(ofpacts);
+    reset_match_for_port_sec_flows(pb, MFF_LOG_INPORT, m);
+    match_set_dl_src(m, phys_mac);
+    match_set_dl_type(m, htons(ETH_TYPE_ARP));
 
-    if (!ps_addr->n_ipv4_addrs) {
+    if (vector_is_empty(ip4_addrs)) {
         /* No IPv4 addresses.
          * Add the below logical flow equivalent OF rules in 'in_port_sec_nd'
          * table.
          * priority: 90
-         * match - "inport == pb->port && eth.src == ps_addr.ea &&
-         *          arp && arp.sha == ps_addr.ea"
+         * match - "inport == pb->port && eth.src == phys_mac &&
+         *          arp && arp.sha == {phys_mac, vrrp4_addrs}"
          * action - "port_sec_failed = 0;"
          */
-        reset_match_for_port_sec_flows(pb, MFF_LOG_INPORT, m);
-        match_set_dl_src(m, ps_addr->ea);
-        match_set_dl_type(m, htons(ETH_TYPE_ARP));
-        match_set_arp_sha(m, ps_addr->ea);
+
+        match_set_arp_sha(m, phys_mac);
         ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND, 90,
                         pb->header_.uuid.parts[0], m, ofpacts,
                         &pb->header_.uuid);
+
+        struct masked_eth_addr *mmac;
+        VECTOR_FOR_EACH_PTR (vrrp4_addrs, mmac) {
+            match_set_arp_sha_masked(m, mmac->addr, mmac->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'
@@ -2578,74 +2695,60 @@ build_in_port_sec_arp_flows(const struct 
sbrec_port_binding *pb,
      *         arp && arp.sha == ps_addr.ea && arp.spa == {ps_addr.ipv4_addrs}"
      * action - "port_sec_failed = 0;"
      */
-    for (size_t j = 0; j < ps_addr->n_ipv4_addrs; j++) {
-        reset_match_for_port_sec_flows(pb, MFF_LOG_INPORT, m);
-        match_set_dl_src(m, ps_addr->ea);
-        match_set_dl_type(m, htons(ETH_TYPE_ARP));
-        match_set_arp_sha(m, ps_addr->ea);
-
-        ovs_be32 mask = ps_addr->ipv4_addrs[j].mask;
-        if (ps_addr->ipv4_addrs[j].plen == 32 ||
-                ps_addr->ipv4_addrs[j].addr & ~mask) {
-            match_set_nw_src(m, ps_addr->ipv4_addrs[j].addr);
-        } else {
-            match_set_nw_src_masked(m, ps_addr->ipv4_addrs[j].addr, mask);
-        }
+    const struct masked_ip4_addr *ip;
+    VECTOR_FOR_EACH_PTR (ip4_addrs, ip) {
+        match_set_nw_src_masked(m, ip->addr, ip->mask);
+
+        match_set_arp_sha(m, phys_mac);
         ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND, 90,
                         pb->header_.uuid.parts[0], m, ofpacts,
                         &pb->header_.uuid);
+
+        struct masked_eth_addr *mmac;
+        VECTOR_FOR_EACH_PTR (vrrp4_addrs, mmac) {
+            match_set_arp_sha_masked(m, mmac->addr, mmac->mask);
+            ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND, 90,
+                            pb->header_.uuid.parts[0], m, ofpacts,
+                            &pb->header_.uuid);
+        }
     }
 }
 
 static void
 build_in_port_sec_ip6_flows(const struct sbrec_port_binding *pb,
-                           struct lport_addresses *ps_addr,
-                           struct match *m, struct ofpbuf *ofpacts,
-                           struct ovn_desired_flow_table *flow_table)
+                            struct eth_addr mac, struct eth_addr mask,
+                            const struct vector *ip6_addrs,
+                            struct match *m, struct ofpbuf *ofpacts,
+                            struct ovn_desired_flow_table *flow_table)
 {
-    if (!ps_addr->n_ipv6_addrs) {
-        /* If no IPv6 addresses, then 'pb' is not allowed to send IPv6 traffic.
-         * build_in_port_sec_default_flows() takes care of this scenario. */
-        return;
-    }
-
     /* Add the below logical flow equivalent OF rules in 'in_port_sec_nd'
      * table.
      * priority: 90
-     * match - "inport == pb->port && eth.src == ps_addr.ea &&
+     * match - "inport == pb->port && eth.src == mac/mask &&
      *         ip6.src == {ps_addr.ipv6_addrs, lla}"
      * action - "next;"
      * description - Advance the packet for Neighbor Solicit/Adv check.
      */
     build_port_sec_adv_nd_check(ofpacts);
+    reset_match_for_port_sec_flows(pb, MFF_LOG_INPORT, m);
+    match_set_dl_src_masked(m, mac, mask);
+    match_set_dl_type(m, htons(ETH_TYPE_IPV6));
 
-    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);
-        match_set_dl_type(m, htons(ETH_TYPE_IPV6));
-
-        if (ps_addr->ipv6_addrs[j].plen == 128
-            || !ipv6_addr_is_host_zero(&ps_addr->ipv6_addrs[j].addr,
-                                        &ps_addr->ipv6_addrs[j].mask)) {
-            match_set_ipv6_src(m, &ps_addr->ipv6_addrs[j].addr);
-        } else {
-            match_set_ipv6_src_masked(m, &ps_addr->ipv6_addrs[j].network,
-                                        &ps_addr->ipv6_addrs[j].mask);
-        }
-
+    const struct masked_ip6_addr *ip;
+    VECTOR_FOR_EACH_PTR (ip6_addrs, ip) {
+        match_set_ipv6_src_masked(m, &ip->addr, &ip->mask);
         ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC, 90,
                         pb->header_.uuid.parts[0], m, ofpacts,
                         &pb->header_.uuid);
     }
 
-    reset_match_for_port_sec_flows(pb, MFF_LOG_INPORT, m);
-    match_set_dl_src(m, ps_addr->ea);
-    match_set_dl_type(m, htons(ETH_TYPE_IPV6));
 
     struct in6_addr lla;
-    in6_generate_lla(ps_addr->ea, &lla);
-    match_set_ipv6_src(m, &lla);
+    in6_generate_lla(mac, &lla);
+    unsigned int plen = 128 - 48 + eth_addr_get_prefix_len(mask);
+    struct in6_addr lla_mask = ipv6_create_mask(plen);
 
+    match_set_ipv6_src_masked(m, &lla, &lla_mask);
     ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC, 90,
                     pb->header_.uuid.parts[0], m, ofpacts,
                     &pb->header_.uuid);
@@ -2660,11 +2763,12 @@ build_in_port_sec_ip6_flows(const struct 
sbrec_port_binding *pb,
      */
     build_port_sec_allow_action(ofpacts);
     match_set_ipv6_src(m, &in6addr_any);
-    struct in6_addr ip6, mask;
-    char *err = ipv6_parse_masked("ff02::/16", &ip6, &mask);
+
+    struct in6_addr ip6, ip_mask;
+    char *err = ipv6_parse_masked("ff02::/16", &ip6, &ip_mask);
     ovs_assert(!err);
 
-    match_set_ipv6_dst_masked(m, &ip6, &mask);
+    match_set_ipv6_dst_masked(m, &ip6, &ip_mask);
     match_set_nw_proto(m, IPPROTO_ICMPV6);
     match_set_icmp_type(m, 131);
     match_set_icmp_code(m, 0);
@@ -2697,99 +2801,111 @@ build_in_port_sec_ip6_flows(const struct 
sbrec_port_binding *pb,
  * 'in_port_sec_nd' table. */
 static void
 build_in_port_sec_nd_flows(const struct sbrec_port_binding *pb,
-                           struct lport_addresses *ps_addr,
+                           struct eth_addr phys_mac,
+                           const struct vector *ip6_addrs,
+                           const struct vector *vrrp6_addrs,
                            struct match *m, struct ofpbuf *ofpacts,
                            struct ovn_desired_flow_table *flow_table)
 {
     build_port_sec_allow_action(ofpacts);
+    reset_match_for_port_sec_flows(pb, MFF_LOG_INPORT, m);
+    match_set_dl_src(m, phys_mac);
+    match_set_dl_type(m, htons(ETH_TYPE_IPV6));
+    match_set_nw_proto(m, IPPROTO_ICMPV6);
+    match_set_icmp_code(m, 0);
+    match_set_nw_ttl(m, 255);
 
     /* Add the below logical flow equivalent OF rules in 'in_port_sec_nd'
      * table.
      * priority: 90
-     * match - "inport == pb->port && eth.src == ps_addr.ea &&
-     *          icmp6 && icmp6.code == 135 && icmp6.type == 0 &&
-     *          ip6.tll == 255 && nd.sll == {00:00:00:00:00:00, ps_addr.ea}"
+     * match - "inport == pb->port && eth.src == phys_mac &&
+     *          icmp6 && icmp6.type == 135 && icmp6.code == 0 &&
+     *          ip6.tll == 255 &&
+     *          nd.sll == {00:00:00:00:00:00, phys_mac, vrrp6_addrs}"
      * action - "port_sec_failed = 0;"
      */
-    reset_match_for_port_sec_flows(pb, MFF_LOG_INPORT, m);
-    match_set_dl_type(m, htons(ETH_TYPE_IPV6));
-    match_set_nw_proto(m, IPPROTO_ICMPV6);
-    match_set_dl_src(m, ps_addr->ea);
-    match_set_nw_ttl(m, 255);
+
     match_set_icmp_type(m, 135);
-    match_set_icmp_code(m, 0);
 
     match_set_arp_sha(m, eth_addr_zero);
     ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND, 90,
                     pb->header_.uuid.parts[0], m, ofpacts,
                     &pb->header_.uuid);
 
-    match_set_arp_sha(m, ps_addr->ea);
+    match_set_arp_sha(m, phys_mac);
     ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND, 90,
                     pb->header_.uuid.parts[0], m, ofpacts,
                     &pb->header_.uuid);
 
+    struct masked_eth_addr *mmac;
+    VECTOR_FOR_EACH_PTR (vrrp6_addrs, mmac) {
+        match_set_arp_sha_masked(m, mmac->addr, mmac->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_arp_sha_masked(m, eth_addr_zero, eth_addr_zero);
     match_set_icmp_type(m, 136);
-    match_set_icmp_code(m, 0);
-    if (ps_addr->n_ipv6_addrs) {
+    if (!vector_is_empty(ip6_addrs)) {
         /* Add the below logical flow equivalent OF rules in 'in_port_sec_nd'
          * table if IPv6 addresses are configured.
          * priority: 90
-         * match - "inport == pb->port && eth.src == ps_addr.ea && icmp6 &&
-         *          icmp6.code == 136 && icmp6.type == 0 && ip6.tll == 255 &&
-         *          nd.tll == {00:00:00:00:00:00, ps_addr.ea} &&
-         *          nd.target == {ps_addr.ipv6_addrs, lla}"
+         * match - "inport == pb->port && eth.src == phys_mac && icmp6 &&
+         *          icmp6.type == 136 && icmp6.code == 0 && ip6.tll == 255 &&
+         *          nd.tll == {00:00:00:00:00:00, phys_mac, vrrp6_addrs} &&
+         *          nd.target == {lla, ip6_addrs}"
          * action - "port_sec_failed = 0;"
          */
         struct in6_addr lla;
-        in6_generate_lla(ps_addr->ea, &lla);
-        match_set_arp_tha(m, eth_addr_zero);
-
+        in6_generate_lla(phys_mac, &lla);
         match_set_nd_target(m, &lla);
+
+        match_set_arp_tha(m, eth_addr_zero);
         ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND, 90,
                         pb->header_.uuid.parts[0], m, ofpacts,
                         &pb->header_.uuid);
-        match_set_arp_tha(m, ps_addr->ea);
-        match_set_nd_target(m, &lla);
+
+        match_set_arp_tha(m, phys_mac);
         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);
-            match_set_dl_type(m, htons(ETH_TYPE_IPV6));
-            match_set_nw_proto(m, IPPROTO_ICMPV6);
-            match_set_nw_ttl(m, 255);
-            match_set_icmp_type(m, 136);
-            match_set_icmp_code(m, 0);
-            match_set_arp_tha(m, eth_addr_zero);
+        VECTOR_FOR_EACH_PTR (vrrp6_addrs, mmac) {
+            match_set_arp_tha_masked(m, mmac->addr, mmac->mask);
+            ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND, 90,
+                            pb->header_.uuid.parts[0], m, ofpacts,
+                            &pb->header_.uuid);
+        }
 
-            if (ps_addr->ipv6_addrs[j].plen == 128
-                || !ipv6_addr_is_host_zero(&ps_addr->ipv6_addrs[j].addr,
-                                            &ps_addr->ipv6_addrs[j].mask)) {
-                match_set_nd_target(m, &ps_addr->ipv6_addrs[j].addr);
-            } else {
-                match_set_nd_target_masked(m, &ps_addr->ipv6_addrs[j].network,
-                                           &ps_addr->ipv6_addrs[j].mask);
-            }
+        const struct masked_ip6_addr *ip;
+        VECTOR_FOR_EACH_PTR (ip6_addrs, ip) {
+            match_set_nd_target_masked(m, &ip->addr, &ip->mask);
 
+            match_set_arp_tha(m, eth_addr_zero);
             ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND, 90,
                             pb->header_.uuid.parts[0], m, ofpacts,
                             &pb->header_.uuid);
 
-            match_set_arp_tha(m, ps_addr->ea);
+            match_set_arp_tha(m, phys_mac);
             ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND, 90,
                             pb->header_.uuid.parts[0], m, ofpacts,
                             &pb->header_.uuid);
+
+            VECTOR_FOR_EACH_PTR (vrrp6_addrs, mmac) {
+                match_set_arp_tha_masked(m, mmac->addr, mmac->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'
          * table if no IPv6 addresses are configured.
          * priority: 90
-         * match - "inport == pb->port && eth.src == ps_addr.ea && icmp6 &&
+         * match - "inport == pb->port && eth.src == phys_mac && icmp6 &&
          *          icmp6.code == 136 && icmp6.type == 0 && ip6.tll == 255 &&
-         *          nd.tll == {00:00:00:00:00:00, ps_addr.ea}"
+         *          nd.tll == {00:00:00:00:00:00, phys_mac, vrrp6_addrs}"
          * action - "port_sec_failed = 0;"
          */
         match_set_arp_tha(m, eth_addr_zero);
@@ -2797,27 +2913,34 @@ build_in_port_sec_nd_flows(const struct 
sbrec_port_binding *pb,
                         pb->header_.uuid.parts[0], m, ofpacts,
                         &pb->header_.uuid);
 
-        match_set_arp_tha(m, ps_addr->ea);
+        match_set_arp_tha(m, phys_mac);
         ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND, 90,
                         pb->header_.uuid.parts[0], m, ofpacts,
                         &pb->header_.uuid);
+
+        VECTOR_FOR_EACH_PTR (vrrp6_addrs, mmac) {
+            match_set_arp_tha_masked(m, mmac->addr, mmac->mask);
+            ofctrl_add_flow(flow_table, OFTABLE_CHK_IN_PORT_SEC_ND, 90,
+                            pb->header_.uuid.parts[0], m, ofpacts,
+                            &pb->header_.uuid);
+        }
     }
 }
 
 static void
 build_out_port_sec_no_ip_flows(const struct sbrec_port_binding *pb,
-                               struct lport_addresses *ps_addr,
+                               struct eth_addr mac, struct eth_addr mask,
                                struct match *m, struct ofpbuf *ofpacts,
                                struct ovn_desired_flow_table *flow_table)
 {
     /* Add the below logical flow equivalent OF rules in 'out_port_sec' table.
      * priority: 85
-     * match - "outport == pb->logical_port && eth.dst == ps_addr.ea"
+     * match - "outport == pb->logical_port && eth.dst == mac/mask"
      * action - "port_sec_failed = 0;"
      * description: "Allow the packet if eth.dst matches."
      */
     reset_match_for_port_sec_flows(pb, MFF_LOG_OUTPORT, m);
-    match_set_dl_dst(m, ps_addr->ea);
+    match_set_dl_dst_masked(m, mac, mask);
     build_port_sec_allow_action(ofpacts);
     ofctrl_add_flow(flow_table, OFTABLE_CHK_OUT_PORT_SEC, 85,
                     pb->header_.uuid.parts[0], m, ofpacts,
@@ -2826,97 +2949,70 @@ build_out_port_sec_no_ip_flows(const struct 
sbrec_port_binding *pb,
 
 static void
 build_out_port_sec_ip4_flows(const struct sbrec_port_binding *pb,
-                            struct lport_addresses *ps_addr,
-                            struct match *m, struct ofpbuf *ofpacts,
-                            struct ovn_desired_flow_table *flow_table)
+                             struct eth_addr mac, struct eth_addr mask,
+                             const struct vector *ip4_addrs,
+                             struct match *m, struct ofpbuf *ofpacts,
+                             struct ovn_desired_flow_table *flow_table)
 {
-    if (!ps_addr->n_ipv4_addrs && !ps_addr->n_ipv6_addrs) {
-         /* No IPv4 and no IPv6 addresses in the port security.
-          * Both IPv4 and IPv6 traffic should be delivered to the
-          * lport. build_out_port_sec_no_ip_flows() takes care of
-          * adding the required flow(s) to allow. */
-        return;
-    }
+    reset_match_for_port_sec_flows(pb, MFF_LOG_OUTPORT, m);
+    match_set_dl_dst_masked(m, mac, mask);
+    match_set_dl_type(m, htons(ETH_TYPE_IP));
 
     /* Add the below logical flow equivalent OF rules in 'out_port_sec' table.
      * priority: 90
-     * match - "outport == pb->logical_port && eth.dst == ps_addr.ea && ip4"
+     * match - "outport == pb->logical_port && eth.dst == mac/mask && ip4"
      * action - "port_sec_failed = 1;"
      * description: Default drop IPv4 packets.  If IPv4 addresses are
      *              configured, then higher priority flows are added
      *              to allow specific IPv4 packets.
      */
-    reset_match_for_port_sec_flows(pb, MFF_LOG_OUTPORT, m);
-    match_set_dl_dst(m, ps_addr->ea);
-    match_set_dl_type(m, htons(ETH_TYPE_IP));
+
     build_port_sec_deny_action(ofpacts);
     ofctrl_add_flow(flow_table, OFTABLE_CHK_OUT_PORT_SEC, 90,
                     pb->header_.uuid.parts[0], m, ofpacts,
                     &pb->header_.uuid);
 
-    if (!ps_addr->n_ipv4_addrs) {
+    if (vector_is_empty(ip4_addrs)) {
         return;
     }
 
+    build_port_sec_allow_action(ofpacts);
     /* Add the below logical flow equivalent OF rules in 'out_port_sec' table.
      * priority: 95
-     * match - "outport == pb->logical_port && eth.dst == ps_addr.ea &&
-     *          ip4.dst == {ps_addr.ipv4_addrs, 255.255.255.255, 224.0.0.0/4},"
+     * match - "outport == pb->logical_port && eth.dst == mac/mask &&
+     *          ip4.dst == {ip4_addrs, 255.255.255.255, 224.0.0.0/4},"
      * action - "port_sec_failed = 0;"
      */
-    build_port_sec_allow_action(ofpacts);
-    for (size_t j = 0; j < ps_addr->n_ipv4_addrs; j++) {
-        reset_match_for_port_sec_flows(pb, MFF_LOG_OUTPORT, m);
-        match_set_dl_dst(m, ps_addr->ea);
-        match_set_dl_type(m, htons(ETH_TYPE_IP));
-        ovs_be32 mask = ps_addr->ipv4_addrs[j].mask;
-        if (ps_addr->ipv4_addrs[j].plen == 32
-                || ps_addr->ipv4_addrs[j].addr & ~mask) {
-
-            if (ps_addr->ipv4_addrs[j].plen != 32) {
-                /* Special case to allow bcast traffic.
-                 * Eg. If ps_addr is 10.0.0.4/24, then add the below flow
-                 * priority: 95
-                 * match - "outport == pb->logical_port &&
-                 *          eth.dst == ps_addr.ea &&
-                 *          ip4.dst == 10.0.0.255"
-                 * action - "port_sec_failed = 0;"
-                 */
-                ovs_be32 bcast_addr;
-                ovs_assert(ip_parse(ps_addr->ipv4_addrs[j].bcast_s,
-                                    &bcast_addr));
-                match_set_nw_dst(m, bcast_addr);
-                ofctrl_add_flow(flow_table, OFTABLE_CHK_OUT_PORT_SEC, 95,
-                                pb->header_.uuid.parts[0], m, ofpacts,
-                                &pb->header_.uuid);
-            }
-
-            match_set_nw_dst(m, ps_addr->ipv4_addrs[j].addr);
-        } else {
-            /* host portion is zero */
-            match_set_nw_dst_masked(m, ps_addr->ipv4_addrs[j].addr,
-                                    mask);
-        }
-
+    const struct masked_ip4_addr *ip;
+    VECTOR_FOR_EACH_PTR (ip4_addrs, ip) {
+        match_set_nw_dst_masked(m, ip->addr, ip->mask);
         ofctrl_add_flow(flow_table, OFTABLE_CHK_OUT_PORT_SEC, 95,
                         pb->header_.uuid.parts[0], m, ofpacts,
                         &pb->header_.uuid);
-    }
 
-    reset_match_for_port_sec_flows(pb, MFF_LOG_OUTPORT, m);
-    match_set_dl_dst(m, ps_addr->ea);
-    match_set_dl_type(m, htons(ETH_TYPE_IP));
+        if (ip->bcast) {
+            /* Special case to allow bcast traffic.
+             * Eg. If address is 10.0.0.4/24, then add the below flow
+             * priority: 95
+             * match - "outport == pb->logical_port &&
+             *          eth.dst == ps_addr.ea &&
+             *          ip4.dst == 10.0.0.255"
+             * action - "port_sec_failed = 0;"
+             */
+            match_set_nw_dst(m, ip->bcast);
+            ofctrl_add_flow(flow_table, OFTABLE_CHK_OUT_PORT_SEC, 95,
+                            pb->header_.uuid.parts[0], m, ofpacts,
+                            &pb->header_.uuid);
+        }
+    }
 
-    ovs_be32 ip4 = htonl(0xffffffff);
-    match_set_nw_dst(m, ip4);
+    match_set_nw_dst(m, htonl(0xffffffff));
     ofctrl_add_flow(flow_table, OFTABLE_CHK_OUT_PORT_SEC, 95,
                     pb->header_.uuid.parts[0], m, ofpacts,
                     &pb->header_.uuid);
 
     /* Allow 224.0.0.0/4 traffic. */
-    ip4 = htonl(0xe0000000);
-    ovs_be32 mask = htonl(0xf0000000);
-    match_set_nw_dst_masked(m, ip4, mask);
+    match_set_nw_dst_masked(m, htonl(0xe0000000), htonl(0xf0000000));
     ofctrl_add_flow(flow_table, OFTABLE_CHK_OUT_PORT_SEC, 95,
                     pb->header_.uuid.parts[0], m, ofpacts,
                     &pb->header_.uuid);
@@ -2924,112 +3020,234 @@ build_out_port_sec_ip4_flows(const struct 
sbrec_port_binding *pb,
 
 static void
 build_out_port_sec_ip6_flows(const struct sbrec_port_binding *pb,
-                            struct lport_addresses *ps_addr,
-                            struct match *m, struct ofpbuf *ofpacts,
-                            struct ovn_desired_flow_table *flow_table)
+                             struct eth_addr mac, struct eth_addr mask,
+                             const struct vector *ip6_addrs,
+                             struct match *m, struct ofpbuf *ofpacts,
+                             struct ovn_desired_flow_table *flow_table)
 {
-    if (!ps_addr->n_ipv4_addrs && !ps_addr->n_ipv6_addrs) {
-        /* No IPv4 and no IPv6 addresses in the port security.
-         * Both IPv4 and IPv6 traffic should be delivered to the
-         * lport. build_out_port_sec_no_ip_flows() takes care of
-         * adding the required flow(s) to allow. */
-        return;
-    }
+    reset_match_for_port_sec_flows(pb, MFF_LOG_OUTPORT, m);
+    match_set_dl_dst_masked(m, mac, mask);
+    match_set_dl_type(m, htons(ETH_TYPE_IPV6));
 
     /* Add the below logical flow equivalent OF rules in 'out_port_sec' table.
      * priority: 90
-     * match - "outport == pb->logical_port && eth.dst == ps_addr.ea && ip6"
+     * match - "outport == pb->logical_port && eth.dst == mac/mask && ip6"
      * action - "port_sec_failed = 1;"
      * description: Default drop IPv6 packets.  If IPv6 addresses are
      *              configured, then higher priority flows are added
      *              to allow specific IPv6 packets.
      */
-    reset_match_for_port_sec_flows(pb, MFF_LOG_OUTPORT, m);
-    match_set_dl_dst(m, ps_addr->ea);
-    match_set_dl_type(m, htons(ETH_TYPE_IPV6));
     build_port_sec_deny_action(ofpacts);
     ofctrl_add_flow(flow_table, OFTABLE_CHK_OUT_PORT_SEC, 90,
                     pb->header_.uuid.parts[0], m, ofpacts,
                     &pb->header_.uuid);
 
-    if (!ps_addr->n_ipv6_addrs) {
+    if (vector_is_empty(ip6_addrs)) {
         return;
     }
 
+    build_port_sec_allow_action(ofpacts);
     /* Add the below logical flow equivalent OF rules in 'out_port_sec' table.
      * priority: 95
-     * match - "outport == pb->logical_port && eth.dst == ps_addr.ea &&
-     *          ip6.dst == {ps_addr.ipv6_addrs, lla, ff00::/8},"
+     * match - "outport == pb->logical_port && eth.dst == mac/mask &&
+     *          ip6.dst == {mac/mask, ip6_addrs, lla, ff00::/8},"
      * action - "port_sec_failed = 0;"
      */
-    build_port_sec_allow_action(ofpacts);
-    for (size_t j = 0; j < ps_addr->n_ipv6_addrs; j++) {
-        reset_match_for_port_sec_flows(pb, MFF_LOG_OUTPORT, m);
-        match_set_dl_dst(m, ps_addr->ea);
-        match_set_dl_type(m, htons(ETH_TYPE_IPV6));
-
-        if (ps_addr->ipv6_addrs[j].plen == 128
-            || !ipv6_addr_is_host_zero(&ps_addr->ipv6_addrs[j].addr,
-                                        &ps_addr->ipv6_addrs[j].mask)) {
-            match_set_ipv6_dst(m, &ps_addr->ipv6_addrs[j].addr);
-        } else {
-            match_set_ipv6_dst_masked(m, &ps_addr->ipv6_addrs[j].network,
-                                      &ps_addr->ipv6_addrs[j].mask);
-        }
-
+    const struct masked_ip6_addr *ip;
+    VECTOR_FOR_EACH_PTR (ip6_addrs, ip) {
+        match_set_ipv6_dst_masked(m, &ip->addr, &ip->mask);
         ofctrl_add_flow(flow_table, OFTABLE_CHK_OUT_PORT_SEC, 95,
                         pb->header_.uuid.parts[0], m, ofpacts,
                         &pb->header_.uuid);
     }
 
     struct in6_addr lla;
-    in6_generate_lla(ps_addr->ea, &lla);
+    in6_generate_lla(mac, &lla);
+    unsigned int plen = 128 - 48 + eth_addr_get_prefix_len(mask);
+    struct in6_addr lla_mask = ipv6_create_mask(plen);
 
-    reset_match_for_port_sec_flows(pb, MFF_LOG_OUTPORT, m);
-    match_set_dl_dst(m, ps_addr->ea);
-    match_set_dl_type(m, htons(ETH_TYPE_IPV6));
-    match_set_ipv6_dst(m, &lla);
+    match_set_ipv6_dst_masked(m, &lla, &lla_mask);
     ofctrl_add_flow(flow_table, OFTABLE_CHK_OUT_PORT_SEC, 95,
                     pb->header_.uuid.parts[0], m, ofpacts,
                     &pb->header_.uuid);
 
-    struct in6_addr ip6, mask;
-    char *err = ipv6_parse_masked("ff00::/8", &ip6, &mask);
+    struct in6_addr ip6, ip_mask;
+    char *err = ipv6_parse_masked("ff00::/8", &ip6, &ip_mask);
     ovs_assert(!err);
 
-    match_set_ipv6_dst_masked(m, &ip6, &mask);
+    match_set_ipv6_dst_masked(m, &ip6, &ip_mask);
     ofctrl_add_flow(flow_table, OFTABLE_CHK_OUT_PORT_SEC, 95,
                     pb->header_.uuid.parts[0], m, ofpacts,
                     &pb->header_.uuid);
 }
 
 static void
-consider_port_sec_flows(const struct sbrec_port_binding *pb,
-                        struct ovn_desired_flow_table *flow_table)
+build_port_sec_entry_flows(const struct sbrec_port_binding *pb,
+                           const struct port_security_addresses *ps_addr,
+                           struct match *m, struct ofpbuf *ofpacts,
+                           struct ovn_desired_flow_table *flow_table)
 {
-    if (!pb->n_port_security) {
-        return;
+    const struct masked_eth_addr *maddr;
+
+    /* Input no-ip flows. */
+    if (vector_is_empty(&ps_addr->ip4) && vector_is_empty(&ps_addr->ip6)) {
+        build_in_port_sec_no_ip_flows(pb, ps_addr->phys_addr, eth_addr_exact,
+                                      m, ofpacts, flow_table);
+
+        VECTOR_FOR_EACH_PTR (&ps_addr->vrrp4, maddr) {
+            build_in_port_sec_no_ip_flows(pb, maddr->addr, maddr->mask,
+                                          m, ofpacts, flow_table);
+        }
+
+        VECTOR_FOR_EACH_PTR (&ps_addr->vrrp6, maddr) {
+            build_in_port_sec_no_ip_flows(pb, maddr->addr, maddr->mask,
+                                          m, ofpacts, flow_table);
+        }
     }
 
-    struct lport_addresses *ps_addrs;   /* Port security addresses. */
-    size_t n_ps_addrs = 0;
+    /* Input IPv4 flows. */
+    if (!vector_is_empty(&ps_addr->ip4)) {
+        build_in_port_sec_ip4_flows(pb, ps_addr->phys_addr, eth_addr_exact,
+                                    &ps_addr->ip4, m, ofpacts, flow_table);
 
-    ps_addrs = xmalloc(sizeof *ps_addrs * pb->n_port_security);
-    for (size_t i = 0; i < pb->n_port_security; i++) {
-        if (!extract_lsp_addresses(pb->port_security[i],
-                                    &ps_addrs[n_ps_addrs])) {
-            static struct vlog_rate_limit rl
-                = VLOG_RATE_LIMIT_INIT(1, 1);
-            VLOG_WARN_RL(&rl, "invalid syntax '%s' in port "
-                         "security. No MAC address found",
-                         pb->port_security[i]);
-            continue;
+        VECTOR_FOR_EACH_PTR (&ps_addr->vrrp4, maddr) {
+            build_in_port_sec_ip4_flows(pb, maddr->addr, maddr->mask,
+                                        &ps_addr->ip4, m, ofpacts, flow_table);
+        }
+    }
+
+    /* Input ARP flows. */
+    if (!vector_is_empty(&ps_addr->ip4) || vector_is_empty(&ps_addr->ip6)) {
+        build_in_port_sec_arp_flows(pb, ps_addr->phys_addr, &ps_addr->ip4,
+                                    &ps_addr->vrrp4, m, ofpacts, flow_table);
+    }
+
+
+    /* Input Ipv6 flows. */
+    if (!vector_is_empty(&ps_addr->ip6)) {
+        build_in_port_sec_ip6_flows(pb, ps_addr->phys_addr, eth_addr_exact,
+                                    &ps_addr->ip6, m, ofpacts, flow_table);
+
+        VECTOR_FOR_EACH_PTR (&ps_addr->vrrp6, maddr) {
+            build_in_port_sec_ip6_flows(pb, maddr->addr, maddr->mask,
+                                        &ps_addr->ip6, m, ofpacts, flow_table);
+        }
+    }
+
+    /* Input ND flows. */
+    build_in_port_sec_nd_flows(pb, ps_addr->phys_addr, &ps_addr->ip6,
+                               &ps_addr->vrrp6, m, ofpacts, flow_table);
+
+    /* Output no-ip flows. */
+    build_out_port_sec_no_ip_flows(pb, ps_addr->phys_addr, eth_addr_exact,
+                                   m, ofpacts, flow_table);
+
+    VECTOR_FOR_EACH_PTR (&ps_addr->vrrp4, maddr) {
+        build_out_port_sec_no_ip_flows(pb, maddr->addr, maddr->mask,
+                                       m, ofpacts, flow_table);
+    }
+
+    VECTOR_FOR_EACH_PTR (&ps_addr->vrrp6, maddr) {
+        build_out_port_sec_no_ip_flows(pb, maddr->addr, maddr->mask,
+                                       m, ofpacts, flow_table);
+    }
+
+    /* Output IPv4 flows. */
+    if (!vector_is_empty(&ps_addr->ip4) || !vector_is_empty(&ps_addr->ip6)) {
+        build_out_port_sec_ip4_flows(pb, ps_addr->phys_addr, eth_addr_exact,
+                                     &ps_addr->ip4, m, ofpacts, flow_table);
+
+        VECTOR_FOR_EACH_PTR (&ps_addr->vrrp4, maddr) {
+            build_out_port_sec_ip4_flows(pb, maddr->addr, maddr->mask,
+                                         &ps_addr->ip4, m, ofpacts,
+                                         flow_table);
+        }
+    }
+
+    /* Output Ipv6 flows. */
+    if (!vector_is_empty(&ps_addr->ip4) || !vector_is_empty(&ps_addr->ip6)) {
+        build_out_port_sec_ip6_flows(pb, ps_addr->phys_addr, eth_addr_exact,
+                                     &ps_addr->ip6, m, ofpacts, flow_table);
+
+        VECTOR_FOR_EACH_PTR (&ps_addr->vrrp6, maddr) {
+            build_out_port_sec_ip6_flows(pb, maddr->addr, maddr->mask,
+                                         &ps_addr->ip6, m, ofpacts,
+                                         flow_table);
+        }
+    }
+}
+
+static bool
+port_security_addresses_parse_entry(const char *entry, const char *lsp,
+                                    struct port_security_addresses *ps_addr)
+{
+    static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+
+    bool vrrpv3 = !strncmp(entry, "VRRPv3", 6);
+    int n = vrrpv3 ? 7 : 0;
+
+    if (!ovs_scan_len(entry, &n, ETH_ADDR_SCAN_FMT,
+                      ETH_ADDR_SCAN_ARGS(ps_addr->phys_addr))) {
+        VLOG_WARN_RL(&rl, "invalid syntax '%s' in port security for LSP %s: "
+                     "No MAC address found", entry, lsp);
+        return false;
+    }
+
+    bool ok = true;
+    /* Only MAC address is provided. */
+    if (!entry[n]) {
+        goto vrrp_check;
+    }
+
+
+    char *save_ptr = NULL;
+    char *tokstr = xstrdup(entry + n);
+    for (char *token = strtok_r(tokstr, " ", &save_ptr);
+         token != NULL;
+         token = strtok_r(NULL, " ", &save_ptr)) {
+        struct eth_addr mac;
+        struct in6_addr ip;
+        unsigned int plen;
+
+        if (vrrpv3 && eth_addr_parse_masked(token, &mac, &plen)) {
+            if (!port_security_addresses_add_vrrp_mac(ps_addr, mac, plen)) {
+                VLOG_WARN_RL(&rl, "invalid syntax '%s' in port security for"
+                             " LSP %s: Invalid VRRPv3 MAC", token, lsp);
+                ok = false;
+                break;
+            }
+        } else if (ip46_parse_cidr(token, &ip, &plen)) {
+            if (!port_security_addresses_add_ip(ps_addr, ip, plen)) {
+                VLOG_WARN_RL(&rl, "invalid syntax '%s' in port security for"
+                             " LSP %s: Invalid IP", token, lsp);
+                ok = false;
+                break;
+            }
+        } else {
+            VLOG_WARN_RL(&rl, "invalid syntax '%s' in port security for"
+                         " LSP %s: Invalid IP or MAC", token, lsp);
+            ok = false;
+            break;
         }
-        n_ps_addrs++;
     }
 
-    if (!n_ps_addrs) {
-        free(ps_addrs);
+    free(tokstr);
+
+vrrp_check:
+    if (vrrpv3 && vector_is_empty(&ps_addr->vrrp4) &&
+        vector_is_empty(&ps_addr->vrrp6)) {
+        vector_push(&ps_addr->vrrp4, &maddr_any_vrrp4);
+        vector_push(&ps_addr->vrrp6, &maddr_any_vrrp6);
+    }
+
+    return ok;
+}
+
+static void
+consider_port_sec_flows(const struct sbrec_port_binding *pb,
+                        struct ovn_desired_flow_table *flow_table)
+{
+    if (!pb->n_port_security) {
         return;
     }
 
@@ -3037,48 +3255,37 @@ consider_port_sec_flows(const struct sbrec_port_binding 
*pb,
     uint64_t stub[1024 / 8];
     struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(stub);
 
-    build_in_port_sec_default_flows(pb, &match, &ofpacts, flow_table);
-
-    for (size_t i = 0; i < n_ps_addrs; i++) {
-        build_in_port_sec_no_ip_flows(pb, &ps_addrs[i], &match, &ofpacts,
-                                      flow_table);
-        build_in_port_sec_ip4_flows(pb, &ps_addrs[i], &match, &ofpacts,
-                                    flow_table);
-        build_in_port_sec_arp_flows(pb, &ps_addrs[i], &match, &ofpacts,
-                                    flow_table);
-        build_in_port_sec_ip6_flows(pb, &ps_addrs[i], &match, &ofpacts,
-                                    flow_table);
-        build_in_port_sec_nd_flows(pb, &ps_addrs[i], &match, &ofpacts,
-                                   flow_table);
-    }
+    bool flows_installed = false;
+    struct port_security_addresses ps_addr = (struct port_security_addresses) {
+        .phys_addr = eth_addr_zero,
+        .vrrp4 = VECTOR_EMPTY_INITIALIZER(struct masked_eth_addr),
+        .vrrp6 = VECTOR_EMPTY_INITIALIZER(struct masked_eth_addr),
+        .ip4 = VECTOR_EMPTY_INITIALIZER(struct masked_ip4_addr),
+        .ip6 = VECTOR_EMPTY_INITIALIZER(struct masked_ip6_addr),
+    };
 
-    /* Out port security. */
+    for (size_t i = 0; i < pb->n_port_security; i++) {
+        if (port_security_addresses_parse_entry(pb->port_security[i],
+                                                pb->logical_port, &ps_addr)) {
+            build_port_sec_entry_flows(pb, &ps_addr, &match,
+                                       &ofpacts, flow_table);
+            flows_installed = true;
+        }
 
-    /* Add the below logical flow equivalent OF rules in 'out_port_sec_nd'
-     * table.
-     * priority: 80
-     * match - "outport == pb->logical_port"
-     * action - "port_sec_failed = 1;"
-     * descrption: "Drop all traffic"
-     */
-    reset_match_for_port_sec_flows(pb, MFF_LOG_OUTPORT, &match);
-    build_port_sec_deny_action(&ofpacts);
-    ofctrl_add_flow(flow_table, OFTABLE_CHK_OUT_PORT_SEC, 80,
-                    pb->header_.uuid.parts[0], &match, &ofpacts,
-                    &pb->header_.uuid);
+        vector_clear(&ps_addr.vrrp4);
+        vector_clear(&ps_addr.vrrp6);
+        vector_clear(&ps_addr.ip4);
+        vector_clear(&ps_addr.ip6);
+    }
 
-    for (size_t i = 0; i < n_ps_addrs; i++) {
-        build_out_port_sec_no_ip_flows(pb, &ps_addrs[i], &match, &ofpacts,
-                                       flow_table);
-        build_out_port_sec_ip4_flows(pb, &ps_addrs[i], &match, &ofpacts,
-                                       flow_table);
-        build_out_port_sec_ip6_flows(pb, &ps_addrs[i], &match, &ofpacts,
-                                       flow_table);
+    if (flows_installed) {
+        build_in_port_sec_default_flows(pb, &match, &ofpacts, flow_table);
+        build_out_port_sec_default_flows(pb, &match, &ofpacts, flow_table);
     }
 
     ofpbuf_uninit(&ofpacts);
-    for (size_t i = 0; i < n_ps_addrs; i++) {
-        destroy_lport_addresses(&ps_addrs[i]);
-    }
-    free(ps_addrs);
+    vector_destroy(&ps_addr.vrrp4);
+    vector_destroy(&ps_addr.vrrp6);
+    vector_destroy(&ps_addr.ip4);
+    vector_destroy(&ps_addr.ip6);
 }
diff --git a/ovn-nb.xml b/ovn-nb.xml
index e9ca27413..a0a465be4 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -2057,6 +2057,15 @@
           addresses within an element may be space or comma separated.
         </p>
 
+        <p>
+          There is also special prefix "VRRPv3" that allows specification of
+          single physical MAC and multiple VRRPv3 MAC addresses. The format
+          allows the same definition of multiple IP addresses associated with
+          the MACs specified. "VRRPv3" without single physical MAC translates
+          allowing traffic for the whole "VRRPv3" range of MACs. See more in
+          the examples.
+        </p>
+
         <p>
           This column is provided as a convenience to cloud management systems,
           but all of the features that it implements can be implemented as ACLs
@@ -2102,6 +2111,30 @@
             255.255.255.255, and any address in 224.0.0.0/4.  The host may not
             send or receive any IPv6 (including IPv6 Neighbor Discovery) 
traffic.
           </dd>
+
+          <dt><code>"VRRPv3 &lt;PHYSICAL_MAC&gt;"</code></dt>
+          <dd>
+            The host may send traffic from and receive traffic to the
+            specified physical MAC addresses, and to all VRRPv3 MAC addresses.
+            This also affects the permutations of inner MAC for ARP/ND. The
+            ARP/ND can be sent with physical MAC as a source and the inner
+            SHA/TLL/SLL can be the physical MAC or any VRRPv3 MAC.
+          </dd>
+
+          <dt><code>"VRRPv3 &lt;PHYSICAL_MAC&gt;
+                    &lt;VRRPV3_MACv4_1&gt;/[&lt;MASK1&gt;]
+                    &lt;VRRPV3_MACv4_N&gt;
+                    &lt;VRRPV3_MACv6_1&gt;/[&lt;MASK2&gt;]
+                    &lt;VRRPV3_MACv6_N&gt;"</code></dt>
+          <dd>
+            The host may send traffic from and receive traffic to the
+            specified physical MAC addresses, and to all VRRPv3 MAC addresses
+            specified in the option. Also note that the MAC addresses can
+            be provided with a mask between /40 and /48 prefix.
+            This also affects the permutations of inner MAC for ARP/ND. The
+            ARP/ND can be sent with physical MAC as a source and the inner
+            SHA/TLL/SLL can be the physical MAC or provided VRRPv3 MAC.
+          </dd>
         </dl>
       </column>
     </group>
diff --git a/tests/ovn.at b/tests/ovn.at
index e9e754a0a..f76281762 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -44244,3 +44244,754 @@ 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 - VRRPv3 ARP/ND])
+AT_SKIP_IF([test $HAVE_SCAPY = no])
+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 ovn-nbctl ls-add ls \
+    -- set logical_switch ls other-config:requested-tnl-key=1
+
+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" \
+    -- set logical_switch_port lsp1 options:requested-tnl-key=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" \
+    -- set logical_switch_port lsp2 options:requested-tnl-key=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')
+    ")
+    check as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
+
+    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')
+    ")
+    check as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
+
+    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') /
+            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:00:00:01', src='00:00:00:00:10:01') /
+        IPv6(src='fd10::1', dst='ff02::1:ff00:2') /
+        ICMPv6ND_NS(tgt='fd10::2') /
+        ICMPv6NDOptSrcLLAddr(lladdr='00:00:5e:00:02:05')
+    ")
+    check as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
+
+    packet=$(fmt_pkt "
+        Ether(dst='33:33:ff:00:00:01', src='00:00:00:00:10:01') /
+        IPv6(src='fd10::1', dst='ff02::1:ff00:1') /
+        ICMPv6ND_NA(tgt='fd10::1') /
+        ICMPv6NDOptDstLLAddr(lladdr='00:00:5e:00:02:05')
+    ")
+    check as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
+
+    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])
+
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [1])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC_ND | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [1])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_OUT_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [1])
+
+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])
+
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=80,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=95,arp,reg14=0x1,metadata=0x1 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC_ND | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, priority=80,arp,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=135 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=136 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_sha=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_OUT_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_OUT_PORT_SEC, priority=80,reg15=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0->NXM_NX_REG10[[12]]
+])
+
+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])
+
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=80,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=131,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=135,icmp_code=0
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=143,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ip,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_src=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=fd10::1
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=fe80::200:ff:fe00:1001
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,udp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_src=0.0.0.0,nw_dst=255.255.255.255,tp_src=68,tp_dst=67
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=95,arp,reg14=0x1,metadata=0x1 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC_ND | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, priority=80,arp,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=135 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=136 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_spa=192.168.10.1,arp_sha=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fd10::1,nd_tll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fd10::1,nd_tll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:1001,nd_tll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:1001,nd_tll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_OUT_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_OUT_PORT_SEC, priority=80,reg15=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=224.0.0.0/4
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=255.255.255.255
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=fd10::1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=fe80::200:ff:fe00:1001
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=ff00::/8
 actions=load:0->NXM_NX_REG10[[12]]
+])
+
+
+AS_BOX([With MAC only port security, VRRPv3=any])
+reset_pcap_and_expected
+check ovn-nbctl --wait=hv lsp-set-port-security lsp1 "VRRPv3 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])
+
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=80,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:01:00/ff:ff:ff:ff:ff:00 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:00/ff:ff:ff:ff:ff:00 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=95,arp,reg14=0x1,metadata=0x1 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC_ND | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, priority=80,arp,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=135 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=136 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_sha=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_sha=00:00:5e:00:01:00/ff:ff:ff:ff:ff:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:5e:00:02:00/ff:ff:ff:ff:ff:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:5e:00:02:00/ff:ff:ff:ff:ff:00
 actions=load:0->NXM_NX_REG10[[12]]
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_OUT_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_OUT_PORT_SEC, priority=80,reg15=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:00/ff:ff:ff:ff:ff:00 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:00/ff:ff:ff:ff:ff:00 
actions=load:0->NXM_NX_REG10[[12]]
+])
+
+AS_BOX([With MAC + IP port security, VRRPv3=any])
+reset_pcap_and_expected
+check ovn-nbctl --wait=hv lsp-set-port-security lsp1 "VRRPv3 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])
+
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=80,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=131,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=135,icmp_code=0
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=143,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:00/ff:ff:ff:ff:ff:00,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=131,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:00/ff:ff:ff:ff:ff:00,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=135,icmp_code=0
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:00/ff:ff:ff:ff:ff:00,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=143,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ip,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_src=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ip,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:01:00/ff:ff:ff:ff:ff:00,nw_src=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=fd10::1
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=fe80::200:ff:fe00:1001
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:00/ff:ff:ff:ff:ff:00,ipv6_src=fd10::1
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:00/ff:ff:ff:ff:ff:00,ipv6_src=fe80::200:5eff:fe00:200/120
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,udp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_src=0.0.0.0,nw_dst=255.255.255.255,tp_src=68,tp_dst=67
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,udp,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:01:00/ff:ff:ff:ff:ff:00,nw_src=0.0.0.0,nw_dst=255.255.255.255,tp_src=68,tp_dst=67
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=95,arp,reg14=0x1,metadata=0x1 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC_ND | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, priority=80,arp,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=135 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=136 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_spa=192.168.10.1,arp_sha=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_spa=192.168.10.1,arp_sha=00:00:5e:00:01:00/ff:ff:ff:ff:ff:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:5e:00:02:00/ff:ff:ff:ff:ff:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fd10::1,nd_tll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fd10::1,nd_tll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fd10::1,nd_tll=00:00:5e:00:02:00/ff:ff:ff:ff:ff:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:1001,nd_tll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:1001,nd_tll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:1001,nd_tll=00:00:5e:00:02:00/ff:ff:ff:ff:ff:00
 actions=load:0->NXM_NX_REG10[[12]]
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_OUT_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_OUT_PORT_SEC, priority=80,reg15=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:00/ff:ff:ff:ff:ff:00 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:00/ff:ff:ff:ff:ff:00 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:00/ff:ff:ff:ff:ff:00
 actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:00/ff:ff:ff:ff:ff:00
 actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=224.0.0.0/4
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=255.255.255.255
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:00/ff:ff:ff:ff:ff:00,nw_dst=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:00/ff:ff:ff:ff:ff:00,nw_dst=224.0.0.0/4
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:00/ff:ff:ff:ff:ff:00,nw_dst=255.255.255.255
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=fd10::1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=fe80::200:ff:fe00:1001
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=ff00::/8
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:00/ff:ff:ff:ff:ff:00,ipv6_dst=fd10::1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:00/ff:ff:ff:ff:ff:00,ipv6_dst=fe80::200:5eff:fe00:200/120
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:00/ff:ff:ff:ff:ff:00,ipv6_dst=ff00::/8
 actions=load:0->NXM_NX_REG10[[12]]
+])
+
+AS_BOX([With MAC only port security, VRRPv3 valid IPv4])
+reset_pcap_and_expected
+check ovn-nbctl --wait=hv lsp-set-port-security lsp1 "VRRPv3 00:00:00:00:10:01 
00:00:5e:00:01:05"
+
+test_arp no
+test_nd yes
+
+OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
+OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [vif2.expected])
+
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=80,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:01:05 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=95,arp,reg14=0x1,metadata=0x1 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC_ND | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, priority=80,arp,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=135 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=136 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_sha=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_sha=00:00:5e:00:01:05
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_OUT_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_OUT_PORT_SEC, priority=80,reg15=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:05 
actions=load:0->NXM_NX_REG10[[12]]
+])
+
+AS_BOX([With MAC + IP port security, VRRPv3 valid IPv4])
+reset_pcap_and_expected
+check ovn-nbctl --wait=hv lsp-set-port-security lsp1 "VRRPv3 00:00:00:00:10:01 
00:00:5e:00:01:05 192.168.10.1 fd10::1"
+
+test_arp no
+test_nd yes
+
+OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
+OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [vif2.expected])
+
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=80,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=131,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=135,icmp_code=0
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=143,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ip,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_src=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ip,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:01:05,nw_src=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=fd10::1
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=fe80::200:ff:fe00:1001
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,udp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_src=0.0.0.0,nw_dst=255.255.255.255,tp_src=68,tp_dst=67
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,udp,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:01:05,nw_src=0.0.0.0,nw_dst=255.255.255.255,tp_src=68,tp_dst=67
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=95,arp,reg14=0x1,metadata=0x1 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC_ND | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, priority=80,arp,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=135 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=136 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_spa=192.168.10.1,arp_sha=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_spa=192.168.10.1,arp_sha=00:00:5e:00:01:05
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fd10::1,nd_tll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fd10::1,nd_tll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:1001,nd_tll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:1001,nd_tll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_OUT_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_OUT_PORT_SEC, priority=80,reg15=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:05 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:05 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=224.0.0.0/4
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=255.255.255.255
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:05,nw_dst=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:05,nw_dst=224.0.0.0/4
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:05,nw_dst=255.255.255.255
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=fd10::1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=fe80::200:ff:fe00:1001
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=ff00::/8
 actions=load:0->NXM_NX_REG10[[12]]
+])
+
+AS_BOX([With MAC only port security, VRRPv3 valid IPv6])
+reset_pcap_and_expected
+check ovn-nbctl --wait=hv lsp-set-port-security lsp1 "VRRPv3 00:00:00:00:10:01 
00:00:5e:00:02:05"
+
+test_arp yes
+test_nd no
+
+OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
+OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [vif2.expected])
+
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=80,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:05 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=95,arp,reg14=0x1,metadata=0x1 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC_ND | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, priority=80,arp,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=135 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=136 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_sha=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:5e:00:02:05
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:5e:00:02:05
 actions=load:0->NXM_NX_REG10[[12]]
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_OUT_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_OUT_PORT_SEC, priority=80,reg15=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:05 
actions=load:0->NXM_NX_REG10[[12]]
+])
+
+AS_BOX([With MAC + IP port security, VRRPv3 valid IPv6])
+reset_pcap_and_expected
+check ovn-nbctl --wait=hv lsp-set-port-security lsp1 "VRRPv3 00:00:00:00:10:01 
00:00:5e:00:02:05 192.168.10.1 fd10::1"
+
+test_arp yes
+test_nd no
+
+OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
+OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [vif2.expected])
+
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=80,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=131,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=135,icmp_code=0
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=143,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:05,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=131,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:05,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=135,icmp_code=0
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:05,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=143,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ip,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_src=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=fd10::1
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=fe80::200:ff:fe00:1001
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:05,ipv6_src=fd10::1
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:05,ipv6_src=fe80::200:5eff:fe00:205
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,udp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_src=0.0.0.0,nw_dst=255.255.255.255,tp_src=68,tp_dst=67
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=95,arp,reg14=0x1,metadata=0x1 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC_ND | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, priority=80,arp,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=135 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=136 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_spa=192.168.10.1,arp_sha=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:5e:00:02:05
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fd10::1,nd_tll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fd10::1,nd_tll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fd10::1,nd_tll=00:00:5e:00:02:05
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:1001,nd_tll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:1001,nd_tll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:1001,nd_tll=00:00:5e:00:02:05
 actions=load:0->NXM_NX_REG10[[12]]
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_OUT_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_OUT_PORT_SEC, priority=80,reg15=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:05 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:05 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=224.0.0.0/4
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=255.255.255.255
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=fd10::1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=fe80::200:ff:fe00:1001
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=ff00::/8
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:05,ipv6_dst=fd10::1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:05,ipv6_dst=fe80::200:5eff:fe00:205
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:05,ipv6_dst=ff00::/8
 actions=load:0->NXM_NX_REG10[[12]]
+])
+
+AS_BOX([With MAC only port security, VRRPv3 valid IPv4 + IPv6])
+reset_pcap_and_expected
+check ovn-nbctl --wait=hv lsp-set-port-security lsp1 "VRRPv3 00:00:00:00:10:01 
00:00:5e:00:01:05 00:00:5e:00:02:05"
+
+test_arp no
+test_nd no
+
+OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
+OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [vif2.expected])
+
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=80,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:01:05 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:05 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=95,arp,reg14=0x1,metadata=0x1 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC_ND | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, priority=80,arp,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=135 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=136 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_sha=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_sha=00:00:5e:00:01:05
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:5e:00:02:05
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:5e:00:02:05
 actions=load:0->NXM_NX_REG10[[12]]
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_OUT_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_OUT_PORT_SEC, priority=80,reg15=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:05 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:05 
actions=load:0->NXM_NX_REG10[[12]]
+])
+
+AS_BOX([With MAC + IP port security, VRRPv3 valid IPv4 + IPv6])
+reset_pcap_and_expected
+check ovn-nbctl --wait=hv lsp-set-port-security lsp1 "VRRPv3 00:00:00:00:10:01 
00:00:5e:00:01:05 00:00:5e:00:02:05 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])
+
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=80,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=131,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=135,icmp_code=0
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=143,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:05,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=131,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:05,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=135,icmp_code=0
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:05,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=143,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ip,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_src=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ip,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:01:05,nw_src=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=fd10::1
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=fe80::200:ff:fe00:1001
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:05,ipv6_src=fd10::1
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:05,ipv6_src=fe80::200:5eff:fe00:205
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,udp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_src=0.0.0.0,nw_dst=255.255.255.255,tp_src=68,tp_dst=67
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,udp,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:01:05,nw_src=0.0.0.0,nw_dst=255.255.255.255,tp_src=68,tp_dst=67
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=95,arp,reg14=0x1,metadata=0x1 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC_ND | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, priority=80,arp,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=135 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=136 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_spa=192.168.10.1,arp_sha=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_spa=192.168.10.1,arp_sha=00:00:5e:00:01:05
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:5e:00:02:05
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fd10::1,nd_tll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fd10::1,nd_tll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fd10::1,nd_tll=00:00:5e:00:02:05
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:1001,nd_tll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:1001,nd_tll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:1001,nd_tll=00:00:5e:00:02:05
 actions=load:0->NXM_NX_REG10[[12]]
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_OUT_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_OUT_PORT_SEC, priority=80,reg15=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:05 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:05 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:05 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:05 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=224.0.0.0/4
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=255.255.255.255
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:05,nw_dst=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:05,nw_dst=224.0.0.0/4
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:05,nw_dst=255.255.255.255
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=fd10::1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=fe80::200:ff:fe00:1001
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=ff00::/8
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:05,ipv6_dst=fd10::1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:05,ipv6_dst=fe80::200:5eff:fe00:205
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:05,ipv6_dst=ff00::/8
 actions=load:0->NXM_NX_REG10[[12]]
+])
+
+AS_BOX([With MAC only port security, VRRPv3 masked IPv4 + IPv6])
+reset_pcap_and_expected
+check ovn-nbctl --wait=hv lsp-set-port-security lsp1 "VRRPv3 00:00:00:00:10:01 
00:00:5e:00:01:00/45 00:00:5e:00:02:00/45"
+
+test_arp no
+test_nd no
+
+OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
+OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [vif2.expected])
+
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=80,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:01:00/ff:ff:ff:ff:ff:f8 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:00/ff:ff:ff:ff:ff:f8 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=95,arp,reg14=0x1,metadata=0x1 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC_ND | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, priority=80,arp,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=135 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=136 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_sha=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_sha=00:00:5e:00:01:00/ff:ff:ff:ff:ff:f8
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:5e:00:02:00/ff:ff:ff:ff:ff:f8
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:5e:00:02:00/ff:ff:ff:ff:ff:f8
 actions=load:0->NXM_NX_REG10[[12]]
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_OUT_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_OUT_PORT_SEC, priority=80,reg15=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:00/ff:ff:ff:ff:ff:f8 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:00/ff:ff:ff:ff:ff:f8 
actions=load:0->NXM_NX_REG10[[12]]
+])
+
+AS_BOX([With MAC + IP port security, VRRPv3 masked IPv4 + IPv6])
+reset_pcap_and_expected
+check ovn-nbctl --wait=hv lsp-set-port-security lsp1 "VRRPv3 00:00:00:00:10:01 
00:00:5e:00:01:00/45 00:00:5e:00:02:00/45 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])
+
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=80,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=131,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=135,icmp_code=0
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=143,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:00/ff:ff:ff:ff:ff:f8,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=131,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:00/ff:ff:ff:ff:ff:f8,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=135,icmp_code=0
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:00/ff:ff:ff:ff:ff:f8,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=143,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ip,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_src=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ip,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:01:00/ff:ff:ff:ff:ff:f8,nw_src=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=fd10::1
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=fe80::200:ff:fe00:1001
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:00/ff:ff:ff:ff:ff:f8,ipv6_src=fd10::1
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:00/ff:ff:ff:ff:ff:f8,ipv6_src=fe80::200:5eff:fe00:200/125
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,udp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_src=0.0.0.0,nw_dst=255.255.255.255,tp_src=68,tp_dst=67
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,udp,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:01:00/ff:ff:ff:ff:ff:f8,nw_src=0.0.0.0,nw_dst=255.255.255.255,tp_src=68,tp_dst=67
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=95,arp,reg14=0x1,metadata=0x1 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC_ND | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, priority=80,arp,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=135 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=136 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_spa=192.168.10.1,arp_sha=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_spa=192.168.10.1,arp_sha=00:00:5e:00:01:00/ff:ff:ff:ff:ff:f8
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:5e:00:02:00/ff:ff:ff:ff:ff:f8
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fd10::1,nd_tll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fd10::1,nd_tll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fd10::1,nd_tll=00:00:5e:00:02:00/ff:ff:ff:ff:ff:f8
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:1001,nd_tll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:1001,nd_tll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:1001,nd_tll=00:00:5e:00:02:00/ff:ff:ff:ff:ff:f8
 actions=load:0->NXM_NX_REG10[[12]]
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_OUT_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_OUT_PORT_SEC, priority=80,reg15=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:00/ff:ff:ff:ff:ff:f8 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:00/ff:ff:ff:ff:ff:f8 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:00/ff:ff:ff:ff:ff:f8
 actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:00/ff:ff:ff:ff:ff:f8
 actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=224.0.0.0/4
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=255.255.255.255
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:00/ff:ff:ff:ff:ff:f8,nw_dst=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:00/ff:ff:ff:ff:ff:f8,nw_dst=224.0.0.0/4
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:00/ff:ff:ff:ff:ff:f8,nw_dst=255.255.255.255
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=fd10::1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=fe80::200:ff:fe00:1001
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=ff00::/8
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:00/ff:ff:ff:ff:ff:f8,ipv6_dst=fd10::1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:00/ff:ff:ff:ff:ff:f8,ipv6_dst=fe80::200:5eff:fe00:200/125
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:00/ff:ff:ff:ff:ff:f8,ipv6_dst=ff00::/8
 actions=load:0->NXM_NX_REG10[[12]]
+])
+
+AS_BOX([With MAC + IP port security, VRRPv3 valid but different IPv4 + IPv6])
+reset_pcap_and_expected
+check ovn-nbctl --wait=hv lsp-set-port-security lsp1 "VRRPv3 00:00:00:00:10:01 
00:00:5e:00:01:01 00:00:5e:00:02: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])
+
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=80,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=131,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=135,icmp_code=0
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=143,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=131,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=135,icmp_code=0
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:01,ipv6_src=::,ipv6_dst=ff02::/16,icmp_type=143,icmp_code=0
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ip,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_src=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ip,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:01:01,nw_src=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=fd10::1
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,ipv6_src=fe80::200:ff:fe00:1001
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:01,ipv6_src=fd10::1
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,ipv6,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:02:01,ipv6_src=fe80::200:5eff:fe00:201
 actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,udp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_src=0.0.0.0,nw_dst=255.255.255.255,tp_src=68,tp_dst=67
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, 
priority=90,udp,reg14=0x1,metadata=0x1,dl_src=00:00:5e:00:01:01,nw_src=0.0.0.0,nw_dst=255.255.255.255,tp_src=68,tp_dst=67
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC, priority=95,arp,reg14=0x1,metadata=0x1 
actions=resubmit(,OFTABLE_CHK_IN_PORT_SEC_ND)
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_IN_PORT_SEC_ND | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, priority=80,arp,reg14=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=135 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=136 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_spa=192.168.10.1,arp_sha=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,arp,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,arp_spa=192.168.10.1,arp_sha=00:00:5e:00:01:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:5e:00:02:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fd10::1,nd_tll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fd10::1,nd_tll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fd10::1,nd_tll=00:00:5e:00:02:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:1001,nd_tll=00:00:00:00:00:00
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:1001,nd_tll=00:00:00:00:10:01
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_IN_PORT_SEC_ND, 
priority=90,icmp6,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:10:01,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:1001,nd_tll=00:00:5e:00:02:01
 actions=load:0->NXM_NX_REG10[[12]]
+])
+AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_CHK_OUT_PORT_SEC | 
ofctl_strip_all | sort | grep -v NXST_FLOW], [0], [dnl
+ table=OFTABLE_CHK_OUT_PORT_SEC, priority=80,reg15=0x1,metadata=0x1 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:01 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=85,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:01 
actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:01 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=90,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:01 
actions=load:0x1->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=224.0.0.0/4
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,nw_dst=255.255.255.255
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:01,nw_dst=192.168.10.1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:01,nw_dst=224.0.0.0/4
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ip,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:01:01,nw_dst=255.255.255.255
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=fd10::1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=fe80::200:ff:fe00:1001
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:00:00:10:01,ipv6_dst=ff00::/8
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:01,ipv6_dst=fd10::1
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:01,ipv6_dst=fe80::200:5eff:fe00:201
 actions=load:0->NXM_NX_REG10[[12]]
+ table=OFTABLE_CHK_OUT_PORT_SEC, 
priority=95,ipv6,reg15=0x1,metadata=0x1,dl_dst=00:00:5e:00:02:01,ipv6_dst=ff00::/8
 actions=load:0->NXM_NX_REG10[[12]]
+])
+
+OVN_CLEANUP([hv1
+/Invalid VRRPv3 MAC address specified/d])
+AT_CLEANUP
+])
-- 
2.52.0

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to