The option activation-strategy supported only "rarp", add "garp" and
"na" to supported protocols. At the same time change to option to
accept comma separated list, which allows CMS to set any combination
of the supported protocols for activation.

Reported-at: https://issues.redhat.com/browse/FDP-1042
Signed-off-by: Ales Musil <[email protected]>
---
 NEWS                  |   3 +
 controller/physical.c | 191 ++++++++++++++++++-----
 ovn-nb.xml            |  10 +-
 ovn-sb.xml            |  17 +-
 tests/ovn.at          | 355 ++++++++++++++++++++++--------------------
 5 files changed, 364 insertions(+), 212 deletions(-)

diff --git a/NEWS b/NEWS
index 455fc12b6..1243c47ec 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,8 @@
 Post v25.03.0
 -------------
+  - Add additional protocol support for options:activation-strategy. The new
+    supported protocols are gARP and NA. The option now supports comma
+    separated to specify selected group of protocols.
 
 OVN v25.03.0 - xx xxx xxxx
 --------------------------
diff --git a/controller/physical.c b/controller/physical.c
index 69bf05347..6737e812c 100644
--- a/controller/physical.c
+++ b/controller/physical.c
@@ -1228,33 +1228,124 @@ enum access_type {
     PORT_HA_REMOTE,
 };
 
+enum activation_strategy {
+    ACTIVATION_RARP = 1 << 0,
+    ACTIVATION_GARP = 1 << 1,
+    ACTIVATION_NA = 1 << 2,
+    ACTIVATION_IP4 = ACTIVATION_GARP | ACTIVATION_RARP,
+    ACTIVATION_IP6 = ACTIVATION_NA,
+};
+
 static void
-setup_rarp_activation_strategy(const struct sbrec_port_binding *binding,
-                               ofp_port_t ofport, struct zone_ids *zone_ids,
-                               struct ovn_desired_flow_table *flow_table)
+setup_arp_activation_strategy(const struct sbrec_port_binding *binding,
+                              ofp_port_t  ofport, struct zone_ids *zone_ids,
+                              struct ofpbuf *ofpacts, struct eth_addr mac,
+                              ovs_be32 ip, bool arp,
+                              struct ovn_desired_flow_table *flow_table)
 {
     struct match match = MATCH_CATCHALL_INITIALIZER;
-    uint64_t stub[1024 / 8];
-    struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(stub);
 
-    /* Unblock the port on ingress RARP. */
-    match_set_dl_type(&match, htons(ETH_TYPE_RARP));
+    /* match: arp/rarp, in_port=<OFPORT>, dl_src=<MAC>, arp_sha=<MAC>,
+     * arp_spa=<IP>, arp_tpa=<IP> */
+    match_set_dl_type(&match, htons(arp ? ETH_TYPE_ARP : ETH_TYPE_RARP));
     match_set_in_port(&match, ofport);
+    match_set_dl_src(&match, mac);
+    match_set_arp_sha(&match, mac);
+    match_set_arp_spa_masked(&match, ip, OVS_BE32_MAX);
+    match_set_arp_tpa_masked(&match, ip, OVS_BE32_MAX);
 
-    load_logical_ingress_metadata(binding, zone_ids, 0, NULL, &ofpacts, true);
-
+    load_logical_ingress_metadata(binding, zone_ids, 0, NULL, ofpacts, true);
+    /* Unblock the traffic when it matches specified strategy. */
     encode_controller_op(ACTION_OPCODE_ACTIVATION_STRATEGY_RARP,
-                         NX_CTLR_NO_METER, &ofpacts);
+                         NX_CTLR_NO_METER, ofpacts);
+    put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, ofpacts);
 
