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!
> 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.
> + 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.
> + }
> +
> + /* 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?
> 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
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev