summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_attr.c141
-rw-r--r--bgpd/bgp_attr.h3
-rw-r--r--lib/nexthop.c7
-rw-r--r--lib/nexthop.h3
-rw-r--r--lib/nexthop_group.c55
-rw-r--r--lib/skiplist.c2
-rw-r--r--lib/zclient.c15
-rw-r--r--lib/zclient.h3
-rw-r--r--pbrd/pbr_zebra.c1
-rw-r--r--pimd/pim_upstream.c1
-rw-r--r--sharpd/sharp_zebra.c2
-rw-r--r--zebra/rt_netlink.c9
-rw-r--r--zebra/zapi_msg.c4
-rw-r--r--zebra/zebra_dplane.c2
-rw-r--r--zebra/zebra_nhg.c2
-rw-r--r--zebra/zebra_vty.c6
16 files changed, 164 insertions, 92 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index ab80aff81b..331c0ece2d 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -421,14 +421,15 @@ static struct transit *transit_intern(struct transit *transit)
return find;
}
-void transit_unintern(struct transit *transit)
+static void transit_unintern(struct transit **transit)
{
- if (transit->refcnt)
- transit->refcnt--;
+ if ((*transit)->refcnt)
+ (*transit)->refcnt--;
- if (transit->refcnt == 0) {
- hash_release(transit_hash, transit);
- transit_free(transit);
+ if ((*transit)->refcnt == 0) {
+ hash_release(transit_hash, *transit);
+ transit_free(*transit);
+ *transit = NULL;
}
}
@@ -851,7 +852,7 @@ void bgp_attr_unintern_sub(struct attr *attr)
UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST));
if (attr->transit)
- transit_unintern(attr->transit);
+ transit_unintern(&attr->transit);
if (attr->encap_subtlvs)
encap_unintern(&attr->encap_subtlvs, ENCAP_SUBTLV_TYPE);
@@ -2483,7 +2484,8 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
- return BGP_ATTR_PARSE_ERROR;
+ ret = BGP_ATTR_PARSE_ERROR;
+ goto done;
}
/* Fetch attribute flag and type. */
@@ -2506,7 +2508,8 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
- return BGP_ATTR_PARSE_ERROR;
+ ret = BGP_ATTR_PARSE_ERROR;
+ goto done;
}
/* Check extended attribue length bit. */
@@ -2527,7 +2530,8 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_MAL_ATTR);
- return BGP_ATTR_PARSE_ERROR;
+ ret = BGP_ATTR_PARSE_ERROR;
+ goto done;
}
/* Set type to bitmap to check duplicate attribute. `type' is
@@ -2584,7 +2588,8 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, ndata,
ndl + lfl + 1);
- return BGP_ATTR_PARSE_ERROR;
+ ret = BGP_ATTR_PARSE_ERROR;
+ goto done;
}
struct bgp_attr_parser_args attr_args = {
@@ -2609,7 +2614,7 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
attr_args.total);
if (ret == BGP_ATTR_PARSE_PROCEED)
continue;
- return ret;
+ goto done;
}
/* OK check attribute and store it's value. */
@@ -2687,32 +2692,25 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_MAL_ATTR);
ret = BGP_ATTR_PARSE_ERROR;
+ goto done;
}
if (ret == BGP_ATTR_PARSE_EOR) {
- if (as4_path)
- aspath_unintern(&as4_path);
- return ret;
+ goto done;
}
- /* If hard error occurred immediately return to the caller. */
if (ret == BGP_ATTR_PARSE_ERROR) {
flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR,
"%s: Attribute %s, parse error", peer->host,
lookup_msg(attr_str, type, NULL));
- if (as4_path)
- aspath_unintern(&as4_path);
- return ret;
+ goto done;
}
if (ret == BGP_ATTR_PARSE_WITHDRAW) {
-
flog_warn(
EC_BGP_ATTRIBUTE_PARSE_WITHDRAW,
"%s: Attribute %s, parse error - treating as withdrawal",
peer->host, lookup_msg(attr_str, type, NULL));
- if (as4_path)
- aspath_unintern(&as4_path);
- return ret;
+ goto done;
}
/* Check the fetched length. */
@@ -2722,9 +2720,8 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
peer->host, lookup_msg(attr_str, type, NULL));
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
- if (as4_path)
- aspath_unintern(&as4_path);
- return BGP_ATTR_PARSE_ERROR;
+ ret = BGP_ATTR_PARSE_ERROR;
+ goto done;
}
}
@@ -2735,9 +2732,9 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
lookup_msg(attr_str, type, NULL));
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
- if (as4_path)
- aspath_unintern(&as4_path);
- return BGP_ATTR_PARSE_ERROR;
+
+ ret = BGP_ATTR_PARSE_ERROR;
+ goto done;
}
/*
@@ -2756,16 +2753,14 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))
&& !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI))) {
if (bgp_attr_nexthop_valid(peer, attr) < 0) {
- return BGP_ATTR_PARSE_ERROR;
+ ret = BGP_ATTR_PARSE_ERROR;
+ goto done;
}
}
/* Check all mandatory well-known attributes are present */
- if ((ret = bgp_attr_check(peer, attr)) < 0) {
- if (as4_path)
- aspath_unintern(&as4_path);
- return ret;
- }
+ if ((ret = bgp_attr_check(peer, attr)) < 0)
+ goto done;
/*
* At this place we can see whether we got AS4_PATH and/or
@@ -2788,28 +2783,10 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
&as4_aggregator_addr)) {
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_MAL_ATTR);
- if (as4_path)
- aspath_unintern(&as4_path);
- return BGP_ATTR_PARSE_ERROR;
+ ret = BGP_ATTR_PARSE_ERROR;
+ goto done;
}
- /* At this stage, we have done all fiddling with as4, and the
- * resulting info is in attr->aggregator resp. attr->aspath
- * so we can chuck as4_aggregator and as4_path alltogether in
- * order to save memory
- */
- if (as4_path) {
- aspath_unintern(&as4_path); /* unintern - it is in the hash */
- /* The flag that we got this is still there, but that does not
- * do any trouble
- */
- }
- /*
- * The "rest" of the code does nothing with as4_aggregator.
- * there is no memory attached specifically which is not part
- * of the attr.
- * so ignoring just means do nothing.
- */
/*
* Finally do the checks on the aspath we did not do yet
* because we waited for a potentially synthesized aspath.
@@ -2817,21 +2794,59 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))) {
ret = bgp_attr_aspath_check(peer, attr);
if (ret != BGP_ATTR_PARSE_PROCEED)
- return ret;
+ goto done;
}
- /* Finally intern unknown attribute. */
+
+ ret = BGP_ATTR_PARSE_PROCEED;
+done:
+
+ /*
+ * At this stage, we have done all fiddling with as4, and the
+ * resulting info is in attr->aggregator resp. attr->aspath so
+ * we can chuck as4_aggregator and as4_path alltogether in order
+ * to save memory
+ */
+ if (as4_path) {
+ /*
+ * unintern - it is in the hash
+ * The flag that we got this is still there, but that
+ * does not do any trouble
+ */
+ aspath_unintern(&as4_path);
+ }
+
+ if (ret != BGP_ATTR_PARSE_ERROR) {
+ /* Finally intern unknown attribute. */
+ if (attr->transit)
+ attr->transit = transit_intern(attr->transit);
+ if (attr->encap_subtlvs)
+ attr->encap_subtlvs = encap_intern(attr->encap_subtlvs,
+ ENCAP_SUBTLV_TYPE);
+#if ENABLE_BGP_VNC
+ if (attr->vnc_subtlvs)
+ attr->vnc_subtlvs = encap_intern(attr->vnc_subtlvs,
+ VNC_SUBTLV_TYPE);
+#endif
+ } else {
+ if (attr->transit) {
+ transit_free(attr->transit);
+ attr->transit = NULL;
+ }
+
+ bgp_attr_flush_encap(attr);
+ };
+
+ /* Sanity checks */
if (attr->transit)
- attr->transit = transit_intern(attr->transit);
+ assert(attr->transit->refcnt > 0);
if (attr->encap_subtlvs)
- attr->encap_subtlvs =
- encap_intern(attr->encap_subtlvs, ENCAP_SUBTLV_TYPE);
+ assert(attr->encap_subtlvs->refcnt > 0);
#if ENABLE_BGP_VNC
if (attr->vnc_subtlvs)
- attr->vnc_subtlvs =
- encap_intern(attr->vnc_subtlvs, VNC_SUBTLV_TYPE);
+ assert(attr->vnc_subtlvs->refcnt > 0);
#endif
- return BGP_ATTR_PARSE_PROCEED;
+ return ret;
}
/*
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 13ed3e1ee3..40e87e190a 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -304,9 +304,6 @@ extern unsigned long int attr_unknown_count(void);
extern int cluster_loop_check(struct cluster_list *, struct in_addr);
extern void cluster_unintern(struct cluster_list *);
-/* Transit attribute prototypes. */
-void transit_unintern(struct transit *);
-
/* Below exported for unit-test purposes only */
struct bgp_attr_parser_args {
struct peer *peer;
diff --git a/lib/nexthop.c b/lib/nexthop.c
index ce8034846f..718cda7355 100644
--- a/lib/nexthop.c
+++ b/lib/nexthop.c
@@ -118,6 +118,12 @@ static int _nexthop_cmp_no_labels(const struct nexthop *next1,
if (next1->type > next2->type)
return 1;
+ if (next1->weight < next2->weight)
+ return -1;
+
+ if (next1->weight > next2->weight)
+ return 1;
+
switch (next1->type) {
case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV6:
@@ -550,6 +556,7 @@ void nexthop_copy(struct nexthop *copy, const struct nexthop *nexthop,
copy->ifindex = nexthop->ifindex;
copy->type = nexthop->type;
copy->flags = nexthop->flags;
+ copy->weight = nexthop->weight;
memcpy(&copy->gate, &nexthop->gate, sizeof(nexthop->gate));
memcpy(&copy->src, &nexthop->src, sizeof(nexthop->src));
memcpy(&copy->rmap_src, &nexthop->rmap_src, sizeof(nexthop->rmap_src));
diff --git a/lib/nexthop.h b/lib/nexthop.h
index 72a4acedb2..040b643a84 100644
--- a/lib/nexthop.h
+++ b/lib/nexthop.h
@@ -110,6 +110,9 @@ struct nexthop {
/* Label(s) associated with this nexthop. */
struct mpls_label_stack *nh_label;
+
+ /* Weight of the nexthop ( for unequal cost ECMP ) */
+ uint8_t weight;
};
struct nexthop *nexthop_new(void);
diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c
index b810d13a5a..991843a047 100644
--- a/lib/nexthop_group.c
+++ b/lib/nexthop_group.c
@@ -42,6 +42,7 @@ struct nexthop_hold {
union sockunion *addr;
char *intf;
char *labels;
+ uint32_t weight;
};
struct nexthop_group_hooks {
@@ -526,8 +527,8 @@ DEFUN_NOSH(no_nexthop_group, no_nexthop_group_cmd, "no nexthop-group NHGNAME",
static void nexthop_group_save_nhop(struct nexthop_group_cmd *nhgc,
const char *nhvrf_name,
const union sockunion *addr,
- const char *intf,
- const char *labels)
+ const char *intf, const char *labels,
+ const uint32_t weight)
{
struct nexthop_hold *nh;
@@ -542,23 +543,26 @@ static void nexthop_group_save_nhop(struct nexthop_group_cmd *nhgc,
if (labels)
nh->labels = XSTRDUP(MTYPE_TMP, labels);
+ nh->weight = weight;
+
listnode_add_sort(nhgc->nhg_list, nh);
}
static void nexthop_group_unsave_nhop(struct nexthop_group_cmd *nhgc,
const char *nhvrf_name,
const union sockunion *addr,
- const char *intf,
- const char *labels)
+ const char *intf, const char *labels,
+ const uint32_t weight)
{
struct nexthop_hold *nh;
struct listnode *node;
for (ALL_LIST_ELEMENTS_RO(nhgc->nhg_list, node, nh)) {
- if (nhgc_cmp_helper(nhvrf_name, nh->nhvrf_name) == 0 &&
- nhgc_addr_cmp_helper(addr, nh->addr) == 0 &&
- nhgc_cmp_helper(intf, nh->intf) == 0 &&
- nhgc_cmp_helper(labels, nh->labels) == 0)
+ if (nhgc_cmp_helper(nhvrf_name, nh->nhvrf_name) == 0
+ && nhgc_addr_cmp_helper(addr, nh->addr) == 0
+ && nhgc_cmp_helper(intf, nh->intf) == 0
+ && nhgc_cmp_helper(labels, nh->labels) == 0
+ && weight == nh->weight)
break;
}
@@ -581,8 +585,8 @@ static void nexthop_group_unsave_nhop(struct nexthop_group_cmd *nhgc,
static bool nexthop_group_parse_nexthop(struct nexthop *nhop,
const union sockunion *addr,
const char *intf, const char *name,
- const char *labels,
- int *lbl_ret)
+ const char *labels, int *lbl_ret,
+ uint32_t weight)
{
int ret = 0;
struct vrf *vrf;
@@ -639,6 +643,8 @@ static bool nexthop_group_parse_nexthop(struct nexthop *nhop,
num, larray);
}
+ nhop->weight = weight;
+
return true;
}
@@ -648,11 +654,9 @@ static bool nexthop_group_parse_nexthop(struct nexthop *nhop,
static bool nexthop_group_parse_nhh(struct nexthop *nhop,
const struct nexthop_hold *nhh)
{
- return (nexthop_group_parse_nexthop(nhop, nhh->addr,
- nhh->intf,
- nhh->nhvrf_name,
- nhh->labels,
- NULL));
+ return (nexthop_group_parse_nexthop(nhop, nhh->addr, nhh->intf,
+ nhh->nhvrf_name, nhh->labels, NULL,
+ nhh->weight));
}
DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
@@ -664,6 +668,7 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
[{ \
nexthop-vrf NAME$vrf_name \
|label WORD \
+ |weight (1-255) \
}]",
NO_STR
"Specify one of the nexthops in this ECMP group\n"
@@ -674,7 +679,9 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
"If the nexthop is in a different vrf tell us\n"
"The nexthop-vrf Name\n"
"Specify label(s) for this nexthop\n"
- "One or more labels in the range (16-1048575) separated by '/'\n")
+ "One or more labels in the range (16-1048575) separated by '/'\n"
+ "Weight to be used by the nexthop for purposes of ECMP\n"
+ "Weight value to be used\n")
{
VTY_DECLVAR_CONTEXT(nexthop_group_cmd, nhgc);
struct nexthop nhop;
@@ -682,8 +689,8 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
int lbl_ret = 0;
bool legal;
- legal = nexthop_group_parse_nexthop(&nhop, addr, intf, vrf_name,
- label, &lbl_ret);
+ legal = nexthop_group_parse_nexthop(&nhop, addr, intf, vrf_name, label,
+ &lbl_ret, weight);
if (nhop.type == NEXTHOP_TYPE_IPV6
&& IN6_IS_ADDR_LINKLOCAL(&nhop.gate.ipv6)) {
@@ -716,7 +723,8 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
nh = nexthop_exists(&nhgc->nhg, &nhop);
if (no) {
- nexthop_group_unsave_nhop(nhgc, vrf_name, addr, intf, label);
+ nexthop_group_unsave_nhop(nhgc, vrf_name, addr, intf, label,
+ weight);
if (nh) {
_nexthop_del(&nhgc->nhg, nh);
@@ -734,7 +742,8 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
_nexthop_add(&nhgc->nhg.nexthop, nh);
}
- nexthop_group_save_nhop(nhgc, vrf_name, addr, intf, label);
+ nexthop_group_save_nhop(nhgc, vrf_name, addr, intf, label,
+ weight);
if (legal && nhg_hooks.add_nexthop)
nhg_hooks.add_nexthop(nhgc, nh);
@@ -794,6 +803,9 @@ void nexthop_group_write_nexthop(struct vty *vty, struct nexthop *nh)
vty_out(vty, " label %s", buf);
}
+ if (nh->weight)
+ vty_out(vty, " weight %u", nh->weight);
+
vty_out(vty, "\n");
}
@@ -816,6 +828,9 @@ static void nexthop_group_write_nexthop_internal(struct vty *vty,
if (nh->labels)
vty_out(vty, " label %s", nh->labels);
+ if (nh->weight)
+ vty_out(vty, " weight %u", nh->weight);
+
vty_out(vty, "\n");
}
diff --git a/lib/skiplist.c b/lib/skiplist.c
index dda442580a..6efa2c362d 100644
--- a/lib/skiplist.c
+++ b/lib/skiplist.c
@@ -608,7 +608,7 @@ void skiplist_test(struct vty *vty)
struct skiplist *l;
register int i, k;
void *keys[sampleSize];
- void *v;
+ void *v = NULL;
zlog_debug("%s: entry", __func__);
diff --git a/lib/zclient.c b/lib/zclient.c
index 5ce1150b05..6982d287a2 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -802,6 +802,12 @@ static int zapi_nexthop_cmp_no_labels(const struct zapi_nexthop *next1,
if (next1->type > next2->type)
return 1;
+ if (next1->weight < next2->weight)
+ return -1;
+
+ if (next1->weight > next2->weight)
+ return 1;
+
switch (next1->type) {
case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV6:
@@ -882,6 +888,9 @@ int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh,
}
}
+ if (api_nh->weight)
+ SET_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_WEIGHT);
+
/* Note that we're only encoding a single octet */
stream_putc(s, nh_flags);
@@ -920,6 +929,9 @@ int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh,
api_nh->label_num * sizeof(mpls_label_t));
}
+ if (api_nh->weight)
+ stream_putl(s, api_nh->weight);
+
/* Router MAC for EVPN routes. */
if (CHECK_FLAG(api_flags, ZEBRA_FLAG_EVPN_ROUTE))
stream_put(s, &(api_nh->rmac),
@@ -1082,6 +1094,9 @@ static int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh,
api_nh->label_num * sizeof(mpls_label_t));
}
+ if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_WEIGHT))
+ STREAM_GETL(s, api_nh->weight);
+
/* Router MAC for EVPN routes. */
if (CHECK_FLAG(api_flags, ZEBRA_FLAG_EVPN_ROUTE))
STREAM_GET(&(api_nh->rmac), s,
diff --git a/lib/zclient.h b/lib/zclient.h
index 9c5c65ffc5..70304127a2 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -323,6 +323,8 @@ struct zapi_nexthop {
mpls_label_t labels[MPLS_MAX_LABELS];
struct ethaddr rmac;
+
+ uint32_t weight;
};
/*
@@ -330,6 +332,7 @@ struct zapi_nexthop {
*/
#define ZAPI_NEXTHOP_FLAG_ONLINK 0x01
#define ZAPI_NEXTHOP_FLAG_LABEL 0x02
+#define ZAPI_NEXTHOP_FLAG_WEIGHT 0x04
/*
* Some of these data structures do not map easily to
diff --git a/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c
index 06ad0f40a4..ec0327d74f 100644
--- a/pbrd/pbr_zebra.c
+++ b/pbrd/pbr_zebra.c
@@ -279,6 +279,7 @@ static void route_add_helper(struct zapi_route *api, struct nexthop_group nhg,
api_nh = &api->nexthops[i];
api_nh->vrf_id = nhop->vrf_id;
api_nh->type = nhop->type;
+ api_nh->weight = nhop->weight;
switch (nhop->type) {
case NEXTHOP_TYPE_IPV4:
api_nh->gate.ipv4 = nhop->gate.ipv4;
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c
index ce26d2b398..a0387cdd4a 100644
--- a/pimd/pim_upstream.c
+++ b/pimd/pim_upstream.c
@@ -884,7 +884,6 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
}
if (up->rpf.source_nexthop.interface) {
- pim_ifp = up->rpf.source_nexthop.interface->info;
pim_upstream_mroute_iif_update(up->channel_oil,
__func__);
}
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
index 797398c791..4fc8f40ae1 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -243,6 +243,8 @@ void route_add(struct prefix *p, vrf_id_t vrf_id,
api_nh = &api.nexthops[i];
api_nh->vrf_id = nh->vrf_id;
api_nh->type = nh->type;
+ api_nh->weight = nh->weight;
+
switch (nh->type) {
case NEXTHOP_TYPE_IPV4:
api_nh->gate = nh->gate;
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index f3a255fd29..e77c923230 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -467,6 +467,8 @@ static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id,
nh = nexthop_from_ifindex(index, nh_vrf_id);
if (nh) {
+ nh->weight = rtnh->rtnh_hops + 1;
+
if (num_labels)
nexthop_add_labels(nh, ZEBRA_LSP_STATIC,
num_labels, labels);
@@ -1419,6 +1421,9 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
"nexthop via if %u",
routedesc, nexthop->ifindex);
}
+
+ if (nexthop->weight)
+ rtnh->rtnh_hops = nexthop->weight - 1;
}
static inline void _netlink_mpls_build_singlepath(const char *routedesc,
@@ -1921,7 +1926,7 @@ static void _netlink_nexthop_build_group(struct nlmsghdr *n, size_t req_size,
if (count) {
for (int i = 0; i < count; i++) {
grp[i].id = z_grp[i].id;
- grp[i].weight = z_grp[i].weight;
+ grp[i].weight = z_grp[i].weight - 1;
if (IS_ZEBRA_DEBUG_KERNEL) {
if (i == 0)
@@ -2347,7 +2352,7 @@ static int netlink_nexthop_process_group(struct rtattr **tb,
for (int i = 0; ((i < count) && (i < z_grp_size)); i++) {
z_grp[i].id = n_grp[i].id;
- z_grp[i].weight = n_grp[i].weight;
+ z_grp[i].weight = n_grp[i].weight + 1;
}
return count;
}
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index e1654a1a3c..1dbe41f462 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -567,6 +567,7 @@ int zsend_redistribute_route(int cmd, struct zserv *client,
api_nh = &api.nexthops[count];
api_nh->vrf_id = nexthop->vrf_id;
api_nh->type = nexthop->type;
+ api_nh->weight = nexthop->weight;
switch (nexthop->type) {
case NEXTHOP_TYPE_BLACKHOLE:
api_nh->bh_type = nexthop->bh_type;
@@ -1544,6 +1545,9 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
+ if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_WEIGHT))
+ nexthop->weight = api_nh->weight;
+
/* MPLS labels for BGP-LU or Segment Routing */
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL)
&& api_nh->type != NEXTHOP_TYPE_IFINDEX
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index ca72ea5227..417c206467 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -2508,7 +2508,7 @@ enum zebra_dplane_result dplane_neigh_add(const struct interface *ifp,
enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
result = neigh_update_internal(DPLANE_OP_NEIGH_INSTALL,
- ifp, mac, ip, flags, 0);
+ ifp, mac, ip, flags, DPLANE_NUD_NOARP);
return result;
}
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index 1a70250627..9065a265ad 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -1790,7 +1790,7 @@ uint8_t zebra_nhg_nhe2grp(struct nh_grp *grp, struct nhg_hash_entry *nhe,
if (!duplicate) {
grp[i].id = depend->id;
/* We aren't using weights for anything right now */
- grp[i].weight = 0;
+ grp[i].weight = depend->nhg->nexthop->weight;
i++;
}
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index eca86d5fe2..78fd57a6bd 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -380,6 +380,9 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
sizeof buf, 1));
}
+ if (nexthop->weight)
+ vty_out(vty, ", weight %u", nexthop->weight);
+
vty_out(vty, "\n");
}
vty_out(vty, "\n");
@@ -1240,6 +1243,9 @@ static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe)
sizeof(buf), 1));
}
+ if (nexthop->weight)
+ vty_out(vty, ", weight %u", nexthop->weight);
+
vty_out(vty, "\n");
}