diff options
| -rw-r--r-- | bgpd/bgp_attr.h | 9 | ||||
| -rw-r--r-- | bgpd/bgp_evpn.c | 132 | ||||
| -rw-r--r-- | bgpd/bgp_evpn_mh.c | 184 | ||||
| -rw-r--r-- | bgpd/bgp_evpn_mh.h | 15 | ||||
| -rw-r--r-- | bgpd/bgp_evpn_private.h | 3 | ||||
| -rw-r--r-- | bgpd/bgp_evpn_vty.c | 65 | ||||
| -rw-r--r-- | bgpd/bgp_route.c | 10 |
7 files changed, 249 insertions, 169 deletions
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 1b176f8716..a583581030 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -243,6 +243,15 @@ struct attr { */ #define ATTR_ES_PEER_ROUTER (1 << 4) + /* These two flags are only set on L3 routes installed in a + * VRF as a result of EVPN MAC-IP route + * XXX - while splitting up per-family attrs these need to be + * classified as non-EVPN + */ +#define ATTR_ES_L3_NHG_USE (1 << 5) +#define ATTR_ES_L3_NHG_ACTIVE (1 << 6) +#define ATTR_ES_L3_NHG (ATTR_ES_L3_NHG_USE | ATTR_ES_L3_NHG_ACTIVE) + /* route tag */ route_tag_t tag; diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index a4d4dbc203..26e880c0dd 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -1597,8 +1597,8 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, } } - /* MAC-IP routes in the VNI route table are linked to the - * destination ES + /* local MAC-IP routes in the VNI table are linked to + * the destination ES */ if (route_change && vpn_rt && (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)) @@ -2378,6 +2378,8 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, afi_t afi = 0; safi_t safi = 0; bool new_pi = false; + bool use_l3nhg = false; + bool is_l3nhg_active = false; memset(pp, 0, sizeof(struct prefix)); ip_prefix_from_evpn_prefix(evp, pp); @@ -2413,6 +2415,13 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, else attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); + bgp_evpn_es_vrf_use_nhg(bgp_vrf, &parent_pi->attr->esi, &use_l3nhg, + &is_l3nhg_active, NULL); + if (use_l3nhg) + attr.es_flags |= ATTR_ES_L3_NHG_USE; + if (is_l3nhg_active) + attr.es_flags |= ATTR_ES_L3_NHG_ACTIVE; + /* Check if route entry is already present. */ for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) if (pi->extra @@ -2532,11 +2541,6 @@ static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, pi->uptime = bgp_clock(); } - /* MAC-IP routes in the VNI table are linked to the destination ES */ - if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) - bgp_evpn_path_es_link(pi, vpn->vni, - bgp_evpn_attr_get_esi(pi->attr)); - /* Perform route selection and update zebra, if required. */ ret = evpn_route_select_install(bgp, vpn, dest); @@ -2857,7 +2861,6 @@ bgp_evpn_skip_vrf_import_of_local_es(struct bgp *bgp_vrf, struct bgp_path_info *pi, int install) { esi_t *esi; - struct in_addr nh; if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) { esi = bgp_evpn_attr_get_esi(pi->attr); @@ -2875,30 +2878,52 @@ bgp_evpn_skip_vrf_import_of_local_es(struct bgp *bgp_vrf, } return true; } + } + return false; +} - /* Don't import routes with ES as destination if L3NHG is in - * use and the nexthop has not been advertised via the EAD-ES - */ - if (pi->attr) - nh = pi->attr->nexthop; +/* + * Install or uninstall a mac-ip route in the provided vrf if + * there is a rt match + */ +int bgp_evpn_route_entry_install_if_vrf_match(struct bgp *bgp_vrf, + struct bgp_path_info *pi, + int install) +{ + int ret = 0; + const struct prefix_evpn *evp = + (const struct prefix_evpn *)bgp_dest_get_prefix(pi->net); + + /* Consider "valid" remote routes applicable for + * this VRF. + */ + if (!(CHECK_FLAG(pi->flags, BGP_PATH_VALID) + && pi->type == ZEBRA_ROUTE_BGP + && pi->sub_type == BGP_ROUTE_NORMAL)) + return 0; + + /* don't import hosts that are locally attached */ + if (bgp_evpn_skip_vrf_import_of_local_es(bgp_vrf, evp, pi, install)) + return 0; + + if (is_route_matching_for_vrf(bgp_vrf, pi)) { + if (bgp_evpn_route_rmac_self_check(bgp_vrf, evp, pi)) + return 0; + + if (install) + ret = install_evpn_route_entry_in_vrf(bgp_vrf, evp, pi); else - nh.s_addr = INADDR_ANY; - if (install && !bgp_evpn_es_vrf_import_ok(bgp_vrf, esi, nh)) { - if (BGP_DEBUG(evpn_mh, EVPN_MH_RT)) { - char esi_buf[ESI_STR_LEN]; + ret = uninstall_evpn_route_entry_in_vrf(bgp_vrf, evp, + pi); - zlog_debug( - "vrf %s %s of evpn prefix %pFX skipped, nh %pI4 inactive in es %s", - bgp_vrf->name, - install ? "import" : "unimport", evp, - &nh, - esi_to_str(esi, esi_buf, - sizeof(esi_buf))); - } - return true; - } + if (ret) + flog_err(EC_BGP_EVPN_FAIL, + "Failed to %s EVPN %pFX route in VRF %s", + install ? "install" : "uninstall", evp, + vrf_id_to_name(bgp_vrf->vrf_id)); } - return false; + + return ret; } /* @@ -2950,46 +2975,10 @@ static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install) for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { - /* Consider "valid" remote routes applicable for - * this VRF. - */ - if (!(CHECK_FLAG(pi->flags, BGP_PATH_VALID) - && pi->type == ZEBRA_ROUTE_BGP - && pi->sub_type == BGP_ROUTE_NORMAL)) - continue; - - /* don't import hosts that are locally attached - */ - if (bgp_evpn_skip_vrf_import_of_local_es( - bgp_vrf, evp, pi, install)) - continue; - - if (is_route_matching_for_vrf(bgp_vrf, pi)) { - if (bgp_evpn_route_rmac_self_check( - bgp_vrf, evp, pi)) - continue; - - if (install) - ret = install_evpn_route_entry_in_vrf( - bgp_vrf, evp, pi); - else - ret = uninstall_evpn_route_entry_in_vrf( - bgp_vrf, evp, pi); - - if (ret) { - flog_err( - EC_BGP_EVPN_FAIL, - "Failed to %s EVPN %pFX route in VRF %s", - install ? "install" - : "uninstall", - evp, - vrf_id_to_name( - bgp_vrf->vrf_id)); - bgp_dest_unlock_node(rd_dest); - bgp_dest_unlock_node(dest); - return ret; - } - } + ret = bgp_evpn_route_entry_install_if_vrf_match( + bgp_vrf, pi, install); + if (ret) + return ret; } } } @@ -3293,6 +3282,13 @@ static int bgp_evpn_install_uninstall_table(struct bgp *bgp, afi_t afi, if (sub_type != ECOMMUNITY_ROUTE_TARGET) continue; + /* non-local MAC-IP routes in the global route table are linked + * to the destination ES + */ + if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) + bgp_evpn_path_es_link(pi, 0, + bgp_evpn_attr_get_esi(pi->attr)); + /* * macip routes (type-2) are imported into VNI and VRF tables. * IMET route is imported into VNI table. diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c index c7e6c01758..9a5fe7aecb 100644 --- a/bgpd/bgp_evpn_mh.c +++ b/bgpd/bgp_evpn_mh.c @@ -69,9 +69,6 @@ static uint32_t bgp_evpn_es_get_active_vtep_cnt(struct bgp_evpn_es *es); static void bgp_evpn_l3nhg_update_on_vtep_chg(struct bgp_evpn_es *es); static struct bgp_evpn_es *bgp_evpn_es_new(struct bgp *bgp, const esi_t *esi); static void bgp_evpn_es_free(struct bgp_evpn_es *es, const char *caller); -static void -bgp_evpn_es_path_update_on_vtep_chg(struct bgp_evpn_es_vtep *es_vtep, - bool active); esi_t zero_esi_buf, *zero_esi = &zero_esi_buf; static int bgp_evpn_run_consistency_checks(struct thread *t); @@ -1291,8 +1288,6 @@ static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp, * removed. */ bgp_evpn_l3nhg_update_on_vtep_chg(es_vtep->es); - bgp_evpn_es_path_update_on_vtep_chg(es_vtep, new_active); - /* queue up the es for background consistency checks */ bgp_evpn_es_cons_checks_pend_add(es_vtep->es); } @@ -1368,33 +1363,15 @@ static void bgp_evpn_es_vtep_del(struct bgp *bgp, bgp_evpn_es_vtep_do_del(bgp, es_vtep, esr); } -bool bgp_evpn_es_is_vtep_active(esi_t *esi, struct in_addr nh) -{ - struct bgp_evpn_es *es; - struct bgp_evpn_es_vtep *es_vtep; - struct listnode *node = NULL; - bool rc = false; - - if (!memcmp(esi, zero_esi, sizeof(*esi)) || !nh.s_addr) - return true; - - es = bgp_evpn_es_find(esi); - if (!es) - return false; - - for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) { - if (es_vtep->vtep_ip.s_addr == nh.s_addr) { - if (CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE)) - rc = true; - break; - } - } - return rc; -} - /********************** ES MAC-IP paths ************************************* - * MAC-IP routes in the VNI routing table are linked to the destination - * ES for efficient updates on ES changes (such as VTEP add/del). + * 1. Local MAC-IP routes in the VNI routing table are linked to the + * destination ES (macip_evi_path_list) for efficient updates on ES oper + * state changes. + * 2. Non-local MAC-IP routes in the global routing table are linked to + * the detination for efficient updates on - + * a. VTEP add/del - this results in a L3NHG update. + * b. ES-VRF add/del - this may result in the host route being migrated to + * L3NHG or vice versa (flat multipath list). ****************************************************************************/ void bgp_evpn_path_es_info_free(struct bgp_path_es_info *es_info) { @@ -1433,7 +1410,12 @@ void bgp_evpn_path_es_unlink(struct bgp_path_es_info *es_info) zlog_debug("vni %u path %pFX unlinked from es %s", es_info->vni, &pi->net->p, es->esi_str); - list_delete_node(es->macip_evi_path_list, &es_info->es_listnode); + if (es_info->vni) + list_delete_node(es->macip_evi_path_list, + &es_info->es_listnode); + else + list_delete_node(es->macip_global_path_list, + &es_info->es_listnode); es_info->es = NULL; /* if there are no other references against the ES it @@ -1450,7 +1432,8 @@ void bgp_evpn_path_es_link(struct bgp_path_info *pi, vni_t vni, esi_t *esi) { struct bgp_path_es_info *es_info; struct bgp_evpn_es *es; - struct bgp *bgp_evpn = bgp_get_evpn(); + struct bgp *bgp_evpn; + struct prefix_evpn *evp; es_info = pi->extra ? pi->extra->es_info : NULL; /* if the esi is zero just unlink the path from the old es */ @@ -1460,9 +1443,18 @@ void bgp_evpn_path_es_link(struct bgp_path_info *pi, vni_t vni, esi_t *esi) return; } + bgp_evpn = bgp_get_evpn(); if (!bgp_evpn) return; + /* Only MAC-IP routes need to be linked (MAC-only routes can be + * skipped) as these lists are maintained for managing + * host routes in the tenant VRF + */ + evp = (struct prefix_evpn *)&pi->net->p; + if (!(is_evpn_prefix_ipaddr_v4(evp) || is_evpn_prefix_ipaddr_v6(evp))) + return; + /* setup es_info against the path if it doesn't aleady exist */ if (!es_info) es_info = bgp_evpn_path_es_info_new(pi, vni); @@ -1486,55 +1478,44 @@ void bgp_evpn_path_es_link(struct bgp_path_info *pi, vni_t vni, esi_t *esi) /* link mac-ip path to the new destination ES */ es_info->es = es; listnode_init(&es_info->es_listnode, es_info); - listnode_add(es->macip_evi_path_list, &es_info->es_listnode); + if (es_info->vni) + listnode_add(es->macip_evi_path_list, &es_info->es_listnode); + else + listnode_add(es->macip_global_path_list, &es_info->es_listnode); } -/* XXX - When a remote ES is added to a VRF, routes using that as - * a destination need to be migrated to a L2NHG and viceversa +/* When a remote ES is added to a VRF, routes using that as + * a destination need to be migrated to a L3NHG or viceversa. + * This is done indirectly by re-attempting an install of the + * route in the associated VRFs. As a part of the VRF install use + * of l3 NHG is evaluated and this results in the + * attr.es_flag ATTR_ES_USE_L3_NHG being set or cleared. */ static void bgp_evpn_es_path_update_on_es_vrf_chg(struct bgp_evpn_es_vrf *es_vrf, - bool active) -{ -} - -static void -bgp_evpn_es_path_update_on_vtep_chg(struct bgp_evpn_es_vtep *es_vtep, - bool active) + const char *reason) { struct listnode *node; struct bgp_path_es_info *es_info; struct bgp_path_info *pi; - struct bgp_path_info *parent_pi; - struct bgp_evpn_es *es = es_vtep->es; + struct bgp_evpn_es *es = es_vrf->es; if (!bgp_mh_info->host_routes_use_l3nhg) return; if (BGP_DEBUG(evpn_mh, EVPN_MH_RT)) - zlog_debug("update paths linked to es %s on vtep chg", - es->esi_str); + zlog_debug("update paths linked to es %s on es-vrf %s %s", + es->esi_str, es_vrf->bgp_vrf->name, reason); - for (ALL_LIST_ELEMENTS_RO(es->macip_evi_path_list, node, es_info)) { + for (ALL_LIST_ELEMENTS_RO(es->macip_global_path_list, node, es_info)) { pi = es_info->pi; - if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)) - continue; - - if (pi->sub_type != BGP_ROUTE_IMPORTED) - continue; - - parent_pi = pi->extra ? pi->extra->parent : NULL; - if (!parent_pi || !parent_pi->attr) - continue; - - if (es_vtep->vtep_ip.s_addr != parent_pi->attr->nexthop.s_addr) - continue; if (BGP_DEBUG(evpn_mh, EVPN_MH_RT)) zlog_debug( - "update path %pFX linked to es %s on vtep chg", - &parent_pi->net->p, es->esi_str); - bgp_evpn_import_route_in_vrfs(parent_pi, active ? 1 : 0); + "update path %pFX linked to es %s on vrf chg", + &pi->net->p, es->esi_str); + bgp_evpn_route_entry_install_if_vrf_match(es_vrf->bgp_vrf, pi, + 1); } } @@ -1593,6 +1574,8 @@ static struct bgp_evpn_es *bgp_evpn_es_new(struct bgp *bgp, const esi_t *esi) /* Initialise the route list used for efficient event handling */ es->macip_evi_path_list = list_new(); listset_app_node_mem(es->macip_evi_path_list); + es->macip_global_path_list = list_new(); + listset_app_node_mem(es->macip_global_path_list); QOBJ_REG(es, bgp_evpn_es); @@ -1606,7 +1589,8 @@ static struct bgp_evpn_es *bgp_evpn_es_new(struct bgp *bgp, const esi_t *esi) static void bgp_evpn_es_free(struct bgp_evpn_es *es, const char *caller) { if ((es->flags & (BGP_EVPNES_LOCAL | BGP_EVPNES_REMOTE)) - || listcount(es->macip_evi_path_list)) + || listcount(es->macip_evi_path_list) + || listcount(es->macip_global_path_list)) return; if (BGP_DEBUG(evpn_mh, EVPN_MH_ES)) @@ -1617,6 +1601,7 @@ static void bgp_evpn_es_free(struct bgp_evpn_es *es, const char *caller) list_delete(&es->es_vrf_list); list_delete(&es->es_vtep_list); list_delete(&es->macip_evi_path_list); + list_delete(&es->macip_global_path_list); bgp_table_unlock(es->route_table); /* remove the entry from various databases */ @@ -1727,10 +1712,12 @@ static void bgp_evpn_mac_update_on_es_oper_chg(struct bgp_evpn_es *es) continue; if (BGP_DEBUG(evpn_mh, EVPN_MH_RT)) - zlog_debug("update path %s linked to es %s on oper chg", - prefix2str(&pi->net->p, prefix_buf, - sizeof(prefix_buf)), - es->esi_str); + zlog_debug( + "update path %d %s linked to es %s on oper chg", + es_info->vni, + prefix2str(&pi->net->p, prefix_buf, + sizeof(prefix_buf)), + es->esi_str); bgp_evpn_update_type2_route_entry(bgp, vpn, pi->net, pi, __func__); @@ -2186,6 +2173,8 @@ static void bgp_evpn_es_show_entry_detail(struct vty *vty, listcount(es->es_vrf_list)); json_object_int_add(json, "macipPathCount", listcount(es->macip_evi_path_list)); + json_object_int_add(json, "macipGlobalPathCount", + listcount(es->macip_global_path_list)); json_object_int_add(json, "inconsistentVniVtepCount", es->incons_evi_vtep_cnt); if (listcount(es->es_vtep_list)) { @@ -2233,8 +2222,10 @@ static void bgp_evpn_es_show_entry_detail(struct vty *vty, vty_out(vty, " Remote VNI Count: %d\n", es->remote_es_evi_cnt); vty_out(vty, " VRF Count: %d\n", listcount(es->es_vrf_list)); - vty_out(vty, " MACIP Path Count: %d\n", + vty_out(vty, " MACIP EVI Path Count: %d\n", listcount(es->macip_evi_path_list)); + vty_out(vty, " MACIP Global Path Count: %d\n", + listcount(es->macip_global_path_list)); vty_out(vty, " Inconsistent VNI VTEP Count: %d\n", es->incons_evi_vtep_cnt); if (es->inconsistencies) { @@ -2465,6 +2456,8 @@ static void bgp_evpn_l3nhg_deactivate(struct bgp_evpn_es_vrf *es_vrf) es_vrf->nhg_id); bgp_evpn_l3nhg_zebra_del(es_vrf); es_vrf->flags &= ~BGP_EVPNES_VRF_NHG_ACTIVE; + /* MAC-IPs can now be installed via the L3NHG */ + bgp_evpn_es_path_update_on_es_vrf_chg(es_vrf, "l3nhg-deactivate"); } static void bgp_evpn_l3nhg_activate(struct bgp_evpn_es_vrf *es_vrf, bool update) @@ -2483,6 +2476,8 @@ static void bgp_evpn_l3nhg_activate(struct bgp_evpn_es_vrf *es_vrf, bool update) es_vrf->es->esi_str, es_vrf->bgp_vrf->vrf_id, es_vrf->nhg_id); es_vrf->flags |= BGP_EVPNES_VRF_NHG_ACTIVE; + /* MAC-IPs can now be installed via the L3NHG */ + bgp_evpn_es_path_update_on_es_vrf_chg(es_vrf, "l3nhg_activate"); } bgp_evpn_l3nhg_zebra_add(es_vrf); @@ -2562,7 +2557,7 @@ static struct bgp_evpn_es_vrf *bgp_evpn_es_vrf_create(struct bgp_evpn_es *es, /* update paths in the VRF that may already be associated with * this destination ES */ - bgp_evpn_es_path_update_on_es_vrf_chg(es_vrf, true); + bgp_evpn_es_path_update_on_es_vrf_chg(es_vrf, "es-vrf-create"); return es_vrf; } @@ -2595,7 +2590,7 @@ static void bgp_evpn_es_vrf_delete(struct bgp_evpn_es_vrf *es_vrf) /* update paths in the VRF that may already be associated with * this destination ES */ - bgp_evpn_es_path_update_on_es_vrf_chg(es_vrf, false); + bgp_evpn_es_path_update_on_es_vrf_chg(es_vrf, "es-vrf-delete"); XFREE(MTYPE_BGP_EVPN_ES_VRF, es_vrf); } @@ -2679,38 +2674,37 @@ void bgp_evpn_es_evi_vrf_ref(struct bgpevpn *vpn) bgp_evpn_es_vrf_ref(es_evi, vpn->bgp_vrf); } -static bool bgp_evpn_es_vrf_use_nhg(struct bgp *bgp_vrf, esi_t *esi, - struct bgp_evpn_es **es_p, - struct bgp_evpn_es_vrf **es_vrf_p) +/* 1. If ES-VRF is not present install the host route with the exploded/flat + * multi-path list. + * 2. If ES-VRF is present - + * - if L3NHG has not been activated for the ES-VRF (this could be because + * all the PEs attached to the VRF are down) do not install the route + * in zebra. + * - if L3NHG has been activated install the route via that L3NHG + */ +void bgp_evpn_es_vrf_use_nhg(struct bgp *bgp_vrf, esi_t *esi, bool *use_l3nhg, + bool *is_l3nhg_active, + struct bgp_evpn_es_vrf **es_vrf_p) { struct bgp_evpn_es *es; struct bgp_evpn_es_vrf *es_vrf; if (!bgp_mh_info->host_routes_use_l3nhg) - return false; + return; es = bgp_evpn_es_find(esi); if (!es) - return false; - if (es_p) - *es_p = es; + return; es_vrf = bgp_evpn_es_vrf_find(es, bgp_vrf); if (!es_vrf) - return false; + return; + + *use_l3nhg = true; + if (es_vrf->flags & BGP_EVPNES_VRF_NHG_ACTIVE) + *is_l3nhg_active = true; if (es_vrf_p) *es_vrf_p = es_vrf; - - return true; -} - -bool bgp_evpn_es_vrf_import_ok(struct bgp *bgp_vrf, esi_t *esi, - struct in_addr nh) -{ - if (!bgp_evpn_es_vrf_use_nhg(bgp_vrf, esi, NULL, NULL)) - return true; - - return bgp_evpn_es_is_vtep_active(esi, nh); } /* returns false if legacy-exploded mp needs to be used for route install */ @@ -2718,12 +2712,13 @@ bool bgp_evpn_path_es_use_nhg(struct bgp *bgp_vrf, struct bgp_path_info *pi, uint32_t *nhg_p) { esi_t *esi; - struct bgp_evpn_es *es = NULL; struct bgp_evpn_es_vrf *es_vrf = NULL; struct bgp_path_info *parent_pi; struct bgp_node *rn; struct prefix_evpn *evp; struct bgp_path_info *mpinfo; + bool use_l3nhg = false; + bool is_l3nhg_active = false; *nhg_p = 0; @@ -2744,14 +2739,17 @@ bool bgp_evpn_path_es_use_nhg(struct bgp *bgp_vrf, struct bgp_path_info *pi, if (!memcmp(esi, zero_esi, sizeof(*esi))) return false; + bgp_evpn_es_vrf_use_nhg(bgp_vrf, esi, &use_l3nhg, &is_l3nhg_active, + &es_vrf); + /* L3NHG support is disabled, use legacy-exploded multipath */ - if (!bgp_evpn_es_vrf_use_nhg(bgp_vrf, esi, &es, &es_vrf)) + if (!use_l3nhg) return false; /* if the NHG has not been installed we cannot install the route yet, * return a 0-NHG to indicate that */ - if (!(es_vrf->flags & BGP_EVPNES_VRF_NHG_ACTIVE)) + if (!is_l3nhg_active) return true; /* this needs to be set the v6NHG if v6route */ diff --git a/bgpd/bgp_evpn_mh.h b/bgpd/bgp_evpn_mh.h index 62414994b6..508766496f 100644 --- a/bgpd/bgp_evpn_mh.h +++ b/bgpd/bgp_evpn_mh.h @@ -105,9 +105,18 @@ struct bgp_evpn_es { /* List of MAC-IP VNI paths using this ES as destination - * element is bgp_path_info_extra->es_info + * Note: Only local/zebra-added MACIP paths in the VNI + * routing table are linked to this list */ struct list *macip_evi_path_list; + /* List of MAC-IP paths in the global routing table using this + * ES as destination - data is bgp_path_info_extra->es_info + * Note: Only non-local/imported MACIP paths in the global + * routing table are linked to this list + */ + struct list *macip_global_path_list; + /* Number of remote VNIs referencing this ES */ uint32_t remote_es_evi_cnt; @@ -381,7 +390,6 @@ extern void bgp_evpn_path_es_info_free(struct bgp_path_es_info *es_info); extern void bgp_evpn_path_es_unlink(struct bgp_path_es_info *es_info); extern void bgp_evpn_path_es_link(struct bgp_path_info *pi, vni_t vni, esi_t *esi); -extern bool bgp_evpn_es_is_vtep_active(esi_t *esi, struct in_addr nh); extern bool bgp_evpn_path_es_use_nhg(struct bgp *bgp_vrf, struct bgp_path_info *pi, uint32_t *nhg_p); extern void bgp_evpn_es_vrf_show(struct vty *vty, bool uj, @@ -389,7 +397,8 @@ extern void bgp_evpn_es_vrf_show(struct vty *vty, bool uj, extern void bgp_evpn_es_vrf_show_esi(struct vty *vty, esi_t *esi, bool uj); extern void bgp_evpn_switch_ead_evi_rx(void); extern bool bgp_evpn_es_add_l3_ecomm_ok(esi_t *esi); -extern bool bgp_evpn_es_vrf_import_ok(struct bgp *bgp_vrf, esi_t *esi, - struct in_addr nh); +extern void bgp_evpn_es_vrf_use_nhg(struct bgp *bgp_vrf, esi_t *esi, + bool *use_l3nhg, bool *is_l3nhg_active, + struct bgp_evpn_es_vrf **es_vrf_p); #endif /* _FRR_BGP_EVPN_MH_H */ diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h index 9a7a477516..dfaac76f02 100644 --- a/bgpd/bgp_evpn_private.h +++ b/bgpd/bgp_evpn_private.h @@ -636,4 +636,7 @@ extern void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgp_node *rn, struct bgp_path_info *local_pi, const char *caller); +extern int bgp_evpn_route_entry_install_if_vrf_match(struct bgp *bgp_vrf, + struct bgp_path_info *pi, + int install); #endif /* _BGP_EVPN_PRIVATE_H */ diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 8f03006705..43516dadad 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -687,8 +687,9 @@ static void show_esi_routes(struct bgp *bgp, } /* Display all MAC-IP VNI routes linked to an ES */ -static void bgp_evpn_show_routes_mac_ip_evi_es(struct vty *vty, esi_t *esi, - json_object *json, int detail) +static void bgp_evpn_show_routes_mac_ip_es(struct vty *vty, esi_t *esi, + json_object *json, int detail, + bool global_table) { struct bgp_node *rn; struct bgp_path_info *pi; @@ -709,12 +710,17 @@ static void bgp_evpn_show_routes_mac_ip_evi_es(struct vty *vty, esi_t *esi, json_paths = json_object_new_array(); RB_FOREACH (es, bgp_es_rb_head, &bgp_mh_info->es_rb_tree) { + struct list *es_list; if (esi && memcmp(esi, &es->esi, sizeof(*esi))) continue; - for (ALL_LIST_ELEMENTS_RO(es->macip_evi_path_list, node, - es_info)) { + if (global_table) + es_list = es->macip_global_path_list; + else + es_list = es->macip_evi_path_list; + + for (ALL_LIST_ELEMENTS_RO(es_list, node, es_info)) { json_object *json_path = NULL; pi = es_info->pi; @@ -759,6 +765,18 @@ static void bgp_evpn_show_routes_mac_ip_evi_es(struct vty *vty, esi_t *esi, } } +static void bgp_evpn_show_routes_mac_ip_evi_es(struct vty *vty, esi_t *esi, + json_object *json, int detail) +{ + return bgp_evpn_show_routes_mac_ip_es(vty, esi, json, detail, false); +} + +static void bgp_evpn_show_routes_mac_ip_global_es(struct vty *vty, esi_t *esi, + json_object *json, int detail) +{ + return bgp_evpn_show_routes_mac_ip_es(vty, esi, json, detail, true); +} + static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type, struct vty *vty, struct in_addr vtep_ip, json_object *json, int detail) @@ -4695,6 +4713,43 @@ DEFPY_HIDDEN( return CMD_SUCCESS; } +DEFPY_HIDDEN( + show_bgp_l2vpn_evpn_route_mac_ip_global_es, + show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd, + "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]", + SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR + "EVPN route information\n" + "MAC IP routes in the global table linked to the ES\n" + "ES ID\n" + "Detailed information\n" JSON_STR) +{ + esi_t esi; + esi_t *esi_p; + json_object *json = NULL; + + if (esi_str) { + if (!str_to_esi(esi_str, &esi)) { + vty_out(vty, "%%Malformed ESI\n"); + return CMD_WARNING; + } + esi_p = &esi; + } else { + esi_p = NULL; + } + + if (uj) + json = json_object_new_object(); + bgp_evpn_show_routes_mac_ip_global_es(vty, esi_p, json, !!detail); + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } + + return CMD_SUCCESS; +} + /* * Display EVPN import route-target hash table */ @@ -5971,6 +6026,8 @@ void bgp_ethernetvpn_init(void) install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd); install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd); + install_element(VIEW_NODE, + &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd); install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd); install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 124a477248..6f8e2536df 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -9626,12 +9626,20 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, buf1, sizeof(buf1)); if (is_pi_family_evpn(parent_ri)) { vty_out(vty, - " Imported from %s:%pFX, VNI %s\n", + " Imported from %s:%pFX, VNI %s", buf1, (struct prefix_evpn *) bgp_dest_get_prefix( dest), tag_buf); + if (attr->es_flags & ATTR_ES_L3_NHG) + vty_out(vty, ", L3NHG %s", + (attr->es_flags + & ATTR_ES_L3_NHG_ACTIVE) + ? "active" + : "inactive"); + vty_out(vty, "\n"); + } else vty_out(vty, " Imported from %s:%pFX\n", |
