diff options
Diffstat (limited to 'bgpd/bgp_zebra.c')
| -rw-r--r-- | bgpd/bgp_zebra.c | 109 |
1 files changed, 92 insertions, 17 deletions
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 91639982be..f6e7b444c6 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -234,6 +234,7 @@ static int bgp_ifp_up(struct interface *ifp) struct connected *c; struct nbr_connected *nc; struct listnode *node, *nnode; + struct bgp *bgp_default = bgp_get_default(); struct bgp *bgp; bgp = ifp->vrf->info; @@ -256,6 +257,14 @@ static int bgp_ifp_up(struct interface *ifp) hook_call(bgp_vrf_status_changed, bgp, ifp); bgp_nht_ifp_up(ifp); + if (bgp_default && if_is_loopback(ifp)) { + vpn_leak_zebra_vrf_label_update(bgp, AFI_IP); + vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6); + vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP); + vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP6); + vpn_leak_postchange_all(); + } + return 0; } @@ -264,6 +273,7 @@ static int bgp_ifp_down(struct interface *ifp) struct connected *c; struct nbr_connected *nc; struct listnode *node, *nnode; + struct bgp *bgp_default = bgp_get_default(); struct bgp *bgp; struct peer *peer; @@ -303,6 +313,14 @@ static int bgp_ifp_down(struct interface *ifp) hook_call(bgp_vrf_status_changed, bgp, ifp); bgp_nht_ifp_down(ifp); + if (bgp_default && if_is_loopback(ifp)) { + vpn_leak_zebra_vrf_label_update(bgp, AFI_IP); + vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6); + vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP); + vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP6); + vpn_leak_postchange_all(); + } + return 0; } @@ -390,10 +408,16 @@ static int bgp_interface_address_add(ZAPI_CALLBACK_ARGS) static int bgp_interface_address_delete(ZAPI_CALLBACK_ARGS) { struct listnode *node, *nnode; + struct bgp_path_info *pi; + struct bgp_table *table; + struct bgp_dest *dest; struct connected *ifc; struct peer *peer; - struct bgp *bgp; + struct bgp *bgp, *from_bgp, *bgp_default; + struct listnode *next; struct prefix *addr; + afi_t afi; + safi_t safi; bgp = bgp_lookup_by_vrf_id(vrf_id); @@ -421,9 +445,6 @@ static int bgp_interface_address_delete(ZAPI_CALLBACK_ARGS) * we do not want the peering to bounce. */ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { - afi_t afi; - safi_t safi; - if (addr->family == AF_INET) continue; @@ -439,6 +460,44 @@ static int bgp_interface_address_delete(ZAPI_CALLBACK_ARGS) } } + bgp_default = bgp_get_default(); + afi = family2afi(addr->family); + safi = SAFI_UNICAST; + + /* When the last IPv4 address was deleted, Linux removes all routes + * using the interface so that bgpd needs to re-send them. + */ + if (bgp_default && afi == AFI_IP) { + for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, from_bgp)) { + table = from_bgp->rib[afi][safi]; + if (!table) + continue; + + for (dest = bgp_table_top(table); dest; + dest = bgp_route_next(dest)) { + for (pi = bgp_dest_get_bgp_path_info(dest); pi; + pi = pi->next) { + if (pi->type == ZEBRA_ROUTE_BGP && + pi->attr && + pi->attr->nh_ifindex == + ifc->ifp->ifindex) { + SET_FLAG(pi->attr->nh_flag, + BGP_ATTR_NH_REFRESH); + } + } + } + + if (from_bgp->inst_type != BGP_INSTANCE_TYPE_VRF) + continue; + + vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi, + bgp_default, from_bgp); + + vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN, afi, + bgp_default, from_bgp); + } + } + connected_free(&ifc); return 0; @@ -1007,7 +1066,8 @@ bgp_path_info_to_ipv6_nexthop(struct bgp_path_info *path, ifindex_t *ifindex) || path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) { /* Check if route-map is set to prefer global over link-local */ - if (path->attr->mp_nexthop_prefer_global) { + if (CHECK_FLAG(path->attr->nh_flag, + BGP_ATTR_NH_MP_PREFER_GLOBAL)) { nexthop = &path->attr->mp_nexthop_global; if (IN6_IS_ADDR_LINKLOCAL(nexthop)) *ifindex = path->attr->nh_ifindex; @@ -1307,6 +1367,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, uint8_t distance; struct peer *peer; struct bgp_path_info *mpinfo; + struct bgp_path_info *bpi_ultimate; struct bgp *bgp_orig; uint32_t metric; struct attr local_attr; @@ -1355,13 +1416,9 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, peer = info->peer; - if (info->type == ZEBRA_ROUTE_BGP - && info->sub_type == BGP_ROUTE_IMPORTED) { - - /* Obtain peer from parent */ - if (info->extra && info->extra->parent) - peer = ((struct bgp_path_info *)(info->extra->parent)) - ->peer; + if (info->type == ZEBRA_ROUTE_BGP) { + bpi_ultimate = bgp_get_imported_bpi_ultimate(info); + peer = bpi_ultimate->peer; } tag = info->attr->tag; @@ -1532,7 +1589,9 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, api_nh->weight = nh_weight; - if (mpinfo->extra && !sid_zero(&mpinfo->extra->sid[0].sid) && + if (mpinfo->extra && + bgp_is_valid_label(&mpinfo->extra->label[0]) && + !sid_zero(&mpinfo->extra->sid[0].sid) && !CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN)) { sid_info = &mpinfo->extra->sid[0]; @@ -1540,12 +1599,16 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, sizeof(api_nh->seg6_segs)); if (sid_info->transposition_len != 0) { - if (!bgp_is_valid_label( - &mpinfo->extra->label[0])) - continue; - mpls_lse_decode(mpinfo->extra->label[0], &label, &ttl, &exp, &bos); + + if (label < MPLS_LABEL_UNRESERVED_MIN) { + if (bgp_debug_zebra(&api.prefix)) + zlog_debug( + "skip invalid SRv6 routes: transposition scheme is used, but label is too small"); + continue; + } + transpose_sid(&api_nh->seg6_segs, label, sid_info->transposition_offset, sid_info->transposition_len); @@ -3187,6 +3250,7 @@ extern struct zebra_privs_t bgpd_privs; static int bgp_ifp_create(struct interface *ifp) { + struct bgp *bgp_default = bgp_get_default(); struct bgp *bgp; if (BGP_DEBUG(zebra, ZEBRA)) @@ -3201,6 +3265,17 @@ static int bgp_ifp_create(struct interface *ifp) bgp_update_interface_nbrs(bgp, ifp, ifp); hook_call(bgp_vrf_status_changed, bgp, ifp); + + if (bgp_default && + (if_is_loopback_exact(ifp) || + (if_is_vrf(ifp) && ifp->vrf->vrf_id != VRF_DEFAULT))) { + vpn_leak_zebra_vrf_label_update(bgp, AFI_IP); + vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6); + vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP); + vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP6); + vpn_leak_postchange_all(); + } + return 0; } |
