diff options
-rw-r--r-- | bgpd/bgp_evpn.c | 86 | ||||
-rw-r--r-- | bgpd/bgp_evpn.h | 14 | ||||
-rw-r--r-- | bgpd/bgp_evpn_vty.c | 44 | ||||
-rw-r--r-- | bgpd/bgpd.h | 9 |
4 files changed, 139 insertions, 14 deletions
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 1db552f11..e08e5b979 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -72,6 +72,10 @@ static void bgp_evpn_remote_ip_hash_add(struct bgpevpn *vpn, struct bgp_path_info *pi); static void bgp_evpn_remote_ip_hash_del(struct bgpevpn *vpn, struct bgp_path_info *pi); +static void bgp_evpn_remote_ip_hash_iterate(struct bgpevpn *vpn, + void (*func)(struct hash_bucket *, + void *), + void *arg); static void bgp_evpn_link_to_vni_svi_hash(struct bgp *bgp, struct bgpevpn *vpn); static void bgp_evpn_unlink_from_vni_svi_hash(struct bgp *bgp, struct bgpevpn *vpn); @@ -5780,9 +5784,10 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni, * Unresolve all the gateway IP nexthops for this VNI * for old SVI */ - hash_iterate(vpn->remote_ip_hash, - (void (*)(struct hash_bucket *, - void *))bgp_evpn_remote_ip_hash_unlink_nexthop, + bgp_evpn_remote_ip_hash_iterate( + vpn, + (void (*)(struct hash_bucket *, void *)) + bgp_evpn_remote_ip_hash_unlink_nexthop, vpn); bgp_evpn_unlink_from_vni_svi_hash(bgp, vpn); vpn->svi_ifindex = svi_ifindex; @@ -5792,9 +5797,10 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni, * Resolve all the gateway IP nexthops for this VNI * for new SVI */ - hash_iterate(vpn->remote_ip_hash, - (void (*)(struct hash_bucket *, - void *))bgp_evpn_remote_ip_hash_link_nexthop, + bgp_evpn_remote_ip_hash_iterate( + vpn, + (void (*)(struct hash_bucket *, void *)) + bgp_evpn_remote_ip_hash_link_nexthop, vpn); } @@ -5805,9 +5811,10 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni, * Unresolve all the gateway IP nexthops for this VNI * in old tenant vrf */ - hash_iterate(vpn->remote_ip_hash, - (void (*)(struct hash_bucket *, - void *))bgp_evpn_remote_ip_hash_unlink_nexthop, + bgp_evpn_remote_ip_hash_iterate( + vpn, + (void (*)(struct hash_bucket *, void *)) + bgp_evpn_remote_ip_hash_unlink_nexthop, vpn); bgpevpn_unlink_from_l3vni(vpn); vpn->tenant_vrf_id = tenant_vrf_id; @@ -5817,9 +5824,10 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni, * Resolve all the gateway IP nexthops for this VNI * in new tenant vrf */ - hash_iterate(vpn->remote_ip_hash, - (void (*)(struct hash_bucket *, - void *))bgp_evpn_remote_ip_hash_link_nexthop, + bgp_evpn_remote_ip_hash_iterate( + vpn, + (void (*)(struct hash_bucket *, void *)) + bgp_evpn_remote_ip_hash_link_nexthop, vpn); } @@ -6091,6 +6099,9 @@ static bool bgp_evpn_remote_ip_hash_cmp(const void *p1, const void *p2) static void bgp_evpn_remote_ip_hash_init(struct bgpevpn *vpn) { + if (!evpn_resolve_overlay_index()) + return; + vpn->remote_ip_hash = hash_create(bgp_evpn_remote_ip_hash_key_make, bgp_evpn_remote_ip_hash_cmp, "BGP EVPN remote IP hash"); @@ -6111,7 +6122,7 @@ static void bgp_evpn_remote_ip_hash_free(struct hash_bucket *bucket, void *args) static void bgp_evpn_remote_ip_hash_destroy(struct bgpevpn *vpn) { - if (vpn->remote_ip_hash == NULL) + if (!evpn_resolve_overlay_index() || vpn->remote_ip_hash == NULL) return; hash_iterate(vpn->remote_ip_hash, @@ -6130,6 +6141,13 @@ static void bgp_evpn_remote_ip_hash_add(struct bgpevpn *vpn, struct evpn_remote_ip *ip; struct prefix_evpn *evp; + if (!evpn_resolve_overlay_index()) + return; + + if (pi->type != ZEBRA_ROUTE_BGP || pi->sub_type != BGP_ROUTE_IMPORTED + || !CHECK_FLAG(pi->flags, BGP_PATH_VALID)) + return; + evp = (struct prefix_evpn *)&pi->net->p; if (evp->family != AF_EVPN @@ -6163,6 +6181,9 @@ static void bgp_evpn_remote_ip_hash_del(struct bgpevpn *vpn, struct evpn_remote_ip *ip; struct prefix_evpn *evp; + if (!evpn_resolve_overlay_index()) + return; + evp = (struct prefix_evpn *)&pi->net->p; if (evp->family != AF_EVPN @@ -6184,6 +6205,17 @@ static void bgp_evpn_remote_ip_hash_del(struct bgpevpn *vpn, } } +static void bgp_evpn_remote_ip_hash_iterate(struct bgpevpn *vpn, + void (*func)(struct hash_bucket *, + void *), + void *arg) +{ + if (!evpn_resolve_overlay_index()) + return; + + hash_iterate(vpn->remote_ip_hash, func, arg); +} + static void show_remote_ip_entry(struct hash_bucket *bucket, void *args) { char buf[INET6_ADDRSTRLEN]; @@ -6211,7 +6243,8 @@ void bgp_evpn_show_remote_ip_hash(struct hash_bucket *bucket, void *args) struct vty *vty = (struct vty *)args; vty_out(vty, "VNI: %u\n", vpn->vni); - hash_iterate(vpn->remote_ip_hash, + bgp_evpn_remote_ip_hash_iterate( + vpn, (void (*)(struct hash_bucket *, void *))show_remote_ip_entry, vty); vty_out(vty, "\n"); @@ -6300,6 +6333,9 @@ bool bgp_evpn_is_gateway_ip_resolved(struct bgp_nexthop_cache *bnc) struct evpn_remote_ip tmp; struct prefix *p; + if (!evpn_resolve_overlay_index()) + return false; + if (!bnc->nexthop || bnc->nexthop->ifindex == 0) return false; @@ -6411,3 +6447,25 @@ static void bgp_evpn_remote_ip_process_nexthops(struct bgpevpn *vpn, } } +void bgp_evpn_handle_resolve_overlay_index_set(struct hash_bucket *bucket, + void *arg) +{ + struct bgpevpn *vpn = (struct bgpevpn *)bucket->data; + struct bgp_dest *dest; + struct bgp_path_info *pi; + + bgp_evpn_remote_ip_hash_init(vpn); + + for (dest = bgp_table_top(vpn->route_table); dest; + dest = bgp_route_next(dest)) + for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) + bgp_evpn_remote_ip_hash_add(vpn, pi); +} + +void bgp_evpn_handle_resolve_overlay_index_unset(struct hash_bucket *bucket, + void *arg) +{ + struct bgpevpn *vpn = (struct bgpevpn *)bucket->data; + + bgp_evpn_remote_ip_hash_destroy(vpn); +} diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index f91b81f10..eec746e3b 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -156,6 +156,14 @@ static inline bool is_route_injectable_into_evpn(struct bgp_path_info *pi) return true; } +static inline bool evpn_resolve_overlay_index(void) +{ + struct bgp *bgp = NULL; + + bgp = bgp_get_evpn(); + return bgp ? bgp->resolve_overlay_index : false; +} + extern void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, const struct prefix *p, struct attr *src_attr, afi_t afi, @@ -215,5 +223,11 @@ extern void bgp_evpn_show_remote_ip_hash(struct hash_bucket *bucket, void *args); extern void bgp_evpn_show_vni_svi_hash(struct hash_bucket *bucket, void *args); extern bool bgp_evpn_is_gateway_ip_resolved(struct bgp_nexthop_cache *bnc); +extern void +bgp_evpn_handle_resolve_overlay_index_set(struct hash_bucket *bucket, + void *arg); +extern void +bgp_evpn_handle_resolve_overlay_index_unset(struct hash_bucket *bucket, + void *arg); #endif /* _QUAGGA_BGP_EVPN_H */ diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index c334992d9..adb7148f2 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -3302,6 +3302,28 @@ static void evpn_unset_advertise_all_vni(struct bgp *bgp) bgp_evpn_cleanup_on_disable(bgp); } +/* Set resolve overlay index flag */ +static void bgp_evpn_set_unset_resolve_overlay_index(struct bgp *bgp, bool set) +{ + if (set == bgp->resolve_overlay_index) + return; + + if (set) { + bgp->resolve_overlay_index = true; + hash_iterate(bgp->vnihash, + (void (*)(struct hash_bucket *, void *)) + bgp_evpn_handle_resolve_overlay_index_set, + NULL); + } else { + hash_iterate( + bgp->vnihash, + (void (*)(struct hash_bucket *, void *)) + bgp_evpn_handle_resolve_overlay_index_unset, + NULL); + bgp->resolve_overlay_index = false; + } +} + /* * EVPN - use RFC8365 to auto-derive RT */ @@ -4117,6 +4139,23 @@ DEFPY (bgp_evpn_ead_evi_tx_disable, return CMD_SUCCESS; } +DEFPY (bgp_evpn_enable_resolve_overlay_index, + bgp_evpn_enable_resolve_overlay_index_cmd, + "[no$no] enable-resolve-overlay-index", + NO_STR + "Enable Recursive Resolution of type-5 route overlay index\n") +{ + struct bgp *bgp = VTY_GET_CONTEXT(bgp); + + if (bgp != bgp_get_evpn()) { + vty_out(vty, "This command is only supported under EVPN VRF\n"); + return CMD_WARNING; + } + + bgp_evpn_set_unset_resolve_overlay_index(bgp, no ? false : true); + return CMD_SUCCESS; +} + DEFPY (bgp_evpn_advertise_pip_ip_mac, bgp_evpn_advertise_pip_ip_mac_cmd, "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]", @@ -6252,6 +6291,9 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi, if (bgp->evpn_info->advertise_svi_macip) vty_out(vty, " advertise-svi-ip\n"); + if (bgp->resolve_overlay_index) + vty_out(vty, " enable-resolve-overlay-index\n"); + if (bgp_mh_info->host_routes_use_l3nhg != BGP_EVPN_MH_USE_ES_L3NHG_DEF) { if (bgp_mh_info->host_routes_use_l3nhg) @@ -6440,6 +6482,8 @@ void bgp_ethernetvpn_init(void) install_element(BGP_EVPN_NODE, &bgp_evpn_use_es_l3nhg_cmd); install_element(BGP_EVPN_NODE, &bgp_evpn_ead_evi_rx_disable_cmd); install_element(BGP_EVPN_NODE, &bgp_evpn_ead_evi_tx_disable_cmd); + install_element(BGP_EVPN_NODE, + &bgp_evpn_enable_resolve_overlay_index_cmd); /* test commands */ install_element(BGP_EVPN_NODE, &test_es_add_cmd); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index a43a21e16..776f4b0a2 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -693,6 +693,15 @@ struct bgp { /* Hash table of EVPN nexthops maintained per-tenant-VRF */ struct hash *evpn_nh_table; + /* + * Flag resolve_overlay_index is used for recursive resolution + * procedures for EVPN type-5 route's gateway IP overlay index. + * When this flag is set, we build remote-ip-hash for + * all L2VNIs and resolve overlay index nexthops using this hash. + * Overlay index nexthops remain unresolved if this flag is not set. + */ + bool resolve_overlay_index; + /* vrf flags */ uint32_t vrf_flags; #define BGP_VRF_AUTO (1 << 0) |