On 12/19/25 11:47 AM, Lorenzo Bianconi wrote:
> Introduce the capability to specify multiple ips for ovn-evpn-local-ip
> option in order to enable dual-stack for EVPN vxlan tunnels.
> The IPs used for vxlan tunnel can be specified using the following
> syntax in the external_ids column of Open_vSwitch table:
>
> external_ids:ovn-evpn-local-ip=10:1.1.1.1,20:[2::2],30:3.3.3.3,40:[4::4],30:[3::3]
>
> Reported-at: https://issues.redhat.com/browse/FDP-2768
> Signed-off-by: Lorenzo Bianconi <[email protected]>
> ---
> Changes in v3:
> - Add default IP configuration
> - Fix possible parsing crashes in evpn_vni_local_ip_map_alloc()
> - Use hashmap for vni_local_ip mapping
> Changes in v2:
> - Add NEWS entry
> - Update documentation
> - Add ip_address_from_str utility routine
> - Fix IPv4 vs IPv6 openflow management in physical_consider_evpn_multicast()
> - Add Dual-Stack entry in EVPN_SWITCH_TESTS function
> ---
Hi Lorenzo,
Thanks for v3!
> NEWS | 2 +
> TODO.rst | 4 -
> controller/neighbor.c | 5 +-
> controller/ovn-controller.8.xml | 11 +-
> controller/physical.c | 216 +++++++++---
> lib/ovn-util.c | 23 ++
> lib/ovn-util.h | 2 +
> tests/system-common-macros.at | 14 +-
> tests/system-ovn.at | 594 +++++++++++++++++++++++++++++++-
> 9 files changed, 800 insertions(+), 71 deletions(-)
>
> diff --git a/NEWS b/NEWS
> index 87500de03..9883fb81d 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -80,6 +80,8 @@ Post v25.09.0
> - Add fallback support for Network Function.
> - Introduce the capability to specify EVPN device names using
> Logical_Switch
> other_config column.
> + - Introduce the capability to specify multiple ips for ovn-evpn-local-ip
> + option.
>
> OVN v25.09.0 - xxx xx xxxx
> --------------------------
> diff --git a/TODO.rst b/TODO.rst
> index 0c9b9598b..9f5e0976d 100644
> --- a/TODO.rst
> +++ b/TODO.rst
> @@ -156,10 +156,6 @@ OVN To-do List
> Otherwise we could try to add duplicated Learned_Routes and the ovnsb
> commit would fail.
>
> - * Allow ovn-evpn-local-ip to accept list of
> - $VNI1:$LOCAL_IP1,$VNI2:$LOCAL_IP2 combinations which will be properly
> - reflected in physical flows for given LS with VNI.
> -
> * Add support for EVPN L3, that involves MAC Binding learning and
> advertisement.
>
> diff --git a/controller/neighbor.c b/controller/neighbor.c
> index 9aeb1e36b..e77b41d29 100644
> --- a/controller/neighbor.c
> +++ b/controller/neighbor.c
> @@ -91,7 +91,6 @@ neigh_parse_device_name(struct sset *device_names, struct
> local_datapath *ld,
> {
> const char *names = smap_get_def(&ld->datapath->external_ids,
> neighbor_opt_name[type], "");
> - sset_clear(device_names);
> sset_from_delimited_string(device_names, names, ",");
> if (sset_is_empty(device_names)) {
> /* Default device name if not specified. */
> @@ -123,7 +122,7 @@ neighbor_run(struct neighbor_ctx_in *n_ctx_in,
> continue;
> }
>
> - struct sset device_names = SSET_INITIALIZER(&device_names);
> + struct sset device_names;
> neigh_parse_device_name(&device_names, ld, NEIGH_IFACE_VXLAN, vni);
> const char *name;
> SSET_FOR_EACH (name, &device_names) {
> @@ -132,6 +131,7 @@ neighbor_run(struct neighbor_ctx_in *n_ctx_in,
> NEIGH_IFACE_VXLAN, vni,
> name);
> vector_push(n_ctx_out->monitored_interfaces, &vxlan);
> }
> + sset_destroy(&device_names);
>
> neigh_parse_device_name(&device_names, ld, NEIGH_IFACE_LOOPBACK,
> vni);
> if (sset_count(&device_names) > 1) {
> @@ -145,6 +145,7 @@ neighbor_run(struct neighbor_ctx_in *n_ctx_in,
> NEIGH_IFACE_LOOPBACK, vni,
> SSET_FIRST(&device_names));
> vector_push(n_ctx_out->monitored_interfaces, &lo);
> + sset_destroy(&device_names);
>
> neigh_parse_device_name(&device_names, ld, NEIGH_IFACE_BRIDGE, vni);
> if (sset_count(&device_names) > 1) {
> diff --git a/controller/ovn-controller.8.xml b/controller/ovn-controller.8.xml
> index dfc7cc217..81f6e2cf6 100644
> --- a/controller/ovn-controller.8.xml
> +++ b/controller/ovn-controller.8.xml
> @@ -432,10 +432,13 @@
>
> <dt><code>external_ids:ovn-evpn-local-ip</code></dt>
> <dd>
> - IP address used as a source address for the EVPN traffic leaving this
> - OVN setup. There is currently support only for single IP address
> - being specified. NOTE: this feature is experimental and may be
> subject
> - to removal/change in the future.
> + IP address list used as a source addresses for the EVPN traffic
> + leaving this OVN setup. The <code>ovn-evpn-local-ip</code> can be
> + specified by the CMS according to the following syntax:
> + <code>external_ids:ovn-evpn-local-ip=vni0:IPv4,vni1:IPv4,vni1:[IPv6]
> + </code>. If the IP is specified without any VNI, it will be used
> + as default local IP address for EVPN traffic. NOTE: this feature is
> + experimental and may be subject to removal/change in the future.
> </dd>
> </dl>
>
> diff --git a/controller/physical.c b/controller/physical.c
> index b9c60c8ab..c678ff34c 100644
> --- a/controller/physical.c
> +++ b/controller/physical.c
> @@ -3178,13 +3178,116 @@ physical_eval_remote_chassis_flows(const struct
> physical_ctx *ctx,
> ofpbuf_uninit(&ingress_ofpacts);
> }
>
> +#define DEFAULT_VNI (1 << 24) /* VNI used for the default local IP. */
> +struct vni_local_ip {
> + struct hmap_node hmap_node;
> + struct in6_addr ip;
> + uint32_t vni;
> +};
> +
> +static struct in6_addr *
> +evpn_local_ip_lookup_by_vni(const struct hmap *map, uint32_t vni, bool ipv4)
> +{
> + struct vni_local_ip *e, *def_e = NULL;
> + HMAP_FOR_EACH (e, hmap_node, map) {
> + if (IN6_IS_ADDR_V4MAPPED(&e->ip) != ipv4) {
> + continue;
> + }
> + if (e->vni == vni) {
> + return &e->ip;
> + }
> + if (e->vni == DEFAULT_VNI) {
> + def_e = e;
> + }
> + }
> + return def_e ? &def_e->ip : NULL;
> +}
> +
This is still a linear lookup. We should hash by VNI + address-family.
But, as discussed offline briefly, that means we need a way to store the
IPs for the default VNI separately.
In that case, I think the alternative suggestion I had on v2, to use two
config options, might be the best way forward:
- ovn-evpn-local-ip: the one we have today, extended to accept at most
two IPs, at most one IPv4 and at most one IPv6
- ovn-evpn-local-ip-mapping: a list of "VNI:IP4,VNI:[IP6]" values.
https://mail.openvswitch.org/pipermail/ovs-dev/2025-December/428765.html
> +static void
> +evpn_vni_local_ip_map_alloc(struct hmap *map, const struct smap *config)
> +{
> + const char *local_ip_str = smap_get(config, "ovn-evpn-local-ip");
> + if (!local_ip_str) {
> + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> + VLOG_WARN_RL(&rl, "Missing ovn-evpn-local-ip configuration");
> + return;
> + }
> +
> + struct vni_local_ip *e;
> + struct in6_addr ip;
> + int addr_family;
> +
> + if (ip_address_from_str(local_ip_str, &ip, &addr_family)) {
> + /* Default mapping */
> + e = xmalloc(sizeof *e);
> + e->ip = ip;
> + e->vni = DEFAULT_VNI;
> + hmap_insert(map, &e->hmap_node, hash_add(e->vni, 0));
> + return;
> + }
> +
> + char *tokstr = xstrdup(local_ip_str);
> + char *token, *ptr0 = NULL;
> +
> + for (token = strtok_r(tokstr, ",", &ptr0); token;
> + token = strtok_r(NULL, ",", &ptr0)) {
> + char *ptr1 = NULL, *vni_str = strtok_r(token, ":", &ptr1);
> + char *ip_str = strtok_r(NULL, "", &ptr1);
> + uint32_t vni;
> +
> + if (!ip_address_from_str(ip_str, &ip, &addr_family)) {
Won't this crash if the user provides as input the string ",,,"?
> + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> + VLOG_WARN_RL(&rl, "EVPN enabled, but required 'evpn-local-ip' is
> "
> + "missing or invalid %s ", local_ip_str);
> + continue;
> + }
> +
> + if (!vni_str) {
> + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> + VLOG_WARN_RL(&rl, "Required VNI not configured");
> + continue;
> + }
> +
> + if (!ovs_scan(vni_str, "%u", &vni) || !ovn_is_valid_vni(vni)) {
> + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> + VLOG_WARN_RL(&rl, "Invalid VNI: %s", vni_str);
> + continue;
> + }
> +
> + e = xmalloc(sizeof *e);
> + e->vni = vni;
> + e->ip = ip;
> + hmap_insert(map, &e->hmap_node, hash_add(vni, 0));
> + }
> + free(tokstr);
> +}
> +
> +static void
> +evpn_vni_local_ip_map_destroy(struct hmap *map)
> +{
> + struct vni_local_ip *e;
> + HMAP_FOR_EACH_POP (e, hmap_node, map) {
> + free(e);
> + }
> + hmap_destroy(map);
> +}
> +
> static void
> physical_consider_evpn_binding(const struct evpn_binding *binding,
> - const struct in6_addr *local_ip,
> + const struct hmap *vni_ip_map,
> struct ofpbuf *ofpacts, struct match *match,
> - struct ovn_desired_flow_table *flow_table,
> - bool ipv4)
> + struct ovn_desired_flow_table *flow_table)
> {
> + bool ipv4 = IN6_IS_ADDR_V4MAPPED(&binding->remote_ip);
> + const struct in6_addr *local_ip = evpn_local_ip_lookup_by_vni(vni_ip_map,
> +
> binding->vni,
> + ipv4);
> + if (!local_ip) {
> + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> + VLOG_WARN_RL(&rl, "failed to get local tunnel ip");
> + return;
> + }
> +
> /* Ingress flows. */
> ofpbuf_clear(ofpacts);
> match_init_catchall(match);
> @@ -3308,39 +3411,66 @@ physical_consider_evpn_binding(const struct
> evpn_binding *binding,
>
> static void
> physical_consider_evpn_multicast(const struct evpn_multicast_group *mc_group,
> - const struct in6_addr *local_ip,
> + const struct hmap *vni_ip_map,
> struct ofpbuf *ofpacts, struct match *match,
> - struct ovn_desired_flow_table *flow_table,
> - bool ipv4)
> + struct ovn_desired_flow_table *flow_table)
> {
> - const struct evpn_binding *binding = NULL;
> + struct in6_addr *local_ip4 =
> + evpn_local_ip_lookup_by_vni(vni_ip_map, mc_group->vni, true);
> + struct in6_addr *local_ip6 =
> + evpn_local_ip_lookup_by_vni(vni_ip_map, mc_group->vni, false);
>
> ofpbuf_clear(ofpacts);
> uint32_t multicast_tunnel_keys[] = {OVN_MCAST_FLOOD_TUNNEL_KEY,
> OVN_MCAST_UNKNOWN_TUNNEL_KEY,
> OVN_MCAST_FLOOD_L2_TUNNEL_KEY};
> - if (ipv4) {
> - ovs_be32 ip4 = in6_addr_get_mapped_ipv4(local_ip);
> +
> + put_load(mc_group->vni, MFF_TUN_ID, 0, 24, ofpacts);
> +
> + ovs_be32 ip4;
> + const struct evpn_binding *binding = NULL;
> + if (local_ip4) {
> + ip4 = in6_addr_get_mapped_ipv4(local_ip4);
> put_load_bytes(&ip4, sizeof ip4, MFF_TUN_SRC, 0, 32, ofpacts);
> - } else {
> - put_load_bytes(local_ip, sizeof *local_ip, MFF_TUN_IPV6_SRC,
> - 0, 128, ofpacts);
> +
> + const struct hmapx_node *node;
> + HMAPX_FOR_EACH (node, &mc_group->bindings) {
> + binding = node->data;
> + if (!IN6_IS_ADDR_V4MAPPED(&binding->remote_ip)) {
> + continue;
> + }
> +
> + ovs_be32 remote_ip4 =
> + in6_addr_get_mapped_ipv4(&binding->remote_ip);
> + put_load_bytes(&remote_ip4, sizeof remote_ip4, MFF_TUN_DST, 0,
> 32,
> + ofpacts);
> + ofpact_put_OUTPUT(ofpacts)->port = binding->tunnel_ofport;
> + }
> + put_resubmit(OFTABLE_LOCAL_OUTPUT, ofpacts);
> }
> - put_load(mc_group->vni, MFF_TUN_ID, 0, 24, ofpacts);
>
> - const struct hmapx_node *node;
> - HMAPX_FOR_EACH (node, &mc_group->bindings) {
> - binding = node->data;
> - if (ipv4) {
> - ovs_be32 ip4 = in6_addr_get_mapped_ipv4(&binding->remote_ip);
> - put_load_bytes(&ip4, sizeof ip4, MFF_TUN_DST, 0, 32, ofpacts);
> - } else {
> + if (local_ip4 && local_ip6) {
> + ip4 = 0;
> + put_load_bytes(&ip4, sizeof ip4, MFF_TUN_SRC, 0, 32, ofpacts);
> + put_load_bytes(&ip4, sizeof ip4, MFF_TUN_DST, 0, 32, ofpacts);
> + }
> +
> + if (local_ip6) {
> + put_load_bytes(local_ip6, sizeof *local_ip6, MFF_TUN_IPV6_SRC,
> + 0, 128, ofpacts);
> + const struct hmapx_node *node;
> + HMAPX_FOR_EACH (node, &mc_group->bindings) {
> + binding = node->data;
> + if (IN6_IS_ADDR_V4MAPPED(&binding->remote_ip)) {
> + continue;
> + }
> +
> put_load_bytes(&binding->remote_ip, sizeof binding->remote_ip,
> MFF_TUN_IPV6_DST, 0, 128, ofpacts);
> + ofpact_put_OUTPUT(ofpacts)->port = binding->tunnel_ofport;
> }
> - ofpact_put_OUTPUT(ofpacts)->port = binding->tunnel_ofport;
> + put_resubmit(OFTABLE_LOCAL_OUTPUT, ofpacts);
> }
> - put_resubmit(OFTABLE_LOCAL_OUTPUT, ofpacts);
>
> ovs_assert(!hmapx_is_empty(&mc_group->bindings));
> for (size_t i = 0; i < ARRAY_SIZE(multicast_tunnel_keys); i++) {
> @@ -3418,30 +3548,23 @@ physical_eval_evpn_flows(const struct physical_ctx
> *ctx,
> return;
> }
>
> - const char *local_ip_str = smap_get_def(&ctx->chassis->other_config,
> - "ovn-evpn-local-ip", "");
> - struct in6_addr local_ip;
> - if (!ip46_parse(local_ip_str, &local_ip)) {
> - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> - VLOG_WARN_RL(&rl, "EVPN enabled, but required 'evpn-local-ip' is "
> - "missing or invalid %s ", local_ip_str);
> - return;
> - }
> + struct hmap vni_ip_map = HMAP_INITIALIZER(&vni_ip_map);
> + evpn_vni_local_ip_map_alloc(&vni_ip_map, &ctx->chassis->other_config);
>
> struct match match = MATCH_CATCHALL_INITIALIZER;
> - bool ipv4 = IN6_IS_ADDR_V4MAPPED(&local_ip);
> -
> const struct evpn_binding *binding;
> +
> HMAP_FOR_EACH (binding, hmap_node, ctx->evpn_bindings) {
> - physical_consider_evpn_binding(binding, &local_ip, ofpacts,
> - &match, flow_table, ipv4);
> + physical_consider_evpn_binding(binding, &vni_ip_map, ofpacts,
> + &match, flow_table);
> }
>
> const struct evpn_multicast_group *mc_group;
> HMAP_FOR_EACH (mc_group, hmap_node, ctx->evpn_multicast_groups) {
> - physical_consider_evpn_multicast(mc_group, &local_ip, ofpacts,
> - &match, flow_table, ipv4);
> + physical_consider_evpn_multicast(mc_group, &vni_ip_map, ofpacts,
> + &match, flow_table);
> }
> + evpn_vni_local_ip_map_destroy(&vni_ip_map);
>
> const struct evpn_fdb *fdb;
> HMAP_FOR_EACH (fdb, hmap_node, ctx->evpn_fdbs) {
> @@ -3569,34 +3692,29 @@ physical_handle_evpn_binding_changes(
> const struct uuidset *removed_bindings,
> const struct uuidset *removed_multicast_groups)
> {
> - const char *local_ip_str = smap_get_def(&ctx->chassis->other_config,
> - "ovn-evpn-local-ip", "");
> - struct in6_addr local_ip;
> - if (!ip46_parse(local_ip_str, &local_ip)) {
> - return;
> - }
> + struct hmap vni_ip_map = HMAP_INITIALIZER(&vni_ip_map);
> + evpn_vni_local_ip_map_alloc(&vni_ip_map, &ctx->chassis->other_config);
>
> struct ofpbuf ofpacts;
> ofpbuf_init(&ofpacts, 0);
> struct match match = MATCH_CATCHALL_INITIALIZER;
> - bool ipv4 = IN6_IS_ADDR_V4MAPPED(&local_ip);
>
> const struct hmapx_node *node;
> HMAPX_FOR_EACH (node, updated_bindings) {
> const struct evpn_binding *binding = node->data;
> -
> ofctrl_remove_flows(flow_table, &binding->flow_uuid);
> - physical_consider_evpn_binding(binding, &local_ip, &ofpacts,
> - &match, flow_table, ipv4);
> + physical_consider_evpn_binding(binding, &vni_ip_map, &ofpacts,
> + &match, flow_table);
> }
>
> HMAPX_FOR_EACH (node, updated_multicast_groups) {
> const struct evpn_multicast_group *mc_group = node->data;
>
> ofctrl_remove_flows(flow_table, &mc_group->flow_uuid);
> - physical_consider_evpn_multicast(mc_group, &local_ip, &ofpacts,
> - &match, flow_table, ipv4);
> + physical_consider_evpn_multicast(mc_group, &vni_ip_map, &ofpacts,
> + &match, flow_table);
> }
> + evpn_vni_local_ip_map_destroy(&vni_ip_map);
>
> ofpbuf_uninit(&ofpacts);
>
> diff --git a/lib/ovn-util.c b/lib/ovn-util.c
> index cec029e42..e60f73522 100644
> --- a/lib/ovn-util.c
> +++ b/lib/ovn-util.c
> @@ -926,6 +926,29 @@ ip_address_and_port_from_lb_key(const char *key, char
> **ip_address,
> return true;
> }
>
> +bool
> +ip_address_from_str(const char *ip_str, struct in6_addr *ip, int
> *addr_family)
> +{
> + memset(ip, 0, sizeof(*ip));
> + *addr_family = 0;
> +
> + struct sockaddr_storage ss;
> + if (!inet_parse_active(ip_str, 0, &ss, false, NULL)) {
> + return false;
> + }
> +
> + if (ss_get_port(&ss)) {
> + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
> + VLOG_WARN_RL(&rl, "port must not be specified");
> + return false;
> + }
> +
> + *ip = ss_get_address(&ss);
> + *addr_family = ss.ss_family;
> +
> + return true;
> +}
> +
> /* Increment this for any logical flow changes, if an existing OVN action is
> * modified or a stage is added to a logical pipeline.
> *
> diff --git a/lib/ovn-util.h b/lib/ovn-util.h
> index daff01995..3f486e736 100644
> --- a/lib/ovn-util.h
> +++ b/lib/ovn-util.h
> @@ -291,6 +291,8 @@ bool ovn_str_to_ushort(const char *, int base, unsigned
> short *);
> bool ip_address_and_port_from_lb_key(const char *key, char **ip_address,
> struct in6_addr *ip, uint16_t *port,
> int *addr_family);
> +bool ip_address_from_str(const char *ip_str, struct in6_addr *ip,
> + int *addr_family);
>
> /* Returns the internal OVN version. The caller must free the returned
> * value. */
> diff --git a/tests/system-common-macros.at b/tests/system-common-macros.at
> index 9c5a124a0..e1a880bd2 100644
> --- a/tests/system-common-macros.at
> +++ b/tests/system-common-macros.at
> @@ -209,18 +209,20 @@ m4_define([SET_EVPN_IFACE_NAMES],
> ifname=$1 switch=$2 vni=$3
>
> [[ $ifname = "default" ]] && BR_NAME=br-$vni || BR_NAME=br-$ifname
> - [[ $ifname = "default" ]] && VXLAN_NAME=vxlan-$vni ||
> VXLAN_NAME=vxlan-$ifname
> + [[ $ifname = "default" ]] && VXLAN_NAME=vxlan-$vni ||
> VXLAN_NAME=vxlan-v4-$ifname
> + [[ $ifname = "default" ]] && VXLAN_V6_NAME=vxlan-v6-$vni ||
> VXLAN_V6_NAME=vxlan-v6-$ifname
> [[ $ifname = "default" ]] && LO_NAME=lo-$vni || LO_NAME=lo-$ifname
>
> if [[ $ifname != "default" ]]; then
> - check ovn-nbctl set logical_switch $switch \
> - other_config:dynamic-routing-bridge-ifname=$BR_NAME \
> - other_config:dynamic-routing-vxlan-ifname=$VXLAN_NAME \
> + check ovn-nbctl set logical_switch $switch
> \
> + other_config:dynamic-routing-bridge-ifname=$BR_NAME
> \
> other_config:dynamic-routing-advertise-ifname=$LO_NAME
> fi
> + check ovn-nbctl set logical_switch $switch \
> +
> other_config:dynamic-routing-vxlan-ifname=$VXLAN_NAME","$VXLAN_V6_NAME
>
> - export BR_NAME VXLAN_NAME LO_NAME
> - on_exit 'unset BR_NAME VXLAN_NAME LO_NAME'
> + export BR_NAME VXLAN_NAME VXLAN_V6_NAME LO_NAME
> + on_exit 'unset BR_NAME VXLAN_NAME VXLAN_V6_NAME LO_NAME'
> ]
> )
>
> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> index ec3b3735f..383d2157b 100644
> --- a/tests/system-ovn.at
> +++ b/tests/system-ovn.at
> @@ -17731,10 +17731,10 @@
> priority=1050,tun_id=0xa,tun_src=169.0.0.10,tun_dst=169.0.0.1,in_port=$ofport
> ac
>
> AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int
> table=OFTABLE_REMOTE_VTEP_OUTPUT | grep output | \
> awk '{print $[7], $[8]}' | sort], [0], [dnl
> -priority=50,reg15=0x8000,metadata=0x$dp_key
> actions=load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xa900000a->NXM_NX_TUN_IPV4_DST[[]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT)
> +priority=50,reg15=0x8000,metadata=0x$dp_key
> actions=load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa900000a->NXM_NX_TUN_IPV4_DST[[]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT)
> priority=50,reg15=0x80000001,metadata=0x$dp_key
> actions=load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa900000a->NXM_NX_TUN_IPV4_DST[[]],load:0xa->NXM_NX_TUN_ID[[0..23]],output:$ofport
> -priority=50,reg15=0x8001,metadata=0x$dp_key
> actions=load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xa900000a->NXM_NX_TUN_IPV4_DST[[]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT)
> -priority=50,reg15=0x8004,metadata=0x$dp_key
> actions=load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xa900000a->NXM_NX_TUN_IPV4_DST[[]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT)
> +priority=50,reg15=0x8001,metadata=0x$dp_key
> actions=load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa900000a->NXM_NX_TUN_IPV4_DST[[]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT)
> +priority=50,reg15=0x8004,metadata=0x$dp_key
> actions=load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa900000a->NXM_NX_TUN_IPV4_DST[[]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT)
> priority=55,reg10=0x1/0x1,reg15=0x80000001,metadata=0x$dp_key
> actions=load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa900000a->NXM_NX_TUN_IPV4_DST[[]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xffff->NXM_OF_IN_PORT[[]],output:$ofport
> ])
>
> @@ -18268,10 +18268,10 @@
> priority=1050,tun_id=0xa,tun_ipv6_src=169::10,tun_ipv6_dst=169::1,in_port=$ofpor
>
> AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int
> table=OFTABLE_REMOTE_VTEP_OUTPUT | grep output | \
> awk '{print $[7], $[8]}' | sort], [0], [dnl
> -priority=50,reg15=0x8000,metadata=0x$dp_key
> actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT)
> +priority=50,reg15=0x8000,metadata=0x$dp_key
> actions=load:0xa->NXM_NX_TUN_ID[[0..23]],load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT)
> priority=50,reg15=0x80000001,metadata=0x$dp_key
> actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],output:$ofport
> -priority=50,reg15=0x8001,metadata=0x$dp_key
> actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT)
> -priority=50,reg15=0x8004,metadata=0x$dp_key
> actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT)
> +priority=50,reg15=0x8001,metadata=0x$dp_key
> actions=load:0xa->NXM_NX_TUN_ID[[0..23]],load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT)
> +priority=50,reg15=0x8004,metadata=0x$dp_key
> actions=load:0xa->NXM_NX_TUN_ID[[0..23]],load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT)
> priority=55,reg10=0x1/0x1,reg15=0x80000001,metadata=0x$dp_key
> actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xffff->NXM_OF_IN_PORT[[]],output:$ofport
> ])
>
> @@ -18684,6 +18684,588 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port
> patch-.*/d
> AT_CLEANUP
> ])
>
> +OVN_FOR_EACH_NORTHD([
> +AT_SETUP([dynamic-routing - EVPN $1 naming - Dual Stack])
> +AT_KEYWORDS([dynamic-routing])
> +
> +CHECK_VRF()
> +CHECK_CONNTRACK()
> +CHECK_CONNTRACK_NAT()
> +
> +IFNAME=$1
> +vni=10
> +VRF_RESERVE([$vni])
> +ovn_start
> +OVS_TRAFFIC_VSWITCHD_START()
> +ADD_BR([br-int])
> +ADD_BR([br-ext], [set Bridge br-ext fail-mode=standalone])
> +
> +# Set external-ids in br-int needed for ovn-controller.
> +check ovs-vsctl \
> + -- set Open_vSwitch . external-ids:system-id=hv1 \
> + -- set Open_vSwitch .
> external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
> + -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
> + -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \
> + -- set Open_vSwitch . external-ids:ovn-bridge-mappings=phynet:br-ext \
> + -- set Open_vSwitch .
> external-ids:ovn-evpn-local-ip=10:169.0.0.1,10:[[169::1]] \
> + -- set Open_vSwitch . external-ids:ovn-evpn-vxlan-ports=4789 \
> + -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
> +
> +# Start ovn-controller.
> +start_daemon ovn-controller
> +
> +OVS_WAIT_WHILE([ip link | grep -q ovnvrf$vni:.*UP])
> +
> +check ovn-nbctl
> \
> + -- ls-add ls-evpn
> \
> + -- lsp-add ls-evpn workload1
> \
> + -- lsp-set-addresses workload1 "f0:00:0f:16:01:10 172.16.1.10
> 172:16::10" \
> + -- lsp-add ls-evpn workload2
> \
> + -- lsp-set-addresses workload2 "f0:00:0f:16:01:20 172.16.1.20
> 172:16::20" \
> + -- lsp-add-localnet-port ls-evpn ln_port phynet
> +
> +SET_EVPN_IFACE_NAMES([$IFNAME], [ls-evpn], [$vni])
> +
> +ADD_NAMESPACES(workload1)
> +ADD_VETH(workload1, workload1, br-int, "172:16::10/64", "f0:00:0f:16:01:10",
> \
> + "172:16::1", "nodad", "172.16.1.10/24", "172.16.1.1")
> +
> +ADD_NAMESPACES(workload2)
> +ADD_VETH(workload2, workload2, br-int, "172:16::20/64", "f0:00:0f:16:01:20",
> \
> + "172:16::1", "nodad", "172.16.1.20/24", "172.16.1.1")
> +
> +OVN_POPULATE_ARP
> +check ovn-nbctl --wait=hv sync
> +wait_for_ports_up
> +
> +# Setup a VRF for the VNI.
> +check ip link add vrf-$vni type vrf table $vni
> +on_exit "ip link del vrf-$vni"
> +check ip link set vrf-$vni up
> +
> +# Add VNI bridge.
> +check ip link add $BR_NAME type bridge
> +on_exit "ip link del $BR_NAME"
> +check ip link set $BR_NAME master vrf-$vni addrgenmode none
> +check ip link set dev $BR_NAME up
> +
> +# Add VXLAN VTEP for the VNI (linked to the OVS vxlan_sys_<port> interface).
> +# Use a dstport different than the one used by OVS.
> +# This is fine because we don't actually want traffic to pass through
> +# the $vxlan interface. FRR should read the dstport from the linked
> +# vxlan_sys_${vxlan_port} device.
> +dstport=$((60000 + $vni))
> +check ip link add $VXLAN_NAME type vxlan \
> + id $vni dstport $dstport local 169.0.0.1 nolearning
> +check ip link add $VXLAN_V6_NAME type vxlan \
> + id $vni dstport $dstport local 169::1 nolearning
> +on_exit "ip link del $VXLAN_NAME; ip link del $VXLAN_V6_NAME"
> +check ip link set dev $VXLAN_NAME up
> +check ip link set dev $VXLAN_V6_NAME up
> +check ip link set $VXLAN_NAME master $BR_NAME
> +check ip link set $VXLAN_V6_NAME master $BR_NAME
> +
> +# Add a dummy loopback to the VNI bridge to be used for advertising local
> +# MACs.
> +check ip link add name $LO_NAME type dummy
> +on_exit "ip link del $LO_NAME"
> +check ip link set $LO_NAME master $BR_NAME
> +check ip link set $LO_NAME up
> +
> +AS_BOX([L2 EVPN VTEP and FDB learning])
> +
> +check ovn-nbctl --wait=hv set logical_switch ls-evpn
> other_config:dynamic-routing-vni=$vni
> +ofport=$(ovs-vsctl --bare --columns ofport find Interface
> name="ovn-evpn-4789")
> +dp_key=$(fetch_column Datapath tunnel_key external_ids:name=ls-evpn)
> +
> +AT_CHECK([ovn-appctl evpn/remote-vtep-list], [0], [dnl
> +])
> +
> +AT_CHECK([ovn-appctl evpn/vtep-binding-list], [0], [dnl
> +])
> +
> +AT_CHECK([ovn-appctl evpn/vtep-multicast-group-list], [0], [dnl
> +])
> +
> +# Simulate remote VTEP.
> +check bridge fdb append 00:00:00:00:00:00 dev $VXLAN_NAME dst 169.0.0.10
> static permanent
> +check bridge fdb append 00:00:00:00:00:00 dev $VXLAN_V6_NAME dst 169::10
> static permanent
> +
> +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/remote-vtep-list], [0], [dnl
> +IP: 169::10, port: 4789, vni: $vni
> +IP: 169.0.0.10, port: 4789, vni: $vni
> +])
> +
> +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/vtep-binding-list | cut -d','
> -f2-], [0], [dnl
> + Remote IP: 169::10, vni: $vni, binding_key: 0x80000002, tunnel_ofport:
> $ofport, dp_key: $dp_key
> + Remote IP: 169.0.0.10, vni: $vni, binding_key: 0x80000001, tunnel_ofport:
> $ofport, dp_key: $dp_key
> +])
> +
> +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/vtep-multicast-group-list |
> grep -q 169.0.0.10])
> +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/vtep-multicast-group-list |
> grep -q 169::10])
> +AT_CHECK([ovn-appctl evpn/vtep-multicast-group-list | wc -l], [0], [1
> +])
> +
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_PHY_TO_LOG |
> grep priority=1050 | \
> + awk '{print $[7], $[8]}' | sort], [0], [dnl
> +priority=1050,tun_id=0xa,tun_ipv6_src=169::10,tun_ipv6_dst=169::1,in_port=$ofport
>
> actions=load:0x$dp_key->OXM_OF_METADATA[[0..31]],load:0x80000002->NXM_NX_REG14[[]],resubmit(,OFTABLE_LEARN_REMOTE_FDB),resubmit(,OFTABLE_LOG_INGRESS_PIPELINE)
> +priority=1050,tun_id=0xa,tun_src=169.0.0.10,tun_dst=169.0.0.1,in_port=$ofport
>
> actions=load:0x$dp_key->OXM_OF_METADATA[[0..31]],load:0x80000001->NXM_NX_REG14[[]],resubmit(,OFTABLE_LEARN_REMOTE_FDB),resubmit(,OFTABLE_LOG_INGRESS_PIPELINE)
> +])
> +
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int
> table=OFTABLE_REMOTE_VTEP_OUTPUT | grep output | \
> + awk '{print $[7], $[8]}' | sort], [0], [dnl
> +priority=50,reg15=0x8000,metadata=0x$dp_key
> actions=load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa900000a->NXM_NX_TUN_IPV4_DST[[]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT),load:0->NXM_NX_TUN_IPV4_SRC[[]],load:0->NXM_NX_TUN_IPV4_DST[[]],load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT)
> +priority=50,reg15=0x80000001,metadata=0x$dp_key
> actions=load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa900000a->NXM_NX_TUN_IPV4_DST[[]],load:0xa->NXM_NX_TUN_ID[[0..23]],output:$ofport
> +priority=50,reg15=0x80000002,metadata=0x$dp_key
> actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],output:$ofport
> +priority=50,reg15=0x8001,metadata=0x$dp_key
> actions=load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa900000a->NXM_NX_TUN_IPV4_DST[[]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT),load:0->NXM_NX_TUN_IPV4_SRC[[]],load:0->NXM_NX_TUN_IPV4_DST[[]],load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT)
> +priority=50,reg15=0x8004,metadata=0x$dp_key
> actions=load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa900000a->NXM_NX_TUN_IPV4_DST[[]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT),load:0->NXM_NX_TUN_IPV4_SRC[[]],load:0->NXM_NX_TUN_IPV4_DST[[]],load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT)
> +priority=55,reg10=0x1/0x1,reg15=0x80000001,metadata=0x$dp_key
> actions=load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa900000a->NXM_NX_TUN_IPV4_DST[[]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xffff->NXM_OF_IN_PORT[[]],output:$ofport
> +priority=55,reg10=0x1/0x1,reg15=0x80000002,metadata=0x$dp_key
> actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xffff->NXM_OF_IN_PORT[[]],output:$ofport
> +])
> +
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int
> table=OFTABLE_LEARN_REMOTE_FDB | grep priority | \
> + awk '{print $[7], $[8]}' | strip_cookie | sort], [0], [dnl
> +priority=100,reg14=0x80000001,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=100,reg14=0x80000002,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +])
> +
> +# Simulate more remote VTEPs.
> +check bridge fdb append 00:00:00:00:00:00 dev $VXLAN_NAME dst 169.0.0.20
> static permanent
> +check bridge fdb append 00:00:00:00:00:01 dev $VXLAN_NAME dst 169.0.0.30
> extern_learn
> +check bridge fdb append 00:00:00:00:00:10 dev $VXLAN_V6_NAME dst 169::30
> extern_learn
> +
> +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/remote-vtep-list | sort], [0],
> [dnl
> +IP: 169.0.0.10, port: 4789, vni: $vni
> +IP: 169.0.0.20, port: 4789, vni: $vni
> +IP: 169.0.0.30, port: 4789, vni: $vni
> +IP: 169::10, port: 4789, vni: 10
> +IP: 169::30, port: 4789, vni: 10
> +])
> +
> +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/vtep-binding-list | cut -d','
> -f2- | sort], [0], [dnl
> + Remote IP: 169.0.0.10, vni: $vni, binding_key: 0x80000001, tunnel_ofport:
> $ofport, dp_key: $dp_key
> + Remote IP: 169.0.0.20, vni: $vni, binding_key: 0x80000003, tunnel_ofport:
> $ofport, dp_key: $dp_key
> + Remote IP: 169.0.0.30, vni: $vni, binding_key: 0x80000004, tunnel_ofport:
> $ofport, dp_key: $dp_key
> + Remote IP: 169::10, vni: $vni, binding_key: 0x80000002, tunnel_ofport:
> $ofport, dp_key: $dp_key
> + Remote IP: 169::30, vni: $vni, binding_key: 0x80000005, tunnel_ofport:
> $ofport, dp_key: $dp_key
> +])
> +
> +# We cannot check the output directly because the order might change.
> +OVS_WAIT_UNTIL([ovn-appctl evpn/vtep-multicast-group-list | grep -q
> "169.0.0.10"])
> +OVS_WAIT_UNTIL([ovn-appctl evpn/vtep-multicast-group-list | grep -q
> "169.0.0.20"])
> +OVS_WAIT_UNTIL([ovn-appctl evpn/vtep-multicast-group-list | grep -q
> "169.0.0.30"])
> +OVS_WAIT_UNTIL([ovn-appctl evpn/vtep-multicast-group-list | grep -q
> "169::10"])
> +OVS_WAIT_UNTIL([ovn-appctl evpn/vtep-multicast-group-list | grep -q
> "169::30"])
> +AT_CHECK([ovn-appctl evpn/vtep-multicast-group-list | wc -l], [0], [1
> +])
> +
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_PHY_TO_LOG |
> grep priority=1050 | \
> + awk '{print $[7], $[8]}' | sort], [0], [dnl
> +priority=1050,tun_id=0xa,tun_ipv6_src=169::10,tun_ipv6_dst=169::1,in_port=$ofport
>
> actions=load:0x1->OXM_OF_METADATA[[0..31]],load:0x80000002->NXM_NX_REG14[[]],resubmit(,OFTABLE_LEARN_REMOTE_FDB),resubmit(,OFTABLE_LOG_INGRESS_PIPELINE)
> +priority=1050,tun_id=0xa,tun_ipv6_src=169::30,tun_ipv6_dst=169::1,in_port=$ofport
>
> actions=load:0x1->OXM_OF_METADATA[[0..31]],load:0x80000005->NXM_NX_REG14[[]],resubmit(,OFTABLE_LEARN_REMOTE_FDB),resubmit(,OFTABLE_LOG_INGRESS_PIPELINE)
> +priority=1050,tun_id=0xa,tun_src=169.0.0.10,tun_dst=169.0.0.1,in_port=$ofport
>
> actions=load:0x$dp_key->OXM_OF_METADATA[[0..31]],load:0x80000001->NXM_NX_REG14[[]],resubmit(,OFTABLE_LEARN_REMOTE_FDB),resubmit(,OFTABLE_LOG_INGRESS_PIPELINE)
> +priority=1050,tun_id=0xa,tun_src=169.0.0.20,tun_dst=169.0.0.1,in_port=$ofport
>
> actions=load:0x$dp_key->OXM_OF_METADATA[[0..31]],load:0x80000003->NXM_NX_REG14[[]],resubmit(,OFTABLE_LEARN_REMOTE_FDB),resubmit(,OFTABLE_LOG_INGRESS_PIPELINE)
> +priority=1050,tun_id=0xa,tun_src=169.0.0.30,tun_dst=169.0.0.1,in_port=$ofport
>
> actions=load:0x$dp_key->OXM_OF_METADATA[[0..31]],load:0x80000004->NXM_NX_REG14[[]],resubmit(,OFTABLE_LEARN_REMOTE_FDB),resubmit(,OFTABLE_LOG_INGRESS_PIPELINE)
> +])
> +
> +ovs-ofctl dump-flows br-int table=OFTABLE_REMOTE_VTEP_OUTPUT >
> oftable_remote_vtep_output
> +AT_CHECK_UNQUOTED([grep "output" oftable_remote_vtep_output | grep -v
> resubmit | \
> + awk '{print $[7], $[8]}' | sort], [0], [dnl
> +priority=50,reg15=0x80000001,metadata=0x$dp_key
> actions=load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa900000a->NXM_NX_TUN_IPV4_DST[[]],load:0xa->NXM_NX_TUN_ID[[0..23]],output:$ofport
> +priority=50,reg15=0x80000002,metadata=0x$dp_key
> actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],output:$ofport
> +priority=50,reg15=0x80000003,metadata=0x$dp_key
> actions=load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa9000014->NXM_NX_TUN_IPV4_DST[[]],load:0xa->NXM_NX_TUN_ID[[0..23]],output:$ofport
> +priority=50,reg15=0x80000004,metadata=0x$dp_key
> actions=load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa900001e->NXM_NX_TUN_IPV4_DST[[]],load:0xa->NXM_NX_TUN_ID[[0..23]],output:$ofport
> +priority=50,reg15=0x80000005,metadata=0x$dp_key
> actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x30->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],output:$ofport
> +priority=55,reg10=0x1/0x1,reg15=0x80000001,metadata=0x$dp_key
> actions=load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa900000a->NXM_NX_TUN_IPV4_DST[[]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xffff->NXM_OF_IN_PORT[[]],output:$ofport
> +priority=55,reg10=0x1/0x1,reg15=0x80000002,metadata=0x$dp_key
> actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xffff->NXM_OF_IN_PORT[[]],output:$ofport
> +priority=55,reg10=0x1/0x1,reg15=0x80000003,metadata=0x$dp_key
> actions=load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa9000014->NXM_NX_TUN_IPV4_DST[[]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xffff->NXM_OF_IN_PORT[[]],output:$ofport
> +priority=55,reg10=0x1/0x1,reg15=0x80000004,metadata=0x$dp_key
> actions=load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa900001e->NXM_NX_TUN_IPV4_DST[[]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xffff->NXM_OF_IN_PORT[[]],output:$ofport
> +priority=55,reg10=0x1/0x1,reg15=0x80000005,metadata=0x1
> actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x30->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xffff->NXM_OF_IN_PORT[[]],output:$ofport
> +])
> +
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int
> table=OFTABLE_LEARN_REMOTE_FDB | grep priority | \
> + awk '{print $[7], $[8]}' | strip_cookie | sort], [0], [dnl
> +priority=100,reg14=0x80000001,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=100,reg14=0x80000002,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=100,reg14=0x80000003,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=100,reg14=0x80000004,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=100,reg14=0x80000005,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=150,reg14=0x80000004,metadata=0x$dp_key,dl_src=00:00:00:00:00:01
> actions=drop
> +priority=150,reg14=0x80000005,metadata=0x$dp_key,dl_src=00:00:00:00:00:10
> actions=drop
> +])
> +
> +AT_CHECK([grep "resubmit" oftable_remote_vtep_output | grep -c
> "load:0xa900000a"], [0], [3
> +])
> +AT_CHECK([grep "resubmit" oftable_remote_vtep_output | grep -c
> "load:0xa9000014"], [0], [3
> +])
> +AT_CHECK([grep "resubmit" oftable_remote_vtep_output | grep -c
> "load:0xa900001e"], [0], [3
> +])
> +
> +# Simulate remote workload.
> +check bridge fdb add f0:00:0f:16:10:50 dev $VXLAN_NAME dst 169.0.0.10 static
> extern_learn
> +check bridge fdb add f0:00:0f:16:10:60 dev $VXLAN_NAME dst 169.0.0.20 static
> extern_learn
> +check bridge fdb add f0:00:0f:16:10:70 dev $VXLAN_NAME dst 169.0.0.30 static
> extern_learn
> +check bridge fdb add f0:00:0f:16:10:80 dev $VXLAN_V6_NAME dst 169::30 static
> extern_learn
> +
> +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/vtep-fdb-list | cut -d',' -f2-
> | sort], [0], [dnl
> + MAC: 00:00:00:00:00:01, vni: $vni, binding_key: 0x80000004, dp_key: $dp_key
> + MAC: 00:00:00:00:00:10, vni: $vni, binding_key: 0x80000005, dp_key: $dp_key
> + MAC: f0:00:0f:16:10:50, vni: $vni, binding_key: 0x80000001, dp_key: $dp_key
> + MAC: f0:00:0f:16:10:60, vni: $vni, binding_key: 0x80000003, dp_key: $dp_key
> + MAC: f0:00:0f:16:10:70, vni: $vni, binding_key: 0x80000004, dp_key: $dp_key
> + MAC: f0:00:0f:16:10:80, vni: $vni, binding_key: 0x80000005, dp_key: $dp_key
> +])
> +
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_GET_REMOTE_FDB
> | grep priority | \
> + awk '{print $[7], $[8]}' | sort], [0], [dnl
> +priority=0 actions=load:0->NXM_NX_REG1[[]]
> +priority=150,metadata=0x$dp_key,dl_dst=00:00:00:00:00:01
> actions=load:0x80000004->NXM_NX_REG1[[]]
> +priority=150,metadata=0x$dp_key,dl_dst=00:00:00:00:00:10
> actions=load:0x80000005->NXM_NX_REG1[[]]
> +priority=150,metadata=0x$dp_key,dl_dst=f0:00:0f:16:10:50
> actions=load:0x80000001->NXM_NX_REG1[[]]
> +priority=150,metadata=0x$dp_key,dl_dst=f0:00:0f:16:10:60
> actions=load:0x80000003->NXM_NX_REG1[[]]
> +priority=150,metadata=0x$dp_key,dl_dst=f0:00:0f:16:10:70
> actions=load:0x80000004->NXM_NX_REG1[[]]
> +priority=150,metadata=0x$dp_key,dl_dst=f0:00:0f:16:10:80
> actions=load:0x80000005->NXM_NX_REG1[[]]
> +])
> +
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int
> table=OFTABLE_LEARN_REMOTE_FDB | grep priority | \
> + awk '{print $[7], $[8]}' | strip_cookie | sort], [0], [dnl
> +priority=100,reg14=0x80000001,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=100,reg14=0x80000002,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=100,reg14=0x80000003,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=100,reg14=0x80000004,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=100,reg14=0x80000005,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=150,reg14=0x80000001,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:50
> actions=drop
> +priority=150,reg14=0x80000003,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:60
> actions=drop
> +priority=150,reg14=0x80000004,metadata=0x$dp_key,dl_src=00:00:00:00:00:01
> actions=drop
> +priority=150,reg14=0x80000004,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:70
> actions=drop
> +priority=150,reg14=0x80000005,metadata=0x$dp_key,dl_src=00:00:00:00:00:10
> actions=drop
> +priority=150,reg14=0x80000005,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:80
> actions=drop
> +])
> +
> +# Check that the recompute won't change the UUIDs and tunnel keys.
> +ovn-appctl evpn/vtep-binding-list > bindings_before
> +ovn-appctl evpn/vtep-multicast-group-list > mc_groups_before
> +ovn-appctl evpn/vtep-fdb-list > fdb_before
> +
> +check ovn-appctl inc-engine/recompute
> +check ovn-nbctl --wait=hv sync
> +
> +ovn-appctl evpn/vtep-binding-list > bindings_after
> +ovn-appctl evpn/vtep-multicast-group-list > mc_groups_after
> +ovn-appctl evpn/vtep-fdb-list > fdb_after
> +
> +check diff -q bindings_before bindings_after
> +check diff -q mc_groups_before mc_groups_after
> +check diff -q fdb_before fdb_after
> +
> +AS_BOX([L2 EVPN FDB advertising])
> +
> +check ovn-nbctl --wait=hv set logical_switch ls-evpn
> other_config:dynamic-routing-redistribute=fdb
> +OVS_WAIT_FOR_OUTPUT_UNQUOTED([bridge fdb show | grep $LO_NAME | grep
> "f0:00:0f:16:01" | sort], [0], [dnl
> +f0:00:0f:16:01:10 dev $LO_NAME master $BR_NAME static
> +f0:00:0f:16:01:10 dev $LO_NAME vlan 1 master $BR_NAME static
> +f0:00:0f:16:01:20 dev $LO_NAME master $BR_NAME static
> +f0:00:0f:16:01:20 dev $LO_NAME vlan 1 master $BR_NAME static
> +])
> +
> +check ovn-nbctl --wait=hv lsp-del workload2
> +OVS_WAIT_FOR_OUTPUT_UNQUOTED([bridge fdb show | grep $LO_NAME | grep
> "f0:00:0f:16:01" | sort], [0], [dnl
> +f0:00:0f:16:01:10 dev $LO_NAME master $BR_NAME static
> +f0:00:0f:16:01:10 dev $LO_NAME vlan 1 master $BR_NAME static
> +])
> +
> +check ovn-nbctl --wait=hv remove logical_switch ls-evpn other_config
> dynamic-routing-redistribute
> +OVS_WAIT_FOR_OUTPUT_UNQUOTED([bridge fdb show | grep $LO_NAME | grep
> "f0:00:0f:16:01" | sort], [0], [dnl
> +])
> +
> +check ovn-nbctl --wait=hv set logical_switch ls-evpn
> other_config:fdb_age_threshold=300
> +ovs-ofctl dump-flows br-int table=OFTABLE_LEARN_REMOTE_FDB
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int
> table=OFTABLE_LEARN_REMOTE_FDB | grep priority | \
> + awk '{print $[7], $[8]}' | strip_cookie | sort], [0], [dnl
> +priority=100,reg14=0x80000001,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,hard_timeout=300,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=100,reg14=0x80000002,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,hard_timeout=300,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=100,reg14=0x80000003,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,hard_timeout=300,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=100,reg14=0x80000004,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,hard_timeout=300,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=100,reg14=0x80000005,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,hard_timeout=300,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=150,reg14=0x80000001,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:50
> actions=drop
> +priority=150,reg14=0x80000003,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:60
> actions=drop
> +priority=150,reg14=0x80000004,metadata=0x$dp_key,dl_src=00:00:00:00:00:01
> actions=drop
> +priority=150,reg14=0x80000004,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:70
> actions=drop
> +priority=150,reg14=0x80000005,metadata=0x$dp_key,dl_src=00:00:00:00:00:10
> actions=drop
> +priority=150,reg14=0x80000005,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:80
> actions=drop
> +])
> +
> +check ovn-nbctl --wait=hv remove logical_switch ls-evpn other_config
> fdb_age_threshold
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int
> table=OFTABLE_LEARN_REMOTE_FDB | grep priority | \
> + awk '{print $[7], $[8]}' | strip_cookie | sort], [0], [dnl
> +priority=100,reg14=0x80000001,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=100,reg14=0x80000002,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=100,reg14=0x80000003,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=100,reg14=0x80000004,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=100,reg14=0x80000005,metadata=0x$dp_key
> actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
> +priority=150,reg14=0x80000001,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:50
> actions=drop
> +priority=150,reg14=0x80000003,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:60
> actions=drop
> +priority=150,reg14=0x80000004,metadata=0x$dp_key,dl_src=00:00:00:00:00:01
> actions=drop
> +priority=150,reg14=0x80000004,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:70
> actions=drop
> +priority=150,reg14=0x80000005,metadata=0x$dp_key,dl_src=00:00:00:00:00:10
> actions=drop
> +priority=150,reg14=0x80000005,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:80
> actions=drop
> +])
> +
> +AS_BOX([L2 EVPN ARP learning])
> +# Add a router connected to the EVPN logical switch.
> +check ovn-nbctl --wait=hv \
> + -- lr-add lr \
> + -- lrp-add lr lr-ls-evpn f0:00:0f:16:01:01 172.16.1.1/24 172:16::1/64 \
> + -- lsp-add-router-port ls-evpn ls-evpn-lr lr-ls-evpn
> +
> +rtr_dp_key=$(fetch_column Datapath tunnel_key external_ids:name=lr)
> +rtr_port_key=$(fetch_column Port_Binding tunnel_key logical_port=lr-ls-evpn)
> +
> +# Simulate remote workload ARPs (type-2 MAC+IP EVPN route).
> +# ovn-controller needs to add OF rules for ARP lookup but no rules for
> +# MAC_CACHE use. These entries do not age out automatically, their lifetime
> +# is controlled by the BGP-EVPN control plane.
> +check ip neigh add dev $BR_NAME 172.16.1.50 lladdr f0:00:0f:16:10:50 nud
> noarp extern_learn
> +check ip neigh add dev $BR_NAME 172.16.1.60 lladdr f0:00:0f:16:10:60 nud
> noarp extern_learn
> +check ip neigh add dev $BR_NAME 172.16.1.70 lladdr f0:00:0f:16:10:70 nud
> noarp extern_learn
> +
> +check ip -6 neigh add dev $BR_NAME 172:16::50 lladdr f0:00:0f:16:10:50 nud
> noarp extern_learn
> +check ip -6 neigh add dev $BR_NAME 172:16::60 lladdr f0:00:0f:16:10:60 nud
> noarp extern_learn
> +check ip -6 neigh add dev $BR_NAME 172:16::70 lladdr f0:00:0f:16:10:70 nud
> noarp extern_learn
> +
> +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/vtep-arp-list | cut -d',' -f2-
> | sort], [0], [dnl
> + VNI: 10, MAC: f0:00:0f:16:10:50, IP: 172.16.1.50, dp_key: $dp_key
> + VNI: 10, MAC: f0:00:0f:16:10:50, IP: 172:16::50, dp_key: $dp_key
> + VNI: 10, MAC: f0:00:0f:16:10:60, IP: 172.16.1.60, dp_key: $dp_key
> + VNI: 10, MAC: f0:00:0f:16:10:60, IP: 172:16::60, dp_key: $dp_key
> + VNI: 10, MAC: f0:00:0f:16:10:70, IP: 172.16.1.70, dp_key: $dp_key
> + VNI: 10, MAC: f0:00:0f:16:10:70, IP: 172:16::70, dp_key: $dp_key
> +])
> +
> +AS_BOX([Check dynamic-routing-arp-prefer-local=true])
> +check ovn-nbctl --wait=hv set Logical_Switch ls-evpn
> other_config:dynamic-routing-arp-prefer-local=true
> +
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING |
> grep priority | \
> + awk '{print $[7], $[8]}' | sort], [0], [dnl
> +priority=100,reg0=0xac10010a,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:01:10,load:0x1->NXM_NX_REG10[[6]]
> +priority=20,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
> +priority=20,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
> +priority=20,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
> +priority=20,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
> +priority=20,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
> +priority=20,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
> +])
> +
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP |
> grep priority | \
> + awk '{print $[7], $[8]}' | sort], [0], [dnl
> +priority=100,arp,reg0=0xac10010a,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10
> actions=load:0x1->NXM_NX_REG10[[6]]
> +priority=20,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
> actions=load:0x1->NXM_NX_REG10[[6]]
> +priority=20,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
> actions=load:0x1->NXM_NX_REG10[[6]]
> +priority=20,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
> actions=load:0x1->NXM_NX_REG10[[6]]
> +priority=20,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
> actions=load:0x1->NXM_NX_REG10[[6]]
> +priority=20,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
> actions=load:0x1->NXM_NX_REG10[[6]]
> +priority=20,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
> actions=load:0x1->NXM_NX_REG10[[6]]
> +])
> +
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE |
> grep priority | \
> + awk '{print $[7], $[8]}' | sort], [0], [dnl
> +priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,arp_spa=172.16.1.10,arp_op=2
> actions=drop
> +priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,nw_src=172.16.1.10
> actions=drop
> +])
> +
> +AS_BOX([Check dynamic-routing-arp-prefer-local=false])
> +check ovn-nbctl --wait=hv set Logical_Switch ls-evpn
> other_config:dynamic-routing-arp-prefer-local=false
> +
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING |
> grep priority | \
> + awk '{print $[7], $[8]}' | sort], [0], [dnl
> +priority=100,reg0=0xac10010a,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:01:10,load:0x1->NXM_NX_REG10[[6]]
> +priority=200,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
> +priority=200,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
> +priority=200,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
> +priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
> +priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
> +priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
> +])
> +
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP |
> grep priority | \
> + awk '{print $[7], $[8]}' | sort], [0], [dnl
> +priority=100,arp,reg0=0xac10010a,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10
> actions=load:0x1->NXM_NX_REG10[[6]]
> +priority=200,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
> actions=load:0x1->NXM_NX_REG10[[6]]
> +priority=200,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
> actions=load:0x1->NXM_NX_REG10[[6]]
> +priority=200,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
> actions=load:0x1->NXM_NX_REG10[[6]]
> +priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
> actions=load:0x1->NXM_NX_REG10[[6]]
> +priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
> actions=load:0x1->NXM_NX_REG10[[6]]
> +priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
> actions=load:0x1->NXM_NX_REG10[[6]]
> +])
> +
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE |
> grep priority | \
> + awk '{print $[7], $[8]}' | sort], [0], [dnl
> +priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,arp_spa=172.16.1.10,arp_op=2
> actions=drop
> +priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,nw_src=172.16.1.10
> actions=drop
> +])
> +
> +# Check that the recompute won't change the UUIDs and flows.
> +ovn-appctl evpn/vtep-arp-list > arp_before
> +
> +check ovn-appctl inc-engine/recompute
> +check ovn-nbctl --wait=hv sync
> +
> +ovn-appctl evpn/vtep-arp-list > arp_after
> +
> +check diff -q arp_before arp_after
> +
> +# Remove remote workload ARP entries and check ovn-controller's state.
> +check ip neigh del dev $BR_NAME 172.16.1.50
> +check ip neigh del dev $BR_NAME 172.16.1.60
> +check ip neigh del dev $BR_NAME 172.16.1.70
> +
> +check ip -6 neigh del dev $BR_NAME 172:16::50
> +check ip -6 neigh del dev $BR_NAME 172:16::60
> +check ip -6 neigh del dev $BR_NAME 172:16::70
> +
> +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/vtep-arp-list | cut -d',' -f2-
> | sort], [0], [dnl
> +])
> +
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING |
> grep priority | \
> + awk '{print $[7], $[8]}' | sort], [0], [dnl
> +priority=100,reg0=0xac10010a,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:01:10,load:0x1->NXM_NX_REG10[[6]]
> +])
> +
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP |
> grep priority | \
> + awk '{print $[7], $[8]}' | sort], [0], [dnl
> +priority=100,arp,reg0=0xac10010a,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10
> actions=load:0x1->NXM_NX_REG10[[6]]
> +])
> +
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE |
> grep priority | \
> + awk '{print $[7], $[8]}' | sort], [0], [dnl
> +priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,arp_spa=172.16.1.10,arp_op=2
> actions=drop
> +priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,nw_src=172.16.1.10
> actions=drop
> +])
> +
> +# Re-add the remote workload ARPs, remove the router, check that flows are
> +# removed (vtep-arp-list should still list the ARPs as they're learned on
> +# the logical switch that still exists).
> +check ip neigh add dev $BR_NAME 172.16.1.50 lladdr f0:00:0f:16:10:50 nud
> noarp extern_learn
> +check ip neigh add dev $BR_NAME 172.16.1.60 lladdr f0:00:0f:16:10:60 nud
> noarp extern_learn
> +check ip neigh add dev $BR_NAME 172.16.1.70 lladdr f0:00:0f:16:10:70 nud
> noarp extern_learn
> +
> +check ip -6 neigh add dev $BR_NAME 172:16::50 lladdr f0:00:0f:16:10:50 nud
> noarp extern_learn
> +check ip -6 neigh add dev $BR_NAME 172:16::60 lladdr f0:00:0f:16:10:60 nud
> noarp extern_learn
> +check ip -6 neigh add dev $BR_NAME 172:16::70 lladdr f0:00:0f:16:10:70 nud
> noarp extern_learn
> +
> +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/vtep-arp-list | cut -d',' -f2-
> | sort], [0], [dnl
> + VNI: 10, MAC: f0:00:0f:16:10:50, IP: 172.16.1.50, dp_key: $dp_key
> + VNI: 10, MAC: f0:00:0f:16:10:50, IP: 172:16::50, dp_key: $dp_key
> + VNI: 10, MAC: f0:00:0f:16:10:60, IP: 172.16.1.60, dp_key: $dp_key
> + VNI: 10, MAC: f0:00:0f:16:10:60, IP: 172:16::60, dp_key: $dp_key
> + VNI: 10, MAC: f0:00:0f:16:10:70, IP: 172.16.1.70, dp_key: $dp_key
> + VNI: 10, MAC: f0:00:0f:16:10:70, IP: 172:16::70, dp_key: $dp_key
> +])
> +
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING |
> grep priority | \
> + awk '{print $[7], $[8]}' | sort], [0], [dnl
> +priority=100,reg0=0xac10010a,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:01:10,load:0x1->NXM_NX_REG10[[6]]
> +priority=200,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
> +priority=200,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
> +priority=200,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
> +priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
> +priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
> +priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
> actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
> +])
> +
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP |
> grep priority | \
> + awk '{print $[7], $[8]}' | sort], [0], [dnl
> +priority=100,arp,reg0=0xac10010a,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10
> actions=load:0x1->NXM_NX_REG10[[6]]
> +priority=200,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
> actions=load:0x1->NXM_NX_REG10[[6]]
> +priority=200,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
> actions=load:0x1->NXM_NX_REG10[[6]]
> +priority=200,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
> actions=load:0x1->NXM_NX_REG10[[6]]
> +priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
> actions=load:0x1->NXM_NX_REG10[[6]]
> +priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
> actions=load:0x1->NXM_NX_REG10[[6]]
> +priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
> actions=load:0x1->NXM_NX_REG10[[6]]
> +])
> +
> +check ovn-nbctl --wait=hv lr-del lr
> +AT_CHECK_UNQUOTED([ovn-appctl evpn/vtep-arp-list | cut -d',' -f2- | sort],
> [0], [dnl
> + VNI: 10, MAC: f0:00:0f:16:10:50, IP: 172.16.1.50, dp_key: $dp_key
> + VNI: 10, MAC: f0:00:0f:16:10:50, IP: 172:16::50, dp_key: $dp_key
> + VNI: 10, MAC: f0:00:0f:16:10:60, IP: 172.16.1.60, dp_key: $dp_key
> + VNI: 10, MAC: f0:00:0f:16:10:60, IP: 172:16::60, dp_key: $dp_key
> + VNI: 10, MAC: f0:00:0f:16:10:70, IP: 172.16.1.70, dp_key: $dp_key
> + VNI: 10, MAC: f0:00:0f:16:10:70, IP: 172:16::70, dp_key: $dp_key
> +])
> +
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING |
> grep priority | \
> + awk '{print $[7], $[8]}' | sort], [0], [dnl
> +])
> +
> +AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP |
> grep priority | \
> + awk '{print $[7], $[8]}' | sort], [0], [dnl
> +])
> +
> +AS_BOX([L2 EVPN ARP advertising])
> +# Add a router connected to the EVPN logical switch.
> +check ovn-nbctl --wait=hv \
> + -- lr-add lr \
> + -- set Logical_Router lr options:chassis=hv1 \
> + -- lrp-add lr lr-ls-evpn f0:00:0f:16:01:01 172.16.1.1/24 172:16::1/64
> +
> +ls_evpn_uuid=$(fetch_column Datapath_Binding _uuid external_ids:name=ls-evpn)
> +check ovn-nbctl --wait=hv set logical_switch ls-evpn
> other_config:dynamic-routing-redistribute=fdb,ip
> +check_row_count Advertised_MAC_Binding 1 ip='172.16.1.10'
> mac='f0\:00\:0f\:16\:01\:10' datapath=$ls_evpn_uuid
> +check_row_count Advertised_MAC_Binding 1 ip='172.16.1.1'
> mac='f0\:00\:0f\:16\:01\:01' datapath=$ls_evpn_uuid
> +check_row_count Advertised_MAC_Binding 1 ip='172\:16\:\:10'
> mac='f0\:00\:0f\:16\:01\:10' datapath=$ls_evpn_uuid
> +check_row_count Advertised_MAC_Binding 1 ip='172\:16\:\:1'
> mac='f0\:00\:0f\:16\:01\:01' datapath=$ls_evpn_uuid
> +check_row_count Advertised_MAC_Binding 4
> +
> +AT_CHECK([ip neigh show dev $BR_NAME nud noarp | grep -q '172.16.1.10 lladdr
> f0:00:0f:16:01:10 NOARP'])
> +AT_CHECK([ip neigh show dev $BR_NAME nud noarp | grep -q '172.16.1.1 lladdr
> f0:00:0f:16:01:01 NOARP'])
> +AT_CHECK([ip -6 neigh show dev $BR_NAME nud noarp | grep -q '172:16::10
> lladdr f0:00:0f:16:01:10 NOARP'])
> +AT_CHECK([ip -6 neigh show dev $BR_NAME nud noarp | grep -q '172:16::1
> lladdr f0:00:0f:16:01:01 NOARP'])
> +
> +OVS_WAIT_FOR_OUTPUT_UNQUOTED([bridge fdb show | grep $LO_NAME | grep
> "f0:00:0f:16:01" | sort], [0], [dnl
> +f0:00:0f:16:01:01 dev $LO_NAME master $BR_NAME static
> +f0:00:0f:16:01:01 dev $LO_NAME vlan 1 master $BR_NAME static
> +f0:00:0f:16:01:10 dev $LO_NAME master $BR_NAME static
> +f0:00:0f:16:01:10 dev $LO_NAME vlan 1 master $BR_NAME static
> +])
> +
> +check ovn-nbctl --wait=hv lsp-add ls-evpn workload2 \
> + -- lsp-set-addresses workload2 "f0:00:0f:16:01:20 172.16.1.20 172:16::20"
> +
> +check_row_count Advertised_MAC_Binding 1 ip='172.16.1.20'
> mac='f0\:00\:0f\:16\:01\:20' datapath=$ls_evpn_uuid
> +AT_CHECK([ip neigh show dev $BR_NAME nud noarp | grep -q '172.16.1.20 lladdr
> f0:00:0f:16:01:20 NOARP'])
> +
> +check_row_count Advertised_MAC_Binding 1 ip='172\:16\:\:20'
> mac='f0\:00\:0f\:16\:01\:20' datapath=$ls_evpn_uuid
> +AT_CHECK([ip -6 neigh show dev $BR_NAME nud noarp | grep -q '172:16::20
> lladdr f0:00:0f:16:01:20 NOARP'])
> +
> +check ovn-nbctl --wait=hv lsp-del workload2
> +AT_CHECK([ip neigh show dev $BR_NAME nud noarp | grep -q '172.16.1.20 lladdr
> f0:00:0f:16:01:20 NOARP'], [1])
> +AT_CHECK([ip -6 neigh show dev $BR_NAME nud noarp | grep -q '172:16::20
> lladdr f0:00:0f:16:01:20 NOARP'], [1])
> +
> +check ovn-nbctl --wait=hv lsp-del workload1
> +check_row_count Advertised_MAC_Binding 2
> +AT_CHECK([ip neigh show dev $BR_NAME nud noarp | grep -q '172.16.1.10 lladdr
> f0:00:0f:16:01:10 NOARP'], [1])
> +AT_CHECK([ip -6 neigh show dev $BR_NAME nud noarp | grep -q '172:16::10
> lladdr f0:00:0f:16:01:10 NOARP'], [1])
> +
> +check ovn-nbctl --wait=hv lrp-del lr-ls-evpn
> +check_row_count Advertised_MAC_Binding 0
> +AT_CHECK([ip neigh show dev $BR_NAME nud noarp | grep -q '172.16.1.1 lladdr
> f0:00:0f:16:01:01 NOARP'], [1])
> +AT_CHECK([ip -6 neigh show dev $BR_NAME nud noarp | grep -q '172:16::1
> lladdr f0:00:0f:16:01:01 NOARP'], [1])
> +
> +check ovn-nbctl --wait=hv ls-del ls-evpn
> +check ovn-nbctl --wait=hv lr-del lr
> +
> +OVN_CLEANUP_CONTROLLER([hv1])
> +
> +OVN_CLEANUP_NORTHD
> +
> +as
> +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
> +/Failed to acquire.*/d
> +/connection dropped.*/d"])
> +AT_CLEANUP
> +])
> +
> ]) dnl EVPN_SWITCH_TESTS
>
> EVPN_SWITCH_TESTS([default])
Regards,
Dumitru
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev