From: Petr Machata Date: Fri, 16 Aug 2024 17:38:12 +0000 (+0200) Subject: ip: nexthop: Support 16-bit nexthop weights X-Git-Tag: v6.12.0~18^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1fa8811c5048daaf32782b5a5e47194bee1f70fb;p=thirdparty%2Fiproute2.git ip: nexthop: Support 16-bit nexthop weights Two interlinked changes related to the nexthop group management have been recently merged in kernel commit e96f6fd30eec ("Merge branch 'net-nexthop-increase-weight-to-u16'"). - One of the reserved bytes in struct nexthop_grp was redefined to carry high-order bits of the nexthop weight, thus allowing 16-bit nexthop weights. - NHA_OP_FLAGS started getting dumped on nexthop group dump to carry a flag, NHA_OP_FLAG_RESP_GRP_RESVD_0, that indicates that reserved fields in struct nexthop_grp are zeroed before dumping. If NHA_OP_FLAG_RESP_GRP_RESVD_0 is given, it is safe to interpret the newly named nexthop_grp.weight_high as high-order bits of nexthop weight. Extend ipnexthop to support configuring nexthop weights of up to 65536, and when dumping, to interpret nexthop_grp.weight_high if safe. Signed-off-by: Petr Machata Signed-off-by: David Ahern --- diff --git a/ip/ipnexthop.c b/ip/ipnexthop.c index 91b731b0..d5c42936 100644 --- a/ip/ipnexthop.c +++ b/ip/ipnexthop.c @@ -234,6 +234,24 @@ static bool __valid_nh_group_attr(const struct rtattr *g_attr) return num && num * sizeof(struct nexthop_grp) == RTA_PAYLOAD(g_attr); } +static __u16 nhgrp_weight(__u32 resp_op_flags, + const struct nexthop_grp *nhgrp) +{ + __u16 weight = nhgrp->weight_high; + + if (!(resp_op_flags & NHA_OP_FLAG_RESP_GRP_RESVD_0)) + weight = 0; + + return ((weight << 8) | nhgrp->weight) + 1; +} + +static void nhgrp_set_weight(struct nexthop_grp *nhgrp, __u16 weight) +{ + weight--; + nhgrp->weight_high = weight >> 8; + nhgrp->weight = weight & 0xff; +} + static void print_nh_group(const struct nh_entry *nhe) { int i; @@ -247,9 +265,10 @@ static void print_nh_group(const struct nh_entry *nhe) print_string(PRINT_FP, NULL, "%s", "/"); print_uint(PRINT_ANY, "id", "%u", nhe->nh_groups[i].id); - if (nhe->nh_groups[i].weight) - print_uint(PRINT_ANY, "weight", ",%u", - nhe->nh_groups[i].weight + 1); + __u16 weight = nhgrp_weight(nhe->nh_resp_op_flags, + &nhe->nh_groups[i]); + if (weight > 1) + print_uint(PRINT_ANY, "weight", ",%u", weight); close_json_object(); } @@ -507,6 +526,9 @@ static int ipnh_parse_nhmsg(FILE *fp, const struct nhmsg *nhm, int len, parse_nh_group_stats_rta(tb[NHA_GROUP_STATS], nhe); } + nhe->nh_resp_op_flags = + tb[NHA_OP_FLAGS] ? rta_getattr_u32(tb[NHA_OP_FLAGS]) : 0; + nhe->nh_blackhole = !!tb[NHA_BLACKHOLE]; nhe->nh_fdb = !!tb[NHA_FDB]; @@ -904,9 +926,9 @@ static int add_nh_group_attr(struct nlmsghdr *n, int maxlen, char *argv) unsigned int w; wsep++; - if (get_unsigned(&w, wsep, 0) || w == 0 || w > 256) + if (get_unsigned(&w, wsep, 0) || w == 0 || w > 65536) invarg("\"weight\" is invalid\n", wsep); - grps[i].weight = w - 1; + nhgrp_set_weight(&grps[i], w); } if (!sep) diff --git a/ip/nh_common.h b/ip/nh_common.h index 33b1d847..afbd16b6 100644 --- a/ip/nh_common.h +++ b/ip/nh_common.h @@ -25,6 +25,7 @@ struct nh_entry { __u32 nh_id; __u32 nh_oif; __u32 nh_flags; + __u32 nh_resp_op_flags; __u16 nh_grp_type; __u8 nh_family; __u8 nh_scope;