Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package iproute2 for openSUSE:Factory 
checked in at 2025-06-04 20:27:39
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/iproute2 (Old)
 and      /work/SRC/openSUSE:Factory/.iproute2.new.16005 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "iproute2"

Wed Jun  4 20:27:39 2025 rev:144 rq:1282068 version:6.15

Changes:
--------
--- /work/SRC/openSUSE:Factory/iproute2/iproute2.changes        2025-04-11 
16:44:38.985851867 +0200
+++ /work/SRC/openSUSE:Factory/.iproute2.new.16005/iproute2.changes     
2025-06-04 20:27:46.039028899 +0200
@@ -1,0 +2,9 @@
+Mon Jun  2 19:43:40 UTC 2025 - Jan Engelhardt <jeng...@inai.de>
+
+- Update to release 6.15
+  * tc_util: Add support for 64-bit hardware packets counter
+  * iprule: Allow specifying ports in hexadecimal notation
+  * iprule: Add port mask support
+  * iprule: Add DSCP mask support
+
+-------------------------------------------------------------------

Old:
----
  iproute2-6.14.0.tar.sign
  iproute2-6.14.0.tar.xz

New:
----
  iproute2-6.15.0.tar.sign
  iproute2-6.15.0.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ iproute2.spec ++++++
--- /var/tmp/diff_new_pack.Idz83t/_old  2025-06-04 20:27:46.583051439 +0200
+++ /var/tmp/diff_new_pack.Idz83t/_new  2025-06-04 20:27:46.583051439 +0200
@@ -18,7 +18,7 @@
 
 %define _buildshell /bin/bash
 Name:           iproute2
-Version:        6.14
+Version:        6.15
 Release:        0
 Summary:        Linux network configuration utilities
 License:        GPL-2.0-only

++++++ _scmsync.obsinfo ++++++
--- /var/tmp/diff_new_pack.Idz83t/_old  2025-06-04 20:27:46.619052930 +0200
+++ /var/tmp/diff_new_pack.Idz83t/_new  2025-06-04 20:27:46.623053096 +0200
@@ -1,5 +1,5 @@
-mtime: 1744289064
-commit: ebba5448a66f5f0ac2924da0a02ed3abf57d40084fb580ff579df97919605695
+mtime: 1748895681
+commit: 03129c9707574e53f40178615f73c53a957180214f0ab7647c9faff5d0acc031
 url: https://src.opensuse.org/jengelh/iproute2
 revision: master
 

++++++ build.specials.obscpio ++++++

++++++ iproute2-6.14.0.tar.xz -> iproute2-6.15.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/MAINTAINERS 
new/iproute2-6.15.0/MAINTAINERS
--- old/iproute2-6.14.0/MAINTAINERS     2025-03-24 17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/MAINTAINERS     2025-05-26 17:19:09.000000000 +0200
@@ -26,7 +26,7 @@
 L: net...@vger.kernel.org
 
 Ethernet Bridging - bridge
-M: Roopa Prabhu <ro...@nvidia.com>
+M: Ido Schimmel <ido...@nvidia.com>
 M: Nikolay Aleksandrov <ra...@blackwall.org>
 L: bri...@lists.linux-foundation.org (moderated for non-subscribers)
 F: bridge/*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/bridge/bridge.c 
new/iproute2-6.15.0/bridge/bridge.c
--- old/iproute2-6.14.0/bridge/bridge.c 2025-03-24 17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/bridge/bridge.c 2025-05-26 17:19:09.000000000 +0200
@@ -103,7 +103,7 @@
 int
 main(int argc, char **argv)
 {
-       int color = CONF_COLOR;
+       int color = default_color_opt();
 
        while (argc > 1) {
                const char *opt = argv[1];
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/etc/iproute2/rt_protos 
new/iproute2-6.15.0/etc/iproute2/rt_protos
--- old/iproute2-6.14.0/etc/iproute2/rt_protos  2025-03-24 17:04:44.000000000 
+0100
+++ new/iproute2-6.15.0/etc/iproute2/rt_protos  2025-05-26 17:19:09.000000000 
+0200
@@ -17,6 +17,7 @@
 16     dhcp
 18     keepalived
 42     babel
+84     ovn
 99     openr
 186    bgp
 187    isis
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/include/color.h 
new/iproute2-6.15.0/include/color.h
--- old/iproute2-6.14.0/include/color.h 2025-03-24 17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/include/color.h 2025-05-26 17:19:09.000000000 +0200
@@ -20,6 +20,7 @@
        COLOR_OPT_ALWAYS = 2
 };
 
+int default_color_opt(void);
 bool check_enable_color(int color, int json);
 bool matches_color(const char *arg, int *val);
 int color_fprintf(FILE *fp, enum color_attr attr, const char *fmt, ...);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/include/uapi/linux/batman_adv.h 
new/iproute2-6.15.0/include/uapi/linux/batman_adv.h
--- old/iproute2-6.14.0/include/uapi/linux/batman_adv.h 2025-03-24 
17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/include/uapi/linux/batman_adv.h 2025-05-26 
17:19:09.000000000 +0200
@@ -342,7 +342,7 @@
        BATADV_ATTR_MCAST_FLAGS_PRIV,
 
        /**
-        * @BATADV_ATTR_VLANID: VLAN id on top of soft interface
+        * @BATADV_ATTR_VLANID: VLAN id on top of mesh interface
         */
        BATADV_ATTR_VLANID,
 
@@ -380,7 +380,7 @@
        /**
         * @BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED: whether the bridge loop
         *  avoidance feature is enabled. This feature detects and avoids loops
-        *  between the mesh and devices bridged with the soft interface
+        *  between the mesh and devices bridged with the mesh interface
         */
        BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED,
 
@@ -509,7 +509,7 @@
        BATADV_CMD_UNSPEC,
 
        /**
-        * @BATADV_CMD_GET_MESH: Get attributes from softif/mesh
+        * @BATADV_CMD_GET_MESH: Get attributes from mesh(if)
         */
        BATADV_CMD_GET_MESH,
 
@@ -535,7 +535,7 @@
 
        /**
         * @BATADV_CMD_GET_HARDIF: Get attributes from a hardif of the
-        *  current softif
+        *  current mesh(if)
         */
        BATADV_CMD_GET_HARDIF,
 
@@ -591,25 +591,25 @@
        BATADV_CMD_GET_MCAST_FLAGS,
 
        /**
-        * @BATADV_CMD_SET_MESH: Set attributes for softif/mesh
+        * @BATADV_CMD_SET_MESH: Set attributes for mesh(if)
         */
        BATADV_CMD_SET_MESH,
 
        /**
         * @BATADV_CMD_SET_HARDIF: Set attributes for hardif of the
-        *  current softif
+        *  current mesh(if)
         */
        BATADV_CMD_SET_HARDIF,
 
        /**
         * @BATADV_CMD_GET_VLAN: Get attributes from a VLAN of the
-        *  current softif
+        *  current mesh(if)
         */
        BATADV_CMD_GET_VLAN,
 
        /**
         * @BATADV_CMD_SET_VLAN: Set attributes for VLAN of the
-        *  current softif
+        *  current mesh(if)
         */
        BATADV_CMD_SET_VLAN,
 
@@ -691,7 +691,7 @@
         */
        IFLA_BATADV_ALGO_NAME,
 
-       /* add attributes above here, update the policy in soft-interface.c */
+       /* add attributes above here, update the policy in mesh-interface.c */
 
        /**
         * @__IFLA_BATADV_MAX: internal use
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/include/uapi/linux/bpf.h 
new/iproute2-6.15.0/include/uapi/linux/bpf.h
--- old/iproute2-6.14.0/include/uapi/linux/bpf.h        2025-03-24 
17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/include/uapi/linux/bpf.h        2025-05-26 
17:19:09.000000000 +0200
@@ -51,6 +51,9 @@
 #define BPF_XCHG       (0xe0 | BPF_FETCH)      /* atomic exchange */
 #define BPF_CMPXCHG    (0xf0 | BPF_FETCH)      /* atomic compare-and-write */
 
+#define BPF_LOAD_ACQ   0x100   /* load-acquire */
+#define BPF_STORE_REL  0x110   /* store-release */
+
 enum bpf_cond_pseudo_jmp {
        BPF_MAY_GOTO = 0,
 };
@@ -1207,6 +1210,7 @@
 #define BPF_F_BEFORE           (1U << 3)
 #define BPF_F_AFTER            (1U << 4)
 #define BPF_F_ID               (1U << 5)
