On Thu, Mar 20, 2025 at 11:35 AM Dumitru Ceara <[email protected]> wrote:

> On 3/4/25 12:41 PM, Ales Musil wrote:
> > 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]>
> > ---
>
> Hi Ales,
>
> Thanks for the patch!
>

Hi Dumitru,

thank you for the review.


> >  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);
>
> This confused me a bit.. it's because arp_tha and nd_tll are the same
> thing in OVS and because there's no match_set_nd_tll().
>
> > +
> > +    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,
>
> Nit: this looks a bit weird to me, we're setting up an ND_NA activation
> strategy but we're using the ACTION_OPCODE_ACTIVATION_STRATEGY_RARP
> opcode.  I understand why it works but I think I'd just rename:
>
> /* activation_strategy_rarp() */
> ACTION_OPCODE(ACTIVATION_STRATEGY_RARP)
>
> to
>
> /* activation_strategy() */
> ACTION_OPCODE(ACTIVATION_STRATEGY)
>

> and while at it rename the pinctrl_rarp_activation_strategy_handler()
> function to pinctrl_activation_strategy_handler() as it's really
> protocol independent; it only reads the logical ingress port and
> datapath from the flow.
>

Yeah, that makes sense. I completely forgot about that action name.


> > +                         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);
> > +        }
>
> I'm afraid this will potentially break live migration with
> activation_strategy=rarp for the case when it's used for logical switch
> ports that either:
> - have "unknown" addresses
> - only have a MAC address configured (no IPv4 address).
>
> We should probably maintain the old behavior, i.e., if
> activation-strategy includes "rarp" then activate the port on any RARP
> received on the LSP VIF.
>

Will revert it back for rarp.


> > +    }
> > +
> > +    /* 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
>
> Nit: "a comma separated list".
>
> > +          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
>
> Nit: "a comma separated list".
>
> > +        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}')/ \
>
> Is this an accidental change?  We don't use test_na() in the activation
> strategy tests.  Or am I missing something?
>

That's leftover from testing. I will revert it back.


> >                               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])
>
> Regards,
> Dumitru
>
>
>
Thanks,
Ales
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to