diff options
| -rw-r--r-- | lib/nexthop.c | 7 | ||||
| -rw-r--r-- | lib/nexthop.h | 3 | ||||
| -rw-r--r-- | lib/nexthop_group.c | 55 | ||||
| -rw-r--r-- | lib/zclient.c | 15 | ||||
| -rw-r--r-- | lib/zclient.h | 3 | ||||
| -rw-r--r-- | pbrd/pbr_zebra.c | 1 | ||||
| -rw-r--r-- | sharpd/sharp_zebra.c | 2 | ||||
| -rw-r--r-- | zebra/rt_netlink.c | 9 | ||||
| -rw-r--r-- | zebra/zapi_msg.c | 4 | ||||
| -rw-r--r-- | zebra/zebra_nhg.c | 2 | ||||
| -rw-r--r-- | zebra/zebra_vty.c | 6 |
11 files changed, 84 insertions, 23 deletions
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(©->gate, &nexthop->gate, sizeof(nexthop->gate)); memcpy(©->src, &nexthop->src, sizeof(nexthop->src)); memcpy(©->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/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/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_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"); } |
