mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-03 00:13:40 +00:00
Merge pull request #5497 from donaldsharp/unequality_ecmp
Unequality ecmp
This commit is contained in:
commit
c81c2303e6
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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++;
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user