]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
ip: support setting multiple features
authorStanislav Fomichev <stfomichev@gmail.com>
Tue, 27 May 2025 21:55:06 +0000 (14:55 -0700)
committerDavid Ahern <dsahern@kernel.org>
Thu, 29 May 2025 01:58:46 +0000 (01:58 +0000)
Commit a043bea75002 ("ip route: add support for TCP usec TS") added
support for tcp_usec_ts but the existing code was not adjusted
to handle multiple features in the same invocation:

$ ip route add .. dev .. features tcp_usec_ts ecn
Error: either "to" is duplicate, or "ecn" is garbage.

The code exits the while loop as soon as it encounters any feature,
make it more flexible. Tested with the following:

$ ip route add .. dev .. features tcp_usec_ts ecn
$ ip route add .. dev .. features tcp_usec_ts ecn quickack 1

Cc: Stephen Hemminger <stephen@networkplumber.org>
Fixes: a043bea75002 ("ip route: add support for TCP usec TS")
Signed-off-by: Stanislav Fomichev <stfomichev@gmail.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
ip/iproute.c

index 0e2c171f4b8e28875b81dd023ddc05a0c96c67ee..c2538894da633b56f5b926ecafda4960a48e9fbd 100644 (file)
@@ -1134,6 +1134,27 @@ static int parse_nexthops(struct nlmsghdr *n, struct rtmsg *r,
        return 0;
 }
 
+static unsigned int parse_features(int *argcp, char ***argvp)
+{
+       unsigned int features = 0;
+       char **argv = *argvp;
+       int argc = *argcp;
+
+       while (++argv, --argc > 0) {
+               if (strcmp(*argv, "ecn") == 0) {
+                       features |= RTAX_FEATURE_ECN;
+               } else if (strcmp(*argv, "tcp_usec_ts") == 0) {
+                       features |= RTAX_FEATURE_TCP_USEC_TS;
+               } else {
+                       break;
+               }
+       }
+
+       *argcp = argc;
+       *argvp = argv;
+       return features;
+}
+
 static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv)
 {
        struct {
@@ -1374,17 +1395,14 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv)
                } else if (matches(*argv, "features") == 0) {
                        unsigned int features = 0;
 
-                       while (argc > 0) {
-                               NEXT_ARG();
+                       features = parse_features(&argc, &argv);
+                       if (!features)
+                               invarg("\"features\" value not valid\n", *argv);
 
-                               if (strcmp(*argv, "ecn") == 0)
-                                       features |= RTAX_FEATURE_ECN;
-                               else if (strcmp(*argv, "tcp_usec_ts") == 0)
-                                       features |= RTAX_FEATURE_TCP_USEC_TS;
-                               else
-                                       invarg("\"features\" value not valid\n", *argv);
-                               break;
-                       }
+                       /* parse_features stops at the first feature it can't
+                        * parse, rewind one argument back.
+                        */
+                       PREV_ARG();
 
                        rta_addattr32(mxrta, sizeof(mxbuf),
                                      RTAX_FEATURES, features);