+#define BPF_F_PREORDER         (1U << 6)
 #define BPF_F_LINK             BPF_F_LINK /* 1 << 13 */
 
 /* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the
@@ -1648,6 +1652,7 @@
                };
                __u32           next_id;
                __u32           open_flags;
+               __s32           fd_by_id_token_fd;
        };
 
        struct { /* anonymous struct used by BPF_OBJ_GET_INFO_BY_FD */
@@ -4963,6 +4968,9 @@
  *             the netns switch takes place from ingress to ingress without
  *             going through the CPU's backlog queue.
  *
+ *             *skb*\ **->mark** and *skb*\ **->tstamp** are not cleared during
+ *             the netns switch.
+ *
  *             The *flags* argument is reserved and must be 0. The helper is
  *             currently only supported for tc BPF program types at the
  *             ingress hook and for veth and netkit target device types. The
@@ -6019,7 +6027,10 @@
        FN(user_ringbuf_drain, 209, ##ctx)              \
        FN(cgrp_storage_get, 210, ##ctx)                \
        FN(cgrp_storage_delete, 211, ##ctx)             \
-       /* */
+       /* This helper list is effectively frozen. If you are trying to \
+        * add a new helper, you should add a kfunc instead which has   \
+        * less stability guarantees. See Documentation/bpf/kfuncs.rst  \
+        */
 
 /* backwards-compatibility macros for users of __BPF_FUNC_MAPPER that don't
  * know or care about integer value that is now passed as second argument
@@ -6913,6 +6924,12 @@
        BPF_SOCK_OPS_ALL_CB_FLAGS       = 0x7F,
 };
 
+enum {
+       SK_BPF_CB_TX_TIMESTAMPING       = 1<<0,
+       SK_BPF_CB_MASK                  = (SK_BPF_CB_TX_TIMESTAMPING - 1) |
+                                          SK_BPF_CB_TX_TIMESTAMPING
+};
+
 /* List of known BPF sock_ops operators.
  * New entries can only be added at the end
  */
@@ -7025,6 +7042,29 @@
                                         * by the kernel or the
                                         * earlier bpf-progs.
                                         */
+       BPF_SOCK_OPS_TSTAMP_SCHED_CB,   /* Called when skb is passing
+                                        * through dev layer when
+                                        * SK_BPF_CB_TX_TIMESTAMPING
+                                        * feature is on.
+                                        */
+       BPF_SOCK_OPS_TSTAMP_SND_SW_CB,  /* Called when skb is about to send
+                                        * to the nic when 
SK_BPF_CB_TX_TIMESTAMPING
+                                        * feature is on.
+                                        */
+       BPF_SOCK_OPS_TSTAMP_SND_HW_CB,  /* Called in hardware phase when
+                                        * SK_BPF_CB_TX_TIMESTAMPING feature
+                                        * is on.
+                                        */
+       BPF_SOCK_OPS_TSTAMP_ACK_CB,     /* Called when all the skbs in the
+                                        * same sendmsg call are acked
+                                        * when SK_BPF_CB_TX_TIMESTAMPING
+                                        * feature is on.
+                                        */
+       BPF_SOCK_OPS_TSTAMP_SENDMSG_CB, /* Called when every sendmsg syscall
+                                        * is triggered. It's used to correlate
+                                        * sendmsg timestamp with corresponding
+                                        * tskey.
+                                        */
 };
 
 /* List of TCP states. There is a build check in net/ipv4/tcp.c to detect
@@ -7091,6 +7131,7 @@
        TCP_BPF_SYN_IP          = 1006, /* Copy the IP[46] and TCP header */
        TCP_BPF_SYN_MAC         = 1007, /* Copy the MAC, IP[46], and TCP header 
*/
        TCP_BPF_SOCK_OPS_CB_FLAGS = 1008, /* Get or Set TCP sock ops flags */
+       SK_BPF_CB_FLAGS         = 1009, /* Get or set sock ops flags in socket 
*/
 };
 
 enum {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/include/uapi/linux/btf.h 
new/iproute2-6.15.0/include/uapi/linux/btf.h
--- old/iproute2-6.14.0/include/uapi/linux/btf.h        2025-03-24 
17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/include/uapi/linux/btf.h        2025-05-26 
17:19:09.000000000 +0200
@@ -36,7 +36,8 @@
         * bits 24-28: kind (e.g. int, ptr, array...etc)
         * bits 29-30: unused
         * bit     31: kind_flag, currently used by
-        *             struct, union, enum, fwd and enum64
+        *             struct, union, enum, fwd, enum64,
+        *             decl_tag and type_tag
         */
        __u32 info;
        /* "size" is used by INT, ENUM, STRUCT, UNION, DATASEC and ENUM64.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/include/uapi/linux/can.h 
new/iproute2-6.15.0/include/uapi/linux/can.h
--- old/iproute2-6.14.0/include/uapi/linux/can.h        2025-03-24 
17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/include/uapi/linux/can.h        2025-05-26 
17:19:09.000000000 +0200
@@ -182,7 +182,7 @@
 /*
  * defined bits for canxl_frame.flags
  *
- * The canxl_frame.flags element contains two bits CANXL_XLF and CANXL_SEC
+ * The canxl_frame.flags element contains three bits CANXL_[XLF|SEC|RRS]
  * and shares the relative position of the struct can[fd]_frame.len element.
  * The CANXL_XLF bit ALWAYS needs to be set to indicate a valid CAN XL frame.
  * As a side effect setting this bit intentionally breaks the length checks
@@ -192,6 +192,7 @@
  */
 #define CANXL_XLF 0x80 /* mandatory CAN XL frame flag (must always be set!) */
 #define CANXL_SEC 0x01 /* Simple Extended Content (security/segmentation) */
+#define CANXL_RRS 0x02 /* Remote Request Substitution */
 
 /* the 8-bit VCID is optionally placed in the canxl_frame.prio element */
 #define CANXL_VCID_OFFSET 16 /* bit offset of VCID in prio element */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/include/uapi/linux/capability.h 
new/iproute2-6.15.0/include/uapi/linux/capability.h
--- old/iproute2-6.14.0/include/uapi/linux/capability.h 2025-03-24 
17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/include/uapi/linux/capability.h 2025-05-26 
17:19:09.000000000 +0200
@@ -273,6 +273,7 @@
 /* Allow setting encryption key on loopback filesystem */
 /* Allow setting zone reclaim policy */
 /* Allow everything under CAP_BPF and CAP_PERFMON for backward compatibility */
+/* Allow setting hardware protection emergency action */
 
 #define CAP_SYS_ADMIN        21
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/include/uapi/linux/const.h 
new/iproute2-6.15.0/include/uapi/linux/const.h
--- old/iproute2-6.14.0/include/uapi/linux/const.h      2025-03-24 
17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/include/uapi/linux/const.h      2025-05-26 
17:19:09.000000000 +0200
@@ -33,7 +33,7 @@
  * Missing __asm__ support
  *
  * __BIT128() would not work in the __asm__ code, as it shifts an
- * 'unsigned __init128' data type as direct representation of
+ * 'unsigned __int128' data type as direct representation of
  * 128 bit constants is not supported in the gcc compiler, as
  * they get silently truncated.
  *
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/include/uapi/linux/fib_rules.h 
new/iproute2-6.15.0/include/uapi/linux/fib_rules.h
--- old/iproute2-6.14.0/include/uapi/linux/fib_rules.h  2025-03-24 
17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/include/uapi/linux/fib_rules.h  2025-05-26 
17:19:09.000000000 +0200
@@ -70,6 +70,9 @@
        FRA_DSCP,       /* dscp */
        FRA_FLOWLABEL,  /* flowlabel */
        FRA_FLOWLABEL_MASK,     /* flowlabel mask */
+       FRA_SPORT_MASK, /* sport mask */
+       FRA_DPORT_MASK, /* dport mask */
+       FRA_DSCP_MASK,  /* dscp mask */
        __FRA_MAX
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/include/uapi/linux/if_link.h 
new/iproute2-6.15.0/include/uapi/linux/if_link.h
--- old/iproute2-6.14.0/include/uapi/linux/if_link.h    2025-03-24 
17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/include/uapi/linux/if_link.h    2025-05-26 
17:19:09.000000000 +0200
@@ -378,6 +378,7 @@
        IFLA_GRO_IPV4_MAX_SIZE,
        IFLA_DPLL_PIN,
        IFLA_MAX_PACING_OFFLOAD_HORIZON,
+       IFLA_NETNS_IMMUTABLE,
        __IFLA_MAX
 };
 
@@ -1436,6 +1437,7 @@
        IFLA_GENEVE_TTL_INHERIT,
        IFLA_GENEVE_DF,
        IFLA_GENEVE_INNER_PROTO_INHERIT,
+       IFLA_GENEVE_PORT_RANGE,
        __IFLA_GENEVE_MAX
 };
 #define IFLA_GENEVE_MAX        (__IFLA_GENEVE_MAX - 1)
@@ -1448,6 +1450,11 @@
        GENEVE_DF_MAX = __GENEVE_DF_END - 1,
 };
 
+struct ifla_geneve_port_range {
+       __be16 low;
+       __be16 high;
+};
+
 /* Bareudp section  */
 enum {
        IFLA_BAREUDP_UNSPEC,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/include/uapi/linux/rtnetlink.h 
new/iproute2-6.15.0/include/uapi/linux/rtnetlink.h
--- old/iproute2-6.14.0/include/uapi/linux/rtnetlink.h  2025-03-24 
17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/include/uapi/linux/rtnetlink.h  2025-05-26 
17:19:09.000000000 +0200
@@ -307,6 +307,7 @@
 #define RTPROT_MROUTED         17      /* Multicast daemon */
 #define RTPROT_KEEPALIVED      18      /* Keepalived daemon */
 #define RTPROT_BABEL           42      /* Babel daemon */
+#define RTPROT_OVN             84      /* OVN daemon */
 #define RTPROT_OPENR           99      /* Open Routing (Open/R) Routes */
 #define RTPROT_BGP             186     /* BGP Routes */
 #define RTPROT_ISIS            187     /* ISIS Routes */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/include/uapi/linux/snmp.h 
new/iproute2-6.15.0/include/uapi/linux/snmp.h
--- old/iproute2-6.14.0/include/uapi/linux/snmp.h       2025-03-24 
17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/include/uapi/linux/snmp.h       2025-05-26 
17:19:09.000000000 +0200
@@ -23,9 +23,14 @@
        IPSTATS_MIB_INPKTS,                     /* InReceives */
        IPSTATS_MIB_INOCTETS,                   /* InOctets */
        IPSTATS_MIB_INDELIVERS,                 /* InDelivers */
-       IPSTATS_MIB_OUTFORWDATAGRAMS,           /* OutForwDatagrams */
+       IPSTATS_MIB_NOECTPKTS,                  /* InNoECTPkts */
+       IPSTATS_MIB_ECT1PKTS,                   /* InECT1Pkts */
+       IPSTATS_MIB_ECT0PKTS,                   /* InECT0Pkts */
+       IPSTATS_MIB_CEPKTS,                     /* InCEPkts */
        IPSTATS_MIB_OUTREQUESTS,                /* OutRequests */
+       IPSTATS_MIB_OUTPKTS,                    /* OutTransmits */
        IPSTATS_MIB_OUTOCTETS,                  /* OutOctets */
+       IPSTATS_MIB_OUTFORWDATAGRAMS,           /* OutForwDatagrams */
 /* other fields */
        IPSTATS_MIB_INHDRERRORS,                /* InHdrErrors */
        IPSTATS_MIB_INTOOBIGERRORS,             /* InTooBigErrors */
@@ -52,12 +57,7 @@
        IPSTATS_MIB_INBCASTOCTETS,              /* InBcastOctets */
        IPSTATS_MIB_OUTBCASTOCTETS,             /* OutBcastOctets */
        IPSTATS_MIB_CSUMERRORS,                 /* InCsumErrors */
-       IPSTATS_MIB_NOECTPKTS,                  /* InNoECTPkts */
-       IPSTATS_MIB_ECT1PKTS,                   /* InECT1Pkts */
-       IPSTATS_MIB_ECT0PKTS,                   /* InECT0Pkts */
-       IPSTATS_MIB_CEPKTS,                     /* InCEPkts */
        IPSTATS_MIB_REASM_OVERLAPS,             /* ReasmOverlaps */
-       IPSTATS_MIB_OUTPKTS,                    /* OutTransmits */
        __IPSTATS_MIB_MAX
 };
 
@@ -186,6 +186,7 @@
        LINUX_MIB_TIMEWAITKILLED,               /* TimeWaitKilled */
        LINUX_MIB_PAWSACTIVEREJECTED,           /* PAWSActiveRejected */
        LINUX_MIB_PAWSESTABREJECTED,            /* PAWSEstabRejected */
+       LINUX_MIB_TSECRREJECTED,                /* TSEcrRejected */
        LINUX_MIB_PAWS_OLD_ACK,                 /* PAWSOldAck */
        LINUX_MIB_DELAYEDACKS,                  /* DelayedACKs */
        LINUX_MIB_DELAYEDACKLOCKED,             /* DelayedACKLocked */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/include/uapi/linux/stddef.h 
new/iproute2-6.15.0/include/uapi/linux/stddef.h
--- old/iproute2-6.14.0/include/uapi/linux/stddef.h     2025-03-24 
17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/include/uapi/linux/stddef.h     2025-05-26 
17:19:09.000000000 +0200
@@ -70,4 +70,6 @@
 #define __counted_by_be(m)
 #endif
 
+#define __kernel_nonstring
+
 #endif /* _LINUX_STDDEF_H */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/include/uapi/linux/tcp.h 
new/iproute2-6.15.0/include/uapi/linux/tcp.h
--- old/iproute2-6.14.0/include/uapi/linux/tcp.h        2025-03-24 
17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/include/uapi/linux/tcp.h        2025-05-26 
17:19:09.000000000 +0200
@@ -28,7 +28,8 @@
        __be32  seq;
        __be32  ack_seq;
 #if defined(__LITTLE_ENDIAN_BITFIELD)
-       __u16   res1:4,
+       __u16   ae:1,
+               res1:3,
                doff:4,
                fin:1,
                syn:1,
@@ -40,7 +41,8 @@
                cwr:1;
 #elif defined(__BIG_ENDIAN_BITFIELD)
        __u16   doff:4,
-               res1:4,
+               res1:3,
+               ae:1,
                cwr:1,
                ece:1,
                urg:1,
@@ -70,6 +72,7 @@
 #define tcp_flag_word(tp) (((union tcp_word_hdr *)(tp))->words[3])
 
 enum {
+       TCP_FLAG_AE  = __constant_cpu_to_be32(0x01000000),
        TCP_FLAG_CWR = __constant_cpu_to_be32(0x00800000),
        TCP_FLAG_ECE = __constant_cpu_to_be32(0x00400000),
        TCP_FLAG_URG = __constant_cpu_to_be32(0x00200000),
@@ -78,7 +81,7 @@
        TCP_FLAG_RST = __constant_cpu_to_be32(0x00040000),
        TCP_FLAG_SYN = __constant_cpu_to_be32(0x00020000),
        TCP_FLAG_FIN = __constant_cpu_to_be32(0x00010000),
-       TCP_RESERVED_BITS = __constant_cpu_to_be32(0x0F000000),
+       TCP_RESERVED_BITS = __constant_cpu_to_be32(0x0E000000),
        TCP_DATA_OFFSET = __constant_cpu_to_be32(0xF0000000)
 };
 
@@ -136,6 +139,9 @@
 #define TCP_AO_REPAIR          42      /* Get/Set SNEs and ISNs */
 
 #define TCP_IS_MPTCP           43      /* Is MPTCP being used? */
+#define TCP_RTO_MAX_MS         44      /* max rto time in ms */
+#define TCP_RTO_MIN_US         45      /* min rto time in us */
+#define TCP_DELACK_MAX_US      46      /* max delayed ack time in us */
 
 #define TCP_REPAIR_ON          1
 #define TCP_REPAIR_OFF         0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/include/uapi/linux/virtio_net.h 
new/iproute2-6.15.0/include/uapi/linux/virtio_net.h
--- old/iproute2-6.14.0/include/uapi/linux/virtio_net.h 2025-03-24 
17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/include/uapi/linux/virtio_net.h 2025-05-26 
17:19:09.000000000 +0200
@@ -327,6 +327,19 @@
        __u8 hash_key_data[/* hash_key_length */];
 };
 