-    put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, &ofpacts);
+    ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 1010,
+                    binding->header_.uuid.parts[0],
+                    &match, ofpacts, &binding->header_.uuid);
+    ofpbuf_clear(ofpacts);
+}
+
+static void
+setup_nd_na_activation_strategy(const struct sbrec_port_binding *binding,
+                                ofp_port_t  ofport, struct zone_ids *zone_ids,
+                                struct ofpbuf *ofpacts, struct eth_addr mac,
+                                const struct in6_addr *ip,
+                                struct ovn_desired_flow_table *flow_table)
+{
+    struct match match = MATCH_CATCHALL_INITIALIZER;
+
+    /* match: icmp6, in_port=<OFPORT>, icmp_type=136, icmp_code=0,
+     * ipv6_src=<IP>, nd_target=<IP>, nd_tll=<MAC> */
+    match_set_dl_type(&match, htons(ETH_TYPE_IPV6));
+    match_set_in_port(&match, ofport);
+    match_set_nw_proto(&match, IPPROTO_ICMPV6);
+    match_set_icmp_type(&match, 136);
+    match_set_icmp_code(&match, 0);
+    match_set_ipv6_src(&match, ip);
+    match_set_nd_target(&match, ip);
+    match_set_arp_tha(&match, mac);
+
+    load_logical_ingress_metadata(binding, zone_ids, 0, NULL, ofpacts, true);
+    /* Unblock the traffic when it matches specified strategy. */
+    encode_controller_op(ACTION_OPCODE_ACTIVATION_STRATEGY_RARP,
+                         NX_CTLR_NO_METER, ofpacts);
+    put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, ofpacts);
 
     ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 1010,
                     binding->header_.uuid.parts[0],
-                    &match, &ofpacts, &binding->header_.uuid);
-    ofpbuf_clear(&ofpacts);
+                    &match, ofpacts, &binding->header_.uuid);
+    ofpbuf_clear(ofpacts);
+}
+
+static void
+setup_activation_strategy_flows(const struct sbrec_port_binding *binding,
+                                ofp_port_t ofport, struct zone_ids *zone_ids,
+                                uint32_t activation_strategies,
+                                const struct lport_addresses *addresses,
+                                struct ovn_desired_flow_table *flow_table)
+{
+    uint64_t stub[1024 / 8];
+    struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(stub);
+
+    bool ip4_activation = (activation_strategies & ACTIVATION_IP4) != 0;
+    bool ip6_activation = (activation_strategies & ACTIVATION_IP6) != 0;
+
+    for (size_t i = 0; ip4_activation && i < addresses->n_ipv4_addrs; i++) {
+        const struct ipv4_netaddr *address = &addresses->ipv4_addrs[i];
+        if (activation_strategies & ACTIVATION_GARP) {
+            setup_arp_activation_strategy(binding, ofport, zone_ids, &ofpacts,
+                                          addresses->ea, address->addr, true,
+                                          flow_table);
+        }
+
+        if (activation_strategies & ACTIVATION_RARP) {
+            setup_arp_activation_strategy(binding, ofport, zone_ids, &ofpacts,
+                                          addresses->ea, address->addr, false,
+                                          flow_table);
+        }
+    }
+
+    /* Always add LLA address activation if there is any IPv6 address. */
+    if (ip6_activation && addresses->n_ipv6_addrs) {
+        struct in6_addr lla;
+        in6_generate_lla(addresses->ea, &lla);
+
+        setup_nd_na_activation_strategy(binding, ofport, zone_ids, &ofpacts,
+                                        addresses->ea, &lla, flow_table);
+    }
+
+    for (size_t i = 0; ip6_activation && i < addresses->n_ipv6_addrs; i++) {
+        const struct ipv6_netaddr *address = &addresses->ipv6_addrs[i];
+        if (activation_strategies & ACTIVATION_NA) {
+            setup_nd_na_activation_strategy(binding, ofport, zone_ids,
+                                            &ofpacts, addresses->ea,
+                                            &address->addr, flow_table);
+        }
+    }
 
     /* Block all non-RARP traffic for the port, both directions. */
-    match_init_catchall(&match);
+    struct match match = MATCH_CATCHALL_INITIALIZER;
     match_set_in_port(&match, ofport);
 
     ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 1000,
@@ -1274,6 +1365,36 @@ setup_rarp_activation_strategy(const struct 
sbrec_port_binding *binding,
     ofpbuf_uninit(&ofpacts);
 }
 
+static uint32_t
+pb_parse_activation_strategy(const struct sbrec_port_binding *pb)
+{
+    static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+    uint32_t strategies = 0;
+
+    const char *strategy = smap_get(&pb->options, "activation-strategy");
+    if (strategy) {
+        char *save_ptr;
+        char *tokstr = xstrdup(strategy);
+        for (const char *name = strtok_r(tokstr, ",", &save_ptr);
+             name != NULL;
+             name = strtok_r(NULL, ",", &save_ptr)) {
+            if (!strcmp(name, "rarp")) {
+                strategies |= ACTIVATION_RARP;
+            } else if (!strcmp(name, "garp")) {
+                strategies |= ACTIVATION_GARP;
+            } else if (!strcmp(name, "na")) {
+                strategies |= ACTIVATION_NA;
+            } else {
+                VLOG_WARN_RL(&rl, "Unknown activation strategy defined for "
+                             "port %s: %s", pb->logical_port, name);
+            }
+        }
+        free(tokstr);
+    }
+
+    return strategies;
+}
+
 static void
 setup_activation_strategy(const struct sbrec_port_binding *binding,
                           const struct sbrec_chassis *chassis,
@@ -1281,28 +1402,28 @@ setup_activation_strategy(const struct 
sbrec_port_binding *binding,
                           ofp_port_t ofport, struct zone_ids *zone_ids,
                           struct ovn_desired_flow_table *flow_table)
 {
-    for (size_t i = 0; i < binding->n_additional_chassis; i++) {
-        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
-        if (binding->additional_chassis[i] == chassis) {
-            const char *strategy = smap_get(&binding->options,
-                                            "activation-strategy");
-            if (strategy
-                    && !lport_is_activated_by_activation_strategy(binding,
-                                                                  chassis)
-                    && !pinctrl_is_port_activated(dp_key, port_key)) {
-                if (!strcmp(strategy, "rarp")) {
-                    setup_rarp_activation_strategy(binding, ofport,
-                                                   zone_ids, flow_table);
-                } else {
-                    VLOG_WARN_RL(&rl,
-                                 "Unknown activation strategy defined for "
-                                 "port %s: %s",
-                                 binding->logical_port, strategy);
-                    return;
-                }
-            }
-            return;
+    if (!is_additional_chassis(binding, chassis)) {
+        return;
+    }
+
+    if (lport_is_activated_by_activation_strategy(binding, chassis) ||
+        pinctrl_is_port_activated(dp_key, port_key)) {
+        return;
+    }
+
+    uint32_t strategies = pb_parse_activation_strategy(binding);
+    if (!strategies) {
+        return;
+    }
+
+    for (size_t i = 0; i < binding->n_mac; i++) {
+        struct lport_addresses addresses;
+        if (!extract_lsp_addresses(binding->mac[i], &addresses)) {
+            continue;
         }
+        setup_activation_strategy_flows(binding, ofport, zone_ids, strategies,
+                                        &addresses, flow_table);
+        destroy_lport_addresses(&addresses);
     }
 }
 
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 3ab514651..48f00632a 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -1360,10 +1360,12 @@
           <ref column="requested-chassis"/>, specifies an activation strategy
           for all additional chassis. By default, no activation strategy is
           used, meaning additional port locations are immediately available for
-          use. When set to "rarp", the port is blocked for ingress and egress
-          communication until a RARP packet is sent from a new location. The
-          "rarp" strategy is useful in live migration scenarios for virtual
-          machines.
+          use. The option supports comma separated list where you can combine
+          3 protocols, "rarp", "garp" and "na". When any of the protocols is
+          set, the port is blocked for ingress and egress communication until
+          a specified protocol packet is sent from a new location. The
+          activation strategy is useful in live migration scenarios for
+          virtual machines.
         </column>
 
         <column name="options" key="iface-id-ver">
diff --git a/ovn-sb.xml b/ovn-sb.xml
index 39acb81a4..072c88ddb 100644
--- a/ovn-sb.xml
+++ b/ovn-sb.xml
@@ -3784,13 +3784,16 @@ tcp.flags = RST;
       </column>
 
       <column name="options" key="activation-strategy">
-        If used with multiple chassis set in <ref column="requested-chassis"/>,
-        specifies an activation strategy for all additional chassis. By
-        default, no activation strategy is used, meaning additional port
-        locations are immediately available for use. When set to "rarp", the
-        port is blocked for ingress and egress communication until a RARP
-        packet is sent from a new location. The "rarp" strategy is useful
-        in live migration scenarios for virtual machines.
+        If used with multiple chassis set in
+        <ref column="requested-chassis"/>, specifies an activation strategy
+        for all additional chassis. By default, no activation strategy is
+        used, meaning additional port locations are immediately available for
+        use. The option supports comma separated list where you can combine
+        3 protocols, "rarp", "garp" and "na". When any of the protocols is
+        set, the port is blocked for ingress and egress communication until
+        a specified protocol packet is sent from a new location. The
+        activation strategy is useful in live migration scenarios for
+        virtual machines.
       </column>
 
       <column name="options" key="additional-chassis-activated">
diff --git a/tests/ovn.at b/tests/ovn.at
index ec8ee8de7..ad31d8482 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -5428,7 +5428,7 @@ test_arp() {
 test_na() {
     local inport=$1 sha=$2 spa=$3 src=${4-$3}
     local request=$(fmt_pkt "Ether(dst='ff:ff:ff:ff:ff:ff', src='${sha}')/ \
-                             IPv6(dst='ff01::1', src='${src}')/ \
+                             IPv6(dst='ff02::1', src='${src}')/ \
                              ICMPv6ND_NA(tgt='${spa}')/ \
                              ICMPv6NDOptDstLLAddr(lladdr='${sha}')")
 
@@ -16487,205 +16487,228 @@ MULTICHASSIS_PATH_MTU_DISCOVERY_TEST([ipv6], 
[geneve], [1404])
 MULTICHASSIS_PATH_MTU_DISCOVERY_TEST([ipv4], [vxlan], [1432])
 MULTICHASSIS_PATH_MTU_DISCOVERY_TEST([ipv6], [vxlan], [1412])
 
-OVN_FOR_EACH_NORTHD([
-AT_SETUP([options:activation-strategy for logical port])
-AT_KEYWORDS([multi-chassis])
-AT_KEYWORDS([slowtest])
-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.11
-
-sim_add hv2
-as hv2
-check ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.12
-
-sim_add hv3
-as hv3
-check ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.13
-
-# Disable local ARP responder to pass ARP requests through tunnels
-check ovn-nbctl ls-add ls0 -- add Logical_Switch ls0 other_config 
vlan-passthru=true
-
-check ovn-nbctl lsp-add ls0 migrator
-check ovn-nbctl lsp-set-options migrator requested-chassis=hv1,hv2 \
-                                         activation-strategy=rarp
-
-check ovn-nbctl lsp-add ls0 first
-check ovn-nbctl lsp-set-options first requested-chassis=hv1
-check ovn-nbctl lsp-add ls0 second
-check ovn-nbctl lsp-set-options second requested-chassis=hv2
-check ovn-nbctl lsp-add ls0 outside
-check ovn-nbctl lsp-set-options outside requested-chassis=hv3
-
-check ovn-nbctl lsp-set-addresses migrator "00:00:00:00:00:10 10.0.0.10"
-check ovn-nbctl lsp-set-addresses first "00:00:00:00:00:01 10.0.0.1"
-check ovn-nbctl lsp-set-addresses second "00:00:00:00:00:02 10.0.0.2"
-check ovn-nbctl lsp-set-addresses outside "00:00:00:00:00:03 10.0.0.3"
-
-for hv in hv1 hv2; do
-    as $hv check ovs-vsctl -- add-port br-int migrator -- \
-        set Interface migrator external-ids:iface-id=migrator \
-                               options:tx_pcap=$hv/migrator-tx.pcap \
-                               options:rxq_pcap=$hv/migrator-rx.pcap
-done
-
-as hv1 check ovs-vsctl -- add-port br-int first -- \
-    set Interface first external-ids:iface-id=first
-as hv2 check ovs-vsctl -- add-port br-int second -- \
-    set Interface second external-ids:iface-id=second
-as hv3 check ovs-vsctl -- add-port br-int outside -- \
-    set Interface outside external-ids:iface-id=outside
-
-for hv in hv1 hv2 hv3; do
-    wait_row_count Chassis 1 name=$hv
-done
-hv1_uuid=$(fetch_column Chassis _uuid name=hv1)
-hv2_uuid=$(fetch_column Chassis _uuid name=hv2)
-hv3_uuid=$(fetch_column Chassis _uuid name=hv3)
+m4_define([ACTIVATION_STRATEGY_TEST],
+  [OVN_FOR_EACH_NORTHD([
+    AT_SETUP([options:activation-strategy=$1 for logical port])
+    AT_KEYWORDS([multi-chassis])
+    AT_KEYWORDS([slowtest])
+    AT_SKIP_IF([test $HAVE_SCAPY = no])
+    ovn_start
 
-wait_column "$hv1_uuid" Port_Binding chassis logical_port=migrator
-wait_column "$hv1_uuid" Port_Binding requested_chassis logical_port=migrator
-wait_column "$hv2_uuid" Port_Binding additional_chassis logical_port=migrator
-wait_column "$hv2_uuid" Port_Binding requested_additional_chassis 
logical_port=migrator
+    net_add n1
 
-wait_column "$hv1_uuid" Port_Binding chassis logical_port=first
-wait_column "$hv2_uuid" Port_Binding chassis logical_port=second
-wait_column "$hv3_uuid" Port_Binding chassis logical_port=outside
-
-OVN_POPULATE_ARP
+    sim_add hv1
+    as hv1
+    check ovs-vsctl add-br br-phys
+    ovn_attach n1 br-phys 192.168.0.11
 
-send_arp() {
-    local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 spa=$5 tpa=$6
-    local 
request=${eth_dst}${eth_src}08060001080006040001${eth_src}${spa}${eth_dst}${tpa}
-    as ${hv} ovs-appctl netdev-dummy/receive $inport $request
-    echo "${request}"
-}
+    sim_add hv2
+    as hv2
+    check ovs-vsctl add-br br-phys
+    ovn_attach n1 br-phys 192.168.0.12
 
-send_rarp() {
-    local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 spa=$5 tpa=$6
-    local 
request=${eth_dst}${eth_src}80350001080006040001${eth_src}${spa}${eth_dst}${tpa}
-    as ${hv} ovs-appctl netdev-dummy/receive $inport $request
-    echo "${request}"
-}
+    sim_add hv3
+    as hv3
+    check ovs-vsctl add-br br-phys
+    ovn_attach n1 br-phys 192.168.0.13
+
+    # Disable local ARP responder to pass ARP requests through tunnels
+    check ovn-nbctl ls-add ls0 -- add Logical_Switch ls0 other_config 
vlan-passthru=true
+
+    check ovn-nbctl lsp-add ls0 migrator
+    check ovn-nbctl lsp-set-options migrator requested-chassis=hv1,hv2 \
+                                             activation-strategy=$1
+
+    check ovn-nbctl lsp-add ls0 first
+    check ovn-nbctl lsp-set-options first requested-chassis=hv1
+    check ovn-nbctl lsp-add ls0 second
+    check ovn-nbctl lsp-set-options second requested-chassis=hv2
+    check ovn-nbctl lsp-add ls0 outside
+    check ovn-nbctl lsp-set-options outside requested-chassis=hv3
+
+    check ovn-nbctl lsp-set-addresses migrator "00:00:00:00:00:10 10.0.0.10 
fd10::10"
+    check ovn-nbctl lsp-set-addresses first "00:00:00:00:00:01 10.0.0.1"
+    check ovn-nbctl lsp-set-addresses second "00:00:00:00:00:02 10.0.0.2"
+    check ovn-nbctl lsp-set-addresses outside "00:00:00:00:00:03 10.0.0.3"
+
+    for hv in hv1 hv2; do
+        as $hv check ovs-vsctl -- add-port br-int migrator -- \
+            set Interface migrator external-ids:iface-id=migrator \
+                                   options:tx_pcap=$hv/migrator-tx.pcap \
+                                   options:rxq_pcap=$hv/migrator-rx.pcap
+    done
 
-reset_env() {
-    as hv1 reset_pcap_file migrator hv1/migrator
-    as hv2 reset_pcap_file migrator hv2/migrator
-    as hv1 reset_pcap_file first hv1/first
-    as hv2 reset_pcap_file second hv2/second
-    as hv3 reset_pcap_file outside hv3/outside
+    as hv1 check ovs-vsctl -- add-port br-int first -- \
+        set Interface first external-ids:iface-id=first
+    as hv2 check ovs-vsctl -- add-port br-int second -- \
+        set Interface second external-ids:iface-id=second
+    as hv3 check ovs-vsctl -- add-port br-int outside -- \
+        set Interface outside external-ids:iface-id=outside
 
-    for port in hv1/migrator hv2/migrator hv1/first hv2/second hv3/outside; do
-        : > $port.expected
+    for hv in hv1 hv2 hv3; do
+        wait_row_count Chassis 1 name=$hv
     done
-}
+    hv1_uuid=$(fetch_column Chassis _uuid name=hv1)
+    hv2_uuid=$(fetch_column Chassis _uuid name=hv2)
+    hv3_uuid=$(fetch_column Chassis _uuid name=hv3)
+
+    wait_column "$hv1_uuid" Port_Binding chassis logical_port=migrator
+    wait_column "$hv1_uuid" Port_Binding requested_chassis 
logical_port=migrator
+    wait_column "$hv2_uuid" Port_Binding additional_chassis 
logical_port=migrator
+    wait_column "$hv2_uuid" Port_Binding requested_additional_chassis 
logical_port=migrator
+
+    wait_column "$hv1_uuid" Port_Binding chassis logical_port=first
+    wait_column "$hv2_uuid" Port_Binding chassis logical_port=second
+    wait_column "$hv3_uuid" Port_Binding chassis logical_port=outside
+
+    OVN_POPULATE_ARP
+
+    send_arp() {
+        local hv=${1} inport=${2} op=${3} eth_src=${4} eth_dst=${5} spa=${6} 
tpa=${7}
+        local request=$(fmt_pkt "Ether(dst='${eth_dst}', src='${eth_src}')/ \
+                        ARP(op=${op}, hwsrc='${eth_src}', hwdst='${eth_dst}', \
+                        psrc='${spa}', pdst='${tpa}')")
+        as ${hv} ovs-appctl netdev-dummy/receive $inport $request
+        echo "${request}"
+    }
+
+    send_rarp() {
+        local hv=${1} inport=${2} eth_src=${3} spa=${4}
+        local request=$(fmt_pkt "Ether(dst='ff:ff:ff:ff:ff:ff', 
src='${eth_src}', type=0x8035)/ \
+                        ARP(op=1, hwsrc='${eth_src}', 
hwdst='00:00:00:00:00:00', \
+                        psrc='${spa}', pdst='${spa}')")
+        as ${hv} ovs-appctl netdev-dummy/receive $inport $request
+        echo "${request}"
+    }
+
+    send_na() {
+        local hv=${1} inport=${2} eth_src=${3} spa=${4}
+        local request=$(fmt_pkt "Ether(dst='ff:ff:ff:ff:ff:ff', 
src='${eth_src}')/ \
+                                 IPv6(dst='ff02::1', src='${spa}')/ \
+                                 ICMPv6ND_NA(tgt='${spa}')/ \
+                                 ICMPv6NDOptDstLLAddr(lladdr='${eth_src}')")
+        as ${hv} ovs-appctl netdev-dummy/receive $inport $request
+        echo "${request}"
+    }
+
+
+    reset_env() {
+        as hv1 reset_pcap_file migrator hv1/migrator
+        as hv2 reset_pcap_file migrator hv2/migrator
+        as hv1 reset_pcap_file first hv1/first
+        as hv2 reset_pcap_file second hv2/second
+        as hv3 reset_pcap_file outside hv3/outside
+
+        for port in hv1/migrator hv2/migrator hv1/first hv2/second 
hv3/outside; do
+            : > $port.expected
+        done
+    }
 
-check_packets() {
-    OVN_CHECK_PACKETS([hv1/migrator-tx.pcap], [hv1/migrator.expected])
-    OVN_CHECK_PACKETS([hv2/migrator-tx.pcap], [hv2/migrator.expected])
-    OVN_CHECK_PACKETS([hv3/outside-tx.pcap], [hv3/outside.expected])
-    OVN_CHECK_PACKETS([hv1/first-tx.pcap], [hv1/first.expected])
-    OVN_CHECK_PACKETS([hv2/second-tx.pcap], [hv2/second.expected])
-}
+    check_packets() {
+        OVN_CHECK_PACKETS([hv1/migrator-tx.pcap], [hv1/migrator.expected])
+        OVN_CHECK_PACKETS([hv2/migrator-tx.pcap], [hv2/migrator.expected])
+        OVN_CHECK_PACKETS([hv3/outside-tx.pcap], [hv3/outside.expected])
+        OVN_CHECK_PACKETS([hv1/first-tx.pcap], [hv1/first.expected])
+        OVN_CHECK_PACKETS([hv2/second-tx.pcap], [hv2/second.expected])
+    }
 
-migrator_spa=$(ip_to_hex 10 0 0 10)
-first_spa=$(ip_to_hex 10 0 0 1)
-second_spa=$(ip_to_hex 10 0 0 2)
-outside_spa=$(ip_to_hex 10 0 0 3)
+    reset_env
 
-reset_env
+    # Packet from hv3:Outside arrives to hv1:Migrator
+    # hv3:Outside cannot reach hv2:Migrator because it is blocked by 
activation strategy
+    request=$(send_arp hv3 outside 1 "00:00:00:00:00:03" "00:00:00:00:00:10" 
"10.0.0.3" "10.0.0.10")
+    echo $request >> hv1/migrator.expected
 
-# Packet from hv3:Outside arrives to hv1:Migrator
-# hv3:Outside cannot reach hv2:Migrator because it is blocked by RARP strategy
-request=$(send_arp hv3 outside 000000000003 000000000010 $outside_spa 
$migrator_spa)
-echo $request >> hv1/migrator.expected
+    # Packet from hv1:First arrives to hv1:Migrator
+    # hv1:First cannot reach hv2:Migrator because it is blocked by activation 
strategy
+    request=$(send_arp hv1 first 1 "00:00:00:00:00:01" "00:00:00:00:00:10" 
"10.0.0.1" "10.0.0.10")
+    echo $request >> hv1/migrator.expected
 
-# Packet from hv1:First arrives to hv1:Migrator
-# hv1:First cannot reach hv2:Migrator because it is blocked by RARP strategy
-request=$(send_arp hv1 first 000000000001 000000000010 $first_spa 
$migrator_spa)
-echo $request >> hv1/migrator.expected
+    # Packet from hv2:Second arrives to hv1:Migrator
+    # hv2:Second cannot reach hv2:Migrator because it is blocked by activation 
strategy
+    request=$(send_arp hv2 second 1 "00:00:00:00:00:02" "00:00:00:00:00:10" 
"10.0.0.2" "10.0.0.10")
+    echo $request >> hv1/migrator.expected
 
-# Packet from hv2:Second arrives to hv1:Migrator
-# hv2:Second cannot reach hv2:Migrator because it is blocked by RARP strategy
-request=$(send_arp hv2 second 000000000002 000000000010 $second_spa 
$migrator_spa)
-echo $request >> hv1/migrator.expected
+    check_packets
+    reset_env
 
-check_packets
-reset_env
+    # Packet from hv1:Migrator arrives to hv3:Outside
+    request=$(send_arp hv1 migrator 1 "00:00:00:00:00:10" "00:00:00:00:00:03" 
"10.0.0.10" "10.0.0.3")
+    echo $request >> hv3/outside.expected
 
-# Packet from hv1:Migrator arrives to hv3:Outside
-request=$(send_arp hv1 migrator 000000000010 000000000003 $migrator_spa 
$outside_spa)
-echo $request >> hv3/outside.expected
+    # Packet from hv1:Migrator arrives to hv1:First
+    request=$(send_arp hv1 migrator 1 "00:00:00:00:00:10" "00:00:00:00:00:01" 
"10.0.0.10" "10.0.0.1")
+    echo $request >> hv1/first.expected
 
-# Packet from hv1:Migrator arrives to hv1:First
-request=$(send_arp hv1 migrator 000000000010 000000000001 $migrator_spa 
$first_spa)
-echo $request >> hv1/first.expected
+    # Packet from hv1:Migrator arrives to hv2:Second
+    request=$(send_arp hv1 migrator 1 "00:00:00:00:00:10" "00:00:00:00:00:02" 
"10.0.0.10" "10.0.0.2")
+    echo $request >> hv2/second.expected
 
-# Packet from hv1:Migrator arrives to hv2:Second
-request=$(send_arp hv1 migrator 000000000010 000000000002 $migrator_spa 
$second_spa)
-echo $request >> hv2/second.expected
+    check_packets
+    reset_env
 
-check_packets
-reset_env
+    # hv2:Migrator cannot reach to hv3:Outside because it is blocked by 
activation strategy
+    request=$(send_arp hv2 migrator 1 "00:00:00:00:00:10" "00:00:00:00:00:03" 
"10.0.0.10" "10.0.0.3")
 
-# hv2:Migrator cannot reach to hv3:Outside because it is blocked by RARP 
strategy
-request=$(send_arp hv2 migrator 000000000010 000000000003 $migrator_spa 
$outside_spa)
+    check_packets
+    reset_env
 
-check_packets
-reset_env
+    AT_CHECK([ovn-sbctl find port_binding logical_port=migrator | grep -q 
additional-chassis-activated], [1])
 
-AT_CHECK([ovn-sbctl find port_binding logical_port=migrator | grep -q 
additional-chassis-activated], [1])
+    # Now activate hv2:Migrator location
+    if [[ "$1" == "rarp" ]]; then
+        request=$(send_rarp hv2 migrator "00:00:00:00:00:10" "10.0.0.10")
+    elif [[ "$1" == "na" ]]; then
+        request=$(send_na hv2 migrator "00:00:00:00:00:10" "fd10::10")
+        echo $request
+    else
+        request=$(send_arp hv2 migrator 1 "00:00:00:00:00:10" 
"ff:ff:ff:ff:ff:ff" "10.0.0.10" "10.0.0.10")
+    fi
 
-# Now activate hv2:Migrator location
-request=$(send_rarp hv2 migrator 000000000010 ffffffffffff $migrator_spa 
$migrator_spa)
+    # Activation packet was reinjected into the pipeline
+    echo $request >> hv3/outside.expected
+    echo $request >> hv1/first.expected
+    echo $request >> hv2/second.expected
 
-# RARP was reinjected into the pipeline
-echo $request >> hv3/outside.expected
-echo $request >> hv1/first.expected
-echo $request >> hv2/second.expected
+    check_packets
+    reset_env
 
-check_packets
-reset_env
+    pb_uuid=$(ovn-sbctl --bare --columns _uuid find Port_Binding 
logical_port=migrator)
+    OVS_WAIT_UNTIL([test xhv2 = x$(ovn-sbctl get Port_Binding $pb_uuid 
options:additional-chassis-activated | tr -d '""')])
 
-pb_uuid=$(ovn-sbctl --bare --columns _uuid find Port_Binding 
logical_port=migrator)
-OVS_WAIT_UNTIL([test xhv2 = x$(ovn-sbctl get Port_Binding $pb_uuid 
options:additional-chassis-activated | tr -d '""')])
+    # Now packet arrives to both locations
+    request=$(send_arp hv3 outside 1 "00:00:00:00:00:03" "00:00:00:00:00:10" 
"10.0.0.3" "10.0.0.10")
+    echo $request >> hv1/migrator.expected
+    echo $request >> hv2/migrator.expected
 
-# Now packet arrives to both locations
-request=$(send_arp hv3 outside 000000000003 000000000010 $outside_spa 
$migrator_spa)
-echo $request >> hv1/migrator.expected
-echo $request >> hv2/migrator.expected
+    check_packets
+    reset_env
 
-check_packets
-reset_env
+    # Packet from hv1:Migrator still arrives to hv3:Outside
+    request=$(send_arp hv1 migrator 1 "00:00:00:00:00:10" "00:00:00:00:00:03" 
"10.0.0.10" "10.0.0.3")
+    echo $request >> hv3/outside.expected
 
-# Packet from hv1:Migrator still arrives to hv3:Outside
-request=$(send_arp hv1 migrator 000000000010 000000000003 $migrator_spa 
$outside_spa)
-echo $request >> hv3/outside.expected
+    check_packets
+    reset_env
 
-check_packets
-reset_env
+    # hv2:Migrator can now reach to hv3:Outside because it was activated
+    request=$(send_arp hv2 migrator 1 "00:00:00:00:00:10" "00:00:00:00:00:03" 
"10.0.0.10" "10.0.0.3")
+    echo $request >> hv3/outside.expected
 
-# hv2:Migrator can now reach to hv3:Outside because RARP strategy activated it
-request=$(send_arp hv2 migrator 000000000010 000000000003 $migrator_spa 
$outside_spa)
-echo $request >> hv3/outside.expected
+    check_packets
 
-check_packets
+    # complete port migration and check that -activated flag is reset
+    check ovn-nbctl lsp-set-options migrator requested-chassis=hv2
+    OVS_WAIT_UNTIL([test x = x$(ovn-sbctl get Port_Binding $pb_uuid 
options:additional-chassis-activated)])
 
-# complete port migration and check that -activated flag is reset
-check ovn-nbctl lsp-set-options migrator requested-chassis=hv2
-OVS_WAIT_UNTIL([test x = x$(ovn-sbctl get Port_Binding $pb_uuid 
options:additional-chassis-activated)])
+    OVN_CLEANUP([hv1],[hv2],[hv3])
 
-OVN_CLEANUP([hv1],[hv2],[hv3])
+    AT_CLEANUP
+])])
 
-AT_CLEANUP
-])
+ACTIVATION_STRATEGY_TEST([rarp])
+ACTIVATION_STRATEGY_TEST([garp])
+ACTIVATION_STRATEGY_TEST([na])
 
 OVN_FOR_EACH_NORTHD([
 AT_SETUP([options:activation-strategy=rarp is not waiting for southbound db])
-- 
2.48.1

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

Reply via email to