* Re: [PATCH iproute2-next 1/5] netshaper: Extract parse_scope() and parse_rate() helpers
From: David Ahern @ 2026-05-01 17:47 UTC (permalink / raw)
To: Mohsin Bashir, netdev; +Cc: stephen, pabeni, kuba, ernis
In-Reply-To: <20260501011611.3533573-2-mohsin.bashr@gmail.com>
On 4/30/26 7:16 PM, Mohsin Bashir wrote:
> diff --git a/netshaper/netshaper.c b/netshaper/netshaper.c
> index 47fb805e..1603e6e5 100644
> --- a/netshaper/netshaper.c
> +++ b/netshaper/netshaper.c
> @@ -47,6 +47,28 @@ static const char *net_shaper_scope_names[NET_SHAPER_SCOPE_MAX + 1] = {
> "node"
> };
>
> +static int parse_scope(const char *str)
> +{
> + if (strcmp(str, "netdev") == 0)
> + return NET_SHAPER_SCOPE_NETDEV;
> + if (strcmp(str, "queue") == 0)
> + return NET_SHAPER_SCOPE_QUEUE;
> + if (strcmp(str, "node") == 0)
> + return NET_SHAPER_SCOPE_NODE;
> + return -1;
net_shaper_scope_names exists. Create 1 table used for both parsing and
printing.
> +}
> +
> +static int parse_rate(const char *str, __u64 *rate_bps)
> +{
> + if (get_rate64(rate_bps, str)) {
> + fprintf(stderr, "Invalid rate value \"%s\"\n", str);
> + return -1;
> + }
> + /* get_rate64 returns bytes/sec, convert to bits/sec */
> + *rate_bps *= 8;
no magic numbers. Add a define for BITS_PER_BYTE to include/utils.h
above BIT()
^ permalink raw reply
* Re: [PATCH net-next 08/12] dt-bindings: net: toshiba,tc965x-dwmac: add TC956x Ethernet bridge
From: Andrew Lunn @ 2026-05-01 17:38 UTC (permalink / raw)
To: Alex Elder
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, maxime.chevallier,
rmk+kernel, andersson, konradybcio, robh, krzk+dt, conor+dt,
linusw, brgl, arnd, gregkh, Daniel Thompson, mohd.anwar,
a0987203069, alexandre.torgue, ast, boon.khai.ng, chenchuangyu,
chenhuacai, daniel, hawk, hkallweit1, inochiama, john.fastabend,
julianbraha, livelycarpet87, matthew.gerlach, mcoquelin.stm32, me,
prabhakar.mahadev-lad.rj, richardcochran, rohan.g.thomas, sdf,
siyanteng, weishangjuan, wens, netdev, bpf, linux-arm-msm,
devicetree, linux-gpio, linux-stm32, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260501155421.3329862-9-elder@riscstar.com>
Your ASCII art of the chip might be useful here as documentation.
> + # We can't allOf reference Ethernet-controller.yaml because we end up with
> + # contradictory $nodename rules (`ethernet@` versus `pci@`). Happily only a
> + # small number of the properties are useful on TC956x so we can just reference
> + # what we need.
Why not add an subnodes for the ethernet interfaces?
> +examples:
> + - |
> + pcie {
> + #address-cells = <3>;
> + #size-cells = <2>;
> +
> + tc956x_emac0: pci@0,0 {
> + compatible = "pci1179,0220";
> + reg = <0x50000 0x0 0x0 0x0 0x0>;
> + #address-cells = <3>;
> + #size-cells = <2>;
> + device_type = "pci";
> + ranges;
> +
> + gpio-controller;
> + #gpio-cells = <2>;
I've not got to the GPIO driver patch yet...
Is the GPIO part of the ethernet device, or part of the chip? The
hierarchy here should match the hierarchy of the hardware.
> + phy-mode = "10gbase-r";
> + phy-handle = <&tc956x_emac0_phy>;
> +
> + mdio {
> + compatible = "snps,dwmac-mdio";
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + tc956x_emac0_phy: ethernet-phy@1c {
> + compatible = "ethernet-phy-id311c.1c12";
> + reg = <0x1c>;
> + };
> + };
> + };
> + pci@0,1 {
> + compatible = "pci1179,0220";
> + reg = <0x50100 0x0 0x0 0x0 0x0>;
> + #address-cells = <3>;
> + #size-cells = <2>;
> + device_type = "pci";
> + ranges;
> +
You second ethernet does not have a gpio controller?
Andrew
^ permalink raw reply
* Re: [PATCH] amd-xgbe: fix PTP addend overflow causing frozen clock
From: Gregory Fuchedgi @ 2026-05-01 17:32 UTC (permalink / raw)
To: Simon Horman
Cc: Raju Rangoju, Prashanth Kumar K R, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran,
netdev, linux-kernel
In-Reply-To: <20260501153253.GJ15617@horms.kernel.org>
Thanks for the review, Simon.
I don't know what frequency gets returned for v1 in practice. Maybe we could
increase v1 SSINC if the ptpclk_rate can be low (<=50MHz), but I don't have
v1 hardware to experiment with.
On Fri, May 1, 2026 at 8:32 AM Simon Horman <horms@kernel.org> wrote:
>
> On Wed, Apr 29, 2026 at 02:54:14PM -0700, Gregory Fuchedgi via B4 Relay wrote:
> > From: Gregory Fuchedgi <gfuchedgi@gmail.com>
> >
> > XGBE_PTP_ACT_CLK_FREQ and XGBE_V2_PTP_ACT_CLK_FREQ were 10x too
> > large (500MHz/1GHz instead of 50MHz/100MHz), causing the computed
> > addend to overflow the 32-bit tstamp_addend. In the general case
> > this would result in the clock advancing at the wrong rate. For v2
> > (PCI), ptpclk_rate is hardcoded to 125MHz, so the addend formula
> > (ACT_CLK_FREQ << 32) / ptpclk_rate yields exactly 8 * 2^32, and
> > when stored to the 32-bit tstamp_addend the value is zero. With
> > addend = 0 the hardware accumulator never overflows and the PTP
> > clock is fully stopped. For v1 (platform), ptpclk_rate is read from
> > ACPI/DT so the exact overflow behavior depends on the
> > firmware-reported frequency.
> >
> > Define the constants as NSEC_PER_SEC / SSINC so the relationship is
> > explicit and cannot drift out of sync.
> >
> > Fixes: fbd47be098b5 ("amd-xgbe: add hardware PTP timestamping support")
> > Tested-by: Gregory Fuchedgi <gfuchedgi@gmail.com>
> > Signed-off-by: Gregory Fuchedgi <gfuchedgi@gmail.com>
>
> Reviewed-by: Simon Horman <horms@kernel.org>
>
> There is an AI generated review of this patch available on sashiko.dev.
> While I do believe the issues flagged there warrant investigation
> as possible follow-up, I do not think they should delay progress
> of this patch.
^ permalink raw reply
* Re: [PATCH net-next 2/3] vsock: convert to getsockopt_iter
From: Bobby Eshleman @ 2026-05-01 17:32 UTC (permalink / raw)
To: Breno Leitao
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Stefano Garzarella, Shuah Khan, sdf.kernel, netdev,
linux-kernel, virtualization, linux-kselftest, kernel-team
In-Reply-To: <20260501-getsock_one-v1-2-810ce23ea70e@debian.org>
On Fri, May 01, 2026 at 08:52:52AM -0700, Breno Leitao wrote:
> Convert AF_VSOCK's getsockopt implementation to use the new
> getsockopt_iter callback with sockopt_t. The single
> vsock_connectible_getsockopt() callback is shared by both
> vsock_stream_ops and vsock_seqpacket_ops, so both proto_ops are
> updated to use .getsockopt_iter.
>
> Key changes:
> - Replace (char __user *optval, int __user *optlen) with sockopt_t *opt
> - Use opt->optlen for buffer length (input) and returned size (output)
> - Use copy_to_iter() instead of put_user()/copy_to_user()
>
> Signed-off-by: Breno Leitao <leitao@debian.org>
> ---
> net/vmw_vsock/af_vsock.c | 16 +++++++---------
> 1 file changed, 7 insertions(+), 9 deletions(-)
>
> diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
> index 44037b066a5ff..d4a97eeb596e6 100644
> --- a/net/vmw_vsock/af_vsock.c
> +++ b/net/vmw_vsock/af_vsock.c
> @@ -155,6 +155,7 @@
> #include <linux/random.h>
> #include <linux/skbuff.h>
> #include <linux/smp.h>
> +#include <linux/uio.h>
> #include <linux/socket.h>
> #include <linux/stddef.h>
> #include <linux/sysctl.h>
> @@ -2091,8 +2092,7 @@ static int vsock_connectible_setsockopt(struct socket *sock,
>
> static int vsock_connectible_getsockopt(struct socket *sock,
> int level, int optname,
> - char __user *optval,
> - int __user *optlen)
> + sockopt_t *opt)
> {
> struct sock *sk = sock->sk;
> struct vsock_sock *vsk = vsock_sk(sk);
> @@ -2110,8 +2110,7 @@ static int vsock_connectible_getsockopt(struct socket *sock,
> if (level != AF_VSOCK)
> return -ENOPROTOOPT;
>
> - if (get_user(len, optlen))
> - return -EFAULT;
> + len = opt->optlen;
>
> memset(&v, 0, sizeof(v));
>
> @@ -2142,11 +2141,10 @@ static int vsock_connectible_getsockopt(struct socket *sock,
> return -EINVAL;
> if (len > lv)
> len = lv;
> - if (copy_to_user(optval, &v, len))
> + if (copy_to_iter(&v, len, &opt->iter_out) != len)
> return -EFAULT;
>
> - if (put_user(len, optlen))
> - return -EFAULT;
> + opt->optlen = len;
>
> return 0;
> }
> @@ -2631,7 +2629,7 @@ static const struct proto_ops vsock_stream_ops = {
> .listen = vsock_listen,
> .shutdown = vsock_shutdown,
> .setsockopt = vsock_connectible_setsockopt,
> - .getsockopt = vsock_connectible_getsockopt,
> + .getsockopt_iter = vsock_connectible_getsockopt,
> .sendmsg = vsock_connectible_sendmsg,
> .recvmsg = vsock_connectible_recvmsg,
> .mmap = sock_no_mmap,
> @@ -2653,7 +2651,7 @@ static const struct proto_ops vsock_seqpacket_ops = {
> .listen = vsock_listen,
> .shutdown = vsock_shutdown,
> .setsockopt = vsock_connectible_setsockopt,
> - .getsockopt = vsock_connectible_getsockopt,
> + .getsockopt_iter = vsock_connectible_getsockopt,
> .sendmsg = vsock_connectible_sendmsg,
> .recvmsg = vsock_connectible_recvmsg,
> .mmap = sock_no_mmap,
>
> --
> 2.52.0
>
Reviewed-by: Bobby Eshleman <bobbyeshleman@meta.com>
^ permalink raw reply
* [PATCH net-next v5 5/5] selftests: net: bridge: add MRC and QQIC field encoding tests
From: Ujjal Roy @ 2026-05-01 17:31 UTC (permalink / raw)
To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Nikolay Aleksandrov, Ido Schimmel, David Ahern,
Shuah Khan, Andy Roulin, Yong Wang, Petr Machata
Cc: Ujjal Roy, bridge, netdev, linux-kernel, linux-kselftest
In-Reply-To: <20260501173130.3486-1-royujjal@gmail.com>
Enhance vlmc_query_intvl_test and vlmc_query_response_intvl_test in
bridge_vlan_mcast.sh to validate IGMPv3/MLDv2 protocol compliance for
MRC and QQIC field encoding across both linear and exponential ranges.
TEST: Vlan multicast snooping enable [ OK ]
TEST: Vlan mcast_query_interval global option default value [ OK ]
TEST: Number of tagged IGMPv2 general query [ OK ]
TEST: IGMPv3 QQIC linear value 60(s) [ OK ]
TEST: MLDv2 QQIC linear value 60(s) [ OK ]
TEST: IGMPv3 QQIC non linear value 160(s) [ OK ]
TEST: MLDv2 QQIC non linear value 160(s) [ OK ]
TEST: Vlan mcast_query_response_interval global option default value [ OK ]
TEST: IGMPv3 MRC linear value of 60(x0.1s) [ OK ]
TEST: MLDv2 MRC linear value of 24000(ms) [ OK ]
TEST: IGMPv3 MRC non linear value of 240(x0.1s) [ OK ]
TEST: MLDv2 MRC non linear value of 48000(ms) [ OK ]
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Ujjal Roy <royujjal@gmail.com>
---
.../net/forwarding/bridge_vlan_mcast.sh | 140 +++++++++++++++++-
1 file changed, 132 insertions(+), 8 deletions(-)
diff --git a/tools/testing/selftests/net/forwarding/bridge_vlan_mcast.sh b/tools/testing/selftests/net/forwarding/bridge_vlan_mcast.sh
index e8031f68200a..07a377652a59 100755
--- a/tools/testing/selftests/net/forwarding/bridge_vlan_mcast.sh
+++ b/tools/testing/selftests/net/forwarding/bridge_vlan_mcast.sh
@@ -162,14 +162,27 @@ vlmc_query_cnt_setup()
{
local type=$1
local dev=$2
+ local match=($3)
if [[ $type == "igmp" ]]; then
- tc filter add dev $dev egress pref 10 prot 802.1Q \
+ # This matches: IP Protocol 2 (IGMP)
+ tc filter add dev "$dev" egress pref 10 prot 802.1Q \
flower vlan_id 10 vlan_ethtype ipv4 dst_ip 224.0.0.1 ip_proto 2 \
+ action goto chain 1
+ # AND Type 0x11 (Query) at offset 0 of IGMP header
+ # 20 bytes IPv4 header + 4 bytes Router Alert option + IGMP[offset 0]
+ tc filter add dev "$dev" egress pref 20 chain 1 prot 802.1Q u32 \
+ match u8 0x11 0xff at 24 "${match[@]}" \
action pass
else
- tc filter add dev $dev egress pref 10 prot 802.1Q \
+ # This matches: ICMPv6
+ tc filter add dev "$dev" egress pref 10 prot 802.1Q \
flower vlan_id 10 vlan_ethtype ipv6 dst_ip ff02::1 ip_proto icmpv6 \
+ action goto chain 1
+ # AND Type 0x82 (Query) at offset 0 of MLD header
+ # 40 bytes IPv6 header + 8 bytes Hop-by-hop option + MLD[offset 0]
+ tc filter add dev "$dev" egress pref 20 chain 1 prot 802.1Q u32 \
+ match u8 0x82 0xff at 48 "${match[@]}" \
action pass
fi
@@ -181,7 +194,39 @@ vlmc_query_cnt_cleanup()
local dev=$1
ip link set dev br0 type bridge mcast_stats_enabled 0
- tc filter del dev $dev egress pref 10
+ tc filter del dev "$dev" egress pref 20 chain 1
+ tc filter del dev "$dev" egress pref 10
+}
+
+vlmc_query_get_intvl_match()
+{
+ local type=$1
+ local version=$2
+ local test=$3
+ local enc_val=$4
+
+ if [ "$test" = "qqic" ]; then
+ # QQIC is 8-bit floating point encoding for IGMPv3 and MLDv2
+ if [ "${type}v${version}" = "igmpv3" ]; then
+ # QQIC is at offset 9 of IGMP header
+ # 20 bytes IPv4 header + 4 bytes Router Alert option + IGMP[offset 9]
+ echo "match u8 $enc_val 0xff at 33"
+ elif [ "${type}v${version}" = "mldv2" ]; then
+ # QQIC is at offset 25 of MLD header
+ # 40 bytes IPv6 header + 8 bytes Hop-by-hop option + MLD[offset 25]
+ echo "match u8 $enc_val 0xff at 73"
+ fi
+ elif [ "$test" = "mrc" ]; then
+ if [ "${type}v${version}" = "igmpv3" ]; then
+ # MRC is 8-bit floating point encoding at offset 1 of IGMP header
+ # 20 bytes IPv4 header + 4 bytes Router Alert option + IGMP[offset 1]
+ echo "match u8 $enc_val 0xff at 25"
+ elif [ "${type}v${version}" = "mldv2" ]; then
+ # MRC is 16-bit floating point encoding at offset 4 of MLD header
+ # 40 bytes IPv6 header + 8 bytes Hop-by-hop option + MLD[offset 4]
+ echo "match u16 $enc_val 0xffff at 52"
+ fi
+ fi
}
vlmc_check_query()
@@ -191,9 +236,13 @@ vlmc_check_query()
local dev=$3
local expect=$4
local time=$5
+ local test=$6
+ local enc_val=$7
+ local intvl_match=""
local ret=0
- vlmc_query_cnt_setup $type $dev
+ intvl_match="$(vlmc_query_get_intvl_match "$type" "$version" "$test" "$enc_val")"
+ vlmc_query_cnt_setup "$type" "$dev" "$intvl_match"
local pre_tx_xstats=$(vlmc_query_cnt_xstats $type $version $dev)
bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_querier 1
@@ -201,7 +250,7 @@ vlmc_check_query()
if [[ $ret -eq 0 ]]; then
sleep $time
- local tcstats=$(tc_rule_stats_get $dev 10 egress)
+ local tcstats=$(tc_rule_stats_get "$dev" 20 egress)
local post_tx_xstats=$(vlmc_query_cnt_xstats $type $version $dev)
if [[ $tcstats != $expect || \
@@ -448,8 +497,46 @@ vlmc_query_intvl_test()
# 1 is sent immediately, then 2 more in the next 5 seconds
vlmc_check_query igmp 2 $swp1 3 5
check_err $? "Wrong number of tagged IGMPv2 general queries sent"
- log_test "Vlan 10 mcast_query_interval option changed to 200"
+ log_test "Number of tagged IGMPv2 general query"
+
+ RET=0
+ bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_igmp_version 3
+ check_err $? "Could not set mcast_igmp_version in vlan 10"
+ bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_mld_version 2
+ check_err $? "Could not set mcast_mld_version in vlan 10"
+ bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_interval 6000
+ check_err $? "Could not set mcast_query_interval in vlan 10"
+ # 1 is sent immediately, IGMPv3 QQIC should match with linear value 60 (0x3c)
+ # which is 8-bit encoded value of 60 [units of seconds]
+ vlmc_check_query igmp 3 $swp1 1 1 qqic 0x3c
+ check_err $? "Wrong QQIC in generated IGMPv3 general queries"
+ log_test "IGMPv3 QQIC linear value 60(s)"
+
+ RET=0
+ # 1 is sent immediately, MLDv2 QQIC should match with linear value 60 (0x3c)
+ # which is 8-bit encoded value of 60 [units of seconds]
+ vlmc_check_query mld 2 $swp1 1 1 qqic 0x3c
+ check_err $? "Wrong QQIC in generated MLDv2 general queries"
+ log_test "MLDv2 QQIC linear value 60(s)"
+
+ RET=0
+ bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_interval 16000
+ check_err $? "Could not set mcast_query_interval in vlan 10"
+ # 1 is sent immediately, IGMPv3 QQIC should match with non linear value 132 (0x84)
+ # which is 8-bit encoded value of 160 [units of seconds]
+ vlmc_check_query igmp 3 $swp1 1 1 qqic 0x84
+ check_err $? "Wrong QQIC in generated IGMPv3 general queries"
+ log_test "IGMPv3 QQIC non linear value 160(s)"
+ RET=0
+ # 1 is sent immediately, MLDv2 QQIC should match with non linear value 132 (0x84)
+ # which is 8-bit encoded value of 160 [units of seconds]
+ vlmc_check_query mld 2 $swp1 1 1 qqic 0x84
+ check_err $? "Wrong QQIC in generated MLDv2 general queries"
+ log_test "MLDv2 QQIC non linear value 160(s)"
+
+ bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_igmp_version 2
+ bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_mld_version 1
bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_query_count 2
bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_interval 12500
}
@@ -469,10 +556,47 @@ vlmc_query_response_intvl_test()
log_test "Vlan mcast_query_response_interval global option default value"
RET=0
- bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_response_interval 200
+ bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_query_count 0
+ bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_igmp_version 3
+ check_err $? "Could not set mcast_igmp_version in vlan 10"
+ bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_mld_version 2
+ check_err $? "Could not set mcast_mld_version in vlan 10"
+ bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_response_interval 600
+ check_err $? "Could not set mcast_query_response_interval in vlan 10"
+ # 1 is sent immediately, IGMPv3 MRC should match with linear value 60 (0x3c)
+ # which is 8-bit encoded value of 60 [units of 0.1s = 6 seconds]
+ vlmc_check_query igmp 3 $swp1 1 1 mrc 0x3c
+ check_err $? "Wrong MRC in generated IGMPv3 general queries"
+ log_test "IGMPv3 MRC linear value of 60(x0.1s)"
+
+ RET=0
+ bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_response_interval 2400
+ check_err $? "Could not set mcast_query_response_interval in vlan 10"
+ # 1 is sent immediately, MLDv2 MRC should match with linear value 0x5dc0 (24000)
+ # which is 16-bit encoded value of 24000 [units of ms / 24 seconds]
+ vlmc_check_query mld 2 $swp1 1 1 mrc 0x5dc0
+ check_err $? "Wrong MRC in generated MLDv2 general queries"
+ log_test "MLDv2 MRC linear value of 24000(ms)"
+
+ RET=0
+ # 1 is sent immediately, IGMPv3 MRC should match with non linear value 142 (0x8e)
+ # which is 8-bit encoded value of 240 [units of 0.1s = 24 seconds]
+ vlmc_check_query igmp 3 $swp1 1 1 mrc 0x8e
+ check_err $? "Wrong MRC in generated IGMPv3 general queries"
+ log_test "IGMPv3 MRC non linear value of 240(x0.1s)"
+
+ RET=0
+ bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_response_interval 4800
check_err $? "Could not set mcast_query_response_interval in vlan 10"
- log_test "Vlan 10 mcast_query_response_interval option changed to 200"
+ # 1 is sent immediately, MLDv2 MRC should match with non linear value 0x8770 (34672)
+ # which is 16-bit encoded value of 48000 [units of ms / 48 seconds]
+ vlmc_check_query mld 2 $swp1 1 1 mrc 0x8770
+ check_err $? "Wrong MRC in generated MLDv2 general queries"
+ log_test "MLDv2 MRC non linear value of 48000(ms)"
+ bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_igmp_version 2
+ bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_mld_version 1
+ bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_query_count 2
bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_response_interval 1000
}
--
2.43.0
^ permalink raw reply related
* [PATCH net-next v5 4/5] ipv6: mld: encode multicast exponential fields
From: Ujjal Roy @ 2026-05-01 17:31 UTC (permalink / raw)
To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Nikolay Aleksandrov, Ido Schimmel, David Ahern,
Shuah Khan, Andy Roulin, Yong Wang, Petr Machata
Cc: Ujjal Roy, bridge, netdev, linux-kernel, linux-kselftest
In-Reply-To: <20260501173130.3486-1-royujjal@gmail.com>
In MLD, MRC and QQIC fields are not correctly encoded when
generating query packets. Since the receiver of the query
interprets these fields using the MLDv2 floating-point
decoding logic, any value that exceeds the linear threshold
is incorrectly parsed as an exponential value, leading to
an incorrect interval calculation.
Encode and assign the corresponding protocol fields during
query generation. Introduce the logic to dynamically
calculate the exponent and mantissa using bit-scan (fls).
This ensures MRC (16-bit) and QQIC (8-bit) fields are
properly encoded when transmitting query packets with
intervals that exceed their respective linear thresholds
(32768 for MRD; 128 for QQI).
RFC3810: If Maximum Response Code >= 32768, the Maximum
Response Code field represents a floating-point value as
follows:
0 1 2 3 4 5 6 7 8 9 A B C D E F
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|1| exp | mant |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
RFC3810: If QQIC >= 128, the QQIC field represents a
floating-point value as follows:
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|1| exp | mant |
+-+-+-+-+-+-+-+-+
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Ujjal Roy <royujjal@gmail.com>
---
include/net/mld.h | 119 ++++++++++++++++++++++++++++++++++++++
net/bridge/br_multicast.c | 4 +-
2 files changed, 121 insertions(+), 2 deletions(-)
diff --git a/include/net/mld.h b/include/net/mld.h
index 10e402e0fe08..23255cc47ced 100644
--- a/include/net/mld.h
+++ b/include/net/mld.h
@@ -91,13 +91,132 @@ struct mld2_query {
/* MLDv2 QQIC floating-point exponential field min threshold */
#define MLD_QQIC_MIN_THRESHOLD 128
+/* MLDv2 QQIC FP max threshold (mant = 0xF, exp = 7) -> 31744 */
+#define MLD_QQIC_MAX_THRESHOLD 31744
/* MLDv2 MRC floating-point exponential field min threshold */
#define MLD_MRC_MIN_THRESHOLD 32768UL
+/* MLDv2 MRC FP max threshold (mant = 0xFFF, exp = 7) -> 8387584 */
+#define MLD_MRC_MAX_THRESHOLD 8387584
#define MLDV1_MRD_MAX_COMPAT (MLD_MRC_MIN_THRESHOLD - 1)
#define MLD_MAX_QUEUE 8
#define MLD_MAX_SKBS 32
+/* V2 exponential field encoding */
+
+/*
+ * Calculate Maximum Response Code from Maximum Response Delay
+ *
+ * MRC represents the 16-bit encoded form of Maximum Response Delay (MRD);
+ * once decoded, the resulting value is in milliseconds.
+ *
+ * RFC3810, 5.1.3. defines only the decoding formula:
+ * Maximum Response Delay = (mant | 0x1000) << (exp + 3)
+ *
+ * but does NOT define the encoding procedure. To derive exponent:
+ *
+ * For the 16-bit MRC, the "hidden bit" (0x1000) is left shifted by 12 to
+ * sit above the 12-bit mantissa. The RFC then shifts this entire block
+ * left by (exp + 3) to reconstruct the value. So, 'hidden bit' is the
+ * MSB which is shifted by (12 + exp + 3).
+ *
+ * Total left shift of the hidden bit = 12 + (exp + 3) = exp + 15.
+ * This is the MSB at the 0-based bit position: (exp + 15).
+ * Since fls() is 1-based, fls(value) - 1 = exp + 15.
+ *
+ * Therefore:
+ * exp = fls(value) - 16
+ * mant = (value >> (exp + 3)) & 0x0FFF
+ *
+ * Final encoding formula:
+ * 0x8000 | (exp << 12) | mant
+ *
+ * Example (value = 1311744):
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0| 1311744
+ * | ^-^--------mant---------^ ^...(exp+3)...^| exp=5
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Encoded:
+ * 0x8000 | (5 << 12) | 0x404 = 0xD404
+ */
+static inline u16 mldv2_mrc(unsigned long mrd)
+{
+ u16 mc_man, mc_exp;
+
+ /* MRC < 32768 is literal */
+ if (mrd < MLD_MRC_MIN_THRESHOLD)
+ return mrd;
+
+ /* Saturate at max representable (mant = 0xFFF, exp = 7) -> 8387584 */
+ if (mrd >= MLD_MRC_MAX_THRESHOLD)
+ return 0xFFFF;
+
+ mc_exp = fls(mrd) - 16;
+ mc_man = (mrd >> (mc_exp + 3)) & 0x0FFF;
+
+ return 0x8000 | (mc_exp << 12) | mc_man;
+}
+
+/*
+ * Calculate Querier's Query Interval Code from Querier's Query Interval
+ *
+ * QQIC represents the 8-bit encoded form of Querier's Query Interval (QQI);
+ * once decoded, the resulting value is in seconds.
+ *
+ * RFC3810, 5.1.9. defines only the decoding formula:
+ * QQI = (mant | 0x10) << (exp + 3)
+ *
+ * but does NOT define the encoding procedure. To derive exponent:
+ *
+ * For any value of mantissa and exponent, the decoding formula indicates
+ * that the "hidden bit" (0x10) is shifted 4 bits left to sit above the
+ * 4-bit mantissa. The RFC again shifts this entire block left by (exp + 3)
+ * to reconstruct the value. So, 'hidden bit' is the MSB which is shifted
+ * by (4 + exp + 3).
+ *
+ * Total left shift of the 'hidden bit' = 4 + (exp + 3) = exp + 7.
+ * This is the MSB at the 0-based bit position: (exp + 7).
+ * Since fls() is 1-based, fls(value) - 1 = exp + 7.
+ *
+ * Therefore:
+ * exp = fls(value) - 8
+ * mant = (value >> (exp + 3)) & 0x0F
+ *
+ * Final encoding formula:
+ * 0x80 | (exp << 4) | mant
+ *
+ * Example (value = 3200):
+ * 0 1
+ * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 0| (value = 3200)
+ * | ^-^-mant^ ^..(exp+3)..^| exp = 4, mant = 9
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Encoded:
+ * 0x80 | (4 << 4) | 9 = 0xC9
+ */
+static inline u8 mldv2_qqic(unsigned long value)
+{
+ u8 mc_man, mc_exp;
+
+ /* QQIC < 128 is literal */
+ if (value < MLD_QQIC_MIN_THRESHOLD)
+ return value;
+
+ /* Saturate at max representable (mant = 0xF, exp = 7) -> 31744 */
+ if (value >= MLD_QQIC_MAX_THRESHOLD)
+ return 0xFF;
+
+ mc_exp = fls(value) - 8;
+ mc_man = (value >> (mc_exp + 3)) & 0x0F;
+
+ return 0x80 | (mc_exp << 4) | mc_man;
+}
+
/* V2 exponential field decoding */
/* Calculate Maximum Response Delay from Maximum Response Code
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 27010744d7ae..49ceea3ff974 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1181,7 +1181,7 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge_mcast *brm
break;
case 2:
mld2q = (struct mld2_query *)icmp6_hdr(skb);
- mld2q->mld2q_mrc = htons((u16)jiffies_to_msecs(interval));
+ mld2q->mld2q_mrc = htons(mldv2_mrc(jiffies_to_msecs(interval)));
mld2q->mld2q_type = ICMPV6_MGM_QUERY;
mld2q->mld2q_code = 0;
mld2q->mld2q_cksum = 0;
@@ -1190,7 +1190,7 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge_mcast *brm
mld2q->mld2q_suppress = sflag;
mld2q->mld2q_qrv = 2;
mld2q->mld2q_nsrcs = htons(llqt_srcs);
- mld2q->mld2q_qqic = brmctx->multicast_query_interval / HZ;
+ mld2q->mld2q_qqic = mldv2_qqic(brmctx->multicast_query_interval / HZ);
mld2q->mld2q_mca = *group;
csum = &mld2q->mld2q_cksum;
csum_start = (void *)mld2q;
--
2.43.0
^ permalink raw reply related
* [PATCH net-next v5 3/5] ipv4: igmp: encode multicast exponential fields
From: Ujjal Roy @ 2026-05-01 17:31 UTC (permalink / raw)
To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Nikolay Aleksandrov, Ido Schimmel, David Ahern,
Shuah Khan, Andy Roulin, Yong Wang, Petr Machata
Cc: Ujjal Roy, bridge, netdev, linux-kernel, linux-kselftest
In-Reply-To: <20260501173130.3486-1-royujjal@gmail.com>
In IGMP, MRC and QQIC fields are not correctly encoded
when generating query packets. Since the receiver of the
query interprets these fields using the IGMPv3 floating-
point decoding logic, any value that exceeds the linear
threshold is incorrectly parsed as an exponential value,
leading to an incorrect interval calculation.
Encode and assign the corresponding protocol fields during
query generation. Introduce the logic to dynamically
calculate the exponent and mantissa using bit-scan (fls).
This ensures MRC and QQIC fields (8-bit) are properly
encoded when transmitting query packets with intervals
that exceed their respective linear threshold value of
128 (for MRT/QQI).
RFC3376: for both MRC and QQIC, values >= 128 represent
the same floating-point encoding as follows:
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|1| exp | mant |
+-+-+-+-+-+-+-+-+
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Ujjal Roy <royujjal@gmail.com>
---
include/linux/igmp.h | 87 +++++++++++++++++++++++++++++++++++++++
net/bridge/br_multicast.c | 14 +++----
2 files changed, 93 insertions(+), 8 deletions(-)
diff --git a/include/linux/igmp.h b/include/linux/igmp.h
index 0e095c9f234e..3a2d35a9f307 100644
--- a/include/linux/igmp.h
+++ b/include/linux/igmp.h
@@ -109,6 +109,93 @@ struct ip_mc_list {
/* IGMPv3 floating-point exponential field min threshold */
#define IGMPV3_EXP_MIN_THRESHOLD 128
+/* IGMPv3 FP max threshold (mant = 0xF, exp = 7) -> 31744 */
+#define IGMPV3_EXP_MAX_THRESHOLD 31744
+
+/* V3 exponential field encoding */
+
+/* IGMPv3 MRC/QQIC 8-bit exponential field encode
+ *
+ * RFC3376, 4.1.1 & 4.1.7. defines only the decoding formula:
+ * MRT/QQI = (mant | 0x10) << (exp + 3)
+ *
+ * but does NOT define the encoding procedure. To derive exponent:
+ *
+ * For any value of mantissa and exponent, the decoding formula
+ * indicates that the "hidden bit" (0x10) is shifted 4 bits left
+ * to sit above the 4-bit mantissa. The RFC again shifts this
+ * entire block left by (exp + 3) to reconstruct the value.
+ * So, 'hidden bit' is the MSB which is shifted by (4 + exp + 3).
+ *
+ * Total left shift of the 'hidden bit' = 4 + (exp + 3) = exp + 7.
+ * This is the MSB at the 0-based bit position: (exp + 7).
+ * Since fls() is 1-based, fls(value) - 1 = exp + 7.
+ *
+ * Therefore:
+ * exp = fls(value) - 8
+ * mant = (value >> (exp + 3)) & 0x0F
+ *
+ * Final encoding formula:
+ * 0x80 | (exp << 4) | mant
+ *
+ * Example (value = 3200):
+ * 0 1
+ * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 0| (value = 3200)
+ * | ^-^-mant^ ^..(exp+3)..^| exp = 4, mant = 9
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Encoded:
+ * 0x80 | (4 << 4) | 9 = 0xC9
+ */
+static inline u8 igmpv3_exp_field_encode(unsigned long value)
+{
+ u8 mc_exp, mc_man;
+
+ /* MRC/QQIC < 128 is literal */
+ if (value < IGMPV3_EXP_MIN_THRESHOLD)
+ return value;
+
+ /* Saturate at max representable (mant = 0xF, exp = 7) -> 31744 */
+ if (value >= IGMPV3_EXP_MAX_THRESHOLD)
+ return 0xFF;
+
+ mc_exp = fls(value) - 8;
+ mc_man = (value >> (mc_exp + 3)) & 0x0F;
+
+ return 0x80 | (mc_exp << 4) | mc_man;
+}
+
+/* Calculate Maximum Response Code from Max Resp Time
+ *
+ * RFC3376, relevant sections:
+ * - 4.1.1. Maximum Response Code
+ * - 8.3. Query Response Interval
+ *
+ * MRC represents the encoded form of Max Resp Time (MRT); once
+ * decoded, the resulting value is in units of 0.1 seconds (100 ms).
+ */
+static inline u8 igmpv3_mrc(unsigned long mrt)
+{
+ return igmpv3_exp_field_encode(mrt);
+}
+
+/* Calculate Querier's Query Interval Code from Querier's Query Interval
+ *
+ * RFC3376, relevant sections:
+ * - 4.1.7. QQIC (Querier's Query Interval Code)
+ * - 8.2. Query Interval
+ * - 8.12. Older Version Querier Present Timeout
+ * (the [Query Interval] in the last Query received)
+ *
+ * QQIC represents the encoded form of Querier's Query Interval (QQI);
+ * once decoded, the resulting value is in units of seconds.
+ */
+static inline u8 igmpv3_qqic(unsigned long qi)
+{
+ return igmpv3_exp_field_encode(qi);
+}
/* V3 exponential field decoding */
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 1438c023db62..27010744d7ae 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -934,12 +934,12 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge_mcast *brm
size_t pkt_size, igmp_hdr_size;
unsigned long now = jiffies;
struct igmpv3_query *ihv3;
+ unsigned long lmqt, mrt;
void *csum_start = NULL;
__sum16 *csum = NULL;
struct sk_buff *skb;
struct igmphdr *ih;
struct ethhdr *eth;
- unsigned long lmqt;
struct iphdr *iph;
u16 lmqt_srcs = 0;
@@ -1004,15 +1004,15 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge_mcast *brm
skb_put(skb, 24);
skb_set_transport_header(skb, skb->len);
+ mrt = group ? brmctx->multicast_last_member_interval :
+ brmctx->multicast_query_response_interval;
*igmp_type = IGMP_HOST_MEMBERSHIP_QUERY;
switch (brmctx->multicast_igmp_version) {
case 2:
ih = igmp_hdr(skb);
ih->type = IGMP_HOST_MEMBERSHIP_QUERY;
- ih->code = (group ? brmctx->multicast_last_member_interval :
- brmctx->multicast_query_response_interval) /
- (HZ / IGMP_TIMER_SCALE);
+ ih->code = mrt / (HZ / IGMP_TIMER_SCALE);
ih->group = group;
ih->csum = 0;
csum = &ih->csum;
@@ -1021,11 +1021,9 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge_mcast *brm
case 3:
ihv3 = igmpv3_query_hdr(skb);
ihv3->type = IGMP_HOST_MEMBERSHIP_QUERY;
- ihv3->code = (group ? brmctx->multicast_last_member_interval :
- brmctx->multicast_query_response_interval) /
- (HZ / IGMP_TIMER_SCALE);
+ ihv3->code = igmpv3_mrc(mrt / (HZ / IGMP_TIMER_SCALE));
ihv3->group = group;
- ihv3->qqic = brmctx->multicast_query_interval / HZ;
+ ihv3->qqic = igmpv3_qqic(brmctx->multicast_query_interval / HZ);
ihv3->nsrcs = htons(lmqt_srcs);
ihv3->resv = 0;
ihv3->suppress = sflag;
--
2.43.0
^ permalink raw reply related
* [PATCH net-next v5 2/5] ipv6: mld: rename mldv2_mrc() and add mldv2_qqi()
From: Ujjal Roy @ 2026-05-01 17:31 UTC (permalink / raw)
To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Nikolay Aleksandrov, Ido Schimmel, David Ahern,
Shuah Khan, Andy Roulin, Yong Wang, Petr Machata
Cc: Ujjal Roy, bridge, netdev, linux-kernel, linux-kselftest
In-Reply-To: <20260501173130.3486-1-royujjal@gmail.com>
Rename mldv2_mrc() to mldv2_mrd() as it is used to calculate
the Maximum Response Delay from the Maximum Response Code.
Introduce a new API mldv2_qqi() to define the existing
calculation logic of QQI from QQIC. This also organizes
the existing mld_update_qi() API.
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Ujjal Roy <royujjal@gmail.com>
---
include/net/mld.h | 66 +++++++++++++++++++++++++++++++++------
net/bridge/br_multicast.c | 2 +-
net/ipv6/mcast.c | 19 ++---------
3 files changed, 61 insertions(+), 26 deletions(-)
diff --git a/include/net/mld.h b/include/net/mld.h
index c07359808493..10e402e0fe08 100644
--- a/include/net/mld.h
+++ b/include/net/mld.h
@@ -89,29 +89,77 @@ struct mld2_query {
#define MLDV2_QQIC_EXP(value) (((value) >> 4) & 0x07)
#define MLDV2_QQIC_MAN(value) ((value) & 0x0f)
-#define MLD_EXP_MIN_LIMIT 32768UL
-#define MLDV1_MRD_MAX_COMPAT (MLD_EXP_MIN_LIMIT - 1)
+/* MLDv2 QQIC floating-point exponential field min threshold */
+#define MLD_QQIC_MIN_THRESHOLD 128
+/* MLDv2 MRC floating-point exponential field min threshold */
+#define MLD_MRC_MIN_THRESHOLD 32768UL
+#define MLDV1_MRD_MAX_COMPAT (MLD_MRC_MIN_THRESHOLD - 1)
#define MLD_MAX_QUEUE 8
#define MLD_MAX_SKBS 32
-static inline unsigned long mldv2_mrc(const struct mld2_query *mlh2)
+/* V2 exponential field decoding */
+
+/* Calculate Maximum Response Delay from Maximum Response Code
+ *
+ * RFC3810, relevant sections:
+ * - 5.1.3. Maximum Response Code defines the decoding formula:
+ * 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |1| exp | mant |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * Maximum Response Delay = (mant | 0x1000) << (exp+3)
+ * - 9.3. Query Response Interval
+ *
+ * After decode, MRC represents the Maximum Response Delay (MRD) in
+ * units of milliseconds.
+ */
+static inline unsigned long mldv2_mrd(const struct mld2_query *mlh2)
{
- /* RFC3810, 5.1.3. Maximum Response Code */
- unsigned long ret, mc_mrc = ntohs(mlh2->mld2q_mrc);
+ unsigned long mc_mrc = ntohs(mlh2->mld2q_mrc);
- if (mc_mrc < MLD_EXP_MIN_LIMIT) {
- ret = mc_mrc;
+ if (mc_mrc < MLD_MRC_MIN_THRESHOLD) {
+ return mc_mrc;
} else {
unsigned long mc_man, mc_exp;
mc_exp = MLDV2_MRC_EXP(mc_mrc);
mc_man = MLDV2_MRC_MAN(mc_mrc);
- ret = (mc_man | 0x1000) << (mc_exp + 3);
+ return (mc_man | 0x1000) << (mc_exp + 3);
}
+}
- return ret;
+/* Calculate Querier's Query Interval from Querier's Query Interval Code
+ *
+ * RFC3810, relevant sections:
+ * - 5.1.9. QQIC (Querier's Query Interval Code) defines the decoding formula:
+ * 0 1 2 3 4 5 6 7
+ * +-+-+-+-+-+-+-+-+
+ * |1| exp | mant |
+ * +-+-+-+-+-+-+-+-+
+ * QQI = (mant | 0x10) << (exp + 3)
+ * - 9.2. Query Interval
+ * - 9.12. Older Version Querier Present Timeout
+ * (the [Query Interval] in the last Query received)
+ *
+ * After decode, QQIC represents the Querier's Query Interval in units
+ * of seconds.
+ */
+static inline unsigned long mldv2_qqi(const struct mld2_query *mlh2)
+{
+ unsigned long qqic = mlh2->mld2q_qqic;
+
+ if (qqic < MLD_QQIC_MIN_THRESHOLD) {
+ return qqic;
+ } else {
+ unsigned long mc_man, mc_exp;
+
+ mc_exp = MLDV2_QQIC_EXP(qqic);
+ mc_man = MLDV2_QQIC_MAN(qqic);
+
+ return (mc_man | 0x10) << (mc_exp + 3);
+ }
}
#endif
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 9fec76e887bc..1438c023db62 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -3606,7 +3606,7 @@ static int br_ip6_multicast_query(struct net_bridge_mcast *brmctx,
mld2q->mld2q_suppress)
goto out;
- max_delay = max(msecs_to_jiffies(mldv2_mrc(mld2q)), 1UL);
+ max_delay = max(msecs_to_jiffies(mldv2_mrd(mld2q)), 1UL);
}
is_general_query = group && ipv6_addr_any(group);
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 3330adcf26db..6ddc18ac59b9 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1315,20 +1315,7 @@ static void mld_update_qi(struct inet6_dev *idev,
* - 9.12. Older Version Querier Present Timeout
* (the [Query Interval] in the last Query received)
*/
- unsigned long mc_qqi;
-
- if (mlh2->mld2q_qqic < 128) {
- mc_qqi = mlh2->mld2q_qqic;
- } else {
- unsigned long mc_man, mc_exp;
-
- mc_exp = MLDV2_QQIC_EXP(mlh2->mld2q_qqic);
- mc_man = MLDV2_QQIC_MAN(mlh2->mld2q_qqic);
-
- mc_qqi = (mc_man | 0x10) << (mc_exp + 3);
- }
-
- idev->mc_qi = mc_qqi * HZ;
+ idev->mc_qi = mldv2_qqi(mlh2) * HZ;
}
static void mld_update_qri(struct inet6_dev *idev,
@@ -1338,7 +1325,7 @@ static void mld_update_qri(struct inet6_dev *idev,
* - 5.1.3. Maximum Response Code
* - 9.3. Query Response Interval
*/
- idev->mc_qri = msecs_to_jiffies(mldv2_mrc(mlh2));
+ idev->mc_qri = msecs_to_jiffies(mldv2_mrd(mlh2));
}
static int mld_process_v1(struct inet6_dev *idev, struct mld_msg *mld,
@@ -1390,7 +1377,7 @@ static int mld_process_v1(struct inet6_dev *idev, struct mld_msg *mld,
static void mld_process_v2(struct inet6_dev *idev, struct mld2_query *mld,
unsigned long *max_delay)
{
- *max_delay = max(msecs_to_jiffies(mldv2_mrc(mld)), 1UL);
+ *max_delay = max(msecs_to_jiffies(mldv2_mrd(mld)), 1UL);
mld_update_qrv(idev, mld);
mld_update_qi(idev, mld);
--
2.43.0
^ permalink raw reply related
* [PATCH net-next v5 1/5] ipv4: igmp: get rid of IGMPV3_{QQIC,MRC} and simplify calculation
From: Ujjal Roy @ 2026-05-01 17:31 UTC (permalink / raw)
To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Nikolay Aleksandrov, Ido Schimmel, David Ahern,
Shuah Khan, Andy Roulin, Yong Wang, Petr Machata
Cc: Ujjal Roy, bridge, netdev, linux-kernel, linux-kselftest
In-Reply-To: <20260501173130.3486-1-royujjal@gmail.com>
Get rid of the IGMPV3_MRC macro and use the igmpv3_mrt() API to
calculate the Max Resp Time from the Maximum Response Code.
Similarly, for IGMPV3_QQIC, use the igmpv3_qqi() API to calculate
the Querier's Query Interval from the QQIC field.
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Ujjal Roy <royujjal@gmail.com>
---
include/linux/igmp.h | 80 +++++++++++++++++++++++++++++++++++----
net/bridge/br_multicast.c | 2 +-
net/ipv4/igmp.c | 6 +--
3 files changed, 76 insertions(+), 12 deletions(-)
diff --git a/include/linux/igmp.h b/include/linux/igmp.h
index 073b30a9b850..0e095c9f234e 100644
--- a/include/linux/igmp.h
+++ b/include/linux/igmp.h
@@ -92,15 +92,79 @@ struct ip_mc_list {
struct rcu_head rcu;
};
+/* RFC3376, relevant sections:
+ * - 4.1.1. Maximum Response Code
+ * - 4.1.7. QQIC (Querier's Query Interval Code)
+ *
+ * For both MRC and QQIC, values >= 128 use the same floating-point
+ * encoding as follows:
+ *
+ * 0 1 2 3 4 5 6 7
+ * +-+-+-+-+-+-+-+-+
+ * |1| exp | mant |
+ * +-+-+-+-+-+-+-+-+
+ */
+#define IGMPV3_FP_EXP(value) (((value) >> 4) & 0x07)
+#define IGMPV3_FP_MAN(value) ((value) & 0x0f)
+
+/* IGMPv3 floating-point exponential field min threshold */
+#define IGMPV3_EXP_MIN_THRESHOLD 128
+
/* V3 exponential field decoding */
-#define IGMPV3_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value))
-#define IGMPV3_EXP(thresh, nbmant, nbexp, value) \
- ((value) < (thresh) ? (value) : \
- ((IGMPV3_MASK(value, nbmant) | (1<<(nbmant))) << \
- (IGMPV3_MASK((value) >> (nbmant), nbexp) + (nbexp))))
-
-#define IGMPV3_QQIC(value) IGMPV3_EXP(0x80, 4, 3, value)
-#define IGMPV3_MRC(value) IGMPV3_EXP(0x80, 4, 3, value)
+
+/* IGMPv3 MRC/QQIC 8-bit exponential field decode
+ *
+ * RFC3376, 4.1.1 & 4.1.7. defines the decoding formula:
+ * 0 1 2 3 4 5 6 7
+ * +-+-+-+-+-+-+-+-+
+ * |1| exp | mant |
+ * +-+-+-+-+-+-+-+-+
+ * Max Resp Time = (mant | 0x10) << (exp + 3)
+ * QQI = (mant | 0x10) << (exp + 3)
+ */
+static inline unsigned long igmpv3_exp_field_decode(const u8 code)
+{
+ if (code < IGMPV3_EXP_MIN_THRESHOLD) {
+ return code;
+ } else {
+ unsigned long mc_man, mc_exp;
+
+ mc_exp = IGMPV3_FP_EXP(code);
+ mc_man = IGMPV3_FP_MAN(code);
+
+ return (mc_man | 0x10) << (mc_exp + 3);
+ }
+}
+
+/* Calculate Max Resp Time from Maximum Response Code
+ *
+ * RFC3376, relevant sections:
+ * - 4.1.1. Maximum Response Code
+ * - 8.3. Query Response Interval
+ *
+ * After decode, MRC represents the Maximum Response Time (MRT) in
+ * units of 0.1 seconds (100 ms).
+ */
+static inline unsigned long igmpv3_mrt(const struct igmpv3_query *ih3)
+{
+ return igmpv3_exp_field_decode(ih3->code);
+}
+
+/* Calculate Querier's Query Interval from Querier's Query Interval Code
+ *
+ * RFC3376, relevant sections:
+ * - 4.1.7. QQIC (Querier's Query Interval Code)
+ * - 8.2. Query Interval
+ * - 8.12. Older Version Querier Present Timeout
+ * (the [Query Interval] in the last Query received)
+ *
+ * After decode, QQIC represents the Querier's Query Interval in units
+ * of seconds.
+ */
+static inline unsigned long igmpv3_qqi(const struct igmpv3_query *ih3)
+{
+ return igmpv3_exp_field_decode(ih3->qqic);
+}
static inline int ip_mc_may_pull(struct sk_buff *skb, unsigned int len)
{
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 881d866d687a..9fec76e887bc 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -3518,7 +3518,7 @@ static void br_ip4_multicast_query(struct net_bridge_mcast *brmctx,
goto out;
max_delay = ih3->code ?
- IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1;
+ igmpv3_mrt(ih3) * (HZ / IGMP_TIMER_SCALE) : 1;
} else {
goto out;
}
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index a674fb44ec25..d7eff36d98c3 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -991,7 +991,7 @@ static bool igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
* different encoding. We use the v3 encoding as more likely
* to be intended in a v3 query.
*/
- max_delay = IGMPV3_MRC(ih3->code)*(HZ/IGMP_TIMER_SCALE);
+ max_delay = igmpv3_mrt(ih3) * (HZ / IGMP_TIMER_SCALE);
if (!max_delay)
max_delay = 1; /* can't mod w/ 0 */
} else { /* v3 */
@@ -1006,7 +1006,7 @@ static bool igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
ih3 = igmpv3_query_hdr(skb);
}
- max_delay = IGMPV3_MRC(ih3->code)*(HZ/IGMP_TIMER_SCALE);
+ max_delay = igmpv3_mrt(ih3) * (HZ / IGMP_TIMER_SCALE);
if (!max_delay)
max_delay = 1; /* can't mod w/ 0 */
WRITE_ONCE(in_dev->mr_maxdelay, max_delay);
@@ -1016,7 +1016,7 @@ static bool igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
* configured value.
*/
in_dev->mr_qrv = ih3->qrv ?: READ_ONCE(net->ipv4.sysctl_igmp_qrv);
- in_dev->mr_qi = IGMPV3_QQIC(ih3->qqic)*HZ ?: IGMP_QUERY_INTERVAL;
+ in_dev->mr_qi = igmpv3_qqi(ih3) * HZ ? : IGMP_QUERY_INTERVAL;
/* RFC3376, 8.3. Query Response Interval:
* The number of seconds represented by the [Query Response
--
2.43.0
^ permalink raw reply related
* [PATCH net-next v5 0/5] net: bridge: mcast: support exponential field encoding
From: Ujjal Roy @ 2026-05-01 17:31 UTC (permalink / raw)
To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Nikolay Aleksandrov, Ido Schimmel, David Ahern,
Shuah Khan, Andy Roulin, Yong Wang, Petr Machata
Cc: Ujjal Roy, bridge, netdev, linux-kernel, linux-kselftest
Description:
This series addresses a mismatch in how multicast query
intervals and response codes are handled across IPv4 (IGMPv3)
and IPv6 (MLDv2). While decoding logic currently exists,
the corresponding encoding logic is missing during query
packet generation. This leads to incorrect intervals being
transmitted when values exceed their linear thresholds.
The patches introduce a unified floating-point encoding
approach based on RFC3376 and RFC3810, ensuring that large
intervals are correctly represented in QQIC and MRC fields
using the exponent-mantissa format.
Key Changes:
* ipv4: igmp: get rid of IGMPV3_{QQIC,MRC} and simplify calculation
Removes legacy macros in favor of a cleaner, unified
calculation for retrieving intervals from encoded fields,
improving code maintainability.
* ipv6: mld: rename mldv2_mrc() and add mldv2_qqi()
Standardizes MLDv2 terminology by renaming mldv2_mrc()
to mldv2_mrd() (Maximum Response Delay) and introducing
a new API mldv2_qqi for QQI calculation, improving code
readability.
* ipv4: igmp: encode multicast exponential fields
Introduces the logic to dynamically calculate the exponent
and mantissa using bit-scan (fls). This ensures QQIC and
MRC fields (8-bit) are properly encoded when transmitting
query packets with intervals that exceed their respective
linear threshold value of 128 (for QQI/MRT).
* ipv6: mld: encode multicast exponential fields
Applies similar encoding logic for MLDv2. This ensures
QQIC (8-bit) and MRC (16-bit) fields are properly encoded
when transmitting query packets with intervals that exceed
their respective linear thresholds (128 for QQI; 32768
for MRD).
* selftests: net: bridge: add MRC and QQIC field encoding tests
Updates bridge selftests to validate both linear and non-linear
(exponential) encoding for MRC and QQIC fields, ensuring
protocol compliance across IGMPv3 and MLDv2.
Impact:
These changes ensure that multicast queriers and listeners
stay synchronized on timing intervals, preventing protocol
timeouts or premature group membership expiration caused
by incorrectly formatted packet headers.
Test results:
Giving results only from modified API vlmc_query_intvl_test() and
vlmc_query_response_intvl_test() of the script bridge_vlan_mcast.sh.
Using old Linux code, here is the result:
- TEST: Vlan multicast snooping enable [ OK ]
- TEST: Vlan mcast_query_interval global option default value [ OK ]
- TEST: Number of tagged IGMPv2 general query [ OK ]
- TEST: IGMPv3 QQIC linear value 60(s) [ OK ]
- TEST: MLDv2 QQIC linear value 60(s) [ OK ]
- TEST: IGMPv3 QQIC non linear value 160(s) [FAIL]
- Wrong QQIC in generated IGMPv3 general queries
- TEST: MLDv2 QQIC non linear value 160(s) [FAIL]
- Wrong QQIC in generated MLDv2 general queries
- TEST: Vlan mcast_query_response_interval global option default value [ OK ]
- TEST: IGMPv3 MRC linear value of 60(x0.1s) [ OK ]
- TEST: MLDv2 MRC linear value of 24000(ms) [ OK ]
- TEST: IGMPv3 MRC non linear value of 240(x0.1s) [FAIL]
- Wrong MRC in generated IGMPv3 general queries
- TEST: MLDv2 MRC non linear value of 48000(ms) [FAIL]
- Wrong MRC in generated MLDv2 general queries
Linux code with this patchset, here is the result:
* TEST: Vlan multicast snooping enable [ OK ]
* TEST: Vlan mcast_query_interval global option default value [ OK ]
* TEST: Number of tagged IGMPv2 general query [ OK ]
* TEST: IGMPv3 QQIC linear value 60(s) [ OK ]
* TEST: MLDv2 QQIC linear value 60(s) [ OK ]
* TEST: IGMPv3 QQIC non linear value 160(s) [ OK ]
* TEST: MLDv2 QQIC non linear value 160(s) [ OK ]
* TEST: Vlan mcast_query_response_interval global option default value [ OK ]
* TEST: IGMPv3 MRC linear value of 60(x0.1s) [ OK ]
* TEST: MLDv2 MRC linear value of 24000(ms) [ OK ]
* TEST: IGMPv3 MRC non linear value of 240(x0.1s) [ OK ]
* TEST: MLDv2 MRC non linear value of 48000(ms) [ OK ]
v5:
- Added 'Reviewed-by:' as requested
- Modified script to fix AND logic in classifiers and updated comments
- Passed expected value as argument rather than hard coding in script
- Added minor comments for macros
v4:
- Removed binary application and related codes for selftests
- Decided hard coded match based on extra arguments for selftests
- Ran shellcheck on modified selftests code and fixed
- Updated comments on patch[1,2,3,4] as per review
- Added 'Reviewed-by:' as requested on patch4
v3:
- Updated the series title for better clarity; old one is here
https://lore.kernel.org/all/20260326150742.50289-1-royujjal@gmail.com/
- Added key changes section for new selftests patch
- Updated netdev style comments and addressed review comments
- Fixed MLDv2 MRC conversion logic during query generation
- Mentioned intervals in units wherever applicable
- Dropped type casting and fixed indentations
v2:
- Retargeted the series to net-next as suggested
- Fixed a compilation warning in the MLD rename change
- Kept reverse xmas tree order in IGMP exponential encoding change
- Added bridge selftests to validate IGMPv3 Query MRC and QQIC handling
Ujjal Roy (5):
ipv4: igmp: get rid of IGMPV3_{QQIC,MRC} and simplify calculation
ipv6: mld: rename mldv2_mrc() and add mldv2_qqi()
ipv4: igmp: encode multicast exponential fields
ipv6: mld: encode multicast exponential fields
selftests: net: bridge: add MRC and QQIC field encoding tests
include/linux/igmp.h | 167 +++++++++++++++-
include/net/mld.h | 185 +++++++++++++++++-
net/bridge/br_multicast.c | 22 +--
net/ipv4/igmp.c | 6 +-
net/ipv6/mcast.c | 19 +-
.../net/forwarding/bridge_vlan_mcast.sh | 140 ++++++++++++-
6 files changed, 483 insertions(+), 56 deletions(-)
base-commit: edf4bee4215a173c0534d1851d7523d827149f9e
--
2.43.0
^ permalink raw reply
* Re: [PATCH net-next 05/12] net: stmmac: dwxgmac2: Add multi MSI interrupt mode
From: Andrew Lunn @ 2026-05-01 17:21 UTC (permalink / raw)
To: Alex Elder
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, maxime.chevallier,
rmk+kernel, andersson, konradybcio, robh, krzk+dt, conor+dt,
linusw, brgl, arnd, gregkh, Daniel Thompson, mohd.anwar,
a0987203069, alexandre.torgue, ast, boon.khai.ng, chenchuangyu,
chenhuacai, daniel, hawk, hkallweit1, inochiama, john.fastabend,
julianbraha, livelycarpet87, matthew.gerlach, mcoquelin.stm32, me,
prabhakar.mahadev-lad.rj, richardcochran, rohan.g.thomas, sdf,
siyanteng, weishangjuan, wens, netdev, bpf, linux-arm-msm,
devicetree, linux-gpio, linux-stm32, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260501155421.3329862-6-elder@riscstar.com>
On Fri, May 01, 2026 at 10:54:13AM -0500, Alex Elder wrote:
> From: Daniel Thompson <daniel@riscstar.com>
>
> Currently there are no XGMAC platforms integrated using the multi MSI
> interrupt mode. In other words no existing driver sets both
> DWMAC_CORE_XGMAC and STMMAC_FLAG_MULTI_MSI_EN.
>
> In order to support systems that do enable both options (such as the
> Toshiba TC9564 whose driver is currently being developed) we need to
> add logic to the XGMAC DMA callbacks. Happily we can simply
> replicate similar code from GMAC4. Let's do that!
The word replicate made me think it has been cut/paste, rather than
being refactored into a helper. However,
> +#define XGMAC_INTM_MASK GENMASK(13, 12)
#define DMA_BUS_MODE_INTM_MASK GENMASK(17, 16)
Different bits in the register, so the code structure is the same, but
the code cannot be shared in a meaningful way. So this is O.K.
Andrew
^ permalink raw reply
* Re: [PATCH net-next 3/3] net: selftests: add getsockopt_iter regression tests
From: Bobby Eshleman @ 2026-05-01 17:17 UTC (permalink / raw)
To: Breno Leitao
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Stefano Garzarella, Shuah Khan, sdf.kernel, netdev,
linux-kernel, virtualization, linux-kselftest, kernel-team
In-Reply-To: <20260501-getsock_one-v1-3-810ce23ea70e@debian.org>
On Fri, May 01, 2026 at 08:52:53AM -0700, Breno Leitao wrote:
> Add a single kselftest covering the proto_ops getsockopt_iter
> conversions for AF_NETLINK and AF_VSOCK, using one fixture per protocol:
>
> netlink:
>
> NETLINK_PKTINFO covers the flag-style int path (exact size, oversize
> clamp, undersize -EINVAL); NETLINK_LIST_MEMBERSHIPS covers the
> size-discovery path that always reports the required buffer length back
> via optlen, even when the user buffer is too small to receive any group
> bits.
>
> vsock:
> SO_VM_SOCKETS_BUFFER_SIZE covers the u64 path (exact size, oversize
> clamp, undersize -EINVAL).
>
> Each fixture also exercises an unknown optname and a bogus level so
> the returned-length / errno semantics preserved by the sockopt_t
> conversion are pinned down.
>
> Signed-off-by: Breno Leitao <leitao@debian.org>
This all looks good to me. My only thought was
SO_VM_SOCKETS_CONNECT_TIMEOUT_NEW/OLD would be a nice add-on for testing
greater than u64, but probably overkill since you already have
NETLINK_LIST_MEMBERSHIPS.
Code all looks reasonable.
Reviewed-by: Bobby Eshleman <bobbyeshleman@meta.com>
> ---
> tools/testing/selftests/net/Makefile | 1 +
> tools/testing/selftests/net/getsockopt_iter.c | 213 ++++++++++++++++++++++++++
> 2 files changed, 214 insertions(+)
>
> diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
> index a275ed5840265..baa30287cf222 100644
> --- a/tools/testing/selftests/net/Makefile
> +++ b/tools/testing/selftests/net/Makefile
> @@ -176,6 +176,7 @@ TEST_GEN_PROGS := \
> bind_timewait \
> bind_wildcard \
> epoll_busy_poll \
> + getsockopt_iter \
> icmp_rfc4884 \
> ipv6_fragmentation \
> proc_net_pktgen \
> diff --git a/tools/testing/selftests/net/getsockopt_iter.c b/tools/testing/selftests/net/getsockopt_iter.c
> new file mode 100644
> index 0000000000000..179f9e84926fd
> --- /dev/null
> +++ b/tools/testing/selftests/net/getsockopt_iter.c
> @@ -0,0 +1,213 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Quick test for getsockopt{_iter} tests.
> + *
> + * Each fixture targets one converted protocol and pins down the
> + * returned-length / errno semantics across buffer-size variations,
> + * an unknown optname and a bogus level.
> + *
> + * - netlink: NETLINK_PKTINFO covers the flag-style int path; the
> + * NETLINK_LIST_MEMBERSHIPS cases cover the size-discovery path
> + * that always reports the required buffer length back via optlen,
> + * even when the user buffer is too small to receive any group bits.
> + * - vsock: SO_VM_SOCKETS_BUFFER_SIZE covers the u64 path.
> + *
> + * Author: Breno Leitao <leitao@debian.org>
> + */
> +
> +#include <errno.h>
> +#include <stdint.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <linux/netlink.h>
> +#include <linux/rtnetlink.h>
> +#include <linux/vm_sockets.h>
> +#include <sys/socket.h>
> +#include "kselftest_harness.h"
> +
> +#ifndef AF_VSOCK
> +#define AF_VSOCK 40
> +#endif
> +
> +/* ---------- netlink ---------- */
> +
> +FIXTURE(netlink)
> +{
> + int fd;
> +};
> +
> +FIXTURE_SETUP(netlink)
> +{
> + int group = RTNLGRP_LINK;
> +
> + self->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
> + if (self->fd < 0)
> + SKIP(return, "AF_NETLINK socket: %s", strerror(errno));
> +
> + /* Joining a multicast group grows nlk->ngroups so the
> + * NETLINK_LIST_MEMBERSHIPS path has a non-zero size to report.
> + */
> + if (setsockopt(self->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
> + &group, sizeof(group)) < 0)
> + SKIP(return, "NETLINK_ADD_MEMBERSHIP: %s", strerror(errno));
> +}
> +
> +FIXTURE_TEARDOWN(netlink)
> +{
> + if (self->fd >= 0)
> + close(self->fd);
> +}
> +
> +TEST_F(netlink, pktinfo_exact)
> +{
> + int val = -1;
> + socklen_t optlen = sizeof(val);
> +
> + ASSERT_EQ(0, getsockopt(self->fd, SOL_NETLINK, NETLINK_PKTINFO,
> + &val, &optlen));
> + ASSERT_EQ(sizeof(int), optlen);
> + ASSERT_TRUE(val == 0 || val == 1);
> +}
> +
> +TEST_F(netlink, pktinfo_oversize_clamped)
> +{
> + char buf[16] = {};
> + socklen_t optlen = sizeof(buf);
> +
> + ASSERT_EQ(0, getsockopt(self->fd, SOL_NETLINK, NETLINK_PKTINFO,
> + buf, &optlen));
> + ASSERT_EQ(sizeof(int), optlen);
> +}
> +
> +TEST_F(netlink, pktinfo_undersize)
> +{
> + char buf[2] = {};
> + socklen_t optlen = sizeof(buf);
> +
> + ASSERT_EQ(-1, getsockopt(self->fd, SOL_NETLINK, NETLINK_PKTINFO,
> + buf, &optlen));
> + ASSERT_EQ(EINVAL, errno);
> +}
> +
> +TEST_F(netlink, list_memberships_size_discovery)
> +{
> + socklen_t optlen = 0;
> + char dummy;
> +
> + ASSERT_EQ(0, getsockopt(self->fd, SOL_NETLINK,
> + NETLINK_LIST_MEMBERSHIPS,
> + &dummy, &optlen));
> + ASSERT_GT(optlen, 0);
> + ASSERT_EQ(0, optlen % sizeof(__u32));
> +}
> +
> +TEST_F(netlink, list_memberships_full_read)
> +{
> + __u32 buf[64] = {};
> + socklen_t optlen = sizeof(buf);
> +
> + ASSERT_EQ(0, getsockopt(self->fd, SOL_NETLINK,
> + NETLINK_LIST_MEMBERSHIPS,
> + buf, &optlen));
> + ASSERT_GT(optlen, 0);
> + ASSERT_LE(optlen, sizeof(buf));
> + ASSERT_EQ(0, optlen % sizeof(__u32));
> +}
> +
> +TEST_F(netlink, bad_level)
> +{
> + int val;
> + socklen_t optlen = sizeof(val);
> +
> + ASSERT_EQ(-1, getsockopt(self->fd, SOL_SOCKET + 1, NETLINK_PKTINFO,
> + &val, &optlen));
> + ASSERT_EQ(ENOPROTOOPT, errno);
> +}
> +
> +TEST_F(netlink, bad_optname)
> +{
> + int val;
> + socklen_t optlen = sizeof(val);
> +
> + ASSERT_EQ(-1, getsockopt(self->fd, SOL_NETLINK, 0x7fff,
> + &val, &optlen));
> + ASSERT_EQ(ENOPROTOOPT, errno);
> +}
> +
> +/* ---------- vsock ---------- */
> +
> +FIXTURE(vsock)
> +{
> + int fd;
> +};
> +
> +FIXTURE_SETUP(vsock)
> +{
> + self->fd = socket(AF_VSOCK, SOCK_STREAM, 0);
> + if (self->fd < 0)
> + SKIP(return, "AF_VSOCK socket: %s", strerror(errno));
> +}
> +
> +FIXTURE_TEARDOWN(vsock)
> +{
> + if (self->fd >= 0)
> + close(self->fd);
> +}
> +
> +TEST_F(vsock, buffer_size_exact)
> +{
> + uint64_t val = 0;
> + socklen_t optlen = sizeof(val);
> +
> + ASSERT_EQ(0, getsockopt(self->fd, AF_VSOCK,
> + SO_VM_SOCKETS_BUFFER_SIZE,
> + &val, &optlen));
> + ASSERT_EQ(sizeof(uint64_t), optlen);
> + ASSERT_GT(val, 0);
> +}
> +
> +TEST_F(vsock, buffer_size_oversize_clamped)
> +{
> + char buf[16] = {};
> + socklen_t optlen = sizeof(buf);
> +
> + ASSERT_EQ(0, getsockopt(self->fd, AF_VSOCK,
> + SO_VM_SOCKETS_BUFFER_SIZE,
> + buf, &optlen));
> + ASSERT_EQ(sizeof(uint64_t), optlen);
> +}
> +
> +TEST_F(vsock, buffer_size_undersize)
> +{
> + char buf[4] = {};
> + socklen_t optlen = sizeof(buf);
> +
> + ASSERT_EQ(-1, getsockopt(self->fd, AF_VSOCK,
> + SO_VM_SOCKETS_BUFFER_SIZE,
> + buf, &optlen));
> + ASSERT_EQ(EINVAL, errno);
> +}
> +
> +TEST_F(vsock, bad_level)
> +{
> + uint64_t val;
> + socklen_t optlen = sizeof(val);
> +
> + ASSERT_EQ(-1, getsockopt(self->fd, SOL_SOCKET + 1,
> + SO_VM_SOCKETS_BUFFER_SIZE,
> + &val, &optlen));
> + ASSERT_EQ(ENOPROTOOPT, errno);
> +}
> +
> +TEST_F(vsock, bad_optname)
> +{
> + uint64_t val;
> + socklen_t optlen = sizeof(val);
> +
> + ASSERT_EQ(-1, getsockopt(self->fd, AF_VSOCK, 0x7fff,
> + &val, &optlen));
> + ASSERT_EQ(ENOPROTOOPT, errno);
> +}
> +
> +TEST_HARNESS_MAIN
>
> --
> 2.52.0
>
^ permalink raw reply
* Re: [PATCH net-next 04/12] net: stmmac: dma: create a separate dma_device pointer
From: Andrew Lunn @ 2026-05-01 17:13 UTC (permalink / raw)
To: Alex Elder
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, maxime.chevallier,
rmk+kernel, andersson, konradybcio, robh, krzk+dt, conor+dt,
linusw, brgl, arnd, gregkh, daniel, mohd.anwar, a0987203069,
alexandre.torgue, ast, boon.khai.ng, chenchuangyu, chenhuacai,
daniel, hawk, hkallweit1, inochiama, john.fastabend, julianbraha,
livelycarpet87, matthew.gerlach, mcoquelin.stm32, me,
prabhakar.mahadev-lad.rj, richardcochran, rohan.g.thomas, sdf,
siyanteng, weishangjuan, wens, netdev, bpf, linux-arm-msm,
devicetree, linux-gpio, linux-stm32, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260501155421.3329862-5-elder@riscstar.com>
> if (priv->dma_cap.host_dma_width) {
> - ret = dma_set_mask_and_coherent(device,
> - DMA_BIT_MASK(priv->dma_cap.host_dma_width));
> + u64 mask = DMA_BIT_MASK(priv->dma_cap.host_dma_width);
> +
> + ret = dma_set_mask_and_coherent(priv->dma_device, mask);
I'm nitpicking, but i don't think you need to introduce mask.
DMA_BIT_MASK... is already on a line of its own, and is within the 80
limit. Nothing changes here with s/device/priv->dma_device/
Andrew
^ permalink raw reply
* Re: [PATCH net-next 03/12] net: pcs: pcs-xpcs: Preserve BMCR_ANENBLE during link up
From: Andrew Lunn @ 2026-05-01 17:06 UTC (permalink / raw)
To: Alex Elder
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, maxime.chevallier,
rmk+kernel, andersson, konradybcio, robh, krzk+dt, conor+dt,
linusw, brgl, arnd, gregkh, Daniel Thompson, mohd.anwar,
a0987203069, alexandre.torgue, ast, boon.khai.ng, chenchuangyu,
chenhuacai, daniel, hawk, hkallweit1, inochiama, john.fastabend,
julianbraha, livelycarpet87, matthew.gerlach, mcoquelin.stm32, me,
prabhakar.mahadev-lad.rj, richardcochran, rohan.g.thomas, sdf,
siyanteng, weishangjuan, wens, netdev, bpf, linux-arm-msm,
devicetree, linux-gpio, linux-stm32, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260501155421.3329862-4-elder@riscstar.com>
On Fri, May 01, 2026 at 10:54:11AM -0500, Alex Elder wrote:
> From: Daniel Thompson <daniel@riscstar.com>
>
> Currently the XCPS found on Toshiba TC9564 (a.k.a. Qualcomm QPS615)
> is unable to operate at 1000base-X and slower with a PHY connected
> using SGMII/2500base-X (in our case a Qualcomm QCA8081). The link
> negotiates speed correctly but the MAC can't get any packets out.
We need to break this down into its components.
I assume you are saying the PHY negotiates the media speed with the
link partner. That is PHY talking to PHY.
But we also have the PCS talking to the PHY. There can be inband
signalling here, for SGMII and 2500BaseX. But not for over clocked
SGMII, which is how some vendors implement 2500BaseX. SGMII signalling
does not work when overclocked to 2.5G.
> This attracted attention to the ANENABLE bit and we observed that the
> bit is currently set during config and cleared during link up.
Here we are talking about the PCS ANEBNABLE, not the PHY ANEBNABLE. So
this is negotiation between the PCS and the PHY.
> Preserving the bit during link up allows the system to work as expected.
> int ret;
>
> if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
> return;
Think about this.
> ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MII_BMCR,
> - mii_bmcr_encode_fixed(speed, duplex));
> + mii_bmcr_encode_fixed(speed, duplex) | an_enable);
And mii_bmcr_encode_fixed().
Andrew
^ permalink raw reply
* Re: [PATCH] selftests: mptcp: add test for IPv6 subflow SLAB placement
From: Vastargazing @ 2026-05-01 17:01 UTC (permalink / raw)
To: matttbe; +Cc: martineau, mptcp, netdev, linux-kselftest, shuah, stable, fw
In-Reply-To: <44e564f8-d059-407b-8f5e-a149dd76dea3@kernel.org>
Hi Matt,
Thanks for the review (and for cc'ing Florian - same mistake twice, noted).
You're right on both. The 755 thing is on me, and i'm convinced the
standalone script is too much for what's essentially a one-time init
ordering issue - the fix commit is the safety net here.
Withdrawing the patch.
One question if you don't mind: if something similar came up again and
a test *was* warranted, which existing script would be the natural
home? mptcp_join.sh seemed closest since it exercises the accept path,
but i'm not sure if checking /proc/slabinfo fits there or if there's a
better mechanism for that kind of thing.
Vastargazing
^ permalink raw reply
* Re: [PATCH net] rxrpc: Also unshare DATA/RESPONSE packets when paged frags are present
From: Hyunwoo Kim @ 2026-05-01 16:57 UTC (permalink / raw)
To: Simon Horman
Cc: dhowells, marc.dionne, davem, edumazet, kuba, pabeni, linux-afs,
netdev, imv4bel
In-Reply-To: <20260501155806.222592-3-horms@kernel.org>
On Fri, May 01, 2026 at 04:58:08PM +0100, Simon Horman wrote:
> From: 'Simon Horman' <horms@kernel.org>
>
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> Full review at: https://sashiko.dev
> ---
> rxrpc: Also unshare DATA/RESPONSE packets when paged frags are present
>
> This commit updates the DATA and RESPONSE packet handlers in rxrpc to copy
> the skb into a linear one if there are paged fragments present. This ensures
> the security handler operates on a fully linear skb during decryption.
>
> > diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c
> > index fdd683261226..6c924ef55208 100644
> > --- a/net/rxrpc/call_event.c
> > +++ b/net/rxrpc/call_event.c
> > @@ -334,7 +334,7 @@ bool rxrpc_input_call_event(struct rxrpc_call *call)
> >
> > if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA &&
> > sp->hdr.securityIndex != 0 &&
> > - skb_cloned(skb)) {
> > + (skb_cloned(skb) || skb->data_len)) {
> > /* Unshare the packet so that it can be
> > * modified by in-place decryption.
> > */
>
> Since modern NIC drivers commonly use page pools where packet payloads are
> placed in page fragments, skb->data_len will be greater than zero for almost
> all standard incoming packets.
>
> By taking this path, the code calls skb_copy() right after this check.
> Will this force a full packet copy for nearly all incoming RxRPC DATA
> packets, bypassing zero-copy receive paths and causing a large performance
> regression?
>
> Additionally, skb_copy() fully linearizes the packet by allocating a single
> contiguous buffer for the entire packet size. For RxRPC Jumbo packets or UDP
> GRO-aggregated packets (which can reach up to ~64KB), this requires an
> order-4 page allocation.
>
> Could relying on an order-4 GFP_ATOMIC allocation cause reliable OOM
> failures and packet drops on fragmented systems?
>
> If the goal is to ensure the skb is writable for in-place decryption, would
> it be safer to use skb_cow_data() instead of forcing a full contiguous
> linearization?
>
> Simon says:
>
> I note that this patch included
> Fixes: d0d5c0cd1e71 ("rxrpc: Use skb_unshare() rather than skb_cow_data()")
> And that the suggestion in the last paragraph above would
> reintroduce back to the problem addressed by d0d5c0cd1e71.
Yes. applying the ai's suggestion would reintroduce the bug fixed
by d0d5c0cd1e71.
The performance concern regarding skb_copy() is, however, valid.
That said, I cannot think of a way to keep the zero-copy path while
still handling in-place decryption properly. Suggestions welcome.
Best regards,
Hyunwoo Kim
^ permalink raw reply
* Re: [PATCH net-next 02/12] net: pcs: pcs-xpcs: select operating mode for 10G-baseR capable PCS
From: Andrew Lunn @ 2026-05-01 16:50 UTC (permalink / raw)
To: Alex Elder
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, maxime.chevallier,
rmk+kernel, andersson, konradybcio, robh, krzk+dt, conor+dt,
linusw, brgl, arnd, gregkh, Daniel Thompson, mohd.anwar,
a0987203069, alexandre.torgue, ast, boon.khai.ng, chenchuangyu,
chenhuacai, daniel, hawk, hkallweit1, inochiama, john.fastabend,
julianbraha, livelycarpet87, matthew.gerlach, mcoquelin.stm32, me,
prabhakar.mahadev-lad.rj, richardcochran, rohan.g.thomas, sdf,
siyanteng, weishangjuan, wens, netdev, bpf, linux-arm-msm,
devicetree, linux-gpio, linux-stm32, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260501155421.3329862-3-elder@riscstar.com>
> +static int xpcs_config_operating_mode(struct dw_xpcs *xpcs, int an_mode)
> +{
> + int mdio_stat2, ret;
> +
> + switch (an_mode) {
> + case DW_AN_C37_SGMII:
> + case DW_AN_C37_1000BASEX:
> + case DW_2500BASEX:
> + mdio_stat2 = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT2);
> + if (mdio_stat2 < 0)
> + return mdio_stat2;
> +
> + /*
> + * If this XPCS supports 10Gbase-R then it will be the default
> + * which prevents 1000base-X and slower from working correctly.
It would be interesting to know if Toshiba messed up the integration
of the PCS, or there is an errata for the licensed IP.
Anybody got access to the databook and erratas?
Andrew
^ permalink raw reply
* [PATCH net] net: usb: asix: ax88772: re-add usbnet_link_change() in phylink callbacks
From: Markus Baier @ 2026-05-01 16:39 UTC (permalink / raw)
To: Oleksij Rempel
Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Russell King, Ethan Nelson-Moore, Miaoqian Lin,
linux-usb, netdev, linux-kernel, Markus Baier
Commit e0bffe3e6894 ("net: asix: ax88772: migrate to phylink") replaced
the asix_adjust_link() PHY callback with phylink's mac_link_up() and
mac_link_down() handlers, but did not carry over the usbnet_link_change()
notification that commit 805206e66fab ("net: asix: fix "can't send until
first packet is send" issue") had added.
As a result, the original symptom returns: when the link comes up,
usbnet is never notified, so the RX URB submission stays dormant until
some other event (e.g. a transmitted packet triggering the status
endpoint interrupt) wakes it up.
This is reproducible with the Apple A1277 USB Ethernet Adapter
(05ac:1402, AX88772A based) on a Banana Pro using a static IPv4
configuration. After bringing the interface up, no incoming packets are
received until the first outgoing frame triggers usbnet's RX path.
Restore the link change notification, gated on a carrier transition so
the call remains idempotent if the status endpoint also reports the
change later.
Fixes: e0bffe3e6894 ("net: asix: ax88772: migrate to phylink")
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Markus Baier <Markus.Baier@soslab.tu-darmstadt.de>
---
Transparency notice: The English formulation of this bug report was
prepared with AI assistance. The actual system testing and verification
of the issue were performed manually without AI involvement.
The bug was originally located via git bisect between v5.13 (good)
and v5.14 (first bad), pointing to commit e532a096be0e ("net: usb: asix:
ax88772: add phylib support"). Commit 805206e66fab later fixed this in
v5.19, but commit e0bffe3e6894 (phylink migration in v6.x) re-introduced
the same symptom by replacing the asix_adjust_link() callback path
without porting the usbnet_link_change() call to the new phylink
mac_link_up/down handlers.
First Tested on Linux 6.18.18-gentoo with Apple A1277 USB Ethernet Adapter
(05ac:1402, AX88772A based) on a Banana Pro (Allwinner A20).
Later on Linux 7.1.0-rc1 with identical hardware setup.
drivers/net/usb/asix_devices.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index df0bcfedddbc..293ef80c4e30 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -756,6 +756,7 @@ static void ax88772_mac_link_down(struct phylink_config *config,
struct usbnet *dev = netdev_priv(to_net_dev(config->dev));
asix_write_medium_mode(dev, 0, 0);
+ usbnet_link_change(dev, false, false);
}
static void ax88772_mac_link_up(struct phylink_config *config,
@@ -786,6 +787,7 @@ static void ax88772_mac_link_up(struct phylink_config *config,
m |= AX_MEDIUM_RFC;
asix_write_medium_mode(dev, m, 0);
+ usbnet_link_change(dev, true, false);
}
static const struct phylink_mac_ops ax88772_phylink_mac_ops = {
--
2.52.0
^ permalink raw reply related
* Re: [PATCH 00/11] mlx5 support for VFIO self test
From: Jason Gunthorpe @ 2026-05-01 16:43 UTC (permalink / raw)
To: David Matlack
Cc: Alex Williamson, kvm, Leon Romanovsky, linux-kselftest,
linux-rdma, Mark Bloch, netdev, Saeed Mahameed, Shuah Khan,
Tariq Toukan, patches, Josh Hilke
In-Reply-To: <CALzav=ci8bi3=sY+F3HJTB5sOQ_pJ8Lm+kz0CDBBWVXry5P98w@mail.gmail.com>
On Fri, May 01, 2026 at 09:11:11AM -0700, David Matlack wrote:
> On Thu, Apr 30, 2026 at 5:08 PM Jason Gunthorpe <jgg@nvidia.com> wrote:
> >
> > Add an mlx5 driver to VFIO self test. This is largely a remix of the
> > existing VFIO mlx5 driver in rdma-core. It uses an RDMA loopback QP
> > to issue RDMA WRITE operations which effectively perform memory
> > copies using DMA. Since mlx5 has a stable programming ABI this
> > should work on devices from CX5 to current HW. The device FW must
> > support the QP loopback configuration.
>
> > This entire series was coded by Claude Code in about 4 days.
>
> Very exciting. Josh Hilke from Google is also working on using AI to
> create a selftest driver for Intel IGB NICs so VFIO selftests can run
> in QEMU [1]. So it's encouraging to see you were able to do it with
> mlx5.
>
> [1] https://www.qemu.org/docs/master/system/devices/igb.html
Yes! I would feed DPDK in as well in this case? Combined with the
kernel driver it should be doable. It is much easier if you understand
how the NIC works, of course. This worked out significantly because I
guided it through sufficiently small steps and knew where to find all
the quality reference material..
> > - Make it work on a PF too (this is surprisingly hard!).
>
> Can it work on CX VFs? We're interested in continuously performing
> memory copies across a Live Update using a VF via selftests to
> demonstrate SR-IOV preservation (when we eventually get there).
Yes, I started with VF because it is simpler. The PF support flow
requires a bunch more complicated stuff.
Jason
^ permalink raw reply
* Re: [PATCH net 4/7] net: tls: fix off-by-one in sg_chain entry count for wrapped sk_msg ring
From: Sabrina Dubroca @ 2026-05-01 16:40 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms, bpf,
john.fastabend, linux-kselftest, 钱一铭, daniel,
jonathan.lemon
In-Reply-To: <20260429222944.2139041-5-kuba@kernel.org>
[I'm slowly trying to catch up with the chunk of ktls patches that
were posted in the past 3 days]
2026-04-29, 15:29:41 -0700, Jakub Kicinski wrote:
[...]
> Every other wrapped-ring arithmetic operation in the sk_msg subsystem
> (sk_msg_iter_dist, sk_msg_iter_var_next, sk_msg_iter_var_prev,
> bpf_msg_pull_data) correctly uses NR_MSG_FRAG_IDS as the ring modulus.
> This sg_chain call is the sole remaining use of MAX_SKB_FRAGS for
> ring-modulus arithmetic and was introduced after the ring expansion.
[...]
> diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
> index 906a1998c630..600e13effaab 100644
> --- a/net/tls/tls_sw.c
> +++ b/net/tls/tls_sw.c
> @@ -802,7 +802,7 @@ static int tls_push_record(struct sock *sk, int flags,
>
> if (msg_pl->sg.end < msg_pl->sg.start) {
> sg_chain(&msg_pl->sg.data[msg_pl->sg.start],
> - MAX_SKB_FRAGS - msg_pl->sg.start + 1,
> + NR_MSG_FRAG_IDS - msg_pl->sg.start + 1,
> msg_pl->sg.data);
And get rid of the [start] / NR - start dance to make this code a bit
clearer?
This should maybe even be an skmsg helper to avoid "random" code
making assumptions on the size of the sg.data array. The last
paragraph in your commit message also tends to suggest that.
--
Sabrina
^ permalink raw reply
* Re: [PATCH net v2] net: mana: Optimize irq affinity for low vcpu configs
From: Yury Norov @ 2026-05-01 16:22 UTC (permalink / raw)
To: Shradha Gupta
Cc: Dexuan Cui, Wei Liu, Haiyang Zhang, K. Y. Srinivasan, Andrew Lunn,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Konstantin Taranov, Simon Horman, Erni Sri Satya Vennela,
Dipayaan Roy, Shiraz Saleem, Michael Kelley, Long Li, Yury Norov,
linux-hyperv, linux-kernel, netdev, Paul Rosswurm, Shradha Gupta,
Saurabh Singh Sengar, stable
In-Reply-To: <20260429090640.1790104-1-shradhagupta@linux.microsoft.com>
On Wed, Apr 29, 2026 at 02:06:37AM -0700, Shradha Gupta wrote:
> In mana driver, the number of IRQs allocated is capped by the
> min(num_cpu + 1, queue count). In cases, where the IRQ count is greater
> than the vcpu count, we want to utilize all the vCPUs, irrespective of
> their NUMA/core bindings.
>
> This is important, especially in the envs where number of vCPUs are so
> few that the softIRQ handling overhead on two IRQs on the same vCPU is
> much more than their overheads if they were spread across sibling vCPUs.
>
> This behaviour is more evident with dynamic IRQ allocation. Since MANA
> IRQs are assigned at a later stage compared to static allocation, other
> device IRQs may already be affinitized to the vCPUs. As a result, IRQ
> weights become imbalanced, causing multiple MANA IRQs to land on the
> same vCPU, while some vCPUs have none.
>
> In such cases when many parallel TCP connections are tested, the
> throughput drops significantly.
>
> Test envs:
> =======================================================
> Case 1: without this patch
> =======================================================
> 4 vcpu(2 cores), 5 MANA IRQs (1 HWC + 4 Queue)
>
> TYPE effective vCPU aff
> =======================================================
> IRQ0: HWC 0
> IRQ1: mana_q1 0
> IRQ2: mana_q2 2
> IRQ3: mana_q3 0
> IRQ4: mana_q4 3
>
> %soft on each vCPU(mpstat -P ALL 1) on receiver
> vCPU 0 1 2 3
> =======================================================
> pass 1: 38.85 0.03 24.89 24.65
> pass 2: 39.15 0.03 24.57 25.28
> pass 3: 40.36 0.03 23.20 23.17
>
> =======================================================
> Case 2: with this patch
> =======================================================
> 4 vcpu(2 cores), 5 MANA IRQs (1 HWC + 4 Queue)
>
> TYPE effective vCPU aff
> =======================================================
> IRQ0: HWC 0
> IRQ1: mana_q1 0
> IRQ2: mana_q2 1
> IRQ3: mana_q3 2
> IRQ4: mana_q4 3
>
> %soft on each vCPU(mpstat -P ALL 1) on receiver
> vCPU 0 1 2 3
> =======================================================
> pass 1: 15.42 15.85 14.99 14.51
> pass 2: 15.53 15.94 15.81 15.93
> pass 3: 16.41 16.35 16.40 16.36
>
> =======================================================
> Throughput Impact(in Gbps, same env)
> =======================================================
> TCP conn with patch w/o patch
> 20480 15.65 7.73
> 10240 15.63 8.93
> 8192 15.64 9.69
> 6144 15.64 13.16
> 4096 15.69 15.75
> 2048 15.69 15.83
> 1024 15.71 15.28
>
> Fixes: 755391121038 ("net: mana: Allocate MSI-X vectors dynamically")
> Cc: stable@vger.kernel.org
> Co-developed-by: Erni Sri Satya Vennela <ernis@linux.microsoft.com>
> Signed-off-by: Erni Sri Satya Vennela <ernis@linux.microsoft.com>
> Signed-off-by: Shradha Gupta <shradhagupta@linux.microsoft.com>
> Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
> ---
> Changes in v2
> * Removed the unused skip_first_cpu variable
> * fixed exit condition in irq_setup_linear() with len == 0
> * changed return type of irq_setup_linear() as it will always be 0
> * removed the unnecessary rcu_read_lock() in irq_setup_linear()
> * added appropriate comments to indicate expected behaviour when
> IRQs are more than or equal to num_online_cpus()
> ---
> .../net/ethernet/microsoft/mana/gdma_main.c | 47 ++++++++++++++++---
> 1 file changed, 40 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
> index 098fbda0d128..d740d1dc43da 100644
> --- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
> +++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
> @@ -167,6 +167,8 @@ static int mana_gd_query_max_resources(struct pci_dev *pdev)
> } else {
> /* If dynamic allocation is enabled we have already allocated
> * hwc msi
> + * Also, we make sure in this case the following is always true
> + * (num_msix_usable - 1 HWC) <= num_online_cpus()
> */
> gc->num_msix_usable = min(resp.max_msix, num_online_cpus() + 1);
> }
> @@ -1672,11 +1674,24 @@ static int irq_setup(unsigned int *irqs, unsigned int len, int node,
> return 0;
> }
>
> +/* should be called with cpus_read_lock() held */
> +static void irq_setup_linear(unsigned int *irqs, unsigned int len)
> +{
> + int cpu;
> +
> + for_each_online_cpu(cpu) {
> + if (len == 0)
> + break;
> +
> + irq_set_affinity_and_hint(*irqs++, cpumask_of(cpu));
> + len--;
> + }
> +}
> +
> static int mana_gd_setup_dyn_irqs(struct pci_dev *pdev, int nvec)
> {
> struct gdma_context *gc = pci_get_drvdata(pdev);
> struct gdma_irq_context *gic;
> - bool skip_first_cpu = false;
> int *irqs, irq, err, i;
>
> irqs = kmalloc_objs(int, nvec);
So what about WARN_ON() and nvec adjustment before kmalloc?
> @@ -1722,13 +1737,31 @@ static int mana_gd_setup_dyn_irqs(struct pci_dev *pdev, int nvec)
> * first CPU sibling group since they are already affinitized to HWC IRQ
> */
> cpus_read_lock();
> - if (gc->num_msix_usable <= num_online_cpus())
> - skip_first_cpu = true;
> + if (gc->num_msix_usable <= num_online_cpus()) {
> + err = irq_setup(irqs, nvec, gc->numa_node, true);
> + if (err) {
> + cpus_read_unlock();
> + goto free_irq;
One thing puzzles me: if you skip first CPU with this 'true', and the
gc->num_msix_usable == num_online_cpus(), it's one more than you can
distribute. What do I miss?
> + }
> + } else {
> + /*
> + * When num_msix_usable are more than num_online_cpus, we try to
> + * make sure we are using all vcpus. In such a case NUMA or
> + * CPU core affinity does not matter.
If it doesn't matter, why don't you assign each IRQ to all CPUs then?
In theory, the system would have most of flexibility to balance them.
> + * Note: in this case the total mana IRQ should always be
> + * num_online_cpus + 1. The first HWC IRQ is already handled
> + * in HWC setup calls
> + * However, if CPUs went offline since num_msix_usable was
> + * computed, nvec count will be more than num_online_cpus().
> + * In such cases remaining extra IRQs will retain their default
> + * affinity.
> + */
> + if (nvec > num_online_cpus())
> + dev_dbg(&pdev->dev,
> + "IRQ count %d exceeds online CPU count %d. Some IRQs will share CPU\n",
I'd better say 'some IRQs will share the default CPU', and in the
perfect world, I'd like to see:
'The IRQs #4-12 will share the default CPU #0'
type of message.
> + nvec, num_online_cpus());
It's not that straightforward as it should be. In one case
nvec > num_online_cpus()
is a problem, while in another - not. It looks already suspicious. So
when you throw a warning, you should mention it, I believe.
In the
gc->num_msix_usable <= num_online_cpus()
case, when nvec is too big, would'n 'some IRQs share some CPU' just
as well? If so, you again should throw a message.
> - err = irq_setup(irqs, nvec, gc->numa_node, skip_first_cpu);
> - if (err) {
> - cpus_read_unlock();
> - goto free_irq;
> + irq_setup_linear(irqs, nvec);
> }
>
> cpus_read_unlock();
>
> base-commit: e728258debd553c95d2e70f9cd97c9fde27c7130
> --
> 2.34.1
^ permalink raw reply
* Re: [PATCH 00/11] mlx5 support for VFIO self test
From: David Matlack @ 2026-05-01 16:11 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Alex Williamson, kvm, Leon Romanovsky, linux-kselftest,
linux-rdma, Mark Bloch, netdev, Saeed Mahameed, Shuah Khan,
Tariq Toukan, patches, Josh Hilke
In-Reply-To: <0-v1-dc5fa250ca1d+3213-mlx5st_jgg@nvidia.com>
On Thu, Apr 30, 2026 at 5:08 PM Jason Gunthorpe <jgg@nvidia.com> wrote:
>
> Add an mlx5 driver to VFIO self test. This is largely a remix of the
> existing VFIO mlx5 driver in rdma-core. It uses an RDMA loopback QP
> to issue RDMA WRITE operations which effectively perform memory
> copies using DMA. Since mlx5 has a stable programming ABI this
> should work on devices from CX5 to current HW. The device FW must
> support the QP loopback configuration.
> This entire series was coded by Claude Code in about 4 days.
Very exciting. Josh Hilke from Google is also working on using AI to
create a selftest driver for Intel IGB NICs so VFIO selftests can run
in QEMU [1]. So it's encouraging to see you were able to do it with
mlx5.
[1] https://www.qemu.org/docs/master/system/devices/igb.html
> For those interested, the flow I used was broadly a prompt sequence
> sort of like:
>
> - Hey Claude, go look at the falcon series, VFIO self test, the
> mlx5 driver, rdma-core and some PDF documentation and make a
> plan to put mlx5 under the selftest.
> - Write an rdma-core application using the built-in VFIO provider
> that can do the required memcpy operations that vfio selftests
> wants.
> (This resulted in a 1k loc C file that compiled and ran the
> first time but had a few bugs related to device programming
> that the AI resolved.)
> - Replace the rdma-core components with open-coded versions to
> create a fully stand-alone program that does the DMA memcpy.
> - Review and audit the thing.
> [Pause and de-slop it]
> - Make it work on a PF too (this is surprisingly hard!).
Can it work on CX VFs? We're interested in continuously performing
memory copies across a Live Update using a VF via selftests to
demonstrate SR-IOV preservation (when we eventually get there).
> [Move to a kernel tree and copy all the .md files and .c program
> it made]
> - Hey Claude, look at all this stuff and make a broad plan to
> actually build a VFIO self test.
> - Here is my 1 sentence advice on what each patch should look
> like, make a detailed plan to make a patch for every one.
> [Pause and polish the patch plans]
> - Execute plan X then commit it [pause and de-slop each patch,
> repeat].
> [Review and final polish]
>
> It is based on a tree with the falcon series applied.
Thanks for sending, I look forward to reviewing!
^ permalink raw reply
* Re: [PATCH ipsec] esp: Force skb_cow_data() on RX when the skb is non-linear
From: Simon Horman @ 2026-05-01 16:09 UTC (permalink / raw)
To: imv4bel
Cc: 'Simon Horman', steffen.klassert, herbert, davem, dsahern,
edumazet, kuba, pabeni, ilant, sowmini.varadhan, netdev
In-Reply-To: <afLDKSvAvMwGh7Fy@v4bel>
From: 'Simon Horman' <horms@kernel.org>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://sashiko.dev
---
esp: Force skb_cow_data() on RX when the skb is non-linear
This commit modifies esp_input() and esp6_input() to unconditionally call
skb_cow_data() for all non-linear skbs. This removes the fast path that
previously allowed in-place AEAD decryption for skbs carrying paged
fragments without a frag_list.
> diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
> index 6dfc0bcdef65..a6fbdec139dc 100644
> --- a/net/ipv4/esp4.c
> +++ b/net/ipv4/esp4.c
> @@ -868,17 +868,10 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
> assoclen += seqhilen;
> }
>
> - if (!skb_cloned(skb)) {
> - if (!skb_is_nonlinear(skb)) {
> - nfrags = 1;
> -
> - goto skip_cow;
> - } else if (!skb_has_frag_list(skb)) {
> - nfrags = skb_shinfo(skb)->nr_frags;
> - nfrags++;
> + if (!skb_cloned(skb) && !skb_is_nonlinear(skb)) {
> + nfrags = 1;
>
> - goto skip_cow;
> - }
> + goto skip_cow;
> }
By removing this fast path and forcing all non-linear skbs to fall through
to skb_cow_data(), does this break the IPsec GRO/GSO fast path?
Looking at skb_cow_data() in net/core/skbuff.c:
int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer)
{
...
if ((skb_cloned(skb) || skb_shinfo(skb)->nr_frags) &&
!__pskb_pull_tail(skb, __skb_pagelen(skb)))
return -ENOMEM;
...
For a large GRO or GSO packet (which can be up to 64KB) with paged fragments,
this attempts to pull the entire paged payload into the linear data area
via __pskb_pull_tail().
Since this runs in the RX softirq path, pulling the entire payload requires
a high-order contiguous memory allocation using GFP_ATOMIC.
Could this lead to widespread packet drops when memory is fragmented and
these high-order atomic allocations fail?
Additionally, even when the allocations succeed, does unconditionally copying
up to 64KB of data per packet introduce a severe performance regression by
entirely negating the software crypto fast path?
[ ... ]
^ permalink raw reply
* Re: [PATCH net] rxrpc: Also unshare DATA/RESPONSE packets when paged frags are present
From: Simon Horman @ 2026-05-01 15:58 UTC (permalink / raw)
To: imv4bel
Cc: 'Simon Horman', dhowells, marc.dionne, davem, edumazet,
kuba, pabeni, linux-afs, netdev
In-Reply-To: <afKV2zGR6rrelPC7@v4bel>
From: 'Simon Horman' <horms@kernel.org>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://sashiko.dev
---
rxrpc: Also unshare DATA/RESPONSE packets when paged frags are present
This commit updates the DATA and RESPONSE packet handlers in rxrpc to copy
the skb into a linear one if there are paged fragments present. This ensures
the security handler operates on a fully linear skb during decryption.
> diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c
> index fdd683261226..6c924ef55208 100644
> --- a/net/rxrpc/call_event.c
> +++ b/net/rxrpc/call_event.c
> @@ -334,7 +334,7 @@ bool rxrpc_input_call_event(struct rxrpc_call *call)
>
> if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA &&
> sp->hdr.securityIndex != 0 &&
> - skb_cloned(skb)) {
> + (skb_cloned(skb) || skb->data_len)) {
> /* Unshare the packet so that it can be
> * modified by in-place decryption.
> */
Since modern NIC drivers commonly use page pools where packet payloads are
placed in page fragments, skb->data_len will be greater than zero for almost
all standard incoming packets.
By taking this path, the code calls skb_copy() right after this check.
Will this force a full packet copy for nearly all incoming RxRPC DATA
packets, bypassing zero-copy receive paths and causing a large performance
regression?
Additionally, skb_copy() fully linearizes the packet by allocating a single
contiguous buffer for the entire packet size. For RxRPC Jumbo packets or UDP
GRO-aggregated packets (which can reach up to ~64KB), this requires an
order-4 page allocation.
Could relying on an order-4 GFP_ATOMIC allocation cause reliable OOM
failures and packet drops on fragmented systems?
If the goal is to ensure the skb is writable for in-place decryption, would
it be safer to use skb_cow_data() instead of forcing a full contiguous
linearization?
Simon says:
I note that this patch included
Fixes: d0d5c0cd1e71 ("rxrpc: Use skb_unshare() rather than skb_cow_data()")
And that the suggestion in the last paragraph above would
reintroduce back to the problem addressed by d0d5c0cd1e71.
^ permalink raw reply
* [PATCH net-next 12/12] arm64: dts: qcom: qcs6490-rb3gen2: enable TC9564 with a single QCS8081 phy
From: Alex Elder @ 2026-05-01 15:54 UTC (permalink / raw)
To: andrew+netdev, davem, edumazet, kuba, pabeni, maxime.chevallier,
rmk+kernel, andersson, konradybcio, robh, krzk+dt, conor+dt,
linusw, brgl, arnd, gregkh
Cc: Daniel Thompson, elder, mohd.anwar, a0987203069, alexandre.torgue,
ast, boon.khai.ng, chenchuangyu, chenhuacai, daniel, hawk,
hkallweit1, inochiama, john.fastabend, julianbraha,
livelycarpet87, matthew.gerlach, mcoquelin.stm32, me,
prabhakar.mahadev-lad.rj, richardcochran, rohan.g.thomas, sdf,
siyanteng, weishangjuan, wens, netdev, bpf, linux-arm-msm,
devicetree, linux-gpio, linux-stm32, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260501155421.3329862-1-elder@riscstar.com>
From: Daniel Thompson <daniel@riscstar.com>
The QCS6490 RB3Gen2 includes a Toshiba TC9564 (a.k.a. Qualcomm QPS615).
TC9564 is an twin Ethernet-AVB/TSN bridge with an integrated PCIe switch.
There are multiple builds of RB3Gen2 with components included/excluded.
That means whether or not there is a phy attached to eMAC0 depends on
the exact board. However all versions include a TC9564 combined with a
single QCS8081 attached to eMAC1.
Add properties to the existing PCI nodes to describe how the TC9564 and
QCS8081 are connected to each other (and to the host SoC).
(Note: "pci1179,0220" is documented in the "net/toshiba,tc956x-dwmac.yaml"
binding, but checkpatch.pl doesn't recognize that.)
Co-developed-by: Alex Elder <elder@riscstar.com>
Signed-off-by: Alex Elder <elder@riscstar.com>
Signed-off-by: Daniel Thompson <daniel@riscstar.com>
---
arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 45 +++++++++++++++++++-
1 file changed, 44 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
index e393ccf1884af..72c89aa7a2e43 100644
--- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
+++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
@@ -308,6 +308,16 @@ vdd_ntn_1p8: regulator-vdd-ntn-1p8 {
regulator-enable-ramp-delay = <10000>;
};
+ qep_1p8: regulator-qep-1p8 {
+ compatible = "regulator-fixed";
+ regulator-name = "qep_1p8";
+ gpio = <&pm7325_gpios 8 GPIO_ACTIVE_HIGH>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
wcn6750-pmu {
compatible = "qcom,wcn6750-pmu";
pinctrl-0 = <&bt_en>;
@@ -937,20 +947,46 @@ pcie@3,0 {
ranges;
bus-range = <0x5 0xff>;
- pci@0,0 {
+ tc956x_emac0: pci@0,0 {
+ compatible = "pci1179,0220";
reg = <0x50000 0x0 0x0 0x0 0x0>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
ranges;
+
+ gpio-controller;
+ #gpio-cells = <2>;
};
pci@0,1 {
+ compatible = "pci1179,0220";
reg = <0x50100 0x0 0x0 0x0 0x0>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
ranges;
+
+ phy-mode = "sgmii";
+ phy-handle = <&tc956x_emac1_phy>;
+
+ mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tc956x_emac1_phy: ethernet-phy@1c {
+ compatible = "ethernet-phy-id004d.d101";
+ reg = <0x1c>;
+ reset-gpios = <&tc956x_emac0 1 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <20>;
+ reset-deassert-us = <20>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&qep_irq_pin>;
+ interrupts-extended = <&tlmm 101 IRQ_TYPE_EDGE_FALLING>;
+ };
+ };
};
};
};
@@ -1524,6 +1560,13 @@ usb_hub_reset_state: usb-hub-reset-state {
drive-strength = <2>;
bias-disable;
};
+
+ qep_irq_pin: qep-irq-state {
+ pins = "gpio101";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
};
&lpass_audiocc {
--
2.51.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox