diff options
Diffstat (limited to 'bgpd/bgp_evpn.c')
| -rw-r--r-- | bgpd/bgp_evpn.c | 184 |
1 files changed, 119 insertions, 65 deletions
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 84f3649758..732cc6d2bb 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -48,6 +48,7 @@ #include "bgpd/bgp_zebra.h" #include "bgpd/bgp_nexthop.h" #include "bgpd/bgp_addpath.h" +#include "bgpd/bgp_mac.h" /* * Definitions and external declarations. @@ -168,17 +169,17 @@ static bool vrf_import_rt_hash_cmp(const void *p1, const void *p2) } /* - * Create a new vrf import_rt in default instance + * Create a new vrf import_rt in evpn instance */ static struct vrf_irt_node *vrf_import_rt_new(struct ecommunity_val *rt) { - struct bgp *bgp_def = NULL; + struct bgp *bgp_evpn = NULL; struct vrf_irt_node *irt; - bgp_def = bgp_get_default(); - if (!bgp_def) { + bgp_evpn = bgp_get_evpn(); + if (!bgp_evpn) { flog_err(EC_BGP_NO_DFLT, - "vrf import rt new - def instance not created yet"); + "vrf import rt new - evpn instance not created yet"); return NULL; } @@ -189,7 +190,7 @@ static struct vrf_irt_node *vrf_import_rt_new(struct ecommunity_val *rt) irt->vrfs = list_new(); /* Add to hash */ - if (!hash_get(bgp_def->vrf_import_rt_hash, irt, hash_alloc_intern)) { + if (!hash_get(bgp_evpn->vrf_import_rt_hash, irt, hash_alloc_intern)) { XFREE(MTYPE_BGP_EVPN_VRF_IMPORT_RT, irt); return NULL; } @@ -202,16 +203,16 @@ static struct vrf_irt_node *vrf_import_rt_new(struct ecommunity_val *rt) */ static void vrf_import_rt_free(struct vrf_irt_node *irt) { - struct bgp *bgp_def = NULL; + struct bgp *bgp_evpn = NULL; - bgp_def = bgp_get_default(); - if (!bgp_def) { + bgp_evpn = bgp_get_evpn(); + if (!bgp_evpn) { flog_err(EC_BGP_NO_DFLT, - "vrf import rt free - def instance not created yet"); + "vrf import rt free - evpn instance not created yet"); return; } - hash_release(bgp_def->vrf_import_rt_hash, irt); + hash_release(bgp_evpn->vrf_import_rt_hash, irt); list_delete(&irt->vrfs); XFREE(MTYPE_BGP_EVPN_VRF_IMPORT_RT, irt); } @@ -222,20 +223,21 @@ static void vrf_import_rt_free(struct vrf_irt_node *irt) */ static struct vrf_irt_node *lookup_vrf_import_rt(struct ecommunity_val *rt) { - struct bgp *bgp_def = NULL; + struct bgp *bgp_evpn = NULL; struct vrf_irt_node *irt; struct vrf_irt_node tmp; - bgp_def = bgp_get_default(); - if (!bgp_def) { - flog_err(EC_BGP_NO_DFLT, - "vrf import rt lookup - def instance not created yet"); + bgp_evpn = bgp_get_evpn(); + if (!bgp_evpn) { + flog_err( + EC_BGP_NO_DFLT, + "vrf import rt lookup - evpn instance not created yet"); return NULL; } memset(&tmp, 0, sizeof(struct vrf_irt_node)); memcpy(&tmp.rt, rt, ECOMMUNITY_SIZE); - irt = hash_lookup(bgp_def->vrf_import_rt_hash, &tmp); + irt = hash_lookup(bgp_evpn->vrf_import_rt_hash, &tmp); return irt; } @@ -1420,7 +1422,7 @@ static int update_evpn_type4_route(struct bgp *bgp, return 0; } -static int update_evpn_type5_route_entry(struct bgp *bgp_def, +static int update_evpn_type5_route_entry(struct bgp *bgp_evpn, struct bgp *bgp_vrf, afi_t afi, safi_t safi, struct bgp_node *rn, struct attr *attr, int *route_changed) @@ -1435,7 +1437,7 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_def, /* locate the local route entry if any */ for (tmp_pi = bgp_node_get_bgp_path_info(rn); tmp_pi; tmp_pi = tmp_pi->next) { - if (tmp_pi->peer == bgp_def->peer_self + if (tmp_pi->peer == bgp_evpn->peer_self && tmp_pi->type == ZEBRA_ROUTE_BGP && tmp_pi->sub_type == BGP_ROUTE_STATIC) local_pi = tmp_pi; @@ -1455,7 +1457,7 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_def, /* create the route info from attribute */ pi = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, - bgp_def->peer_self, attr_new, rn); + bgp_evpn->peer_self, attr_new, rn); SET_FLAG(pi->flags, BGP_PATH_VALID); /* Type-5 routes advertise the L3-VNI */ @@ -1501,11 +1503,11 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp, safi_t safi = SAFI_EVPN; struct attr attr; struct bgp_node *rn = NULL; - struct bgp *bgp_def = NULL; + struct bgp *bgp_evpn = NULL; int route_changed = 0; - bgp_def = bgp_get_default(); - if (!bgp_def) + bgp_evpn = bgp_get_evpn(); + if (!bgp_evpn) return 0; /* Build path attribute for this route - use the source attr, if @@ -1527,17 +1529,17 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp, build_evpn_type5_route_extcomm(bgp_vrf, &attr); /* get the route node in global table */ - rn = bgp_afi_node_get(bgp_def->rib[afi][safi], afi, safi, + rn = bgp_afi_node_get(bgp_evpn->rib[afi][safi], afi, safi, (struct prefix *)evp, &bgp_vrf->vrf_prd); assert(rn); /* create or update the route entry within the route node */ - update_evpn_type5_route_entry(bgp_def, bgp_vrf, afi, safi, rn, &attr, + update_evpn_type5_route_entry(bgp_evpn, bgp_vrf, afi, safi, rn, &attr, &route_changed); /* schedule for processing and unlock node */ if (route_changed) { - bgp_process(bgp_def, rn, afi, safi); + bgp_process(bgp_evpn, rn, afi, safi); bgp_unlock_node(rn); } @@ -1924,21 +1926,21 @@ static int delete_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp) safi_t safi = SAFI_EVPN; struct bgp_node *rn = NULL; struct bgp_path_info *pi = NULL; - struct bgp *bgp_def = NULL; /* default bgp instance */ + struct bgp *bgp_evpn = NULL; /* evpn bgp instance */ - bgp_def = bgp_get_default(); - if (!bgp_def) + bgp_evpn = bgp_get_evpn(); + if (!bgp_evpn) return 0; /* locate the global route entry for this type-5 prefix */ - rn = bgp_afi_node_lookup(bgp_def->rib[afi][safi], afi, safi, + rn = bgp_afi_node_lookup(bgp_evpn->rib[afi][safi], afi, safi, (struct prefix *)evp, &bgp_vrf->vrf_prd); if (!rn) return 0; - delete_evpn_route_entry(bgp_def, afi, safi, rn, &pi); + delete_evpn_route_entry(bgp_evpn, afi, safi, rn, &pi); if (pi) - bgp_process(bgp_def, rn, afi, safi); + bgp_process(bgp_evpn, rn, afi, safi); bgp_unlock_node(rn); return 0; } @@ -2502,6 +2504,9 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, /* Perform route selection and update zebra, if required. */ bgp_process(bgp_vrf, rn, afi, safi); + /* Process for route leaking. */ + vpn_leak_from_vrf_update(bgp_get_default(), bgp_vrf, pi); + return ret; } @@ -2667,6 +2672,9 @@ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, if (!pi) return 0; + /* Process for route leaking. */ + vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp_vrf, pi); + bgp_aggregate_decrement(bgp_vrf, &rn->p, pi, afi, safi); /* Mark entry for deletion */ @@ -2939,6 +2947,41 @@ static int install_uninstall_routes_for_es(struct bgp *bgp, return 0; } +/* This API will scan evpn routes for checking attribute's rmac + * macthes with bgp instance router mac. It avoid installing + * route into bgp vrf table and remote rmac in bridge table. + */ +static int bgp_evpn_route_rmac_self_check(struct bgp *bgp_vrf, + struct prefix_evpn *evp, + struct bgp_path_info *pi) +{ + /* evpn route could have learnt prior to L3vni has come up, + * perform rmac check before installing route and + * remote router mac. + * The route will be removed from global bgp table once + * SVI comes up with MAC and stored in hash, triggers + * bgp_mac_rescan_all_evpn_tables. + */ + if (pi->attr && + memcmp(&bgp_vrf->rmac, &pi->attr->rmac, ETH_ALEN) == 0) { + if (bgp_debug_update(pi->peer, NULL, NULL, 1)) { + char buf1[PREFIX_STRLEN]; + char attr_str[BUFSIZ] = {0}; + + bgp_dump_attr(pi->attr, attr_str, BUFSIZ); + + zlog_debug("%s: bgp %u prefix %s with attr %s - DENIED due to self mac", + __func__, bgp_vrf->vrf_id, + prefix2str(evp, buf1, sizeof(buf1)), + attr_str); + } + + return 1; + } + + return 0; +} + /* * Install or uninstall mac-ip routes are appropriate for this * particular VRF. @@ -2952,19 +2995,19 @@ static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install) struct bgp_path_info *pi; int ret; char buf[PREFIX_STRLEN]; - struct bgp *bgp_def = NULL; + struct bgp *bgp_evpn = NULL; afi = AFI_L2VPN; safi = SAFI_EVPN; - bgp_def = bgp_get_default(); - if (!bgp_def) + bgp_evpn = bgp_get_evpn(); + if (!bgp_evpn) return -1; /* Walk entire global routing table and evaluate routes which could be * imported into this VRF. Note that we need to loop through all global * routes to determine which route matches the import rt on vrf */ - for (rd_rn = bgp_table_top(bgp_def->rib[afi][safi]); rd_rn; + for (rd_rn = bgp_table_top(bgp_evpn->rib[afi][safi]); rd_rn; rd_rn = bgp_route_next(rd_rn)) { table = bgp_node_get_bgp_table_info(rd_rn); if (!table) @@ -2995,6 +3038,10 @@ static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int 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); @@ -4111,14 +4158,14 @@ static void free_vni_entry(struct hash_bucket *bucket, struct bgp *bgp) */ static void evpn_auto_rt_import_add_for_vrf(struct bgp *bgp_vrf) { - struct bgp *bgp_def = NULL; + struct bgp *bgp_evpn = NULL; form_auto_rt(bgp_vrf, bgp_vrf->l3vni, bgp_vrf->vrf_import_rtl); UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_IMPORT_RT_CFGD); /* Map RT to VRF */ - bgp_def = bgp_get_default(); - if (!bgp_def) + bgp_evpn = bgp_get_evpn(); + if (!bgp_evpn) return; bgp_evpn_map_vrf_to_its_rts(bgp_vrf); } @@ -4150,12 +4197,12 @@ static void evpn_auto_rt_export_delete_for_vrf(struct bgp *bgp_vrf) static void bgp_evpn_handle_export_rt_change_for_vrf(struct bgp *bgp_vrf) { - struct bgp *bgp_def = NULL; + struct bgp *bgp_evpn = NULL; struct listnode *node = NULL; struct bgpevpn *vpn = NULL; - bgp_def = bgp_get_default(); - if (!bgp_def) + bgp_evpn = bgp_get_evpn(); + if (!bgp_evpn) return; /* update all type-5 routes */ @@ -4163,7 +4210,7 @@ static void bgp_evpn_handle_export_rt_change_for_vrf(struct bgp *bgp_vrf) /* update all type-2 routes */ for (ALL_LIST_ELEMENTS_RO(bgp_vrf->l2vnis, node, vpn)) - update_routes_for_vni(bgp_def, vpn); + update_routes_for_vni(bgp_evpn, vpn); } /* @@ -4222,11 +4269,13 @@ void bgp_evpn_withdraw_type5_routes(struct bgp *bgp_vrf, afi_t afi, safi_t safi) table = bgp_vrf->rib[afi][safi]; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { - /* Only care about "selected" routes - non-imported. */ + /* Only care about "selected" routes. Also ensure that + * these are routes that are injectable into EVPN. + */ /* TODO: Support for AddPath for EVPN. */ for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) { if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) - && (!pi->extra || !pi->extra->parent)) { + && is_route_injectable_into_evpn(pi)) { bgp_evpn_withdraw_type5_route(bgp_vrf, &rn->p, afi, safi); break; @@ -4293,12 +4342,13 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi, table = bgp_vrf->rib[afi][safi]; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { /* Need to identify the "selected" route entry to use its - * attribute. Also, we only consider "non-imported" routes. + * attribute. Also, ensure that the route is injectable + * into EVPN. * TODO: Support for AddPath for EVPN. */ for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) { if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) - && (!pi->extra || !pi->extra->parent)) { + && is_route_injectable_into_evpn(pi)) { /* apply the route-map */ if (bgp_vrf->adv_cmd_rmap[afi][safi].map) { @@ -5032,6 +5082,9 @@ void bgp_evpn_derive_auto_rt_export(struct bgp *bgp, struct bgpevpn *vpn) */ void bgp_evpn_derive_auto_rd_for_vrf(struct bgp *bgp) { + if (is_vrf_rd_configured(bgp)) + return; + form_auto_rd(bgp->router_id, bgp->vrf_rd_id, &bgp->vrf_prd); } @@ -5377,10 +5430,10 @@ static void link_l2vni_hash_to_l3vni(struct hash_bucket *bucket, struct bgp *bgp_vrf) { struct bgpevpn *vpn = (struct bgpevpn *)bucket->data; - struct bgp *bgp_def = NULL; + struct bgp *bgp_evpn = NULL; - bgp_def = bgp_get_default(); - assert(bgp_def); + bgp_evpn = bgp_get_evpn(); + assert(bgp_evpn); if (vpn->tenant_vrf_id == bgp_vrf->vrf_id) bgpevpn_link_to_l3vni(vpn); @@ -5391,32 +5444,33 @@ int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id, struct ethaddr *rmac, ifindex_t svi_ifindex) { struct bgp *bgp_vrf = NULL; /* bgp VRF instance */ - struct bgp *bgp_def = NULL; /* default bgp instance */ + struct bgp *bgp_evpn = NULL; /* EVPN bgp instance */ struct listnode *node = NULL; struct bgpevpn *vpn = NULL; as_t as = 0; - /* get the default instance - required to get the AS number for VRF + /* get the EVPN instance - required to get the AS number for VRF * auto-creatio */ - bgp_def = bgp_get_default(); - if (!bgp_def) { + bgp_evpn = bgp_get_evpn(); + if (!bgp_evpn) { flog_err( EC_BGP_NO_DFLT, - "Cannot process L3VNI %u ADD - default BGP instance not yet created", + "Cannot process L3VNI %u ADD - EVPN BGP instance not yet created", l3vni); return -1; } - as = bgp_def->as; + as = bgp_evpn->as; /* if the BGP vrf instance doesn't exist - create one */ - bgp_vrf = bgp_lookup_by_name(vrf_id_to_name(vrf_id)); + bgp_vrf = bgp_lookup_by_vrf_id(vrf_id); if (!bgp_vrf) { int ret = 0; ret = bgp_get(&bgp_vrf, &as, vrf_id_to_name(vrf_id), - BGP_INSTANCE_TYPE_VRF); + vrf_id == VRF_DEFAULT ? BGP_INSTANCE_TYPE_DEFAULT + : BGP_INSTANCE_TYPE_VRF); switch (ret) { case BGP_ERR_MULTIPLE_INSTANCE_NOT_SET: flog_err(EC_BGP_MULTI_INSTANCE, @@ -5459,7 +5513,7 @@ int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id, struct ethaddr *rmac, bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf); /* link all corresponding l2vnis */ - hash_iterate(bgp_def->vnihash, + hash_iterate(bgp_evpn->vnihash, (void (*)(struct hash_bucket *, void *))link_l2vni_hash_to_l3vni, bgp_vrf); @@ -5469,7 +5523,7 @@ int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id, struct ethaddr *rmac, */ if (!filter) for (ALL_LIST_ELEMENTS_RO(bgp_vrf->l2vnis, node, vpn)) - update_routes_for_vni(bgp_def, vpn); + update_routes_for_vni(bgp_evpn, vpn); /* advertise type-5 routes if needed */ update_advertise_vrf_routes(bgp_vrf); @@ -5484,7 +5538,7 @@ int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id, struct ethaddr *rmac, int bgp_evpn_local_l3vni_del(vni_t l3vni, vrf_id_t vrf_id) { struct bgp *bgp_vrf = NULL; /* bgp vrf instance */ - struct bgp *bgp_def = NULL; /* default bgp instance */ + struct bgp *bgp_evpn = NULL; /* EVPN bgp instance */ struct listnode *node = NULL; struct listnode *next = NULL; struct bgpevpn *vpn = NULL; @@ -5498,11 +5552,11 @@ int bgp_evpn_local_l3vni_del(vni_t l3vni, vrf_id_t vrf_id) return -1; } - bgp_def = bgp_get_default(); - if (!bgp_def) { + bgp_evpn = bgp_get_evpn(); + if (!bgp_evpn) { flog_err( EC_BGP_NO_DFLT, - "Cannot process L3VNI %u Del - Could not find default BGP instance", + "Cannot process L3VNI %u Del - Could not find EVPN BGP instance", l3vni); return -1; } @@ -5540,7 +5594,7 @@ int bgp_evpn_local_l3vni_del(vni_t l3vni, vrf_id_t vrf_id) if (!CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)) { for (ALL_LIST_ELEMENTS_RO(bgp_vrf->l2vnis, node, vpn)) { UNSET_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS); - update_routes_for_vni(bgp_def, vpn); + update_routes_for_vni(bgp_evpn, vpn); } } |
