The per-VNI local IP lookup code is not specific to the physical flow generation, so move struct evpn_local_ip_map and its helpers from controller/physical.c to lib/ovn-util.c to make them available to other users.
Signed-off-by: Alexandra Rukomoinikova <[email protected]> --- controller/physical.c | 157 ------------------------------------------ lib/ovn-util.c | 144 ++++++++++++++++++++++++++++++++++++++ lib/ovn-util.h | 26 +++++++ 3 files changed, 170 insertions(+), 157 deletions(-) diff --git a/controller/physical.c b/controller/physical.c index b3b247e20..629e5ef73 100644 --- a/controller/physical.c +++ b/controller/physical.c @@ -3249,163 +3249,6 @@ 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; -}; - -struct evpn_local_ip_map { - struct hmap vni_ip4; /* Per VNI local IPv4 vni_local_ips. */ - struct hmap vni_ip6; /* Per VNI local IPv6 vni_local_ips. */ - struct in6_addr default_ip4; /* Default local IPv4. */ - struct in6_addr default_ip6; /* Default local IPv6. */ -}; - -static const struct in6_addr * -evpn_local_ip_lookup(const struct hmap *map, uint32_t vni) -{ - struct vni_local_ip *e; - HMAP_FOR_EACH_WITH_HASH (e, hmap_node, hash_add(vni, 0), map) { - if (e->vni == vni) { - return &e->ip; - } - } - return NULL; -} - -static ovs_be32 -evpn_local_ip_find_v4(const struct evpn_local_ip_map *vni_ip_map, - uint32_t vni) -{ - const struct in6_addr *addr = evpn_local_ip_lookup(&vni_ip_map->vni_ip4, - vni); - if (addr) { - return in6_addr_get_mapped_ipv4(addr); - } - - if (ipv6_addr_is_set(&vni_ip_map->default_ip4)) { - return in6_addr_get_mapped_ipv4(&vni_ip_map->default_ip4); - } - - return 0; -} - -static const struct in6_addr * -evpn_local_ip_find_v6(const struct evpn_local_ip_map *vni_ip_map, - uint32_t vni) -{ - const struct in6_addr *addr = evpn_local_ip_lookup(&vni_ip_map->vni_ip6, - vni); - if (addr) { - return addr; - } - - if (ipv6_addr_is_set(&vni_ip_map->default_ip6)) { - return &vni_ip_map->default_ip6; - } - - return NULL; -} - -static void -evpn_local_ip_map_init(struct evpn_local_ip_map *vni_ip_map, - const struct smap *config) -{ - char *tokstr, *token, *ptr0 = NULL; - - const char *local_ip_str = smap_get_def(config, "ovn-evpn-local-ip", ""); - 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); - struct in6_addr ip; - uint32_t vni; - - if (ptr1 && *ptr1) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "Malformed 'ovn-evpn-local-ip': %s", tokstr); - break; - } - - if (!ip_str) { /* default IP */ - if (!ip46_parse(vni_str, &ip)) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "Invalid IP %s in 'ovn-evpn-local-ip'", - vni_str); - continue; - } - struct in6_addr *ip_ptr = IN6_IS_ADDR_V4MAPPED(&ip) - ? &vni_ip_map->default_ip4 - : &vni_ip_map->default_ip6; - if (ipv6_addr_is_set(ip_ptr)) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "Default ovn-evpn-local-ip IP%d " - "already configured", - IN6_IS_ADDR_V4MAPPED(&ip) ? 4 : 6); - continue; - } - *ip_ptr = ip; - } else { - if (!ip46_parse(ip_str, &ip)) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, - "EVPN enabled, but required 'ovn-evpn-local-ip' " - "is missing or invalid for vni %s", vni_str); - continue; - } - - if (!vni_str) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "Required 'ovn-evpn-local-ip' VNI not " - "configured for IP %s", - ip_str); - 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 in 'ovn-evpn-local-ip'", - vni_str); - continue; - } - - struct hmap *map = IN6_IS_ADDR_V4MAPPED(&ip) - ? &vni_ip_map->vni_ip4 - : &vni_ip_map->vni_ip6; - if (evpn_local_ip_lookup(map, vni)) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "Duplicated VNI entry: %s", vni_str); - continue; - } - - struct vni_local_ip *e = xmalloc(sizeof *e); - *e = (struct vni_local_ip) { - .vni = vni, - .ip = ip, - }; - hmap_insert(map, &e->hmap_node, hash_add(vni, 0)); - } - } - free(tokstr); -} - -static void -evpn_local_ip_map_destroy(struct evpn_local_ip_map *map) -{ - struct vni_local_ip *e; - HMAP_FOR_EACH_POP (e, hmap_node, &map->vni_ip4) { - free(e); - } - hmap_destroy(&map->vni_ip4); - - HMAP_FOR_EACH_POP (e, hmap_node, &map->vni_ip6) { - free(e); - } - hmap_destroy(&map->vni_ip6); -} - static void physical_consider_evpn_binding(const struct evpn_binding *binding, const struct evpn_local_ip_map *vni_ip_map, diff --git a/lib/ovn-util.c b/lib/ovn-util.c index 9842afb3c..6e9d1150e 100644 --- a/lib/ovn-util.c +++ b/lib/ovn-util.c @@ -1897,3 +1897,147 @@ port_contains_duplicate_ip(struct lport_addresses *laddrs1, return false; } + +const struct in6_addr * +evpn_local_ip_lookup(const struct hmap *map, uint32_t vni) +{ + struct vni_local_ip *e; + HMAP_FOR_EACH_WITH_HASH (e, hmap_node, hash_add(vni, 0), map) { + if (e->vni == vni) { + return &e->ip; + } + } + return NULL; +} + +ovs_be32 +evpn_local_ip_find_v4(const struct evpn_local_ip_map *vni_ip_map, + uint32_t vni) +{ + const struct in6_addr *addr = evpn_local_ip_lookup(&vni_ip_map->vni_ip4, + vni); + if (addr) { + return in6_addr_get_mapped_ipv4(addr); + } + + if (ipv6_addr_is_set(&vni_ip_map->default_ip4)) { + return in6_addr_get_mapped_ipv4(&vni_ip_map->default_ip4); + } + + return 0; +} + +const struct in6_addr * +evpn_local_ip_find_v6(const struct evpn_local_ip_map *vni_ip_map, + uint32_t vni) +{ + const struct in6_addr *addr = evpn_local_ip_lookup(&vni_ip_map->vni_ip6, + vni); + if (addr) { + return addr; + } + + if (ipv6_addr_is_set(&vni_ip_map->default_ip6)) { + return &vni_ip_map->default_ip6; + } + + return NULL; +} + +void +evpn_local_ip_map_init(struct evpn_local_ip_map *vni_ip_map, + const struct smap *config) +{ + char *tokstr, *token, *ptr0 = NULL; + + const char *local_ip_str = smap_get_def(config, "ovn-evpn-local-ip", ""); + 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); + struct in6_addr ip; + uint32_t vni; + + if (ptr1 && *ptr1) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "Malformed 'ovn-evpn-local-ip': %s", tokstr); + break; + } + + if (!ip_str) { /* default IP */ + if (!ip46_parse(vni_str, &ip)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "Invalid IP %s in 'ovn-evpn-local-ip'", + vni_str); + continue; + } + struct in6_addr *ip_ptr = IN6_IS_ADDR_V4MAPPED(&ip) + ? &vni_ip_map->default_ip4 + : &vni_ip_map->default_ip6; + if (ipv6_addr_is_set(ip_ptr)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "Default ovn-evpn-local-ip IP%d " + "already configured", + IN6_IS_ADDR_V4MAPPED(&ip) ? 4 : 6); + continue; + } + *ip_ptr = ip; + } else { + if (!ip46_parse(ip_str, &ip)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, + "EVPN enabled, but required 'ovn-evpn-local-ip' " + "is missing or invalid for vni %s", vni_str); + continue; + } + + if (!vni_str) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "Required 'ovn-evpn-local-ip' VNI not " + "configured for IP %s", + ip_str); + 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 in 'ovn-evpn-local-ip'", + vni_str); + continue; + } + + struct hmap *map = IN6_IS_ADDR_V4MAPPED(&ip) + ? &vni_ip_map->vni_ip4 + : &vni_ip_map->vni_ip6; + if (evpn_local_ip_lookup(map, vni)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "Duplicated VNI entry: %s", vni_str); + continue; + } + + struct vni_local_ip *e = xmalloc(sizeof *e); + *e = (struct vni_local_ip) { + .vni = vni, + .ip = ip, + }; + hmap_insert(map, &e->hmap_node, hash_add(vni, 0)); + } + } + free(tokstr); +} + +void +evpn_local_ip_map_destroy(struct evpn_local_ip_map *map) +{ + struct vni_local_ip *e; + HMAP_FOR_EACH_POP (e, hmap_node, &map->vni_ip4) { + free(e); + } + hmap_destroy(&map->vni_ip4); + + HMAP_FOR_EACH_POP (e, hmap_node, &map->vni_ip6) { + free(e); + } + hmap_destroy(&map->vni_ip6); +} diff --git a/lib/ovn-util.h b/lib/ovn-util.h index 3ffcf42c3..8364ede5c 100644 --- a/lib/ovn-util.h +++ b/lib/ovn-util.h @@ -838,4 +838,30 @@ parse_neigh_dynamic_redistribute(const struct smap *options); size_t *shuffled_range(size_t n); +struct vni_local_ip { + struct hmap_node hmap_node; + struct in6_addr ip; + uint32_t vni; +}; + +struct evpn_local_ip_map { + struct hmap vni_ip4; /* Per VNI local IPv4 vni_local_ips. */ + struct hmap vni_ip6; /* Per VNI local IPv6 vni_local_ips. */ + struct in6_addr default_ip4; /* Default local IPv4. */ + struct in6_addr default_ip6; /* Default local IPv6. */ +}; + +const struct in6_addr *evpn_local_ip_lookup(const struct hmap *map, + uint32_t vni); +ovs_be32 evpn_local_ip_find_v4(const struct evpn_local_ip_map *vni_ip_map, + uint32_t vni); +const struct in6_addr *evpn_local_ip_find_v6( + const struct evpn_local_ip_map *vni_ip_map, uint32_t vni); +void evpn_local_ip_map_init(struct evpn_local_ip_map *vni_ip_map, + const struct smap *config); +const struct in6_addr * +evpn_local_ip_map_lookup(const struct evpn_local_ip_map *map, + uint32_t vni, bool ipv4); +void evpn_local_ip_map_destroy(struct evpn_local_ip_map *map); + #endif /* OVN_UTIL_H */ -- 2.48.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
