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.c132
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);
}