diff options
Diffstat (limited to 'bgpd/bgp_zebra.c')
| -rw-r--r-- | bgpd/bgp_zebra.c | 132 |
1 files changed, 90 insertions, 42 deletions
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index f3ab608492..4f54bc81fb 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -51,7 +51,7 @@ #include "bgpd/bgp_nht.h" #include "bgpd/bgp_bfd.h" #include "bgpd/bgp_label.h" -#if ENABLE_BGP_VNC +#ifdef ENABLE_BGP_VNC #include "bgpd/rfapi/rfapi_backend.h" #include "bgpd/rfapi/vnc_export_bgp.h" #endif @@ -66,19 +66,19 @@ struct zclient *zclient = NULL; /* Can we install into zebra? */ -static inline int bgp_install_info_to_zebra(struct bgp *bgp) +static inline bool bgp_install_info_to_zebra(struct bgp *bgp) { if (zclient->sock <= 0) - return 0; + return false; if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) { zlog_debug( "%s: No zebra instance to talk to, not installing information", __func__); - return 0; + return false; } - return 1; + return true; } int zclient_num_connects; @@ -928,8 +928,8 @@ bgp_path_info_to_ipv6_nexthop(struct bgp_path_info *path, ifindex_t *ifindex) return nexthop; } -static int bgp_table_map_apply(struct route_map *map, struct prefix *p, - struct bgp_path_info *path) +static bool bgp_table_map_apply(struct route_map *map, const struct prefix *p, + struct bgp_path_info *path) { route_map_result_t ret; @@ -937,7 +937,7 @@ static int bgp_table_map_apply(struct route_map *map, struct prefix *p, bgp_attr_flush(path->attr); if (ret != RMAP_DENYMATCH) - return 1; + return true; if (bgp_debug_zebra(p)) { if (p->family == AF_INET) { @@ -965,7 +965,7 @@ static int bgp_table_map_apply(struct route_map *map, struct prefix *p, buf[1], sizeof(buf[1]))); } } - return 0; + return false; } static struct thread *bgp_tm_thread_connect; @@ -1058,12 +1058,10 @@ int bgp_zebra_get_table_range(uint32_t chunk_size, return 0; } -static int update_ipv4nh_for_route_install(int nh_othervrf, - struct bgp *nh_bgp, - struct in_addr *nexthop, - struct attr *attr, - bool is_evpn, - struct zapi_nexthop *api_nh) +static bool update_ipv4nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, + struct in_addr *nexthop, + struct attr *attr, bool is_evpn, + struct zapi_nexthop *api_nh) { api_nh->gate.ipv4 = *nexthop; api_nh->vrf_id = nh_bgp->vrf_id; @@ -1083,15 +1081,16 @@ static int update_ipv4nh_for_route_install(int nh_othervrf, } else api_nh->type = NEXTHOP_TYPE_IPV4; - return 1; + return true; } -static int -update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, - struct in6_addr *nexthop, - ifindex_t ifindex, struct bgp_path_info *pi, - struct bgp_path_info *best_pi, bool is_evpn, - struct zapi_nexthop *api_nh) +static bool update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, + struct in6_addr *nexthop, + ifindex_t ifindex, + struct bgp_path_info *pi, + struct bgp_path_info *best_pi, + bool is_evpn, + struct zapi_nexthop *api_nh) { struct attr *attr; @@ -1108,7 +1107,7 @@ update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, api_nh->ifindex = attr->nh_ifindex; } else if (IN6_IS_ADDR_LINKLOCAL(nexthop)) { if (ifindex == 0) - return 0; + return false; api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; api_nh->ifindex = ifindex; } else { @@ -1136,7 +1135,7 @@ update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, } if (ifindex == 0) - return 0; + return false; api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; api_nh->ifindex = ifindex; } else { @@ -1146,10 +1145,35 @@ update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, } api_nh->gate.ipv6 = *nexthop; - return 1; + return true; } -void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, +static bool bgp_zebra_use_nhop_weighted(struct bgp *bgp, struct attr *attr, + uint64_t tot_bw, uint32_t *nh_weight) +{ + uint32_t bw; + uint64_t tmp; + + bw = attr->link_bw; + /* zero link-bandwidth and link-bandwidth not present are treated + * as the same situation. + */ + if (!bw) { + /* the only situations should be if we're either told + * to skip or use default weight. + */ + if (bgp->lb_handling == BGP_LINK_BW_SKIP_MISSING) + return false; + *nh_weight = BGP_ZEBRA_DEFAULT_NHOP_WEIGHT; + } else { + tmp = (uint64_t)bw * 100; + *nh_weight = ((uint32_t)(tmp / tot_bw)); + } + + return true; +} + +void bgp_zebra_announce(struct bgp_node *rn, const struct prefix *p, struct bgp_path_info *info, struct bgp *bgp, afi_t afi, safi_t safi) { @@ -1171,6 +1195,8 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, char buf_prefix[PREFIX_STRLEN]; /* filled in if we are debugging */ bool is_evpn; int nh_updated; + bool do_wt_ecmp; + uint64_t cum_bw = 0; /* Don't try to install if we're not connected to Zebra or Zebra doesn't * know of this instance. @@ -1185,7 +1211,8 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, prefix2str(p, buf_prefix, sizeof(buf_prefix)); if (safi == SAFI_FLOWSPEC) { - bgp_pbr_update_entry(bgp, &rn->p, info, afi, safi, true); + bgp_pbr_update_entry(bgp, bgp_node_get_prefix(rn), + info, afi, safi, true); return; } @@ -1240,11 +1267,20 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, /* Metric is currently based on the best-path only */ metric = info->attr->med; + + /* Determine if we're doing weighted ECMP or not */ + do_wt_ecmp = bgp_path_info_mpath_chkwtd(bgp, info); + if (do_wt_ecmp) + cum_bw = bgp_path_info_mpath_cumbw(info); + for (mpinfo = info; mpinfo; mpinfo = bgp_path_info_mpath_next(mpinfo)) { + uint32_t nh_weight; + if (valid_nh_count >= multipath_num) break; *mpinfo_cp = *mpinfo; + nh_weight = 0; /* Get nexthop address-family */ if (p->family == AF_INET @@ -1257,6 +1293,15 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, else continue; + /* If processing for weighted ECMP, determine the next hop's + * weight. Based on user setting, we may skip the next hop + * in some situations. + */ + if (do_wt_ecmp) { + if (!bgp_zebra_use_nhop_weighted(bgp, mpinfo->attr, + cum_bw, &nh_weight)) + continue; + } api_nh = &api.nexthops[valid_nh_count]; if (nh_family == AF_INET) { if (bgp_debug_zebra(&api.prefix)) { @@ -1356,6 +1401,8 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, } memcpy(&api_nh->rmac, &(mpinfo->attr->rmac), sizeof(struct ethaddr)); + api_nh->weight = nh_weight; + valid_nh_count++; } @@ -1435,9 +1482,10 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, snprintf(eth_buf, sizeof(eth_buf), " RMAC %s", prefix_mac2str(&api_nh->rmac, buf1, sizeof(buf1))); - zlog_debug(" nhop [%d]: %s if %u VRF %u %s %s", + zlog_debug(" nhop [%d]: %s if %u VRF %u wt %u %s %s", i + 1, nh_buf, api_nh->ifindex, - api_nh->vrf_id, label_buf, eth_buf); + api_nh->vrf_id, api_nh->weight, + label_buf, eth_buf); } } @@ -1481,11 +1529,11 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi) && (pi->sub_type == BGP_ROUTE_NORMAL || pi->sub_type == BGP_ROUTE_IMPORTED))) - bgp_zebra_announce(rn, &rn->p, pi, bgp, afi, - safi); + bgp_zebra_announce(rn, bgp_node_get_prefix(rn), + pi, bgp, afi, safi); } -void bgp_zebra_withdraw(struct prefix *p, struct bgp_path_info *info, +void bgp_zebra_withdraw(const struct prefix *p, struct bgp_path_info *info, struct bgp *bgp, safi_t safi) { struct zapi_route api; @@ -1605,7 +1653,7 @@ int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type, if (vrf_bitmap_check(zclient->redist[afi][type], bgp->vrf_id)) return CMD_WARNING; -#if ENABLE_BGP_VNC +#ifdef ENABLE_BGP_VNC if (EVPN_ENABLED(bgp) && type == ZEBRA_ROUTE_VNC_DIRECT) { vnc_export_bgp_enable( bgp, afi); /* only enables if mode bits cfg'd */ @@ -1660,11 +1708,11 @@ int bgp_redistribute_resend(struct bgp *bgp, afi_t afi, int type, } /* Redistribute with route-map specification. */ -int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name, - struct route_map *route_map) +bool bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name, + struct route_map *route_map) { if (red->rmap.name && (strcmp(red->rmap.name, name) == 0)) - return 0; + return false; XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name); /* Decrement the count for existing routemap and @@ -1675,18 +1723,18 @@ int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name, red->rmap.map = route_map; route_map_counter_increment(red->rmap.map); - return 1; + return true; } /* Redistribute with metric specification. */ -int bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red, - afi_t afi, int type, uint32_t metric) +bool bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red, + afi_t afi, int type, uint32_t metric) { struct bgp_node *rn; struct bgp_path_info *pi; if (red->redist_metric_flag && red->redist_metric == metric) - return 0; + return false; red->redist_metric_flag = 1; red->redist_metric = metric; @@ -1713,7 +1761,7 @@ int bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red, } } - return 1; + return true; } /* Unset redistribution. */ @@ -1766,7 +1814,7 @@ int bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type, * they operate within bgpd irrespective of zebra connection * status. red lookup fails if there is no zebra connection. */ -#if ENABLE_BGP_VNC +#ifdef ENABLE_BGP_VNC if (EVPN_ENABLED(bgp) && type == ZEBRA_ROUTE_VNC_DIRECT) { vnc_export_bgp_disable(bgp, afi); } |