+struct virtio_net_rss_config_hdr {
+       __le32 hash_types;
+       __le16 indirection_table_mask;
+       __le16 unclassified_queue;
+       __le16 indirection_table[/* 1 + indirection_table_mask */];
+};
+
+struct virtio_net_rss_config_trailer {
+       __le16 max_tx_vq;
+       __u8 hash_key_length;
+       __u8 hash_key_data[/* hash_key_length */];
+};
+
  #define VIRTIO_NET_CTRL_MQ_RSS_CONFIG          1
 
 /*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/include/version.h 
new/iproute2-6.15.0/include/version.h
--- old/iproute2-6.14.0/include/version.h       2025-03-24 17:04:44.000000000 
+0100
+++ new/iproute2-6.15.0/include/version.h       2025-05-26 17:19:09.000000000 
+0200
@@ -1 +1 @@
-static const char version[] = "6.14.0";
+static const char version[] = "6.15.0";
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/ip/ila_common.h 
new/iproute2-6.15.0/ip/ila_common.h
--- old/iproute2-6.14.0/ip/ila_common.h 2025-03-24 17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/ip/ila_common.h 2025-05-26 17:19:09.000000000 +0200
@@ -31,8 +31,6 @@
                return ILA_CSUM_NEUTRAL_MAP_AUTO;
        else if (strcmp(name, "no-action") == 0)
                return ILA_CSUM_NO_ACTION;
-       else if (strcmp(name, "neutral-map-auto") == 0)
-               return ILA_CSUM_NEUTRAL_MAP_AUTO;
        else
                return -1;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/ip/ip.c new/iproute2-6.15.0/ip/ip.c
--- old/iproute2-6.14.0/ip/ip.c 2025-03-24 17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/ip/ip.c 2025-05-26 17:19:09.000000000 +0200
@@ -166,7 +166,7 @@
        const char *libbpf_version;
        char *batch_file = NULL;
        char *basename;
-       int color = CONF_COLOR;
+       int color = default_color_opt();
 
        /* to run vrf exec without root, capabilities might be set, drop them
         * if not needed as the first thing.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/ip/iplink_netkit.c 
new/iproute2-6.15.0/ip/iplink_netkit.c
--- old/iproute2-6.14.0/ip/iplink_netkit.c      2025-03-24 17:04:44.000000000 
+0100
+++ new/iproute2-6.15.0/ip/iplink_netkit.c      2025-05-26 17:19:09.000000000 
+0200
@@ -24,13 +24,19 @@
        [NETKIT_DROP]           = "blackhole",
 };
 
+static const char * const netkit_scrub_strings[] = {
+       [NETKIT_SCRUB_NONE]     = "none",
+       [NETKIT_SCRUB_DEFAULT]  = "default",
+};
+
 static void explain(struct link_util *lu, FILE *f)
 {
        fprintf(f,
-               "Usage: ... %s [ mode MODE ] [ POLICY ] [ peer [ POLICY 
<options> ] ]\n"
+               "Usage: ... %s [ mode MODE ] [ POLICY ] [ scrub SCRUB ] [ peer 
[ POLICY <options> ] ]\n"
                "\n"
                "MODE: l3 | l2\n"
                "POLICY: forward | blackhole\n"
+               "SCRUB: default | none\n"
                "(first values are the defaults if nothing is specified)\n"
                "\n"
                "To get <options> type 'ip link add help'.\n",
@@ -91,6 +97,23 @@
                        if (seen_peer)
                                duparg("peer", *(argv + 1));
                        seen_peer = true;
+               } else if (strcmp(*argv, "scrub") == 0) {
+                       int attr_name = seen_peer ?
+                                       IFLA_NETKIT_PEER_SCRUB :
+                                       IFLA_NETKIT_SCRUB;
+                       enum netkit_scrub scrub;
+
+                       NEXT_ARG();
+
+                       if (strcmp(*argv, "none") == 0) {
+                               scrub = NETKIT_SCRUB_NONE;
+                       } else if (strcmp(*argv, "default") == 0) {
+                               scrub = NETKIT_SCRUB_DEFAULT;
+                       } else {
+                               fprintf(stderr, "Error: scrub must be either 
\"none\" or \"default\"\n");
+                               return -1;
+                       }
+                       addattr32(n, 1024, attr_name, scrub);
                } else {
                        char *type = NULL;
 
@@ -144,6 +167,15 @@
        return netkit_mode_strings[mode] ? : inv;
 }
 
+static const char *netkit_print_scrub(enum netkit_scrub scrub)
+{
+       const char *inv = "UNKNOWN";
+
+       if (scrub >= ARRAY_SIZE(netkit_scrub_strings))
+               return inv;
+       return netkit_scrub_strings[scrub] ? : inv;
+}
+
 static void netkit_print_opt(struct link_util *lu, FILE *f, struct rtattr 
*tb[])
 {
        if (!tb)
@@ -172,6 +204,18 @@
                print_string(PRINT_ANY, "peer_policy", "peer policy %s ",
                             netkit_print_policy(policy));
        }
+       if (tb[IFLA_NETKIT_SCRUB]) {
+               enum netkit_scrub scrub = 
rta_getattr_u32(tb[IFLA_NETKIT_SCRUB]);
+
+               print_string(PRINT_ANY, "scrub", "scrub %s ",
+                            netkit_print_scrub(scrub));
+       }
+       if (tb[IFLA_NETKIT_PEER_SCRUB]) {
+               enum netkit_scrub scrub = 
rta_getattr_u32(tb[IFLA_NETKIT_PEER_SCRUB]);
+
+               print_string(PRINT_ANY, "peer_scrub", "peer scrub %s ",
+                            netkit_print_scrub(scrub));
+       }
 }
 
 static void netkit_print_help(struct link_util *lu,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/ip/ipmonitor.c 
new/iproute2-6.15.0/ip/ipmonitor.c
--- old/iproute2-6.14.0/ip/ipmonitor.c  2025-03-24 17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/ip/ipmonitor.c  2025-05-26 17:19:09.000000000 +0200
@@ -5,6 +5,7 @@
  * Authors:    Alexey Kuznetsov, <kuz...@ms2.inr.ac.ru>
  */
 
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -328,38 +329,46 @@
 
        if (lmask & IPMON_LNEXTHOP &&
            rtnl_add_nl_group(&rth, RTNLGRP_NEXTHOP) < 0) {
-               fprintf(stderr, "Failed to add nexthop group to list\n");
-               exit(1);
+               if (errno != EINVAL) {
+                       fprintf(stderr, "Failed to add nexthop group to 
list\n");
+                       exit(1);
+               }
        }
 
        if (lmask & IPMON_LSTATS &&
            rtnl_add_nl_group(&rth, RTNLGRP_STATS) < 0 &&
            nmask & IPMON_LSTATS) {
-               fprintf(stderr, "Failed to add stats group to list\n");
-               exit(1);
+               if (errno != EINVAL) {
+                       fprintf(stderr, "Failed to add stats group to list\n");
+                       exit(1);
+               }
        }
 
        if (lmask & IPMON_LMADDR) {
                if ((!preferred_family || preferred_family == AF_INET) &&
                    rtnl_add_nl_group(&rth, RTNLGRP_IPV4_MCADDR) < 0) {
-                       fprintf(stderr,
-                               "Failed to add ipv4 mcaddr group to list\n");
-                       exit(1);
+                       if (errno != EINVAL) {
+                               fprintf(stderr, "Failed to add ipv4 mcaddr 
group to list\n");
+                               exit(1);
+                       }
                }
                if ((!preferred_family || preferred_family == AF_INET6) &&
                    rtnl_add_nl_group(&rth, RTNLGRP_IPV6_MCADDR) < 0) {
-                       fprintf(stderr,
-                               "Failed to add ipv6 mcaddr group to list\n");
-                       exit(1);
+                       if (errno != EINVAL) {
+                               fprintf(stderr,
+                                       "Failed to add ipv6 mcaddr group to 
list\n");
+                               exit(1);
+                       }
                }
        }
 
        if (lmask & IPMON_LACADDR) {
                if ((!preferred_family || preferred_family == AF_INET6) &&
                    rtnl_add_nl_group(&rth, RTNLGRP_IPV6_ACADDR) < 0) {
-                       fprintf(stderr,
-                               "Failed to add ipv6 acaddr group to list\n");
-                       exit(1);
+                       if (errno != EINVAL) {
+                               fprintf(stderr, "Failed to add ipv6 acaddr 
group to list\n");
+                               exit(1);
+                       }
                }
        }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/ip/iproute.c 
new/iproute2-6.15.0/ip/iproute.c
--- old/iproute2-6.14.0/ip/iproute.c    2025-03-24 17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/ip/iproute.c    2025-05-26 17:19:09.000000000 +0200
@@ -1729,7 +1729,10 @@
 
        if (filter.cloned) {
                if (family != AF_INET6) {
-                       iproute_flush_cache();
+                       ret = iproute_flush_cache();
+                       if (ret < 0)
+                               return ret;
+
                        if (show_stats)
                                printf("*** IPv4 routing cache is flushed.\n");
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/ip/iprule.c 
new/iproute2-6.15.0/ip/iprule.c
--- old/iproute2-6.14.0/ip/iprule.c     2025-03-24 17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/ip/iprule.c     2025-05-26 17:19:09.000000000 +0200
@@ -23,6 +23,9 @@
 #include "ip_common.h"
 #include "json_print.h"
 
+#define PORT_MAX_MASK 0xFFFF
+#define DSCP_MAX_MASK 0x3F
+
 enum list_action {
        IPRULE_LIST,
        IPRULE_FLUSH,
@@ -44,9 +47,9 @@
                "            [ iif STRING ] [ oif STRING ] [ pref NUMBER ] [ 
l3mdev ]\n"
                "            [ uidrange NUMBER-NUMBER ]\n"
                "            [ ipproto PROTOCOL ]\n"
-               "            [ sport [ NUMBER | NUMBER-NUMBER ]\n"
-               "            [ dport [ NUMBER | NUMBER-NUMBER ] ]\n"
-               "            [ dscp DSCP ] [ flowlabel FLOWLABEL[/MASK] ]\n"
+               "            [ sport [ NUMBER[/MASK] | NUMBER-NUMBER ]\n"
+               "            [ dport [ NUMBER[/MASK] | NUMBER-NUMBER ] ]\n"
+               "            [ dscp DSCP[/MASK] ] [ flowlabel FLOWLABEL[/MASK] 
]\n"
                "ACTION := [ table TABLE_ID ]\n"
                "          [ protocol PROTO ]\n"
                "          [ nat ADDRESS ]\n"
@@ -80,6 +83,7 @@
        int protocolmask;
        struct fib_rule_port_range sport;
        struct fib_rule_port_range dport;
+       __u16 sport_mask, dport_mask;
        __u8 ipproto;
 } filter;
 
@@ -186,8 +190,9 @@
                        return false;
        }
 
-       if (filter.sport.start) {
+       if (filter.sport_mask) {
                const struct fib_rule_port_range *r;
+               __u16 sport_mask = PORT_MAX_MASK;
 
                if (!tb[FRA_SPORT_RANGE])
                        return false;
@@ -196,10 +201,16 @@
                if (r->start != filter.sport.start ||
                    r->end != filter.sport.end)
                        return false;
+
+               if (tb[FRA_SPORT_MASK])
+                       sport_mask = rta_getattr_u16(tb[FRA_SPORT_MASK]);
+               if (filter.sport_mask != sport_mask)
+                       return false;
        }
 
-       if (filter.dport.start) {
+       if (filter.dport_mask) {
                const struct fib_rule_port_range *r;
+               __u16 dport_mask = PORT_MAX_MASK;
 
                if (!tb[FRA_DPORT_RANGE])
                        return false;
@@ -208,6 +219,11 @@
                if (r->start != filter.dport.start ||
                    r->end != filter.dport.end)
                        return false;
+
+               if (tb[FRA_DPORT_MASK])
+                       dport_mask = rta_getattr_u16(tb[FRA_DPORT_MASK]);
+               if (filter.dport_mask != dport_mask)
+                       return false;
        }
 
        if (filter.tun_id) {
@@ -223,14 +239,21 @@
        }
 
        if (filter.dscpmask) {
-               if (tb[FRA_DSCP]) {
-                       __u8 dscp = rta_getattr_u8(tb[FRA_DSCP]);
+               __u8 dscp_mask = DSCP_MAX_MASK;
+               __u8 dscp;
 
-                       if (filter.dscp != dscp)
-                               return false;
-               } else {
+               if (!tb[FRA_DSCP])
+                       return false;
+
+               dscp = rta_getattr_u8(tb[FRA_DSCP]);
+               if (filter.dscp != dscp)
+                       return false;
+
+               if (tb[FRA_DSCP_MASK])
+                       dscp_mask = rta_getattr_u8(tb[FRA_DSCP_MASK]);
+
+               if (filter.dscpmask != dscp_mask)
                        return false;
-               }
        }
 
        if (filter.flowlabel_mask) {
@@ -390,7 +413,26 @@
                struct fib_rule_port_range *r = RTA_DATA(tb[FRA_SPORT_RANGE]);
 
                if (r->start == r->end) {
-                       print_uint(PRINT_ANY, "sport", " sport %u", r->start);
+                       if (tb[FRA_SPORT_MASK]) {
+                               __u16 mask;
+
+                               mask = rta_getattr_u16(tb[FRA_SPORT_MASK]);
+                               print_uint(PRINT_JSON, "sport", NULL, r->start);
+                               print_0xhex(PRINT_JSON, "sport_mask", NULL,
+                                           mask);
+                               if (mask == PORT_MAX_MASK) {
+                                       print_uint(PRINT_FP, NULL, " sport %u",
+                                                  r->start);
+                               } else {
+                                       print_0xhex(PRINT_FP, NULL,
+                                                   " sport %#x", r->start);
+                                       print_0xhex(PRINT_FP, NULL, "/%#x",
+                                                   mask);
+                               }
+                       } else {
+                               print_uint(PRINT_ANY, "sport", " sport %u",
+                                          r->start);
+                       }
                } else {
                        print_uint(PRINT_ANY, "sport_start", " sport %u",
                                   r->start);
@@ -402,7 +444,26 @@
                struct fib_rule_port_range *r = RTA_DATA(tb[FRA_DPORT_RANGE]);
 
                if (r->start == r->end) {
-                       print_uint(PRINT_ANY, "dport", " dport %u", r->start);
+                       if (tb[FRA_DPORT_MASK]) {
+                               __u16 mask;
+
+                               mask = rta_getattr_u16(tb[FRA_DPORT_MASK]);
+                               print_uint(PRINT_JSON, "dport", NULL, r->start);
+                               print_0xhex(PRINT_JSON, "dport_mask", NULL,
+                                           mask);
+                               if (mask == 0xFFFF) {
+                                       print_uint(PRINT_FP, NULL, " dport %u",
+                                                  r->start);
+                               } else {
+                                       print_0xhex(PRINT_FP, NULL,
+                                                   " dport %#x", r->start);
+                                       print_0xhex(PRINT_FP, NULL, "/%#x",
+                                                   mask);
+                               }
+                       } else {
+                               print_uint(PRINT_ANY, "dport", " dport %u",
+                                          r->start);
+                       }
                } else {
                        print_uint(PRINT_ANY, "dport_start", " dport %u",
                                   r->start);
@@ -499,8 +560,24 @@
        if (tb[FRA_DSCP]) {
                __u8 dscp = rta_getattr_u8(tb[FRA_DSCP]);
 
-               print_string(PRINT_ANY, "dscp", " dscp %s",
-                            rtnl_dscp_n2a(dscp, b1, sizeof(b1)));
+               if (tb[FRA_DSCP_MASK]) {
+                       __u8 mask = rta_getattr_u8(tb[FRA_DSCP_MASK]);
+
+                       print_string(PRINT_JSON, "dscp", NULL,
+                                    rtnl_dscp_n2a(dscp, b1, sizeof(b1)));
+                       print_0xhex(PRINT_JSON, "dscp_mask", NULL, mask);
+                       if (mask == DSCP_MAX_MASK) {
+                               print_string(PRINT_FP, NULL, " dscp %s",
+                                            rtnl_dscp_n2a(dscp, b1,
+                                                          sizeof(b1)));
+                       } else {
+                               print_0xhex(PRINT_FP, NULL, " dscp %#x", dscp);
+                               print_0xhex(PRINT_FP, NULL, "/%#x", mask);
+                       }
+               } else {
+                       print_string(PRINT_ANY, "dscp", " dscp %s",
+                                    rtnl_dscp_n2a(dscp, b1, sizeof(b1)));
+               }
        }
 
        /* The kernel will either provide both attributes, or none */
@@ -600,6 +677,55 @@
        return 0;
 }
 
+static void iprule_port_parse(char *arg, struct fib_rule_port_range *r,
+                             __u16 *mask)
+{
+       char *sep;
+
+       *mask = PORT_MAX_MASK;
+
+       sep = strchr(arg, '-');
+       if (sep) {
+               *sep = '\0';
+
+               if (get_u16(&r->start, arg, 0))
+                       invarg("invalid port range start", arg);
+
+               if (get_u16(&r->end, sep + 1, 0))
+                       invarg("invalid port range end", sep + 1);
+
+               return;
+       }
+
+       sep = strchr(arg, '/');
+       if (sep) {
+               *sep = '\0';
+
+               if (get_u16(mask, sep + 1, 0))
+                       invarg("invalid mask", sep + 1);
+       }
+
+       if (get_u16(&r->start, arg, 0))
+               invarg("invalid port", arg);
+
+       r->end = r->start;
+}
+
+static void iprule_dscp_parse(char *arg, __u32 *dscp, __u32 *mask)
+{
+       char *slash;
+
+       *mask = DSCP_MAX_MASK;
+
+       slash = strchr(arg, '/');
+       if (slash != NULL)
+               *slash = '\0';
+       if (rtnl_dscp_a2n(dscp, arg))
+               invarg("invalid dscp", arg);
+       if (slash && get_u32(mask, slash + 1, 0))
+               invarg("invalid dscp mask", slash + 1);
+}
+
 static void iprule_flowlabel_parse(char *arg, __u32 *flowlabel,
                                   __u32 *flowlabel_mask)
 {
@@ -746,35 +872,17 @@
                                invarg("Invalid \"ipproto\" value\n", *argv);
                        filter.ipproto = ipproto;
                } else if (strcmp(*argv, "sport") == 0) {
-                       struct fib_rule_port_range r;
-                       int ret;
-
                        NEXT_ARG();
-                       ret = sscanf(*argv, "%hu-%hu", &r.start, &r.end);
-                       if (ret == 1)
-                               r.end = r.start;
-                       else if (ret != 2)
-                               invarg("invalid port range\n", *argv);
-                       filter.sport = r;
+                       iprule_port_parse(*argv, &filter.sport,
+                                         &filter.sport_mask);
                } else if (strcmp(*argv, "dport") == 0) {
-                       struct fib_rule_port_range r;
-                       int ret;
-
                        NEXT_ARG();
-                       ret = sscanf(*argv, "%hu-%hu", &r.start, &r.end);
-                       if (ret == 1)
-                               r.end = r.start;
-                       else if (ret != 2)
-                               invarg("invalid dport range\n", *argv);
-                       filter.dport = r;
+                       iprule_port_parse(*argv, &filter.dport,
+                                         &filter.dport_mask);
                } else if (strcmp(*argv, "dscp") == 0) {
-                       __u32 dscp;
-
                        NEXT_ARG();
-                       if (rtnl_dscp_a2n(&dscp, *argv))
-                               invarg("invalid dscp\n", *argv);
-                       filter.dscp = dscp;
-                       filter.dscpmask = 1;
+                       iprule_dscp_parse(*argv, &filter.dscp,
+                                         &filter.dscpmask);
                } else if (strcmp(*argv, "flowlabel") == 0) {
                        NEXT_ARG();
 
@@ -1036,35 +1144,35 @@
                        addattr8(&req.n, sizeof(req), FRA_IP_PROTO, ipproto);
                } else if (strcmp(*argv, "sport") == 0) {
                        struct fib_rule_port_range r;
-                       int ret = 0;
+                       __u16 sport_mask;
 
                        NEXT_ARG();
-                       ret = sscanf(*argv, "%hu-%hu", &r.start, &r.end);
-                       if (ret == 1)
-                               r.end = r.start;
-                       else if (ret != 2)
-                               invarg("invalid port range\n", *argv);
+                       iprule_port_parse(*argv, &r, &sport_mask);
                        addattr_l(&req.n, sizeof(req), FRA_SPORT_RANGE, &r,
                                  sizeof(r));
+                       if (sport_mask != PORT_MAX_MASK)
+                               addattr16(&req.n, sizeof(req), FRA_SPORT_MASK,
+                                         sport_mask);
                } else if (strcmp(*argv, "dport") == 0) {
                        struct fib_rule_port_range r;
-                       int ret = 0;
+                       __u16 dport_mask;
 
                        NEXT_ARG();
-                       ret = sscanf(*argv, "%hu-%hu", &r.start, &r.end);
-                       if (ret == 1)
-                               r.end = r.start;
-                       else if (ret != 2)
-                               invarg("invalid dport range\n", *argv);
+                       iprule_port_parse(*argv, &r, &dport_mask);
                        addattr_l(&req.n, sizeof(req), FRA_DPORT_RANGE, &r,
                                  sizeof(r));
+                       if (dport_mask != PORT_MAX_MASK)
+                               addattr16(&req.n, sizeof(req), FRA_DPORT_MASK,
+                                         dport_mask);
                } else if (strcmp(*argv, "dscp") == 0) {
-                       __u32 dscp;
+                       __u32 dscp, dscp_mask;
 
                        NEXT_ARG();
-                       if (rtnl_dscp_a2n(&dscp, *argv))
-                               invarg("invalid dscp\n", *argv);
+                       iprule_dscp_parse(*argv, &dscp, &dscp_mask);
                        addattr8(&req.n, sizeof(req), FRA_DSCP, dscp);
+                       if (dscp_mask != DSCP_MAX_MASK)
+                               addattr8(&req.n, sizeof(req), FRA_DSCP_MASK,
+                                        dscp_mask);
                } else if (strcmp(*argv, "flowlabel") == 0) {
                        __u32 flowlabel, flowlabel_mask;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/ip/ipxfrm.c 
new/iproute2-6.15.0/ip/ipxfrm.c
--- old/iproute2-6.14.0/ip/ipxfrm.c     2025-03-24 17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/ip/ipxfrm.c     2025-05-26 17:19:09.000000000 +0200
@@ -351,7 +351,10 @@
                t = (long)time;
                tp = localtime(&t);
 
-               strftime(str, sizeof(str), "%Y-%m-%d %T", tp);
+               if (!tp)
+                       strcpy(str, "invalid-time");
+               else
+                       strftime(str, sizeof(str), "%Y-%m-%d %T", tp);
        }
 
        return str;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/lib/color.c 
new/iproute2-6.15.0/lib/color.c
--- old/iproute2-6.14.0/lib/color.c     2025-03-24 17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/lib/color.c     2025-05-26 17:19:09.000000000 +0200
@@ -81,6 +81,18 @@
        set_color_palette();
 }
 
+int default_color_opt(void)
+{
+       const char *no_color;
+
+       /* If NO_COLOR has a non-empty value, coloured output is never wanted */
+       no_color = getenv("NO_COLOR");
+       if (no_color && *no_color)
+               return COLOR_OPT_NEVER;
+
+       return CONF_COLOR;
+}
+
 bool check_enable_color(int color, int json)
 {
        if (json || color == COLOR_OPT_NEVER)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/lib/utils.c 
new/iproute2-6.15.0/lib/utils.c
--- old/iproute2-6.14.0/lib/utils.c     2025-03-24 17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/lib/utils.c     2025-05-26 17:19:09.000000000 +0200
@@ -304,10 +304,6 @@
        if (res == ULLONG_MAX && errno == ERANGE)
                return -1;
 
-       /* in case ULL is 128 bits */
-       if (res > 0xFFFFFFFFFFFFFFFFULL)
-               return -1;
-
        *val = res;
        return 0;
 }
@@ -399,8 +395,6 @@
                return -1;
        if ((res == LLONG_MIN || res == LLONG_MAX) && errno == ERANGE)
                return -1;
-       if (res > INT64_MAX || res < INT64_MIN)
-               return -1;
 
        *val = res;
        return 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/man/man8/ip-link.8.in 
new/iproute2-6.15.0/man/man8/ip-link.8.in
--- old/iproute2-6.14.0/man/man8/ip-link.8.in   2025-03-24 17:04:44.000000000 
+0100
+++ new/iproute2-6.15.0/man/man8/ip-link.8.in   2025-05-26 17:19:09.000000000 
+0200
@@ -882,10 +882,14 @@
 [
 .BI mode " MODE "
 ] [
+.BI scrub " SCRUB "
+] [
 .I "POLICY "
 ] [
 .BR peer
 [
+.BI scrub " SCRUB "
+] [
 .I "POLICY "
 ] [
 .I "NAME "
@@ -899,6 +903,17 @@
 as possible values. Default option is "l3".
 
 .sp
+.BI scrub " SCRUB"
+- specifies the scrub behavior of the netkit device with "default" and
+"none" as possible values. With "default" the device zeroes the
+skb->{mark,priority} fields before invoking the attached BPF program
+when its peer device resides in a different network namespace. With
+"none" the device leaves clearing skb->{mark,priority} up to the BPF
+program. Default option is "default". Specifying scrub before the peer
+option refers to the primary device, after the peer option refers to
+the peer device.
+
+.sp
 .I "POLICY"
 - specifies the default device policy when no BPF programs are attached
 with "forward" and "blackhole" as possible values. Default option is
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/man/man8/ip-rule.8.in 
new/iproute2-6.15.0/man/man8/ip-rule.8.in
--- old/iproute2-6.14.0/man/man8/ip-rule.8.in   2025-03-24 17:04:44.000000000 
+0100
+++ new/iproute2-6.15.0/man/man8/ip-rule.8.in   2025-05-26 17:19:09.000000000 
+0200
@@ -37,7 +37,7 @@
 .B  tos
 .IR TOS " ] [ "
 .B  dscp
-.IR DSCP " ] [ "
+.IR DSCP\fR[\fB/\fIMASK "] ] [ "
 .B  fwmark
 .IR FWMARK\fR[\fB/\fIMASK "] ] [ "
 .B  iif
@@ -52,10 +52,10 @@
 .B ipproto
 .IR PROTOCOL " ] [ "
 .BR sport " [ "
-.IR NUMBER " | "
+.IR NUMBER\fR[\fB/\fIMASK "] | "
 .IR NUMBER "-" NUMBER " ] ] [ "
 .BR dport " [ "
-.IR NUMBER " | "
+.IR NUMBER\fR[\fB/\fIMASK "] | "
 .IR NUMBER "-" NUMBER " ] ] [ "
 .B  tun_id
 .IR TUN_ID " ] [ "
@@ -239,9 +239,10 @@
 select the TOS value to match.
 
 .TP
-.BI dscp " DSCP"
-select the DSCP value to match. DSCP values can be written either directly as
-numeric values (valid values are 0-63), or using symbolic names specified in
+.BI dscp " DSCP\fR[\fB/\fIMASK\fR]"
+select the DSCP value to match with an optional mask. DSCP values can be
+written either directly as numeric values (valid values are 0-63), or using
+symbolic names specified in
 .BR @SYSCONF_USR_DIR@/rt_dsfield " or " @SYSCONF_ETC_DIR@/rt_dsfield
 (has precedence if exists).
 However, note that the file specifies full 8-bit dsfield values, whereas
@@ -270,12 +271,14 @@
 select the ip protocol value to match.
 
 .TP
-.BI sport " NUMBER | NUMBER-NUMBER"
-select the source port value to match. supports port range.
+.BI sport " NUMBER\fR[\fB/\fIMASK\fR] | NUMBER-NUMBER"
+select the source port value to match with an optional mask. Supports port
+range.
 
 .TP
-.BI dport " NUMBER | NUMBER-NUMBER"
-select the destination port value to match. supports port range.
+.BI dport " NUMBER\fR[\fB/\fIMASK\fR] | NUMBER-NUMBER"
+select the destination port value to match with an optional mask. Supports port
+range.
 
 .TP
 .BI priority " PREFERENCE"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/man/man8/rdma-statistic.8 
new/iproute2-6.15.0/man/man8/rdma-statistic.8
--- old/iproute2-6.14.0/man/man8/rdma-statistic.8       2025-03-24 
17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/man/man8/rdma-statistic.8       2025-05-26 
17:19:09.000000000 +0200
@@ -39,6 +39,7 @@
 .B auto
 .RI "{ " CRITERIA " | "
 .BR off " }"
+.B [ optional-counters | on/off ]
 
 .ti -8
 .B rdma statistic
@@ -180,6 +181,11 @@
 On device mlx5_2 port 1, for each new user QP bind it with a counter 
automatically. Per counter for QPs with same qp type.
 .RE
 .PP
+rdma statistic qp set link mlx5_2/1 auto type on optional-counters on
+.RS 4
+On device mlx5_2 port 1, for each new user QP bind it with a counter 
automatically. Per counter for QPs with same qp type. Whilst also binding the 
currently enabled optional-counters.
+.RE
+.PP
 rdma statistic qp set link mlx5_2/1 auto pid on
 .RS 4
 On device mlx5_2 port 1, for each new user QP bind it with a counter 
automatically. Per counter for QPs with same pid.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/misc/nstat.c 
new/iproute2-6.15.0/misc/nstat.c
--- old/iproute2-6.14.0/misc/nstat.c    2025-03-24 17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/misc/nstat.c    2025-05-26 17:19:09.000000000 +0200
@@ -218,6 +218,10 @@
                        p = next;
                }
                n = db;
+               if (n == NULL) {
+                       fprintf(stderr, "Error: Invalid input – line has ':' 
but no entries. Add values after ':'.\n");
+                       exit(-2);
+               }
                nread = getline(&buf, &buflen, fp);
                if (nread == -1) {
                        fprintf(stderr, "%s:%d: error parsing history file\n",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/iproute2-6.14.0/rdma/include/uapi/rdma/rdma_netlink.h 
new/iproute2-6.15.0/rdma/include/uapi/rdma/rdma_netlink.h
--- old/iproute2-6.14.0/rdma/include/uapi/rdma/rdma_netlink.h   2025-03-24 
17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/rdma/include/uapi/rdma/rdma_netlink.h   2025-05-26 
17:19:09.000000000 +0200
@@ -580,6 +580,8 @@
        RDMA_NLDEV_ATTR_EVENT_TYPE,             /* u8 */
 
        RDMA_NLDEV_SYS_ATTR_MONITOR_MODE,       /* u8 */
+
+       RDMA_NLDEV_ATTR_STAT_OPCOUNTER_ENABLED, /* u8 */
        /*
         * Always the end
         */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/rdma/stat.c 
new/iproute2-6.15.0/rdma/stat.c
--- old/iproute2-6.14.0/rdma/stat.c     2025-03-24 17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/rdma/stat.c     2025-05-26 17:19:09.000000000 +0200
@@ -7,6 +7,7 @@
 #include "rdma.h"
 #include "res.h"
 #include "stat.h"
+#include "utils.h"
 #include <inttypes.h>
 
 static int stat_help(struct rd *rd)
@@ -62,7 +63,8 @@
        { NULL },
 };
 
-static int prepare_auto_mode_str(uint32_t mask, char *output, int len)
+static int prepare_auto_mode_str(uint32_t mask, bool opcnt, char *output,
+                                int len)
 {
        char s[] = "qp auto";
        int i, outlen = strlen(s);
@@ -90,6 +92,10 @@
                if (outlen + strlen(" on") >= len)
                        return -EINVAL;
                strcat(output, " on");
+
+               strcat(output, " optional-counters ");
+               strcat(output, (opcnt) ? "on" : "off");
+
        } else {
                if (outlen + strlen(" off") >= len)
                        return -EINVAL;
@@ -104,6 +110,7 @@
        struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
        uint32_t mode = 0, mask = 0;
        char output[128] = {};
+       bool opcnt = false;
        uint32_t idx, port;
        const char *name;
 
@@ -126,7 +133,10 @@
                if (!tb[RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK])
                        return MNL_CB_ERROR;
                mask = 
mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK]);
-               prepare_auto_mode_str(mask, output, sizeof(output));
+               if (tb[RDMA_NLDEV_ATTR_STAT_OPCOUNTER_ENABLED])
+                       opcnt = mnl_attr_get_u8(
+                               tb[RDMA_NLDEV_ATTR_STAT_OPCOUNTER_ENABLED]);
+               prepare_auto_mode_str(mask, opcnt, output, sizeof(output));
        } else {
                snprintf(output, sizeof(output), "qp auto off");
        }
@@ -351,6 +361,7 @@
        { .name = "lqpn", .is_number = true },
        { .name = "pid", .is_number = true },
        { .name = "qp-type", .is_number = false },
+       { .name = "optional-counters", .is_number = false },
 };
 
 static int stat_qp_show_one_link(struct rd *rd)
@@ -395,9 +406,37 @@
        return rd_exec_cmd(rd, cmds, "parameter");
 }
 
+static bool stat_get_on_off(struct rd *rd, const char *arg, int *ret)
+{
+       bool value = false;
+
+       if (strcmpx(rd_argv(rd), arg) != 0) {
+               *ret = -EINVAL;
+               return false;
+       }
+
+       rd_arg_inc(rd);
+
+       if (rd_is_multiarg(rd)) {
+               pr_err("The parameter %s shouldn't include range\n", arg);
+               *ret = EINVAL;
+               return false;
+       }
+
+       value = parse_on_off(arg, rd_argv(rd), ret);
+       if (*ret)
+               return false;
+
+       rd_arg_inc(rd);
+
+       return value;
+}
+
 static int stat_qp_set_link_auto_sendmsg(struct rd *rd, uint32_t mask)
 {
        uint32_t seq;
+       bool opcnt;
+       int ret;
 
        rd_prepare_msg(rd, RDMA_NLDEV_CMD_STAT_SET,
                       &seq, (NLM_F_REQUEST | NLM_F_ACK));
@@ -408,6 +447,13 @@
        mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_STAT_MODE,
                         RDMA_COUNTER_MODE_AUTO);
        mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK, mask);
+       if (rd_argc(rd)) {
+               opcnt = stat_get_on_off(rd, "optional-counters", &ret);
+               if (ret)
+                       return ret;
+               mnl_attr_put_u8(rd->nlh, RDMA_NLDEV_ATTR_STAT_OPCOUNTER_ENABLED,
+                               opcnt);
+       }
 
        return rd_sendrecv_msg(rd, seq);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/rdma/utils.c 
new/iproute2-6.15.0/rdma/utils.c
--- old/iproute2-6.14.0/rdma/utils.c    2025-03-24 17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/rdma/utils.c    2025-05-26 17:19:09.000000000 +0200
@@ -479,6 +479,7 @@
        [RDMA_NLDEV_ATTR_PARENT_NAME] = MNL_TYPE_STRING,
        [RDMA_NLDEV_ATTR_EVENT_TYPE] = MNL_TYPE_U8,
        [RDMA_NLDEV_SYS_ATTR_MONITOR_MODE] = MNL_TYPE_U8,
+       [RDMA_NLDEV_ATTR_STAT_OPCOUNTER_ENABLED] = MNL_TYPE_U8,
 };
 
 static int rd_attr_check(const struct nlattr *attr, int *typep)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/tc/tc.c new/iproute2-6.15.0/tc/tc.c
--- old/iproute2-6.14.0/tc/tc.c 2025-03-24 17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/tc/tc.c 2025-05-26 17:19:09.000000000 +0200
@@ -254,7 +254,7 @@
 {
        const char *libbpf_version;
        char *batch_file = NULL;
-       int color = CONF_COLOR;
+       int color = default_color_opt();
        int ret;
 
        while (argc > 1) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/tc/tc_core.c 
new/iproute2-6.15.0/tc/tc_core.c
--- old/iproute2-6.14.0/tc/tc_core.c    2025-03-24 17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/tc/tc_core.c    2025-05-26 17:19:09.000000000 +0200
@@ -23,12 +23,12 @@
 static double tick_in_usec = 1;
 static double clock_factor = 1;
 
-static unsigned int tc_core_time2tick(unsigned int time)
+static double tc_core_time2tick(double time)
 {
        return time * tick_in_usec;
 }
 
-unsigned int tc_core_tick2time(unsigned int tick)
+double tc_core_tick2time(double tick)
 {
        return tick / tick_in_usec;
 }
@@ -45,7 +45,7 @@
 
 unsigned int tc_calc_xmittime(__u64 rate, unsigned int size)
 {
-       return 
tc_core_time2tick(TIME_UNITS_PER_SEC*((double)size/(double)rate));
+       return 
ceil(tc_core_time2tick(TIME_UNITS_PER_SEC*((double)size/(double)rate)));
 }
 
 unsigned int tc_calc_xmitsize(__u64 rate, unsigned int ticks)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/tc/tc_core.h 
new/iproute2-6.15.0/tc/tc_core.h
--- old/iproute2-6.14.0/tc/tc_core.h    2025-03-24 17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/tc/tc_core.h    2025-05-26 17:19:09.000000000 +0200
@@ -12,7 +12,7 @@
 };
 
 
-unsigned tc_core_tick2time(unsigned tick);
+double tc_core_tick2time(double tick);
 unsigned tc_core_time2ktime(unsigned time);
 unsigned tc_core_ktime2time(unsigned ktime);
 unsigned tc_calc_xmittime(__u64 rate, unsigned size);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iproute2-6.14.0/tc/tc_util.c 
new/iproute2-6.15.0/tc/tc_util.c
--- old/iproute2-6.14.0/tc/tc_util.c    2025-03-24 17:04:44.000000000 +0100
+++ new/iproute2-6.15.0/tc/tc_util.c    2025-05-26 17:19:09.000000000 +0200
@@ -665,7 +665,8 @@
                           tm->expires / hz);
 }
 
-static void print_tcstats_basic_hw(struct rtattr **tbs, const char *prefix)
+static void print_tcstats_basic_hw(struct rtattr **tbs, const char *prefix,
+                                  __u64 packets64, __u64 packets64_hw)
 {
        struct gnet_stats_basic bs_hw;
 
@@ -674,8 +675,9 @@
 
        memcpy(&bs_hw, RTA_DATA(tbs[TCA_STATS_BASIC_HW]),
               MIN(RTA_PAYLOAD(tbs[TCA_STATS_BASIC_HW]), sizeof(bs_hw)));
+       packets64_hw = packets64_hw ? : bs_hw.packets;
 
-       if (bs_hw.bytes == 0 && bs_hw.packets == 0)
+       if (bs_hw.bytes == 0 && packets64_hw == 0)
                return;
 
        if (tbs[TCA_STATS_BASIC]) {
@@ -684,15 +686,16 @@
                memcpy(&bs, RTA_DATA(tbs[TCA_STATS_BASIC]),
                       MIN(RTA_PAYLOAD(tbs[TCA_STATS_BASIC]),
                           sizeof(bs)));
+               packets64 = packets64 ? : bs.packets;
 
-               if (bs.bytes >= bs_hw.bytes && bs.packets >= bs_hw.packets) {
+               if (bs.bytes >= bs_hw.bytes && packets64 >= packets64_hw) {
                        print_nl();
                        print_string(PRINT_FP, NULL, "%s", prefix);
                        print_lluint(PRINT_ANY, "sw_bytes",
                                     "Sent software %llu bytes",
                                     bs.bytes - bs_hw.bytes);
-                       print_uint(PRINT_ANY, "sw_packets", " %u pkt",
-                                  bs.packets - bs_hw.packets);
+                       print_lluint(PRINT_ANY, "sw_packets", " %llu pkt",
+                                    packets64 - packets64_hw);
                }
        }
 
@@ -700,21 +703,40 @@
        print_string(PRINT_FP, NULL, "%s", prefix);
        print_lluint(PRINT_ANY, "hw_bytes", "Sent hardware %llu bytes",
                     bs_hw.bytes);
-       print_uint(PRINT_ANY, "hw_packets", " %u pkt", bs_hw.packets);
+       print_lluint(PRINT_ANY, "hw_packets", " %llu pkt", packets64_hw);
+}
+
+static void parse_packets64(const struct rtattr *nest, __u64 *p_packets64,
+                           __u64 *p_packets64_hw)
+{
+       unsigned short prev_type = __TCA_STATS_MAX;
+       const struct rtattr *pos;
+
+       /* 'TCA_STATS_PKT64' can appear twice in the 'TCA_ACT_STATS' nest.
+        * Whether the attribute carries the combined or hardware only
+        * statistics depends on the attribute that precedes it in the nest.
+        */
+       rtattr_for_each_nested(pos, nest) {
+               if (pos->rta_type == TCA_STATS_PKT64 &&
+                   prev_type == TCA_STATS_BASIC)
+                       *p_packets64 = rta_getattr_u64(pos);
+               else if (pos->rta_type == TCA_STATS_PKT64 &&
+                        prev_type == TCA_STATS_BASIC_HW)
+                       *p_packets64_hw = rta_getattr_u64(pos);
+               prev_type = pos->rta_type;
+       }
 }
 
 void print_tcstats2_attr(struct rtattr *rta, const char *prefix, struct rtattr 
**xstats)
 {
        struct rtattr *tbs[TCA_STATS_MAX + 1];
+       __u64 packets64 = 0, packets64_hw = 0;
 
        parse_rtattr_nested(tbs, TCA_STATS_MAX, rta);
+       parse_packets64(rta, &packets64, &packets64_hw);
 
        if (tbs[TCA_STATS_BASIC]) {
                struct gnet_stats_basic bs = {0};
-               __u64 packets64 = 0;
-
-               if (tbs[TCA_STATS_PKT64])
-                       packets64 = rta_getattr_u64(tbs[TCA_STATS_PKT64]);
 
                memcpy(&bs, RTA_DATA(tbs[TCA_STATS_BASIC]),
                       MIN(RTA_PAYLOAD(tbs[TCA_STATS_BASIC]), sizeof(bs)));
@@ -740,7 +762,7 @@
        }
 
        if (tbs[TCA_STATS_BASIC_HW])
-               print_tcstats_basic_hw(tbs, prefix);
+               print_tcstats_basic_hw(tbs, prefix, packets64, packets64_hw);
 
        if (tbs[TCA_STATS_RATE_EST64]) {
                struct gnet_stats_rate_est64 re = {0};

Reply via email to