@@ -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)
@@ -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;
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 <petrm@nvidia.com> --- ip/ipnexthop.c | 32 +++++++++++++++++++++++++++----- ip/nh_common.h | 1 + 2 files changed, 28 insertions(+), 5 deletions(-)