]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
ip: nexthop: Support 16-bit nexthop weights
authorPetr Machata <petrm@nvidia.com>
Fri, 16 Aug 2024 17:38:12 +0000 (19:38 +0200)
committerDavid Ahern <dsahern@kernel.org>
Mon, 19 Aug 2024 01:06:46 +0000 (01:06 +0000)
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>
Signed-off-by: David Ahern <dsahern@kernel.org>
ip/ipnexthop.c
ip/nh_common.h

index 91b731b05b367af71dee45b61ab5f4f00d9ac068..d5c429369d10f629823639fa7e6bfb70be5226d6 100644 (file)
@@ -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)
index 33b1d847466096cb23d14393f6d19beca9b78a83..afbd16b6759f17c768362f94532fb9f01b1b32a6 100644 (file)
@@ -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;