> Hi Lorenzo, > > Thanks for the new revision! Hi Dumitru,
thx for the review. > > On 12/19/25 3:35 PM, 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] > > This is not accurate anymore, it should be ovn-evpn-local-ip-mapping but > please see below. ack, I will fix it. > > > > > Reported-at: https://issues.redhat.com/browse/FDP-2768 > > Signed-off-by: Lorenzo Bianconi <[email protected]> > > --- > > Changes in v4: > > - Do not use linear lookup in evpn_local_ip_lookup_by_vni() > > - Introduce ovn-evpn-local-ip-mapping config option > > I know we had discussed it on the v3 patch but, probably because I was > off for a few weeks :), I changed my mind, I'm sorry. It's a bit > annoying that we had to add a new option for the mapping. > > What if we go back to a single option, ovn-evpn-local-ip but use a > different separator, e.g.: > > ovn-evpn-local-ip=<VNI1>-<IP4_1>,<VNI1>-<IP6_1>,<VNI2>-<IP4_1>,<DEF_IP4>,<DEF_IP6> > > Some examples: > 10-1.1.1.1,20-2.2.2.2,30-3.3.3.3,10-1::1,20-2::2,5::5 > > yields: > - VNI 10: 1.1.1.1 and 1::1 > - VNI 20: 2.2.2.2 and 2::2 > - VNI 30: 3.3.3.3 (no IPv6 local IP) > - default-v4: not present > - default-v6: 5::5 > > 10-1.1.1.1,5.5.5.5,20-2.2.2.2,5::5,10-1::1,20-2::2 > > yields: > - VNI 10: 1.1.1.1 and 1::1 > - VNI 20: 2.2.2.2 and 2::2 > - default-v4: 5.5.5.5 > - default-v6: 5::5 > > So the parsing would be: > - split by ',' > - for each token: > - split by '-': > - if only one token results then this is a > default IP (v4 or v6) > - if two token result then the first token > should be parsed as VNI and the second one > as an IP (v4 or v6) > - if more tokens result then report an error > > What do you think? ack, I am fine with this approach. > > > 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 > > --- > > NEWS | 2 + > > TODO.rst | 4 - > > controller/chassis.c | 21 ++ > > controller/neighbor.c | 5 +- > > controller/ovn-controller.8.xml | 20 +- > > controller/physical.c | 232 ++++++++++--- > > lib/ovn-util.c | 23 ++ > > lib/ovn-util.h | 2 + > > tests/system-common-macros.at | 14 +- > > tests/system-ovn.at | 596 +++++++++++++++++++++++++++++++- > > 10 files changed, 847 insertions(+), 72 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. > > Same here, this is now inaccurate. with the new approach you suggested now this is fine. > > > > > 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/chassis.c b/controller/chassis.c > > index 4afb6da93..b152fabc5 100644 > > --- a/controller/chassis.c > > +++ b/controller/chassis.c > > @@ -60,6 +60,7 @@ struct ovs_chassis_cfg { > > const char *trim_timeout_ms; > > const char *evpn_vxlan_port; > > const char *evpn_local_ip; > > + const char *evpn_local_ip_mapping; > > > > /* Set of encap types parsed from the 'ovn-encap-type' external-id. */ > > struct sset encap_type_set; > > @@ -220,6 +221,13 @@ get_evpn_local_ip(const struct smap *ext_ids, const > > char *chassis_id) > > "ovn-evpn-local-ip", ""); > > } > > > > +static const char * > > +get_evpn_local_ip_mapping(const struct smap *ext_ids, const char > > *chassis_id) > > +{ > > + return get_chassis_external_id_value(ext_ids, chassis_id, > > + "ovn-evpn-local-ip-mapping", ""); > > +} > > + > > static const char * > > get_datapath_type(const struct ovsrec_bridge *br_int) > > { > > @@ -358,6 +366,8 @@ chassis_parse_ovs_config(const struct > > ovsrec_open_vswitch_table *ovs_table, > > get_evpn_vxlan_port(&cfg->external_ids, chassis_id); > > ovs_cfg->evpn_local_ip = > > get_evpn_local_ip(&cfg->external_ids, chassis_id); > > + ovs_cfg->evpn_local_ip_mapping = > > + get_evpn_local_ip_mapping(&cfg->external_ids, chassis_id); > > > > chassis_parse_ovs_encap_type(encap_type, &ovs_cfg->encap_type_set); > > > > @@ -412,6 +422,8 @@ chassis_build_other_config(const struct ovs_chassis_cfg > > *ovs_cfg, > > smap_replace(config, "ovn-chassis-mac-mappings", > > ovs_cfg->chassis_macs); > > smap_replace(config, "ovn-evpn-vxlan-ports", ovs_cfg->evpn_vxlan_port); > > smap_replace(config, "ovn-evpn-local-ip", ovs_cfg->evpn_local_ip); > > + smap_replace(config, "ovn-evpn-local-ip-mapping", > > + ovs_cfg->evpn_local_ip_mapping); > > smap_replace(config, "is-interconn", > > ovs_cfg->is_interconn ? "true" : "false"); > > smap_replace(config, OVN_FEATURE_PORT_UP_NOTIF, "true"); > > @@ -544,6 +556,14 @@ chassis_other_config_changed(const struct > > ovs_chassis_cfg *ovs_cfg, > > return true; > > } > > > > + const char *chassis_evpn_local_ip_mapping = > > + get_evpn_local_ip_mapping(&chassis_rec->other_config, > > + chassis_rec->name); > > + if (strcmp(ovs_cfg->evpn_local_ip_mapping, > > + chassis_evpn_local_ip_mapping)) { > > + return true; > > + } > > + > > if (!smap_get_bool(&chassis_rec->other_config, > > OVN_FEATURE_PORT_UP_NOTIF, > > false)) { > > return true; > > @@ -787,6 +807,7 @@ update_supported_sset(struct sset *supported) > > sset_add(supported, "is-interconn"); > > sset_add(supported, "ovn-evpn-vxlan-ports"); > > sset_add(supported, "ovn-evpn-local-ip"); > > + sset_add(supported, "ovn-evpn-local-ip-mapping"); > > > > /* Internal options. */ > > sset_add(supported, "is-vtep"); > > 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..1c394c6a0 100644 > > --- a/controller/ovn-controller.8.xml > > +++ b/controller/ovn-controller.8.xml > > @@ -432,10 +432,22 @@ > > > > <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. > > + Default 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=IPv4,IPv6</code>. > > + NOTE: this feature is experimental and may be subject to > > removal/change > > + in the future. > > + </dd> > > + > > + <dt><code>external_ids:ovn-evpn-local-ip-mapping</code></dt> > > + <dd> > > + IP address list used as a source addresses for the EVPN traffic > > + leaving this OVN setup. The <code>ovn-evpn-local-ip-mapping</code> > > + can be specified by the CMS according to the following syntax: > > + <code>external_ids:ovn-evpn-local-ip-mapping=vni0:IPv4,vni1:IPv4, > > + vni1:[IPv6]</code>. NOTE: this feature is experimental and may be > > + ubject to removal/change in the future. > > Typo: ubject > > > </dd> > > </dl> > > > > diff --git a/controller/physical.c b/controller/physical.c > > index b9c60c8ab..760eda423 100644 > > --- a/controller/physical.c > > +++ b/controller/physical.c > > @@ -3178,13 +3178,132 @@ physical_eval_remote_chassis_flows(const struct > > physical_ctx *ctx, > > ofpbuf_uninit(&ingress_ofpacts); > > } > > > > +struct vni_local_ip { > > + struct hmap_node hmap_node; > > + struct in6_addr ip; > > + uint32_t vni; > > +}; > > + > > +/* Default local ip mapping */ > > +static struct in6_addr def_local_ip4, def_local_ip6; > > + > > It's unfortunate we have to set up global variables for defaults. I > think a better way to do this is to use a proper type for EVPN VNI > mappings instead of a raw hmap initialized by evpn_vni_local_ip_map_alloc(). > > I.e., we could have a new type: > > struct evpn_local_ip_map { > struct hmap vni_ip_v4; /* Per VNI local IPv4 vni_local_ips. */ > struct hmap vni_ip_v6; /* Per VNI local IPv4 vni_local_ips. */ > struct in6_addr default_ip4; /* Default local IPv4. */ > struct in6_addr default_ip6; /* Default local IPv6. */ > }; > > And have the evpn_local_ip_lookup_by_vni() and > evpn_vni_local_ip_map_alloc() functions operate on a 'struct > evpn_local_ip_map` instead of a raw hmap. ack, I will work on it. > > > +static struct in6_addr * > > +evpn_local_ip_lookup_by_vni(const struct hmap *map, uint32_t vni, bool > > ipv4) > > Nit: evpn_local_ip_find() is explicit enough in my opinion. ack, I will fix it > > > +{ > > + struct vni_local_ip *e; > > + HMAP_FOR_EACH_WITH_HASH (e, hmap_node, hash_add(vni, ipv4), map) { > > + if (IN6_IS_ADDR_V4MAPPED(&e->ip) != ipv4) { > > + continue; > > + } > > + if (e->vni == vni) { > > + return &e->ip; > > + } > > + } > > + > > + if (ipv4 && ipv6_addr_is_set(&def_local_ip4)) { > > + return &def_local_ip4; > > + } > > + > > + if (!ipv4 && ipv6_addr_is_set(&def_local_ip6)) { > > + return &def_local_ip6; > > + } > > + > > + return NULL; > > +} > > + > > +static void > > +evpn_vni_local_ip_map_alloc(struct hmap *map, const struct smap *config) > > Nit: s/evpn_vni_local_ip_map_alloc/evpn_local_ip_map_init/ ack, I will fix it > > > +{ > > + char *tokstr, *token, *ptr0 = NULL; > > + struct in6_addr ip; > > + int addr_family; > > + > > + const char *local_ip_str = smap_get_def(config, "ovn-evpn-local-ip", > > ""); > > + if (strlen(local_ip_str)) { > > + tokstr = xstrdup(local_ip_str); > > + token = strtok_r(tokstr, ",", &ptr0); > > + /* Primary default IP */ > > + if (!ip_address_from_str(token, &ip, &addr_family)) { > > + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); > > + VLOG_WARN_RL(&rl, "Invalid IP: %s", token); > > We leak 'tokstr' here. ack, I will fix it > > > + return; > > + } > > + > > + struct in6_addr *ip_ptr = addr_family == AF_INET ? &def_local_ip4 > > + : &def_local_ip6; > > + *ip_ptr = ip; > > + char *ip_str = strtok_r(NULL, "", &ptr0); > > + if (ip_str && ip_address_from_str(ip_str, &ip, &addr_family)) { > > If we use the new ovn-evpn-local-ip scheme I suggested in the beggining > of the email we can just use ip46_parse(ip_str, &ip) here without having > to add a new helper. > > > + /* Secondary default IP */ > > + ip_ptr = addr_family == AF_INET ? &def_local_ip4 : > > &def_local_ip6; > > + *ip_ptr = ip; > > We don't warn if the user incorrectly specified more than one local IP. > Even with the unified ovn-evpn-local-ip suggestion above we should > validate that: > > - there's at most one default IPv4 > - there's at most one default IPv6 > - we don't have duplicate IPs for a given family for any VNI ack, I will fix it > > > + } > > + > > + free(tokstr); > > + return; > > + } > > + > > + local_ip_str = smap_get_def(config, "ovn-evpn-local-ip-mapping", ""); > > + tokstr = xstrdup(local_ip_str); > > + 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)) { > > + 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; > > + } > > + > > + struct vni_local_ip *e = xmalloc(sizeof *e); > > + e->vni = vni; > > + e->ip = ip; > > Nit: please use designated initializers, we've been trying to encourage > that lately, that is: > > *e = (struct vni_local_ip) { > .vni = vni, > .ip = ip, ack, I will fix it > }; > > > + hmap_insert(map, &e->hmap_node, hash_add(vni, addr_family == > > AF_INET)); > > We should first do a lookup here to avoid inserting duplicates. And > warn if a duplicate is detected. ack, I will fix it > > > + } > > + free(tokstr); > > +} > > + > > +static void > > +evpn_vni_local_ip_map_destroy(struct hmap *map) > > Nit: s/evpn_vni_local_ip_map_destroy/evpn_local_ip_map_destroy/ ack, I will fix it > > > +{ > > + 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"); > > This warning message is not very helpful if we don't log the > binding->vni here. ack, I will fix it > > > + return; > > + } > > + > > /* Ingress flows. */ > > ofpbuf_clear(ofpacts); > > match_init_catchall(match); > > @@ -3308,39 +3427,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); > > Maybe we should have a evpn_local_ip_find_v4() that returns the IPv4 > address as ovs_be32 (or 0 if not found). > > > + struct in6_addr *local_ip6 = > > + evpn_local_ip_lookup_by_vni(vni_ip_map, mc_group->vni, false); > > > > Same here, I think a evpn_local_ip_find_v6() that returns the IPv6 > address would be nice. ok, I will work on it > > > 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); > > If you take into account the previous comments this could become: > > if (ip4) { > put_load_bytes(...) > } > > > - } 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) { > > We should add a comment here explaining why we need to zero the tunnel > v4 fields before moving on to the IPv6 remotes. It might not be too > obvious that we: > - first walk all the v4 remotes, generate tun encap actions for them > - zero out the tun_v4 OVS fields to avoid having inconsistent OVS flow > actions (set non-zero tunnel IPv4 src/dst followed by set non-zero > tunnel IPv6 src/dst) > - walk all the v6 remotes, generate tun encap actions for them ack, I will add it > > > + 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 +3564,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 +3708,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; > > - > > Nit: unrelated change. > > > 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) > > We won't need this anymore if we move the per vni config back into > ovn-evpn-local-ip as suggested above. ack, I will drop ip_address_from_str > > > +{ > > + 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"); > > This warning message is not that useful if we don't specify for which > ip_str we failed parsing. > > > + 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 > > \ > > Unrelated change. ack, I will fix it > > > 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..482908de6 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 > > ]) > > > > @@ -18170,7 +18170,7 @@ check ovs-vsctl \ > > -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ > > -- set Open_vSwitch . external-ids:ovn-encap-ip=169::1 \ > > -- set Open_vSwitch . external-ids:ovn-bridge-mappings=phynet:br-ext \ > > - -- set Open_vSwitch . external-ids:ovn-evpn-local-ip=169::1 \ > > + -- set Open_vSwitch . external-ids:ovn-evpn-local-ip=169.0.0.1,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 > > > > @@ -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:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],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: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:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],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[[]],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: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-mapping=10:169.0.0.1,10:[[169::1]] \ > > Nit: we could use $vni instead of hardcoded 10. ack, I will fix it > > > + -- 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" > > If the "ip link" fails for the $VXLAN_V6_NAME device we don't cleanup > the v4 one. We should split this on_exit into two separate ones, one > for v4 one for v6. ack, I will fix it Regards, Lorenzo > > > +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
