Control: tags -1 moreinfo On 2025-05-27 00:53:10 +0100, Luca Boccassi wrote: > Package: release.debian.org > Severity: normal > Control: affects -1 + src:iproute2 > User: release.debian....@packages.debian.org > Usertags: unblock > > Dear RT, > > Please unblock iproute2/6.15.0-1
Issues preventing migration: ∙ ∙ autopkgtest for iproute2/6.15.0-1: amd64: Pass, arm64: No tests, superficial or marked flaky ♻ (reference ♻), armel: No tests, superficial or marked flaky ♻ (reference ♻), armhf: No tests, superficial or marked flaky ♻ (reference ♻), i386: No tests, superficial or marked flaky ♻ (reference ♻), ppc64el: No tests, superficial or marked flaky ♻ (reference ♻), riscv64: No tests, superficial or marked flaky ♻ (reference ♻), s390x: No tests, superficial or marked flaky ♻ (reference ♻) ∙ ∙ autopkgtest for systemd/257.5-2: amd64: Regression or new test ♻ (reference ♻), arm64: Pass, armel: Pass, armhf: Pass, i386: Pass, ppc64el: Pass, riscv64: Pass, s390x: Pass Could you check what's wrong with systemd? Cheers > > The new bug fix release only contains small bug fixes and changes, and > allows to drop all previously backported patches. Crucially, it fixes a > regression introduced in 6.14 that broke a major and popular feature, > #1106321. > > Full debdiff attached. > > Thanks. > diff -Nru iproute2-6.14.0/bridge/bridge.c iproute2-6.15.0/bridge/bridge.c > --- iproute2-6.14.0/bridge/bridge.c 2025-03-24 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/bridge/bridge.c 2025-05-26 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/debian/changelog iproute2-6.15.0/debian/changelog > --- iproute2-6.14.0/debian/changelog 2025-04-12 12:15:56.000000000 +0100 > +++ iproute2-6.15.0/debian/changelog 2025-05-27 00:16:26.000000000 +0100 > @@ -1,3 +1,12 @@ > +iproute2 (6.15.0-1) unstable; urgency=medium > + > + * Update upstream source from tag 'upstream/6.15.0' > + (Closes: #1106321) > + * Drop all backported patches, merged upstream > + * d/copyright: use GPL URL instead of old FSF postal address > + > + -- Luca Boccassi <bl...@debian.org> Tue, 27 May 2025 00:16:26 +0100 > + > iproute2 (6.14.0-3) unstable; urgency=medium > > * autopkgtest: remove build-essential and dpkg-dev deps, add gcc > diff -Nru iproute2-6.14.0/debian/copyright iproute2-6.15.0/debian/copyright > --- iproute2-6.14.0/debian/copyright 2024-11-24 11:21:07.000000000 +0000 > +++ iproute2-6.15.0/debian/copyright 2025-05-27 00:16:26.000000000 +0100 > @@ -52,8 +52,7 @@ > GNU General Public License for more details. > . > You should have received a copy of the GNU General Public License > - along with this package; if not, write to the Free Software > - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA > + along with this package; if not, see <https://www.gnu.org/licenses/> > . > On Debian systems, the complete text of the GNU General Public License > version > 2 can be found in `/usr/share/common-licenses/GPL-2'. > diff -Nru > iproute2-6.14.0/debian/patches/0002-color-Introduce-and-use-default_color_opt-function.patch > > iproute2-6.15.0/debian/patches/0002-color-Introduce-and-use-default_color_opt-function.patch > --- > iproute2-6.14.0/debian/patches/0002-color-Introduce-and-use-default_color_opt-function.patch > 2025-04-12 12:14:49.000000000 +0100 > +++ > iproute2-6.15.0/debian/patches/0002-color-Introduce-and-use-default_color_opt-function.patch > 1970-01-01 01:00:00.000000000 +0100 > @@ -1,61 +0,0 @@ > -Author: Ben Hutchings <b...@debian.org> > -Description: color: Introduce and use default_color_opt() function > -Origin: commit:446edf9ef8055125a8ef28a9d9218b05971ee465 > -Forwarded: > https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/commit/?id=446edf9ef8055125a8ef28a9d9218b05971ee465 > ---- a/bridge/bridge.c > -+++ b/bridge/bridge.c > -@@ -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]; > ---- a/include/color.h > -+++ b/include/color.h > -@@ -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, ...); > ---- a/ip/ip.c > -+++ b/ip/ip.c > -@@ -180,7 +180,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. > ---- a/lib/color.c > -+++ b/lib/color.c > -@@ -81,6 +81,11 @@ > - set_color_palette(); > - } > - > -+int default_color_opt(void) > -+{ > -+ return CONF_COLOR; > -+} > -+ > - bool check_enable_color(int color, int json) > - { > - if (json || color == COLOR_OPT_NEVER) > ---- a/tc/tc.c > -+++ b/tc/tc.c > -@@ -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 -Nru > iproute2-6.14.0/debian/patches/0003-color-Handle-NO_COLOR-environment-variable-in-defaul.patch > > iproute2-6.15.0/debian/patches/0003-color-Handle-NO_COLOR-environment-variable-in-defaul.patch > --- > iproute2-6.14.0/debian/patches/0003-color-Handle-NO_COLOR-environment-variable-in-defaul.patch > 2025-04-12 12:14:49.000000000 +0100 > +++ > iproute2-6.15.0/debian/patches/0003-color-Handle-NO_COLOR-environment-variable-in-defaul.patch > 1970-01-01 01:00:00.000000000 +0100 > @@ -1,20 +0,0 @@ > -Author: Ben Hutchings <b...@debian.org> > -Description: color: Handle NO_COLOR environment variable in > default_color_opt() > -Origin: commit:f0076a016cf7926f39c47b95dae0002249c082dc > -Forwarded: > https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/commit/?id=f0076a016cf7926f39c47b95dae0002249c082dc > ---- a/lib/color.c > -+++ b/lib/color.c > -@@ -83,6 +83,13 @@ > - > - 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; > - } > - > diff -Nru > iproute2-6.14.0/debian/patches/0004-color-Assume-background-is-dark-if-unknown.patch > > iproute2-6.15.0/debian/patches/0004-color-Assume-background-is-dark-if-unknown.patch > --- > iproute2-6.14.0/debian/patches/0004-color-Assume-background-is-dark-if-unknown.patch > 2025-04-12 12:14:49.000000000 +0100 > +++ > iproute2-6.15.0/debian/patches/0004-color-Assume-background-is-dark-if-unknown.patch > 1970-01-01 01:00:00.000000000 +0100 > @@ -1,36 +0,0 @@ > -Author: Ben Hutchings <b...@debian.org> > -Description: color: Assume background is dark if unknown > -Origin: commit:cc0f1109d2864686180ba2ce6fba5fcb3bf437bf > -Forwarded: > https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/commit/?id=cc0f1109d2864686180ba2ce6fba5fcb3bf437bf > ---- a/lib/color.c > -+++ b/lib/color.c > -@@ -72,7 +72,11 @@ > - C_CLEAR > - }; > - > --static int is_dark_bg; > -+/* > -+ * Assume dark background until we know otherwise. The dark-background > -+ * colours work better on a light background than vice versa. > -+ */ > -+static int is_dark_bg = 1; > - static int color_is_enabled; > - > - static void enable_color(void) > -@@ -138,12 +142,12 @@ > - /* > - * COLORFGBG environment variable usually contains either two or three > - * values separated by semicolons; we want the last value in either > case. > -- * If this value is 0-6 or 8, background is dark. > -+ * If this value is 0-6 or 8, background is dark; otherwise it's light. > - */ > - if (p && (p = strrchr(p, ';')) != NULL > -- && ((p[1] >= '0' && p[1] <= '6') || p[1] == '8') > -- && p[2] == '\0') > -- is_dark_bg = 1; > -+ && !(((p[1] >= '0' && p[1] <= '6') || p[1] == '8') > -+ && p[2] == '\0')) > -+ is_dark_bg = 0; > - } > - > - __attribute__((format(printf, 3, 4))) > diff -Nru > iproute2-6.14.0/debian/patches/0005-color-Do-not-use-dark-blue-in-dark-background-palett.patch > > iproute2-6.15.0/debian/patches/0005-color-Do-not-use-dark-blue-in-dark-background-palett.patch > --- > iproute2-6.14.0/debian/patches/0005-color-Do-not-use-dark-blue-in-dark-background-palett.patch > 2025-04-12 12:14:49.000000000 +0100 > +++ > iproute2-6.15.0/debian/patches/0005-color-Do-not-use-dark-blue-in-dark-background-palett.patch > 1970-01-01 01:00:00.000000000 +0100 > @@ -1,33 +0,0 @@ > -Author: Ben Hutchings <b...@debian.org> > -Description: color: Do not use dark blue in dark-background palette > -Origin: commit:46a4659313c2610427a088d8f03b731819f2b87a > -Forwarded: > https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/commit/?id=46a4659313c2610427a088d8f03b731819f2b87a > ---- a/lib/color.c > -+++ b/lib/color.c > -@@ -24,7 +24,7 @@ > - C_BOLD_RED, > - C_BOLD_GREEN, > - C_BOLD_YELLOW, > -- C_BOLD_BLUE, > -+ C_BOLD_LIGHT_BLUE, > - C_BOLD_MAGENTA, > - C_BOLD_CYAN, > - C_BOLD_WHITE, > -@@ -42,7 +42,7 @@ > - "\e[1;31m", > - "\e[1;32m", > - "\e[1;33m", > -- "\e[1;34m", > -+ "\e[1;94m", > - "\e[1;35m", > - "\e[1;36m", > - "\e[1;37m", > -@@ -66,7 +66,7 @@ > - C_BOLD_CYAN, > - C_BOLD_YELLOW, > - C_BOLD_MAGENTA, > -- C_BOLD_BLUE, > -+ C_BOLD_LIGHT_BLUE, > - C_BOLD_GREEN, > - C_BOLD_RED, > - C_CLEAR > diff -Nru > iproute2-6.14.0/debian/patches/0006-nstat-NULL-Dereference-when-no-entries-specified.patch > > iproute2-6.15.0/debian/patches/0006-nstat-NULL-Dereference-when-no-entries-specified.patch > --- > iproute2-6.14.0/debian/patches/0006-nstat-NULL-Dereference-when-no-entries-specified.patch > 2025-04-12 12:15:36.000000000 +0100 > +++ > iproute2-6.15.0/debian/patches/0006-nstat-NULL-Dereference-when-no-entries-specified.patch > 1970-01-01 01:00:00.000000000 +0100 > @@ -1,17 +0,0 @@ > -Author: ZiAo Li <23110240...@m.fudan.edu.cn> > -Description: nstat: NULL Dereference when no entries specified > -Origin: commit:866e1d107b7de68ca1fcd1d4d5ffecf9d96bff30 > -Forwarded: > https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/commit/?id=866e1d107b7de68ca1fcd1d4d5ffecf9d96bff30 > ---- a/misc/nstat.c > -+++ b/misc/nstat.c > -@@ -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 -Nru iproute2-6.14.0/debian/patches/series > iproute2-6.15.0/debian/patches/series > --- iproute2-6.14.0/debian/patches/series 2025-04-12 12:13:53.000000000 > +0100 > +++ iproute2-6.15.0/debian/patches/series 2025-05-27 00:16:02.000000000 > +0100 > @@ -1,6 +1 @@ > 0001-Add-moo-feature.patch > -0002-color-Introduce-and-use-default_color_opt-function.patch > -0003-color-Handle-NO_COLOR-environment-variable-in-defaul.patch > -0004-color-Assume-background-is-dark-if-unknown.patch > -0005-color-Do-not-use-dark-blue-in-dark-background-palett.patch > -0006-nstat-NULL-Dereference-when-no-entries-specified.patch > diff -Nru iproute2-6.14.0/etc/iproute2/rt_protos > iproute2-6.15.0/etc/iproute2/rt_protos > --- iproute2-6.14.0/etc/iproute2/rt_protos 2025-03-24 16:04:44.000000000 > +0000 > +++ iproute2-6.15.0/etc/iproute2/rt_protos 2025-05-26 16:19:09.000000000 > +0100 > @@ -17,6 +17,7 @@ > 16 dhcp > 18 keepalived > 42 babel > +84 ovn > 99 openr > 186 bgp > 187 isis > diff -Nru iproute2-6.14.0/include/color.h iproute2-6.15.0/include/color.h > --- iproute2-6.14.0/include/color.h 2025-03-24 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/include/color.h 2025-05-26 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/include/uapi/linux/batman_adv.h > iproute2-6.15.0/include/uapi/linux/batman_adv.h > --- iproute2-6.14.0/include/uapi/linux/batman_adv.h 2025-03-24 > 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/include/uapi/linux/batman_adv.h 2025-05-26 > 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/include/uapi/linux/bpf.h > iproute2-6.15.0/include/uapi/linux/bpf.h > --- iproute2-6.14.0/include/uapi/linux/bpf.h 2025-03-24 16:04:44.000000000 > +0000 > +++ iproute2-6.15.0/include/uapi/linux/bpf.h 2025-05-26 16:19:09.000000000 > +0100 > @@ -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 -Nru iproute2-6.14.0/include/uapi/linux/btf.h > iproute2-6.15.0/include/uapi/linux/btf.h > --- iproute2-6.14.0/include/uapi/linux/btf.h 2025-03-24 16:04:44.000000000 > +0000 > +++ iproute2-6.15.0/include/uapi/linux/btf.h 2025-05-26 16:19:09.000000000 > +0100 > @@ -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 -Nru iproute2-6.14.0/include/uapi/linux/can.h > iproute2-6.15.0/include/uapi/linux/can.h > --- iproute2-6.14.0/include/uapi/linux/can.h 2025-03-24 16:04:44.000000000 > +0000 > +++ iproute2-6.15.0/include/uapi/linux/can.h 2025-05-26 16:19:09.000000000 > +0100 > @@ -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 -Nru iproute2-6.14.0/include/uapi/linux/capability.h > iproute2-6.15.0/include/uapi/linux/capability.h > --- iproute2-6.14.0/include/uapi/linux/capability.h 2025-03-24 > 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/include/uapi/linux/capability.h 2025-05-26 > 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/include/uapi/linux/const.h > iproute2-6.15.0/include/uapi/linux/const.h > --- iproute2-6.14.0/include/uapi/linux/const.h 2025-03-24 > 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/include/uapi/linux/const.h 2025-05-26 > 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/include/uapi/linux/fib_rules.h > iproute2-6.15.0/include/uapi/linux/fib_rules.h > --- iproute2-6.14.0/include/uapi/linux/fib_rules.h 2025-03-24 > 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/include/uapi/linux/fib_rules.h 2025-05-26 > 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/include/uapi/linux/if_link.h > iproute2-6.15.0/include/uapi/linux/if_link.h > --- iproute2-6.14.0/include/uapi/linux/if_link.h 2025-03-24 > 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/include/uapi/linux/if_link.h 2025-05-26 > 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/include/uapi/linux/rtnetlink.h > iproute2-6.15.0/include/uapi/linux/rtnetlink.h > --- iproute2-6.14.0/include/uapi/linux/rtnetlink.h 2025-03-24 > 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/include/uapi/linux/rtnetlink.h 2025-05-26 > 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/include/uapi/linux/snmp.h > iproute2-6.15.0/include/uapi/linux/snmp.h > --- iproute2-6.14.0/include/uapi/linux/snmp.h 2025-03-24 16:04:44.000000000 > +0000 > +++ iproute2-6.15.0/include/uapi/linux/snmp.h 2025-05-26 16:19:09.000000000 > +0100 > @@ -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 -Nru iproute2-6.14.0/include/uapi/linux/stddef.h > iproute2-6.15.0/include/uapi/linux/stddef.h > --- iproute2-6.14.0/include/uapi/linux/stddef.h 2025-03-24 > 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/include/uapi/linux/stddef.h 2025-05-26 > 16:19:09.000000000 +0100 > @@ -70,4 +70,6 @@ > #define __counted_by_be(m) > #endif > > +#define __kernel_nonstring > + > #endif /* _LINUX_STDDEF_H */ > diff -Nru iproute2-6.14.0/include/uapi/linux/tcp.h > iproute2-6.15.0/include/uapi/linux/tcp.h > --- iproute2-6.14.0/include/uapi/linux/tcp.h 2025-03-24 16:04:44.000000000 > +0000 > +++ iproute2-6.15.0/include/uapi/linux/tcp.h 2025-05-26 16:19:09.000000000 > +0100 > @@ -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 -Nru iproute2-6.14.0/include/uapi/linux/virtio_net.h > iproute2-6.15.0/include/uapi/linux/virtio_net.h > --- iproute2-6.14.0/include/uapi/linux/virtio_net.h 2025-03-24 > 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/include/uapi/linux/virtio_net.h 2025-05-26 > 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/include/version.h iproute2-6.15.0/include/version.h > --- iproute2-6.14.0/include/version.h 2025-03-24 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/include/version.h 2025-05-26 16:19:09.000000000 +0100 > @@ -1 +1 @@ > -static const char version[] = "6.14.0"; > +static const char version[] = "6.15.0"; > diff -Nru iproute2-6.14.0/ip/ila_common.h iproute2-6.15.0/ip/ila_common.h > --- iproute2-6.14.0/ip/ila_common.h 2025-03-24 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/ip/ila_common.h 2025-05-26 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/ip/ip.c iproute2-6.15.0/ip/ip.c > --- iproute2-6.14.0/ip/ip.c 2025-03-24 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/ip/ip.c 2025-05-26 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/ip/iplink_netkit.c > iproute2-6.15.0/ip/iplink_netkit.c > --- iproute2-6.14.0/ip/iplink_netkit.c 2025-03-24 16:04:44.000000000 > +0000 > +++ iproute2-6.15.0/ip/iplink_netkit.c 2025-05-26 16:19:09.000000000 > +0100 > @@ -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 -Nru iproute2-6.14.0/ip/ipmonitor.c iproute2-6.15.0/ip/ipmonitor.c > --- iproute2-6.14.0/ip/ipmonitor.c 2025-03-24 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/ip/ipmonitor.c 2025-05-26 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/ip/iproute.c iproute2-6.15.0/ip/iproute.c > --- iproute2-6.14.0/ip/iproute.c 2025-03-24 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/ip/iproute.c 2025-05-26 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/ip/iprule.c iproute2-6.15.0/ip/iprule.c > --- iproute2-6.14.0/ip/iprule.c 2025-03-24 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/ip/iprule.c 2025-05-26 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/ip/ipxfrm.c iproute2-6.15.0/ip/ipxfrm.c > --- iproute2-6.14.0/ip/ipxfrm.c 2025-03-24 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/ip/ipxfrm.c 2025-05-26 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/lib/color.c iproute2-6.15.0/lib/color.c > --- iproute2-6.14.0/lib/color.c 2025-03-24 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/lib/color.c 2025-05-26 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/lib/utils.c iproute2-6.15.0/lib/utils.c > --- iproute2-6.14.0/lib/utils.c 2025-03-24 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/lib/utils.c 2025-05-26 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/MAINTAINERS iproute2-6.15.0/MAINTAINERS > --- iproute2-6.14.0/MAINTAINERS 2025-03-24 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/MAINTAINERS 2025-05-26 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/man/man8/ip-link.8.in > iproute2-6.15.0/man/man8/ip-link.8.in > --- iproute2-6.14.0/man/man8/ip-link.8.in 2025-03-24 16:04:44.000000000 > +0000 > +++ iproute2-6.15.0/man/man8/ip-link.8.in 2025-05-26 16:19:09.000000000 > +0100 > @@ -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 -Nru iproute2-6.14.0/man/man8/ip-rule.8.in > iproute2-6.15.0/man/man8/ip-rule.8.in > --- iproute2-6.14.0/man/man8/ip-rule.8.in 2025-03-24 16:04:44.000000000 > +0000 > +++ iproute2-6.15.0/man/man8/ip-rule.8.in 2025-05-26 16:19:09.000000000 > +0100 > @@ -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 -Nru iproute2-6.14.0/man/man8/rdma-statistic.8 > iproute2-6.15.0/man/man8/rdma-statistic.8 > --- iproute2-6.14.0/man/man8/rdma-statistic.8 2025-03-24 16:04:44.000000000 > +0000 > +++ iproute2-6.15.0/man/man8/rdma-statistic.8 2025-05-26 16:19:09.000000000 > +0100 > @@ -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 -Nru iproute2-6.14.0/misc/nstat.c iproute2-6.15.0/misc/nstat.c > --- iproute2-6.14.0/misc/nstat.c 2025-03-24 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/misc/nstat.c 2025-05-26 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/rdma/include/uapi/rdma/rdma_netlink.h > iproute2-6.15.0/rdma/include/uapi/rdma/rdma_netlink.h > --- iproute2-6.14.0/rdma/include/uapi/rdma/rdma_netlink.h 2025-03-24 > 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/rdma/include/uapi/rdma/rdma_netlink.h 2025-05-26 > 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/rdma/stat.c iproute2-6.15.0/rdma/stat.c > --- iproute2-6.14.0/rdma/stat.c 2025-03-24 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/rdma/stat.c 2025-05-26 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/rdma/utils.c iproute2-6.15.0/rdma/utils.c > --- iproute2-6.14.0/rdma/utils.c 2025-03-24 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/rdma/utils.c 2025-05-26 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/tc/tc.c iproute2-6.15.0/tc/tc.c > --- iproute2-6.14.0/tc/tc.c 2025-03-24 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/tc/tc.c 2025-05-26 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/tc/tc_core.c iproute2-6.15.0/tc/tc_core.c > --- iproute2-6.14.0/tc/tc_core.c 2025-03-24 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/tc/tc_core.c 2025-05-26 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/tc/tc_core.h iproute2-6.15.0/tc/tc_core.h > --- iproute2-6.14.0/tc/tc_core.h 2025-03-24 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/tc/tc_core.h 2025-05-26 16:19:09.000000000 +0100 > @@ -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 -Nru iproute2-6.14.0/tc/tc_util.c iproute2-6.15.0/tc/tc_util.c > --- iproute2-6.14.0/tc/tc_util.c 2025-03-24 16:04:44.000000000 +0000 > +++ iproute2-6.15.0/tc/tc_util.c 2025-05-26 16:19:09.000000000 +0100 > @@ -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}; -- Sebastian Ramacher