summaryrefslogtreecommitdiff
path: root/bgpd/bgp_zebra.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_zebra.c')
-rw-r--r--bgpd/bgp_zebra.c109
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;
}