diff options
Diffstat (limited to 'bgpd/bgp_zebra.c')
| -rw-r--r-- | bgpd/bgp_zebra.c | 141 |
1 files changed, 132 insertions, 9 deletions
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 23f626e960..22284fd28d 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -54,6 +54,7 @@ #include "bgpd/rfapi/vnc_export_bgp.h" #endif #include "bgpd/bgp_evpn.h" +#include "bgpd/bgp_mplsvpn.h" /* All information about zebra. */ struct zclient *zclient = NULL; @@ -987,6 +988,7 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, struct bgp_info *mpinfo_cp = &local_info; route_tag_t tag; mpls_label_t label; + int nh_othervrf = 0; /* Don't try to install if we're not connected to Zebra or Zebra doesn't * know of this instance. @@ -997,6 +999,12 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, if (bgp->main_zebra_update_hold) return; + /* + * vrf leaking support (will have only one nexthop) + */ + if (info->extra && info->extra->bgp_orig) + nh_othervrf = 1; + /* Make Zebra API structure. */ memset(&api, 0, sizeof(api)); memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr)); @@ -1008,6 +1016,21 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, peer = info->peer; + if (info->type == ZEBRA_ROUTE_BGP + && info->sub_type == BGP_ROUTE_IMPORTED) { + + struct bgp_info *bi; + + /* + * Look at parent chain for peer sort + */ + for (bi = info; bi->extra && bi->extra->parent; + bi = bi->extra->parent) { + + peer = ((struct bgp_info *)(bi->extra->parent))->peer; + } + } + tag = info->attr->tag; /* When we create an aggregate route we must also install a Null0 route @@ -1060,12 +1083,38 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, if (nh_family == AF_INET) { struct in_addr *nexthop; - if (bgp->table_map[afi][safi].name) { + if (bgp_debug_zebra(&api.prefix)) { + char buf_prefix[PREFIX_STRLEN]; + prefix2str(&api.prefix, buf_prefix, + sizeof(buf_prefix)); + if (mpinfo->extra) { + zlog_debug( + "%s: p=%s, bgp_is_valid_label: %d", + __func__, buf_prefix, + bgp_is_valid_label( + &mpinfo->extra + ->label[0])); + } else { + zlog_debug( + "%s: p=%s, extra is NULL, no label", + __func__, buf_prefix); + } + } + + if (bgp->table_map[afi][safi].name || nh_othervrf) { /* Copy info and attributes, so the route-map apply doesn't modify the BGP route info. */ local_attr = *mpinfo->attr; mpinfo_cp->attr = &local_attr; + if (nh_othervrf) { + /* allow route-map to modify */ + local_attr.nexthop = + info->extra->nexthop_orig.u + .prefix4; + } + } + if (bgp->table_map[afi][safi].name) { if (!bgp_table_map_apply( bgp->table_map[afi][safi].map, p, mpinfo_cp)) @@ -1082,6 +1131,9 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, nexthop = &mpinfo_cp->attr->nexthop; api_nh->gate.ipv4 = *nexthop; + api_nh->vrf_id = nh_othervrf + ? info->extra->bgp_orig->vrf_id + : bgp->vrf_id; /* EVPN type-2 routes are programmed as onlink on l3-vni SVI */ @@ -1095,6 +1147,21 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, ifindex = 0; + if (bgp->table_map[afi][safi].name || nh_othervrf) { + /* Copy info and attributes, so the route-map + apply doesn't modify the BGP route info. */ + local_attr = *mpinfo->attr; + mpinfo_cp->attr = &local_attr; + if (nh_othervrf) { + /* allow route-map to modify */ + local_attr.mp_nexthop_global = + info->extra->nexthop_orig.u + .prefix6; + local_attr.mp_nexthop_len = + BGP_ATTR_NHLEN_IPV6_GLOBAL; + } + } + if (bgp->table_map[afi][safi].name) { /* Copy info and attributes, so the route-map apply doesn't modify the BGP route info. */ @@ -1139,6 +1206,9 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, api_nh->gate.ipv6 = *nexthop; api_nh->ifindex = ifindex; api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; + /* api_nh->vrf_id is not set for normal case? */ + if (nh_othervrf) + api_nh->vrf_id = info->extra->bgp_orig->vrf_id; } if (mpinfo->extra @@ -1229,9 +1299,12 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi) for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) for (ri = rn->info; ri; ri = ri->next) - if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED) - && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_NORMAL) + if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED) && + + (ri->type == ZEBRA_ROUTE_BGP + && (ri->sub_type == BGP_ROUTE_NORMAL + || ri->sub_type == BGP_ROUTE_IMPORTED))) + bgp_zebra_announce(rn, &rn->p, ri, bgp, afi, safi); } @@ -1244,6 +1317,21 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi) peer = info->peer; assert(peer); + if (info->type == ZEBRA_ROUTE_BGP + && info->sub_type == BGP_ROUTE_IMPORTED) { + + struct bgp_info *bi; + + /* + * Look at parent chain for peer sort + */ + for (bi = info; bi->extra && bi->extra->parent; + bi = bi->extra->parent) { + + peer = ((struct bgp_info *)(bi->extra->parent))->peer; + } + } + /* Don't try to install if we're not connected to Zebra or Zebra doesn't * know of this instance. */ @@ -1363,7 +1451,27 @@ int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type, u_short instance) } #endif + /* vpn -> vrf (happens within bgp but we hijack redist bits */ + if ((bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT + || bgp->inst_type == BGP_INSTANCE_TYPE_VRF) + && type == ZEBRA_ROUTE_BGP_VPN) { + + /* leak update all */ + vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, afi, + bgp_get_default(), bgp); + } + vrf_bitmap_set(zclient->redist[afi][type], bgp->vrf_id); + + /* vpn -> vrf (happens within bgp but we hijack redist bits */ + if ((bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT + || bgp->inst_type == BGP_INSTANCE_TYPE_VRF) + && type == ZEBRA_ROUTE_BGP_VPN) { + + /* leak update all */ + vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN, afi, + bgp_get_default(), bgp); + } } /* @@ -1484,11 +1592,6 @@ int bgp_redistribute_unreg(struct bgp *bgp, afi_t afi, int type, vrf_bitmap_unset(zclient->redist[afi][type], bgp->vrf_id); } -#if ENABLE_BGP_VNC - if (bgp->vrf_id == VRF_DEFAULT && type == ZEBRA_ROUTE_VNC_DIRECT) { - vnc_export_bgp_disable(bgp, afi); - } -#endif if (bgp_install_info_to_zebra(bgp)) { /* Send distribute delete message to zebra. */ @@ -1512,6 +1615,26 @@ int bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type, { struct bgp_redist *red; +/* + * vnc and vpn->vrf checks must be before red check because + * they operate within bgpd irrespective of zebra connection + * status. red lookup fails if there is no zebra connection. + */ +#if ENABLE_BGP_VNC + if (bgp->vrf_id == VRF_DEFAULT && type == ZEBRA_ROUTE_VNC_DIRECT) { + vnc_export_bgp_disable(bgp, afi); + } +#endif + /* vpn -> vrf (happend within bgp but we hijack redist bits */ + if ((bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT + || bgp->inst_type == BGP_INSTANCE_TYPE_VRF) + && type == ZEBRA_ROUTE_BGP_VPN) { + + /* leak withdraw all */ + vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, afi, + bgp_get_default(), bgp); + } + red = bgp_redist_lookup(bgp, afi, type, instance); if (!red) return CMD_SUCCESS; |
