* Re: [PATCH net-next v7 5/5] veth: time-based BQL completion coalescing via ethtool tx-usecs
From: Simon Schippers @ 2026-06-30 19:07 UTC (permalink / raw)
To: Jonas Köppeler, hawk, netdev
Cc: kernel-team, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Alexei Starovoitov, Daniel Borkmann,
John Fastabend, Stanislav Fomichev, linux-kernel, bpf
In-Reply-To: <c4154d9c-8930-436d-b8b8-01951e8bd9f4@tu-berlin.de>
On 6/30/26 16:00, Jonas Köppeler wrote:
> On 6/13/26 4:14 PM, Simon Schippers wrote:
>> On 6/12/26 10:35, hawk@kernel.org wrote:
>>> From: Simon Schippers <simon.schippers@tu-dortmund.de>
>>>
>>> Per-packet BQL completion forces DQL to converge on limit=2, causing
>>> excessive NAPI scheduling overhead and qdisc requeues.
>>>
>>> Accumulate BQL completions and flush them when a configurable time
>>> threshold (tx-usecs) is exceeded, letting DQL discover a limit that
>>> bounds actual queuing delay to the configured interval. Coalescing
>>> state persists across NAPI polls in struct veth_rq so completions can
>>> accumulate beyond a single budget=64 cycle.
>>>
>>> The flush condition is:
>>>
>>> state->time + bql_flush_ns <= current_time || state->n_bql > dql.limit
>>>
>>> Flushing when n_bql exceeds dql.limit handles BQL starvation.
>>>
>>> The comparison is strictly greater-than because netdev_tx_sent_queue()
>>> always lets the producer exceed the limit by one before it stops, so
>>> n_bql == dql.limit is a normal in-flight state. dql.limit lives in
>>> the same cacheline as the completion path, so the check is cheap.
>>>
>>> Add ethtool tx-usecs support for runtime tuning. Default is 100 us;
>>> setting tx-usecs to 0 disables coalescing and falls back to per-packet
>>> completion.
>>>
>>> ethtool -C <veth-dev> tx-usecs 500 # 500us coalescing
>>> ethtool -C <veth-dev> tx-usecs 0 # per-packet (no coalescing)
>>>
>>> Co-developed-by: Jesper Dangaard Brouer <hawk@kernel.org>
>>> Signed-off-by: Jesper Dangaard Brouer <hawk@kernel.org>
>>> Co-developed-by: Jonas Köppeler <j.koeppeler@tu-berlin.de>
>>> Signed-off-by: Jonas Köppeler <j.koeppeler@tu-berlin.de>
>>> Signed-off-by: Simon Schippers <simon.schippers@tu-dortmund.de>
>>> ---
>>> drivers/net/veth.c | 123 ++++++++++++++++++++++++++++++++++++++++++---
>>> 1 file changed, 117 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/net/veth.c b/drivers/net/veth.c
>>> index 2473f730734b..c62d87a8402c 100644
>>> --- a/drivers/net/veth.c
>>> +++ b/drivers/net/veth.c
>>> @@ -28,6 +28,7 @@
>>> #include <linux/bpf_trace.h>
>>> #include <linux/net_tstamp.h>
>>> #include <linux/skbuff_ref.h>
>>> +#include <linux/sched/clock.h>
>>> #include <net/page_pool/helpers.h>
>>> #define DRV_NAME "veth"
>>> @@ -50,6 +51,7 @@
>>> * delay => 64 * 250 ms = 16 s.
>>> */
>>> #define VETH_WATCHDOG_TIMEOUT_MS (64 * 250)
>>> +#define VETH_BQL_COAL_TX_USECS 100 /* default tx-usecs for BQL batching*/
>>> struct veth_stats {
>>> u64 rx_drops;
>>> @@ -69,6 +71,11 @@ struct veth_rq_stats {
>>> struct u64_stats_sync syncp;
>>> };
>>> +struct veth_bql_state {
>>> + u64 time; /* sched_clock() when current coalescing window started */
>>> + uint n_bql; /* BQL completions batched in the current window */
>>> +};
>>> +
>>> struct veth_rq {
>>> struct napi_struct xdp_napi;
>>> struct napi_struct __rcu *napi; /* points to xdp_napi when the latteris initialized */
>>> @@ -76,6 +83,7 @@ struct veth_rq {
>>> struct bpf_prog __rcu *xdp_prog;
>>> struct xdp_mem_info xdp_mem;
>>> struct veth_rq_stats stats;
>>> + struct veth_bql_state bql_state;
>>> bool rx_notify_masked;
>>> struct ptr_ring xdp_ring;
>>> struct xdp_rxq_info xdp_rxq;
>>> @@ -88,6 +96,7 @@ struct veth_priv {
>>> struct bpf_prog *_xdp_prog;
>>> struct veth_rq *rq;
>>> unsigned int requested_headroom;
>>> + unsigned int tx_coal_usecs; /* BQL completion coalescing */
>>> };
>>> struct veth_xdp_tx_bq {
>>> @@ -272,7 +281,56 @@ static void veth_get_channels(struct net_device *dev,
>>> static int veth_set_channels(struct net_device *dev,
>>> struct ethtool_channels *ch);
>>> +static int veth_get_coalesce(struct net_device *dev,
>>> + struct ethtool_coalesce *ec,
>>> + struct kernel_ethtool_coalesce *kernel_coal,
>>> + struct netlink_ext_ack *extack)
>>> +{
>>> + struct veth_priv *priv = netdev_priv(dev);
>>> +
>>> + ec->tx_coalesce_usecs = priv->tx_coal_usecs;
>>> + return 0;
>>> +}
>>> +
>>> +static int veth_set_coalesce(struct net_device *dev,
>>> + struct ethtool_coalesce *ec,
>>> + struct kernel_ethtool_coalesce *kernel_coal,
>>> + struct netlink_ext_ack *extack)
>>> +{
>>> + struct veth_priv *priv = netdev_priv(dev);
>>> + struct net_device *peer;
>>> +
>>> + /* The coalescing window delays BQL completions, so keep tx-usecs well
>>> + * below the tx_timeout watchdog; otherwise a large value could stall a
>>> + * stopped queue long enough to trip a false watchdog timeout. Cap at
>>> + * half the watchdog to leave a generous safety margin. tx-usecs is
>>> + * microseconds, the watchdog is milliseconds.
>>> + */
>>> + if (ec->tx_coalesce_usecs > VETH_WATCHDOG_TIMEOUT_MS / 2 * USEC_PER_MSEC) {
>>> + NL_SET_ERR_MSG_MOD(extack,
>>> + "tx-usecs must stay below half the tx_timeout watchdog");
>>> + return -ERANGE;
>>> + }
>>> +
>>> + /* Paired with READ_ONCE in veth_xdp_rcv(). */
>>> + WRITE_ONCE(priv->tx_coal_usecs, ec->tx_coalesce_usecs);
>>> +
>>> + /* veth_xdp_rcv() reads each device's own value, so mirror it onto
>>> + * the peer to keep the pair symmetric: both directions coalesce
>>> + * with the same tx-usecs. Called under RTNL, rtnl_dereference() is safe.
>>> + */
>>> + peer = rtnl_dereference(priv->peer);
>>> + if (peer) {
>>> + struct veth_priv *peer_priv = netdev_priv(peer);
>>> +
>>> + WRITE_ONCE(peer_priv->tx_coal_usecs, ec->tx_coalesce_usecs);
>>> + }
>>> +
>>> + return 0;
>>> +}
>>> +
>>> static const struct ethtool_ops veth_ethtool_ops = {
>>> + .supported_coalesce_params = ETHTOOL_COALESCE_TX_USECS,
>>> .get_drvinfo = veth_get_drvinfo,
>>> .get_link = ethtool_op_get_link,
>>> .get_strings = veth_get_strings,
>>> @@ -282,6 +340,8 @@ static const struct ethtool_ops veth_ethtool_ops ={
>>> .get_ts_info = ethtool_op_get_ts_info,
>>> .get_channels = veth_get_channels,
>>> .set_channels = veth_set_channels,
>>> + .get_coalesce = veth_get_coalesce,
>>> + .set_coalesce = veth_set_coalesce,
>>> };
>>> /* general routines */
>>> @@ -969,13 +1029,54 @@ static struct sk_buff *veth_xdp_rcv_skb(struct veth_rq *rq,
>>> return NULL;
>>> }
>>> +static void veth_bql_maybe_complete(struct veth_bql_state *state,
>>> + struct netdev_queue *peer_txq,
>>> + u64 bql_flush_ns)
>>> +{
>>> + u64 current_time;
>>> +
>>> + /* There is no reason to complete with 0 and
>>> + * peer_txq could go away.
>>> + */
>>> + if (!state->n_bql || !peer_txq)
>>> + return;
>>> +
>>> + current_time = sched_clock();
>>> +
>>> + /* We complete if:
>>> + * 1. We reach bql_flush_ns.
>>> + * 2. We potentially have BQL starvation.
>>> + */
>>> + if (state->time + bql_flush_ns <= current_time ||
>>> + state->n_bql > peer_txq->dql.limit) {
>>
> Indeed, this does not compile when CONFIG_BQL is not set. I think we should just bring back the 'queue is empty + queue is stopped' check from v6 back at the end of the poll and remove the n_bql > dql.limit check.
We would put #ifdef CONFIG_BQL around that logic aswell.
> It also feels not obvious why this is handling the starvation case. This only works, because the producer has went overlimit previously and was stopped. So more than 'limit' packets have been enqueued to the ring, and they are eventually drained when this check is true.
I think it just needs some comment tweaking:
/* We complete if:
* 1. We reach bql_flush_ns.
* 2. We have BQL starvation. This means that the queue was over-limit
* in the last interval, and there is no more data in the queue,
* which is equivalent to we consumed more than limit items.
*/
> By removing this we can also avoid accessing dql internal members, but if you don't think that's a problem we can leave as is.
I agree accessing dql internal variables is not perfect.
That is why I have locally implemented DQL for software interfaces in
a generic way inside dynamic_queue_limits.{h,c}.
I was able to squeeze the time and n_bql variables into the completion
cacheline of the dql struct by moving around variables.
The logic applies inside dql_completed() if enabled.
With this we just have to call netdev_completed_queue().
Also it allows for per-queue tweaking of tx_usecs via sysfs.
Works well for me, can share it if we want to use it.
>
> Further, this is only works if VETH_BQL_UNIT stays 1, otherwise it will never fire. Anyway, still its necessary to check for CONFIG_BQL. But we could solve this by adding VETH_BQL_UNIT to n_bql instead of 1. This is also safe from any overflows, since limit is bound to limit_max, inflight is always less than limit + 1*VETH_BQL_UNIT and n_bql <= inflight.
You are right.
But I think there is no reason for VETH_BQL_UNIT anyway.
There should be no difference in the BQL algorithm, I personally
would replace VETH_BQL_UNIT with a hard-coded 1.
>
> In a version of bringing back the 'queue-empty' check and keeping most of the current logic (so a mixture of v6 and v7) resulted in the same performance on an x86_64 architecture.
>
>> Both Sashiko-Nipa and Sashiko-Gemini are right, this is missing a
>> #ifdef CONFIG_BQL. Not sure what is the best way to add them.
>> And for the struct we could maybe do:
>>
>> #ifdef CONFIG_BQL
>> struct veth_bql_state {
>> u64 time; /* sched_clock() when current coalescing window started */
>> uint n_bql; /* BQL completions batched in the current window */
>> };
>> #else
>> struct veth_bql_state {};
>> #endif
> Regarding the configs: we can just do something along those lines.
> struct veth_rq {
> ...
> #ifdef CONFIG_BQL
> struct veth_bql_state dql;
> #endif
> ...
> }
>
> and we put the rest of the code that accesses or performs an action regarding bql in some functions and do it like in netdev_* functions with
>
> Function-Signature()
> {
> #ifdef CONFIG_BQL
> // Code
> #endif
> }
>
> Wdyt?
> - Jonas
Yes, we have to. Unless we put it into dynamic_queue_limits.{h,c}
of course :^)
Thanks,
Simon
>>
>>> + netdev_tx_completed_queue(peer_txq, state->n_bql,
>>> + state->n_bql * VETH_BQL_UNIT);
>>> + state->time = current_time;
>>> + state->n_bql = 0;
>>> + }
>>> +}
>>> +
>>> static int veth_xdp_rcv(struct veth_rq *rq, int budget,
>>> struct veth_xdp_tx_bq *bq,
>>> struct veth_stats *stats,
>>> struct netdev_queue *peer_txq)
>>> {
>>> + struct veth_priv *priv = netdev_priv(rq->dev);
>>> + struct veth_bql_state *state = &rq->bql_state;
>>> int i, done = 0, n_xdpf = 0;
>>> void *xdpf[VETH_XDP_BATCH];
>>> + u64 bql_flush_ns;
>>> +
>>> + /* Mirrored to both peers; paired with WRITE_ONCE() in veth_set_coalesce */
>>> + bql_flush_ns = (u64)READ_ONCE(priv->tx_coal_usecs) * 1000;
>>> +
>>> + /* Clamp stored timestamp in case we migrated to a CPU with a behind
>>> + * sched_clock(); tries to reduce late BQL flushes.
>>> + */
>>> + state->time = min(state->time, sched_clock());
>>> +
>>> + /* Flush completions that timed out since the previous NAPI poll. */
>>> + veth_bql_maybe_complete(state, peer_txq, bql_flush_ns);>>
>>> for (i = 0; i < budget; i++) {
>>> void *ptr = __ptr_ring_consume(&rq->xdp_ring);
>>> @@ -1000,12 +1101,11 @@ static int veth_xdp_rcv(struct veth_rq *rq, int budget,
>>> }
>>> } else {
>>> /* ndo_start_xmit */
>>> - bool bql_charged = veth_ptr_is_bql(ptr);
>>> struct sk_buff *skb = veth_ptr_to_skb(ptr);
>>> + if (veth_ptr_is_bql(ptr))
>>> + state->n_bql++;
>>> stats->xdp_bytes += skb->len;
>>> - if (peer_txq && bql_charged)
>>> - netdev_tx_completed_queue(peer_txq, 1, VETH_BQL_UNIT);
>>> skb = veth_xdp_rcv_skb(rq, skb, bq, stats);
>>> if (skb) {
>>> @@ -1015,6 +1115,7 @@ static int veth_xdp_rcv(struct veth_rq *rq, int budget,
>>> napi_gro_receive(&rq->xdp_napi, skb);
>>> }
>>> }
>>> + veth_bql_maybe_complete(state, peer_txq, bql_flush_ns);
>>> done++;
>>
>> Sashiko-Nipa reports:
>>
>> "If veth_xdp_rcv() finishes and returns a done count less than the budget,
>> NAPI will go to sleep in veth_poll(). Do we need to unconditionally flush
>> any stranded BQL completions in veth_poll() before sleeping?
>> If completions are left in rq->bql_state indefinitely across NAPI idle
>> periods, it might present an artificially massive delay to DQL. This could
>> cause DQL to mistakenly conclude the hardware is extremely slow and
>> aggressively shrink dql.limit to its minimum, crippling throughput on
>> subsequent bursts."
>>
>> Again the issue that I found to be non-problematic in [1] and can be
>> seen by an BQL inflight > 0 when for example pktgen suddenly stops.
>>
>> If we would "unconditionally flush any stranded BQL completions in
>> veth_poll() before sleeping" we would *not* accumulate BQL completions
>> across NAPI polls but we want to do that.
>>
>> Do you agree?
>>
>> [1] https://lore.kernel.org/netdev/c8650d3a-e488-4279-b28f-549d766c23a1@tu-dortmund.de/
>
^ permalink raw reply
* [PATCH net] net/tls: Consume empty data records in tls_sw_read_sock()
From: Chuck Lever @ 2026-06-30 19:15 UTC (permalink / raw)
To: john.fastabend, kuba, sd; +Cc: davem, edumazet, pabeni, horms, netdev
A peer may send a zero-length TLS application_data record; TLS 1.3
explicitly permits these as a traffic-analysis countermeasure (RFC
8446, Section 5.1). After decryption such a record has full_len ==
0. tls_sw_read_sock() hands it to the read_actor, which has no
payload to consume and returns zero. The loop treats a zero return
as backpressure (used <= 0), requeues the skb at the head of
rx_list, and stops. rx_list is serviced head-first on the next
call, so the empty record is dequeued, fails the same way, and is
requeued again; every later record on the connection is blocked
behind it.
tls_sw_recvmsg() does not stall on this: a zero-length data record
copies nothing and falls through to consume_skb(). Mirror that in
the read_sock() path by recognizing an empty data record before
the actor runs, consuming it, and continuing.
Fixes: 662fbcec32f4 ("net/tls: implement ->read_sock()")
Signed-off-by: Chuck Lever <cel@kernel.org>
---
net/tls/tls_sw.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 9324e4ed20a3..d4afc90fd796 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -2115,6 +2115,17 @@ int tls_sw_read_sock(struct sock *sk, read_descriptor_t *desc,
goto read_sock_requeue;
}
+ /* An empty data record (legal in TLS 1.3) gives a zero
+ * read_actor return, indistinguishable from the consumer
+ * stalling; the used <= 0 path would requeue it at the
+ * head of rx_list and block all later records. Consume it
+ * here instead.
+ */
+ if (rxm->full_len == 0) {
+ consume_skb(skb);
+ continue;
+ }
+
used = read_actor(desc, skb, rxm->offset, rxm->full_len);
if (used <= 0) {
if (!copied)
--
2.54.0
^ permalink raw reply related
* [RFC PATCH bpf-next v1 0/7] xdp: RX checksum metadata hint and checksum assertion over redirect
From: Vladimir Vdovin @ 2026-06-30 19:15 UTC (permalink / raw)
To: bpf, netdev
Cc: ast, daniel, andrii, martin.lau, sdf, hawk, john.fastabend, kuba,
Vladimir Vdovin
This series lets XDP programs work with the hardware RX checksum verdict:
read what the NIC concluded about a packet, and carry a "the L4 checksum
is correct" assertion across a redirect so the stack does not revalidate
it in software.
When an XDP program redirects a frame to a cpumap (or any other path that
rebuilds an skb from an xdp_frame via __xdp_build_skb_from_frame()), the
HW RX checksum status is lost and the stack revalidates the L4 checksum in
software.
Two kfuncs are added:
- bpf_xdp_metadata_rx_csum(): a device-bound RX-metadata hint, like the
existing rx_hash / rx_vlan_tag ones. It reports enum xdp_csum_status
(XDP_CSUM_NONE / XDP_CSUM_VERIFIED) and is implemented for mlx5e, ice
and veth.
- bpf_xdp_assert_rx_csum(): a generic, non-device-bound kfunc that lets
the program assert the L4 checksum is correct. It sets a buff flag
that rides into the xdp_frame, and __xdp_build_skb_from_frame() turns
it into skb->ip_summed = CHECKSUM_UNNECESSARY. The kernel cannot
verify the assertion; the program takes responsibility, as it already
does when rewriting packet contents.
Posted as RFC to get feedback on:
- whether the read hint (bpf_xdp_metadata_rx_csum() and its driver
support) belongs in this series at all. bpf_xdp_assert_rx_csum() is
self-contained and already covers the main use case: a program that
computes or fixes the L4 checksum itself, or trusts the source, and
wants the rebuilt skb to skip software revalidation. The read hint is
an optimization for programs that did not touch the payload and only
want to relay the hardware verdict. These could just as well be two
independent series (assert-only first);
- the kfunc naming, bpf_xdp_assert_rx_csum() in particular.
Testing:
- new selftest xdp_cpumap_rx_csum drives a frame through a native-XDP
veth into a cpumap redirect and checks, via fexit on
__xdp_build_skb_from_frame(), that the rebuilt skb is
CHECKSUM_UNNECESSARY iff the program called bpf_xdp_assert_rx_csum();
- xdp_metadata calls bpf_xdp_metadata_rx_csum() over veth and checks both
verdicts: XDP_CSUM_NONE for an AF_XDP-injected frame and
XDP_CSUM_VERIFIED for one sent through the stack.
Vladimir Vdovin (7):
xdp: let XDP programs assert the RX checksum over redirect
selftests/bpf: add test for bpf_xdp_assert_rx_csum over cpumap
xdp: add bpf_xdp_metadata_rx_csum() RX metadata kfunc
net/mlx5e: support the rx_csum XDP metadata hint
ice: support the rx_csum XDP metadata hint
veth: support the rx_csum XDP metadata hint
selftests/bpf: cover bpf_xdp_metadata_rx_csum in xdp_metadata
Documentation/netlink/specs/netdev.yaml | 5 +
drivers/net/ethernet/intel/ice/ice_txrx_lib.c | 32 ++++
.../net/ethernet/mellanox/mlx5/core/en/xdp.c | 23 +++
drivers/net/veth.c | 23 +++
include/net/xdp.h | 23 +++
include/uapi/linux/netdev.h | 3 +
net/core/xdp.c | 73 ++++++++-
tools/include/uapi/linux/netdev.h | 3 +
.../bpf/prog_tests/xdp_cpumap_rx_csum.c | 150 ++++++++++++++++++
.../selftests/bpf/prog_tests/xdp_metadata.c | 10 ++
.../selftests/bpf/progs/bpf_tracing_net.h | 1 +
.../bpf/progs/test_xdp_cpumap_rx_csum.c | 51 ++++++
.../selftests/bpf/progs/xdp_metadata.c | 9 ++
tools/testing/selftests/bpf/xdp_metadata.h | 8 +
14 files changed, 412 insertions(+), 2 deletions(-)
create mode 100644 tools/testing/selftests/bpf/prog_tests/xdp_cpumap_rx_csum.c
create mode 100644 tools/testing/selftests/bpf/progs/test_xdp_cpumap_rx_csum.c
base-commit: f456c1922c49e6be5ce407ddb74a6e61af5b65cf
--
2.47.0
^ permalink raw reply
* [RFC PATCH bpf-next v1 1/7] xdp: let XDP programs assert the RX checksum over redirect
From: Vladimir Vdovin @ 2026-06-30 19:15 UTC (permalink / raw)
To: bpf, netdev
Cc: ast, daniel, andrii, martin.lau, sdf, hawk, john.fastabend, kuba,
Vladimir Vdovin
In-Reply-To: <20260630191510.81402-1-deliran@verdict.gg>
When an XDP program redirects a frame to a cpumap (or any other path
that rebuilds an skb from an xdp_frame via __xdp_build_skb_from_frame()),
the HW RX checksum status is lost and the stack revalidates the L4
checksum in software.
Add a non-dev-bound kfunc, bpf_xdp_assert_rx_csum(), that lets the program
assert the L4 checksum is correct. It sets XDP_FLAGS_RX_CSUM_UNNECESSARY
on the buffer; the flag rides into the xdp_frame and
__xdp_build_skb_from_frame() turns it into skb->ip_summed =
CHECKSUM_UNNECESSARY. The kernel cannot verify the assertion, the program
takes responsibility, the same way it is already trusted to rewrite
arbitrary packet contents.
Signed-off-by: Vladimir Vdovin <deliran@verdict.gg>
---
include/net/xdp.h | 11 +++++++++++
net/core/xdp.c | 50 +++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 59 insertions(+), 2 deletions(-)
diff --git a/include/net/xdp.h b/include/net/xdp.h
index aa742f413c35..5a1e2cc9c312 100644
--- a/include/net/xdp.h
+++ b/include/net/xdp.h
@@ -81,6 +81,11 @@ enum xdp_buff_flags {
* XDP program is not attached.
*/
XDP_FLAGS_FRAGS_UNREADABLE = BIT(2),
+ /* XDP program asserts the L4 checksum is correct, so the skb built
+ * out of this frame (e.g. on the cpumap redirect path) can be marked
+ * CHECKSUM_UNNECESSARY instead of being validated in software.
+ */
+ XDP_FLAGS_RX_CSUM_UNNECESSARY = BIT(3),
};
struct xdp_buff {
@@ -316,6 +321,12 @@ xdp_frame_get_skb_flags(const struct xdp_frame *frame)
return frame->flags;
}
+static __always_inline bool
+xdp_frame_rx_csum_unnecessary(const struct xdp_frame *frame)
+{
+ return !!(frame->flags & XDP_FLAGS_RX_CSUM_UNNECESSARY);
+}
+
#define XDP_BULK_QUEUE_SIZE 16
struct xdp_frame_bulk {
int count;
diff --git a/net/core/xdp.c b/net/core/xdp.c
index 9890a30584ba..63ee36ec93de 100644
--- a/net/core/xdp.c
+++ b/net/core/xdp.c
@@ -830,8 +830,11 @@ struct sk_buff *__xdp_build_skb_from_frame(struct xdp_frame *xdpf,
/* Essential SKB info: protocol and skb->dev */
skb->protocol = eth_type_trans(skb, dev);
+ /* HW checksum info, if the XDP program asserted it */
+ if (xdp_frame_rx_csum_unnecessary(xdpf))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
/* Optional SKB info, currently missing:
- * - HW checksum info (skb->ip_summed)
* - HW RX hash (skb_set_hash)
* - RX ring dev queue index (skb_record_rx_queue)
*/
@@ -961,6 +964,31 @@ __bpf_kfunc int bpf_xdp_metadata_rx_vlan_tag(const struct xdp_md *ctx,
return -EOPNOTSUPP;
}
+/**
+ * bpf_xdp_assert_rx_csum - Assert the packet's L4 checksum is correct.
+ * @ctx: XDP context pointer.
+ *
+ * Mark the frame so that an skb later built out of it (e.g. on the cpumap
+ * redirect path, see __xdp_build_skb_from_frame()) is set to
+ * CHECKSUM_UNNECESSARY instead of being validated in software when it enters
+ * the stack.
+ *
+ * This is an assertion made by the XDP program: the kernel cannot verify it.
+ * The program takes responsibility for the checksum being correct, the same
+ * way it is already trusted to rewrite arbitrary packet contents. If the
+ * program modifies L4 data after calling this kfunc the assertion may no
+ * longer hold.
+ *
+ * Return: 0.
+ */
+__bpf_kfunc int bpf_xdp_assert_rx_csum(struct xdp_md *ctx)
+{
+ struct xdp_buff *xdp = (struct xdp_buff *)ctx;
+
+ xdp->flags |= XDP_FLAGS_RX_CSUM_UNNECESSARY;
+ return 0;
+}
+
__bpf_kfunc_end_defs();
BTF_KFUNCS_START(xdp_metadata_kfunc_ids)
@@ -974,6 +1002,18 @@ static const struct btf_kfunc_id_set xdp_metadata_kfunc_set = {
.set = &xdp_metadata_kfunc_ids,
};
+/* Generic XDP kfuncs that need no driver support and are therefore not
+ * dev-bound (unlike the rx-metadata kfuncs above).
+ */
+BTF_KFUNCS_START(xdp_kfunc_ids)
+BTF_ID_FLAGS(func, bpf_xdp_assert_rx_csum)
+BTF_KFUNCS_END(xdp_kfunc_ids)
+
+static const struct btf_kfunc_id_set xdp_kfunc_set = {
+ .owner = THIS_MODULE,
+ .set = &xdp_kfunc_ids,
+};
+
BTF_ID_LIST(xdp_metadata_kfunc_ids_unsorted)
#define XDP_METADATA_KFUNC(name, _, str, __) BTF_ID(func, str)
XDP_METADATA_KFUNC_xxx
@@ -992,7 +1032,13 @@ bool bpf_dev_bound_kfunc_id(u32 btf_id)
static int __init xdp_metadata_init(void)
{
- return register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, &xdp_metadata_kfunc_set);
+ int ret;
+
+ ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, &xdp_metadata_kfunc_set);
+ if (ret)
+ return ret;
+
+ return register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, &xdp_kfunc_set);
}
late_initcall(xdp_metadata_init);
--
2.47.0
^ permalink raw reply related
* [RFC PATCH bpf-next v1 2/7] selftests/bpf: add test for bpf_xdp_assert_rx_csum over cpumap
From: Vladimir Vdovin @ 2026-06-30 19:15 UTC (permalink / raw)
To: bpf, netdev
Cc: ast, daniel, andrii, martin.lau, sdf, hawk, john.fastabend, kuba,
Vladimir Vdovin
In-Reply-To: <20260630191510.81402-1-deliran@verdict.gg>
Drive a frame through a native-XDP veth into a cpumap redirect and
observe, via fexit on __xdp_build_skb_from_frame(), that the rebuilt skb
is CHECKSUM_UNNECESSARY when the program called bpf_xdp_assert_rx_csum()
and CHECKSUM_NONE otherwise. fexit is used because cpumap GRO would
otherwise normalize ip_summed before any later hook can observe it.
Signed-off-by: Vladimir Vdovin <deliran@verdict.gg>
---
.../bpf/prog_tests/xdp_cpumap_rx_csum.c | 150 ++++++++++++++++++
.../selftests/bpf/progs/bpf_tracing_net.h | 1 +
.../bpf/progs/test_xdp_cpumap_rx_csum.c | 51 ++++++
3 files changed, 202 insertions(+)
create mode 100644 tools/testing/selftests/bpf/prog_tests/xdp_cpumap_rx_csum.c
create mode 100644 tools/testing/selftests/bpf/progs/test_xdp_cpumap_rx_csum.c
diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_cpumap_rx_csum.c b/tools/testing/selftests/bpf/prog_tests/xdp_cpumap_rx_csum.c
new file mode 100644
index 000000000000..2def92fe1111
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/xdp_cpumap_rx_csum.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <net/if.h>
+#include <linux/if_ether.h>
+#include <linux/if_link.h>
+#include <linux/if_packet.h>
+#include <linux/ipv6.h>
+#include <netinet/in.h>
+#include <netinet/udp.h>
+#include <sys/socket.h>
+
+#include "test_progs.h"
+#include "network_helpers.h"
+#include <bpf/bpf_endian.h>
+#include "test_xdp_cpumap_rx_csum.skel.h"
+
+#define TEST_NS "xdp_cm_csum_ns"
+#define UDP_TEST_PORT 7777
+
+/* Kernel skb->ip_summed values, not exported to userspace headers. */
+#define CHECKSUM_NONE 0
+#define CHECKSUM_UNNECESSARY 1
+
+struct udp_pkt {
+ struct ethhdr eth;
+ struct ipv6hdr iph;
+ struct udphdr udp;
+ __u8 payload[16];
+} __packed;
+
+static struct udp_pkt pkt = {
+ .eth.h_proto = __bpf_constant_htons(ETH_P_IPV6),
+ .eth.h_dest = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .eth.h_source = {0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb},
+ .iph.version = 6,
+ .iph.nexthdr = IPPROTO_UDP,
+ .iph.payload_len = __bpf_constant_htons(sizeof(struct udphdr) + 16),
+ .iph.hop_limit = 64,
+ .udp.source = __bpf_constant_htons(1),
+ .udp.dest = __bpf_constant_htons(UDP_TEST_PORT),
+ .udp.len = __bpf_constant_htons(sizeof(struct udphdr) + 16),
+};
+
+/* Inject one frame on veth0; it is received on veth1 where native XDP
+ * redirects it into the cpumap. Report the ip_summed the rebuilt skb carried.
+ */
+static int inject_and_observe(struct test_xdp_cpumap_rx_csum *skel, int sfd,
+ int ifindex_src, bool assert_csum, int *ip_summed)
+{
+ struct sockaddr_ll sll = {
+ .sll_family = AF_PACKET,
+ .sll_ifindex = ifindex_src,
+ .sll_halen = 0,
+ };
+ int i, n;
+
+ skel->bss->assert_csum = assert_csum;
+ skel->bss->seen = false;
+ skel->data->observed_ip_summed = -1;
+
+ n = sendto(sfd, &pkt, sizeof(pkt), 0, (void *)&sll, sizeof(sll));
+ if (!ASSERT_EQ(n, sizeof(pkt), "sendto"))
+ return -1;
+
+ /* The skb is built asynchronously by the cpumap kthread. */
+ for (i = 0; i < 20 && !skel->bss->seen; i++)
+ usleep(50000);
+
+ if (!ASSERT_TRUE(skel->bss->seen, "skb built from frame"))
+ return -1;
+
+ *ip_summed = skel->data->observed_ip_summed;
+ return 0;
+}
+
+void test_xdp_cpumap_rx_csum(void)
+{
+ struct test_xdp_cpumap_rx_csum *skel = NULL;
+ struct bpf_cpumap_val val = { .qsize = 192 };
+ struct bpf_link *fexit_link = NULL;
+ struct nstoken *nstoken = NULL;
+ int err, map_fd, ifindex_dst = 0, ifindex_src, sfd = -1, ip_summed;
+ bool xdp_attached = false;
+ __u32 idx = 0;
+
+ SYS(out, "ip netns add %s", TEST_NS);
+ nstoken = open_netns(TEST_NS);
+ if (!ASSERT_OK_PTR(nstoken, "open_netns"))
+ goto out;
+
+ /* veth pair: a frame TX'd on veth0 is RX'd on veth1. */
+ SYS(out, "ip link add veth0 type veth peer name veth1");
+ SYS(out, "ip link set veth0 up");
+ SYS(out, "ip link set veth1 up");
+
+ skel = test_xdp_cpumap_rx_csum__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "skel open_and_load"))
+ goto out;
+
+ /* cpumap entry without a program: a plain redirect that forces the
+ * frame->skb conversion in __xdp_build_skb_from_frame().
+ */
+ map_fd = bpf_map__fd(skel->maps.cpu_map);
+ err = bpf_map_update_elem(map_fd, &idx, &val, 0);
+ if (!ASSERT_OK(err, "cpumap update"))
+ goto out;
+
+ ifindex_dst = if_nametoindex("veth1");
+ ifindex_src = if_nametoindex("veth0");
+ if (!ASSERT_GT(ifindex_dst, 0, "veth1 ifindex") ||
+ !ASSERT_GT(ifindex_src, 0, "veth0 ifindex"))
+ goto out;
+
+ /* Native XDP so the redirect goes through xdp_convert_buff_to_frame(),
+ * which propagates the rx-csum flag into the frame. Generic mode would
+ * redirect a ready-made skb and never hit our code path.
+ */
+ err = bpf_xdp_attach(ifindex_dst, bpf_program__fd(skel->progs.xdp_redir),
+ XDP_FLAGS_DRV_MODE, NULL);
+ if (!ASSERT_OK(err, "attach native xdp"))
+ goto out;
+ xdp_attached = true;
+
+ fexit_link = bpf_program__attach(skel->progs.on_build);
+ if (!ASSERT_OK_PTR(fexit_link, "attach fexit"))
+ goto out;
+
+ sfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+ if (!ASSERT_GE(sfd, 0, "AF_PACKET socket"))
+ goto out;
+
+ /* Program asserts the checksum -> CHECKSUM_UNNECESSARY. */
+ if (!inject_and_observe(skel, sfd, ifindex_src, true, &ip_summed))
+ ASSERT_EQ(ip_summed, CHECKSUM_UNNECESSARY,
+ "ip_summed marked unnecessary");
+
+ /* No assertion -> skb is left CHECKSUM_NONE for the stack to validate. */
+ if (!inject_and_observe(skel, sfd, ifindex_src, false, &ip_summed))
+ ASSERT_EQ(ip_summed, CHECKSUM_NONE, "ip_summed left none");
+
+out:
+ if (sfd >= 0)
+ close(sfd);
+ bpf_link__destroy(fexit_link);
+ if (xdp_attached)
+ bpf_xdp_detach(ifindex_dst, XDP_FLAGS_DRV_MODE, NULL);
+ test_xdp_cpumap_rx_csum__destroy(skel);
+ if (nstoken)
+ close_netns(nstoken);
+ SYS_NOFAIL("ip netns del %s", TEST_NS);
+}
diff --git a/tools/testing/selftests/bpf/progs/bpf_tracing_net.h b/tools/testing/selftests/bpf/progs/bpf_tracing_net.h
index d8dacef37c16..c3a0b2696035 100644
--- a/tools/testing/selftests/bpf/progs/bpf_tracing_net.h
+++ b/tools/testing/selftests/bpf/progs/bpf_tracing_net.h
@@ -87,6 +87,7 @@
#define TCPOLEN_SACK_PERM 2
#define CHECKSUM_NONE 0
+#define CHECKSUM_UNNECESSARY 1
#define CHECKSUM_PARTIAL 3
#define IFNAMSIZ 16
diff --git a/tools/testing/selftests/bpf/progs/test_xdp_cpumap_rx_csum.c b/tools/testing/selftests/bpf/progs/test_xdp_cpumap_rx_csum.c
new file mode 100644
index 000000000000..86c691887d25
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_xdp_cpumap_rx_csum.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "vmlinux.h"
+#include "bpf_tracing_net.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_endian.h>
+
+extern int bpf_xdp_assert_rx_csum(struct xdp_md *ctx) __ksym;
+
+struct {
+ __uint(type, BPF_MAP_TYPE_CPUMAP);
+ __uint(key_size, sizeof(__u32));
+ __uint(value_size, sizeof(struct bpf_cpumap_val));
+ __uint(max_entries, 1);
+} cpu_map SEC(".maps");
+
+/* Set from userspace before injecting each packet. */
+bool assert_csum = false;
+
+/* Filled in by the fexit program when the cpumap skb is built. */
+bool seen = false;
+int observed_ip_summed = -1;
+
+SEC("xdp")
+int xdp_redir(struct xdp_md *ctx)
+{
+ /* Assert the L4 checksum so the skb built on the cpumap redirect
+ * path is marked CHECKSUM_UNNECESSARY instead of validated in software.
+ */
+ if (assert_csum)
+ bpf_xdp_assert_rx_csum(ctx);
+
+ return bpf_redirect_map(&cpu_map, 0, 0);
+}
+
+/* Observe ip_summed exactly as __xdp_build_skb_from_frame() leaves it, before
+ * GRO in the cpumap kthread can normalize it. tc-ingress would be too late:
+ * GRO software-validates a CHECKSUM_NONE skb and marks it UNNECESSARY anyway.
+ */
+SEC("fexit/__xdp_build_skb_from_frame")
+int BPF_PROG(on_build, struct xdp_frame *xdpf, struct sk_buff *skb,
+ struct net_device *dev, struct sk_buff *ret)
+{
+ if (ret && ret->protocol == bpf_htons(ETH_P_IPV6)) {
+ observed_ip_summed = ret->ip_summed;
+ seen = true;
+ }
+ return 0;
+}
+
+char _license[] SEC("license") = "GPL";
--
2.47.0
^ permalink raw reply related
* [RFC PATCH bpf-next v1 3/7] xdp: add bpf_xdp_metadata_rx_csum() RX metadata kfunc
From: Vladimir Vdovin @ 2026-06-30 19:15 UTC (permalink / raw)
To: bpf, netdev
Cc: ast, daniel, andrii, martin.lau, sdf, hawk, john.fastabend, kuba,
Vladimir Vdovin
In-Reply-To: <20260630191510.81402-1-deliran@verdict.gg>
Add a device-bound RX-metadata kfunc that reports the hardware
checksum verdict (enum xdp_csum_status: XDP_CSUM_NONE / XDP_CSUM_VERIFIED)
through a new xmo_rx_csum operation, so an XDP program can make an
informed decision (e.g. call bpf_xdp_assert_rx_csum()) instead of trusting
blindly. Wire it into the XDP_METADATA_KFUNC machinery and advertise it
via NETDEV_XDP_RX_METADATA_CSUM.
Signed-off-by: Vladimir Vdovin <deliran@verdict.gg>
---
Documentation/netlink/specs/netdev.yaml | 5 +++++
include/net/xdp.h | 12 ++++++++++++
include/uapi/linux/netdev.h | 3 +++
net/core/xdp.c | 23 +++++++++++++++++++++++
tools/include/uapi/linux/netdev.h | 3 +++
5 files changed, 46 insertions(+)
diff --git a/Documentation/netlink/specs/netdev.yaml b/Documentation/netlink/specs/netdev.yaml
index 5f143da7458c..86017f7402d9 100644
--- a/Documentation/netlink/specs/netdev.yaml
+++ b/Documentation/netlink/specs/netdev.yaml
@@ -61,6 +61,11 @@ definitions:
doc: |
Device is capable of exposing receive packet VLAN tag via
bpf_xdp_metadata_rx_vlan_tag().
+ -
+ name: csum
+ doc: |
+ Device is capable of exposing receive packet checksum status via
+ bpf_xdp_metadata_rx_csum().
-
type: flags
name: xsk-flags
diff --git a/include/net/xdp.h b/include/net/xdp.h
index 5a1e2cc9c312..40f6fba41962 100644
--- a/include/net/xdp.h
+++ b/include/net/xdp.h
@@ -597,6 +597,10 @@ void xdp_attachment_setup(struct xdp_attachment_info *info,
NETDEV_XDP_RX_METADATA_VLAN_TAG, \
bpf_xdp_metadata_rx_vlan_tag, \
xmo_rx_vlan_tag) \
+ XDP_METADATA_KFUNC(XDP_METADATA_KFUNC_RX_CSUM, \
+ NETDEV_XDP_RX_METADATA_CSUM, \
+ bpf_xdp_metadata_rx_csum, \
+ xmo_rx_csum) \
enum xdp_rx_metadata {
#define XDP_METADATA_KFUNC(name, _, __, ___) name,
@@ -654,12 +658,20 @@ enum xdp_rss_hash_type {
XDP_RSS_TYPE_L4_IPV6_SCTP_EX = XDP_RSS_TYPE_L4_IPV6_SCTP | XDP_RSS_L3_DYNHDR,
};
+/* Checksum status reported by bpf_xdp_metadata_rx_csum(). */
+enum xdp_csum_status {
+ XDP_CSUM_NONE = 0, /* HW did not validate the checksum */
+ XDP_CSUM_VERIFIED, /* HW validated the L4 checksum; it is correct */
+};
+
struct xdp_metadata_ops {
int (*xmo_rx_timestamp)(const struct xdp_md *ctx, u64 *timestamp);
int (*xmo_rx_hash)(const struct xdp_md *ctx, u32 *hash,
enum xdp_rss_hash_type *rss_type);
int (*xmo_rx_vlan_tag)(const struct xdp_md *ctx, __be16 *vlan_proto,
u16 *vlan_tci);
+ int (*xmo_rx_csum)(const struct xdp_md *ctx,
+ enum xdp_csum_status *csum_status);
};
#ifdef CONFIG_NET
diff --git a/include/uapi/linux/netdev.h b/include/uapi/linux/netdev.h
index 2f3ab75e8cc0..99cda716f0ee 100644
--- a/include/uapi/linux/netdev.h
+++ b/include/uapi/linux/netdev.h
@@ -47,11 +47,14 @@ enum netdev_xdp_act {
* hash via bpf_xdp_metadata_rx_hash().
* @NETDEV_XDP_RX_METADATA_VLAN_TAG: Device is capable of exposing receive
* packet VLAN tag via bpf_xdp_metadata_rx_vlan_tag().
+ * @NETDEV_XDP_RX_METADATA_CSUM: Device is capable of exposing receive packet
+ * checksum status via bpf_xdp_metadata_rx_csum().
*/
enum netdev_xdp_rx_metadata {
NETDEV_XDP_RX_METADATA_TIMESTAMP = 1,
NETDEV_XDP_RX_METADATA_HASH = 2,
NETDEV_XDP_RX_METADATA_VLAN_TAG = 4,
+ NETDEV_XDP_RX_METADATA_CSUM = 8,
};
/**
diff --git a/net/core/xdp.c b/net/core/xdp.c
index 63ee36ec93de..7f4b5c6f7c87 100644
--- a/net/core/xdp.c
+++ b/net/core/xdp.c
@@ -964,6 +964,29 @@ __bpf_kfunc int bpf_xdp_metadata_rx_vlan_tag(const struct xdp_md *ctx,
return -EOPNOTSUPP;
}
+/**
+ * bpf_xdp_metadata_rx_csum - Read the device's RX checksum verdict.
+ * @ctx: XDP context pointer.
+ * @csum_status: Destination pointer for the checksum status.
+ *
+ * Report what the hardware concluded about the packet's checksum, so the
+ * program can decide whether to assert it (e.g. via bpf_xdp_assert_rx_csum()
+ * before a cpumap redirect) instead of having the stack validate it again.
+ *
+ * On ``XDP_CSUM_VERIFIED`` the device has checked the L4 checksum and it is
+ * correct. ``XDP_CSUM_NONE`` means the device did not validate it.
+ *
+ * Return:
+ * * Returns 0 on success or ``-errno`` on error.
+ * * ``-EOPNOTSUPP`` : device driver doesn't implement kfunc
+ * * ``-ENODATA`` : checksum information is not available
+ */
+__bpf_kfunc int bpf_xdp_metadata_rx_csum(const struct xdp_md *ctx,
+ enum xdp_csum_status *csum_status)
+{
+ return -EOPNOTSUPP;
+}
+
/**
* bpf_xdp_assert_rx_csum - Assert the packet's L4 checksum is correct.
* @ctx: XDP context pointer.
diff --git a/tools/include/uapi/linux/netdev.h b/tools/include/uapi/linux/netdev.h
index 2f3ab75e8cc0..99cda716f0ee 100644
--- a/tools/include/uapi/linux/netdev.h
+++ b/tools/include/uapi/linux/netdev.h
@@ -47,11 +47,14 @@ enum netdev_xdp_act {
* hash via bpf_xdp_metadata_rx_hash().
* @NETDEV_XDP_RX_METADATA_VLAN_TAG: Device is capable of exposing receive
* packet VLAN tag via bpf_xdp_metadata_rx_vlan_tag().
+ * @NETDEV_XDP_RX_METADATA_CSUM: Device is capable of exposing receive packet
+ * checksum status via bpf_xdp_metadata_rx_csum().
*/
enum netdev_xdp_rx_metadata {
NETDEV_XDP_RX_METADATA_TIMESTAMP = 1,
NETDEV_XDP_RX_METADATA_HASH = 2,
NETDEV_XDP_RX_METADATA_VLAN_TAG = 4,
+ NETDEV_XDP_RX_METADATA_CSUM = 8,
};
/**
--
2.47.0
^ permalink raw reply related
* [RFC PATCH bpf-next v1 4/7] net/mlx5e: support the rx_csum XDP metadata hint
From: Vladimir Vdovin @ 2026-06-30 19:15 UTC (permalink / raw)
To: bpf, netdev
Cc: ast, daniel, andrii, martin.lau, sdf, hawk, john.fastabend, kuba,
Vladimir Vdovin
In-Reply-To: <20260630191510.81402-1-deliran@verdict.gg>
Implement xmo_rx_csum by reading CQE_L3_OK/CQE_L4_OK, mirroring the
verdict mlx5e_handle_csum() uses for CHECKSUM_UNNECESSARY.
CHECKSUM_COMPLETE is intentionally not surfaced: it is already
disabled while an XDP program is loaded.
Signed-off-by: Vladimir Vdovin <deliran@verdict.gg>
---
.../net/ethernet/mellanox/mlx5/core/en/xdp.c | 23 +++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
index d8c7cb8837d7..6ac06bd24c79 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
@@ -277,10 +277,33 @@ static int mlx5e_xdp_rx_vlan_tag(const struct xdp_md *ctx, __be16 *vlan_proto,
return 0;
}
+static int mlx5e_xdp_rx_csum(const struct xdp_md *ctx,
+ enum xdp_csum_status *csum_status)
+{
+ const struct mlx5e_xdp_buff *_ctx = (void *)ctx;
+ const struct mlx5_cqe64 *cqe = _ctx->cqe;
+
+ if (unlikely(!(_ctx->xdp.rxq->dev->features & NETIF_F_RXCSUM)))
+ return -ENODATA;
+
+ /* Same verdict the normal RX path uses for CHECKSUM_UNNECESSARY.
+ * CHECKSUM_COMPLETE is deliberately not surfaced here: it is disabled
+ * while an XDP program is loaded (see mlx5e_handle_csum()).
+ */
+ if (likely((cqe->hds_ip_ext & CQE_L3_OK) &&
+ (cqe->hds_ip_ext & CQE_L4_OK)))
+ *csum_status = XDP_CSUM_VERIFIED;
+ else
+ *csum_status = XDP_CSUM_NONE;
+
+ return 0;
+}
+
const struct xdp_metadata_ops mlx5e_xdp_metadata_ops = {
.xmo_rx_timestamp = mlx5e_xdp_rx_timestamp,
.xmo_rx_hash = mlx5e_xdp_rx_hash,
.xmo_rx_vlan_tag = mlx5e_xdp_rx_vlan_tag,
+ .xmo_rx_csum = mlx5e_xdp_rx_csum,
};
struct mlx5e_xsk_tx_complete {
--
2.47.0
^ permalink raw reply related
* [RFC PATCH bpf-next v1 5/7] ice: support the rx_csum XDP metadata hint
From: Vladimir Vdovin @ 2026-06-30 19:15 UTC (permalink / raw)
To: bpf, netdev
Cc: ast, daniel, andrii, martin.lau, sdf, hawk, john.fastabend, kuba,
Vladimir Vdovin
In-Reply-To: <20260630191510.81402-1-deliran@verdict.gg>
Implement xmo_rx_csum from the Rx flex descriptor status0 bits
(L3L4P set and no XSUM_L4E), mirroring ice_rx_csum(). Return -ENODATA
when RX checksum offload (NETIF_F_RXCSUM) is disabled, since the status
bits are not meaningful then.
Signed-off-by: Vladimir Vdovin <deliran@verdict.gg>
---
drivers/net/ethernet/intel/ice/ice_txrx_lib.c | 32 +++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx_lib.c b/drivers/net/ethernet/intel/ice/ice_txrx_lib.c
index e695a664e53d..d13c5e76bc13 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_txrx_lib.c
@@ -594,8 +594,40 @@ static int ice_xdp_rx_vlan_tag(const struct xdp_md *ctx, __be16 *vlan_proto,
return 0;
}
+/**
+ * ice_xdp_rx_csum - RX checksum XDP hint handler
+ * @ctx: XDP buff pointer
+ * @csum_status: destination for the checksum verdict
+ *
+ * Report whether the hardware validated the packet's L4 checksum, mirroring
+ * the verdict ice_rx_csum() uses for CHECKSUM_UNNECESSARY. Return -ENODATA
+ * when RX checksum offload is disabled, since the status bits are not
+ * meaningful then.
+ */
+static int ice_xdp_rx_csum(const struct xdp_md *ctx,
+ enum xdp_csum_status *csum_status)
+{
+ const struct libeth_xdp_buff *xdp_ext = (void *)ctx;
+ struct ice_rx_ring *rx_ring;
+ u16 status0;
+
+ rx_ring = libeth_xdp_buff_to_rq(xdp_ext, typeof(*rx_ring), xdp_rxq);
+ if (!(rx_ring->netdev->features & NETIF_F_RXCSUM))
+ return -ENODATA;
+
+ status0 = le16_to_cpu(xdp_ext->desc->wb.status_error0);
+ if ((status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_L3L4P_S)) &&
+ !(status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_XSUM_L4E_S)))
+ *csum_status = XDP_CSUM_VERIFIED;
+ else
+ *csum_status = XDP_CSUM_NONE;
+
+ return 0;
+}
+
const struct xdp_metadata_ops ice_xdp_md_ops = {
.xmo_rx_timestamp = ice_xdp_rx_hw_ts,
.xmo_rx_hash = ice_xdp_rx_hash,
.xmo_rx_vlan_tag = ice_xdp_rx_vlan_tag,
+ .xmo_rx_csum = ice_xdp_rx_csum,
};
--
2.47.0
^ permalink raw reply related
* [RFC PATCH bpf-next v1 6/7] veth: support the rx_csum XDP metadata hint
From: Vladimir Vdovin @ 2026-06-30 19:15 UTC (permalink / raw)
To: bpf, netdev
Cc: ast, daniel, andrii, martin.lau, sdf, hawk, john.fastabend, kuba,
Vladimir Vdovin
In-Reply-To: <20260630191510.81402-1-deliran@verdict.gg>
Implement xmo_rx_csum from skb->ip_summed. veth has no real hardware;
this surfaces whatever checksum verdict the skb already carries and makes
the metadata kfunc testable without a NIC.
Signed-off-by: Vladimir Vdovin <deliran@verdict.gg>
---
drivers/net/veth.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 1c5142149175..b7bc5a3b07e5 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1700,6 +1700,28 @@ static int veth_xdp_rx_vlan_tag(const struct xdp_md *ctx, __be16 *vlan_proto,
return err;
}
+static int veth_xdp_rx_csum(const struct xdp_md *ctx,
+ enum xdp_csum_status *csum_status)
+{
+ const struct veth_xdp_buff *_ctx = (void *)ctx;
+ const struct sk_buff *skb = _ctx->skb;
+
+ if (!skb)
+ return -ENODATA;
+
+ /* veth has no real hardware; surface whatever checksum verdict the
+ * skb already carries (e.g. CHECKSUM_PARTIAL/UNNECESSARY from a local
+ * sender or a previous validation).
+ */
+ if (skb->ip_summed == CHECKSUM_UNNECESSARY ||
+ skb->ip_summed == CHECKSUM_PARTIAL)
+ *csum_status = XDP_CSUM_VERIFIED;
+ else
+ *csum_status = XDP_CSUM_NONE;
+
+ return 0;
+}
+
static const struct net_device_ops veth_netdev_ops = {
.ndo_init = veth_dev_init,
.ndo_open = veth_open,
@@ -1725,6 +1747,7 @@ static const struct xdp_metadata_ops veth_xdp_metadata_ops = {
.xmo_rx_timestamp = veth_xdp_rx_timestamp,
.xmo_rx_hash = veth_xdp_rx_hash,
.xmo_rx_vlan_tag = veth_xdp_rx_vlan_tag,
+ .xmo_rx_csum = veth_xdp_rx_csum,
};
#define VETH_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HW_CSUM | \
--
2.47.0
^ permalink raw reply related
* [RFC PATCH bpf-next v1 7/7] selftests/bpf: cover bpf_xdp_metadata_rx_csum in xdp_metadata
From: Vladimir Vdovin @ 2026-06-30 19:15 UTC (permalink / raw)
To: bpf, netdev
Cc: ast, daniel, andrii, martin.lau, sdf, hawk, john.fastabend, kuba,
Vladimir Vdovin
In-Reply-To: <20260630191510.81402-1-deliran@verdict.gg>
Call bpf_xdp_metadata_rx_csum() in the xdp_metadata program and export the
status to userspace. veth surfaces skb->ip_summed: a frame injected via
AF_XDP carries no checksum context (XDP_CSUM_NONE), while one sent through
the stack is CHECKSUM_PARTIAL (XDP_CSUM_VERIFIED). Assert each.
Signed-off-by: Vladimir Vdovin <deliran@verdict.gg>
---
tools/testing/selftests/bpf/prog_tests/xdp_metadata.c | 10 ++++++++++
tools/testing/selftests/bpf/progs/xdp_metadata.c | 9 +++++++++
tools/testing/selftests/bpf/xdp_metadata.h | 8 ++++++++
3 files changed, 27 insertions(+)
diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_metadata.c b/tools/testing/selftests/bpf/prog_tests/xdp_metadata.c
index 5c31054ad4a4..77f55696eb78 100644
--- a/tools/testing/selftests/bpf/prog_tests/xdp_metadata.c
+++ b/tools/testing/selftests/bpf/prog_tests/xdp_metadata.c
@@ -310,6 +310,16 @@ static int verify_xsk_metadata(struct xsk *xsk, bool sent_from_af_xdp)
if (!ASSERT_NEQ(meta->rx_hash, 0, "rx_hash"))
return -1;
+ /* veth surfaces the checksum verdict from skb->ip_summed. A packet
+ * injected via AF_XDP carries no checksum context and is CHECKSUM_NONE,
+ * while one sent through the stack is CHECKSUM_PARTIAL and reads back as
+ * verified.
+ */
+ if (!ASSERT_EQ(meta->rx_csum_status,
+ sent_from_af_xdp ? XDP_META_CSUM_NONE : XDP_META_CSUM_VERIFIED,
+ "rx_csum_status"))
+ return -1;
+
if (!sent_from_af_xdp) {
if (!ASSERT_NEQ(meta->rx_hash_type & XDP_RSS_TYPE_L4, 0, "rx_hash_type"))
return -1;
diff --git a/tools/testing/selftests/bpf/progs/xdp_metadata.c b/tools/testing/selftests/bpf/progs/xdp_metadata.c
index 09bb8a038d52..0089c6c5a2e4 100644
--- a/tools/testing/selftests/bpf/progs/xdp_metadata.c
+++ b/tools/testing/selftests/bpf/progs/xdp_metadata.c
@@ -33,6 +33,8 @@ extern int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, __u32 *hash,
extern int bpf_xdp_metadata_rx_vlan_tag(const struct xdp_md *ctx,
__be16 *vlan_proto,
__u16 *vlan_tci) __ksym;
+extern int bpf_xdp_metadata_rx_csum(const struct xdp_md *ctx,
+ enum xdp_csum_status *csum_status) __ksym;
SEC("xdp")
int rx(struct xdp_md *ctx)
@@ -43,6 +45,7 @@ int rx(struct xdp_md *ctx)
struct udphdr *udp = NULL;
struct iphdr *iph = NULL;
struct xdp_meta *meta;
+ enum xdp_csum_status csum_status;
u64 timestamp = -1;
int ret;
@@ -99,6 +102,12 @@ int rx(struct xdp_md *ctx)
bpf_xdp_metadata_rx_vlan_tag(ctx, &meta->rx_vlan_proto,
&meta->rx_vlan_tci);
+ ret = bpf_xdp_metadata_rx_csum(ctx, &csum_status);
+ if (ret < 0)
+ meta->rx_csum_err = ret;
+ else
+ meta->rx_csum_status = csum_status;
+
return bpf_redirect_map(&xsk, ctx->rx_queue_index, XDP_PASS);
}
diff --git a/tools/testing/selftests/bpf/xdp_metadata.h b/tools/testing/selftests/bpf/xdp_metadata.h
index 87318ad1117a..ba1b2902b371 100644
--- a/tools/testing/selftests/bpf/xdp_metadata.h
+++ b/tools/testing/selftests/bpf/xdp_metadata.h
@@ -30,6 +30,10 @@ enum xdp_meta_field {
XDP_META_FIELD_VLAN_TAG = BIT(2),
};
+/* Mirror of enum xdp_csum_status (include/net/xdp.h) for userspace asserts. */
+#define XDP_META_CSUM_NONE 0
+#define XDP_META_CSUM_VERIFIED 1
+
struct xdp_meta {
union {
__u64 rx_timestamp;
@@ -48,5 +52,9 @@ struct xdp_meta {
};
__s32 rx_vlan_tag_err;
};
+ union {
+ __u32 rx_csum_status;
+ __s32 rx_csum_err;
+ };
enum xdp_meta_field hint_valid;
};
--
2.47.0
^ permalink raw reply related
* Re: [syzbot] [wireless?] WARNING in mac80211_hwsim_tx (2)
From: syzbot @ 2026-06-30 19:33 UTC (permalink / raw)
To: johannes, linux-kernel, linux-wireless, netdev, syzkaller-bugs
In-Reply-To: <6a00f268.170a0220.1c0296.021c.GAE@google.com>
syzbot has found a reproducer for the following issue on:
HEAD commit: dc59e4fea9d8 Linux 7.2-rc1
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=12f58032580000
kernel config: https://syzkaller.appspot.com/x/.config?x=3c3d59be33cf7e9a
dashboard link: https://syzkaller.appspot.com/bug?extid=435fdb053cf98bfa5778
compiler: Debian clang version 22.1.8 (++20260613092233+e80beda6e255-1~exp1~20260613092250.77), Debian LLD 22.1.8
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=13a73289580000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=135db61e580000
Downloadable assets:
disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-dc59e4fe.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/9ee1f0ea24f2/vmlinux-dc59e4fe.xz
kernel image: https://storage.googleapis.com/syzbot-assets/729e963a1370/bzImage-dc59e4fe.xz
IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+435fdb053cf98bfa5778@syzkaller.appspotmail.com
mac80211_hwsim hwsim5 wlan1: entered allmulticast mode
------------[ cut here ]------------
hwsim_get_chanwidth(bw) > hwsim_get_chanwidth(confbw)
WARNING: drivers/net/wireless/virtual/mac80211_hwsim_main.c:2248 at mac80211_hwsim_tx+0x1ab4/0x2500 drivers/net/wireless/virtual/mac80211_hwsim_main.c:2248, CPU#0: syz.0.17/5510
Modules linked in:
CPU: 0 UID: 0 PID: 5510 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
RIP: 0010:mac80211_hwsim_tx+0x1ab4/0x2500 drivers/net/wireless/virtual/mac80211_hwsim_main.c:2248
Code: c6 05 da 65 07 09 01 48 c7 c7 e0 74 7a 8c be 6b 08 00 00 48 c7 c2 20 76 7a 8c e8 a7 d6 8c fa e9 ff ee ff ff e8 7d eb b0 fa 90 <0f> 0b 90 49 bc 00 00 00 00 00 fc ff df e9 dd fe ff ff e8 65 eb b0
RSP: 0018:ffffc9000278efe0 EFLAGS: 00010293
RAX: ffffffff87158693 RBX: 0000000000000000 RCX: ffff888000ad8000
RDX: 0000000000000000 RSI: 0000000000000014 RDI: 00000000000000a0
RBP: ffffc9000278f170 R08: ffff888000ad8000 R09: 000000000000000e
R10: 000000000000000d R11: 0000000000000000 R12: 0000000000000014
R13: ffff8880120b3cb0 R14: 00000000000000a0 R15: 0000000000000030
FS: 000055559073c500(0000) GS:ffff88808c815000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00005562391e0138 CR3: 0000000012ea1000 CR4: 0000000000352ef0
Call Trace:
<TASK>
drv_tx net/mac80211/driver-ops.h:38 [inline]
ieee80211_tx_frags+0x3df/0x890 net/mac80211/tx.c:1746
__ieee80211_tx+0x267/0x580 net/mac80211/tx.c:1801
ieee80211_tx+0x312/0x4b0 net/mac80211/tx.c:1984
ieee80211_monitor_start_xmit+0xb33/0x1280 net/mac80211/tx.c:2479
__netdev_start_xmit include/linux/netdevice.h:5400 [inline]
netdev_start_xmit include/linux/netdevice.h:5409 [inline]
xmit_one net/core/dev.c:3889 [inline]
dev_hard_start_xmit+0x2cd/0x830 net/core/dev.c:3905
__dev_queue_xmit+0x1435/0x37f0 net/core/dev.c:4872
packet_snd net/packet/af_packet.c:3082 [inline]
packet_sendmsg+0x3d95/0x5040 net/packet/af_packet.c:3114
sock_sendmsg_nosec+0x13a/0x180 net/socket.c:775
__sock_sendmsg net/socket.c:790 [inline]
__sys_sendto+0x408/0x5a0 net/socket.c:2252
__do_sys_sendto net/socket.c:2259 [inline]
__se_sys_sendto net/socket.c:2255 [inline]
__x64_sys_sendto+0xde/0x100 net/socket.c:2255
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x174/0x580 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fc04219ce59
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffcb766be38 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
RAX: ffffffffffffffda RBX: 00007fc042415fa0 RCX: 00007fc04219ce59
RDX: 0000000000000030 RSI: 0000200000000640 RDI: 0000000000000008
RBP: 00007fc042232e6f R08: 0000200000000380 R09: 0000000000000014
R10: 0000000004000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fc042415fac R14: 00007fc042415fa0 R15: 00007fc042415fa0
</TASK>
---
If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.
^ permalink raw reply
* Re: [PATCH v2 1/7] ata: don't keep pci_device_id
From: Danilo Krummrich @ 2026-06-30 19:46 UTC (permalink / raw)
To: Gary Guo
Cc: Bjorn Helgaas, Zhenzhong Duan, Greg Kroah-Hartman,
Rafael J. Wysocki, Damien Le Moal, Niklas Cassel, GOTO Masanori,
YOKOTA Hiroshi, James E.J. Bottomley, Martin K. Petersen,
Vaibhav Gupta, Jens Taprogge, Ido Schimmel, Petr Machata,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, linux-pci, driver-core, linux-kernel, linux-ide,
linux-scsi, industrypack-devel, netdev
In-Reply-To: <20260630-pci_id_fix-v2-1-b834a98c0af2@garyguo.net>
On Tue Jun 30, 2026 at 1:09 PM CEST, Gary Guo wrote:
> pci_device_id is not guaranteed to live longer than probe due to presence
> of dynamic ID. All information apart from driver_data can be easily
> retrieved from pci_dev, so just store driver_data.
>
> Signed-off-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Danilo Krummrich <dakr@kernel.org>
^ permalink raw reply
* Re: [PATCH v2 2/7] nsp32: don't keep pci_device_id
From: Danilo Krummrich @ 2026-06-30 19:46 UTC (permalink / raw)
To: Gary Guo
Cc: Bjorn Helgaas, Zhenzhong Duan, Greg Kroah-Hartman,
Rafael J. Wysocki, Damien Le Moal, Niklas Cassel, GOTO Masanori,
YOKOTA Hiroshi, James E.J. Bottomley, Martin K. Petersen,
Vaibhav Gupta, Jens Taprogge, Ido Schimmel, Petr Machata,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, linux-pci, driver-core, linux-kernel, linux-ide,
linux-scsi, industrypack-devel, netdev
In-Reply-To: <20260630-pci_id_fix-v2-2-b834a98c0af2@garyguo.net>
On Tue Jun 30, 2026 at 1:09 PM CEST, Gary Guo wrote:
> pci_device_id is not guaranteed to live longer than probe due to presence
> of dynamic ID. All information apart from driver_data can be easily
> retrieved from pci_dev, so just store driver_data.
>
> Signed-off-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Danilo Krummrich <dakr@kernel.org>
^ permalink raw reply
* Re: [PATCH v2 3/7] ipack: tpci200: don't keep pci_device_id
From: Danilo Krummrich @ 2026-06-30 19:47 UTC (permalink / raw)
To: Gary Guo
Cc: Bjorn Helgaas, Zhenzhong Duan, Greg Kroah-Hartman,
Rafael J. Wysocki, Damien Le Moal, Niklas Cassel, GOTO Masanori,
YOKOTA Hiroshi, James E.J. Bottomley, Martin K. Petersen,
Vaibhav Gupta, Jens Taprogge, Ido Schimmel, Petr Machata,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, linux-pci, driver-core, linux-kernel, linux-ide,
linux-scsi, industrypack-devel, netdev
In-Reply-To: <20260630-pci_id_fix-v2-3-b834a98c0af2@garyguo.net>
On Tue Jun 30, 2026 at 1:09 PM CEST, Gary Guo wrote:
> pci_device_id is not guaranteed to live longer than probe due to presence
> of dynamic ID. This stored ID is unused so remove it.
>
> Signed-off-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Danilo Krummrich <dakr@kernel.org>
^ permalink raw reply
* Re: [PATCH v2 4/7] mlxsw: don't keep pci_device_id
From: Danilo Krummrich @ 2026-06-30 19:48 UTC (permalink / raw)
To: Gary Guo
Cc: Bjorn Helgaas, Zhenzhong Duan, Greg Kroah-Hartman,
Rafael J. Wysocki, Damien Le Moal, Niklas Cassel, GOTO Masanori,
YOKOTA Hiroshi, James E.J. Bottomley, Martin K. Petersen,
Vaibhav Gupta, Jens Taprogge, Ido Schimmel, Petr Machata,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, linux-pci, driver-core, linux-kernel, linux-ide,
linux-scsi, industrypack-devel, netdev
In-Reply-To: <20260630-pci_id_fix-v2-4-b834a98c0af2@garyguo.net>
On Tue Jun 30, 2026 at 1:09 PM CEST, Gary Guo wrote:
> pci_device_id is not guaranteed to live longer than probe due to presence
> of dynamic ID. This stored ID is unused so remove it.
>
> Signed-off-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Danilo Krummrich <dakr@kernel.org>
^ permalink raw reply
* [PATCH net] llc: fix SAP refcount leak in llc_ui_autobind()
From: Shuangpeng Bai @ 2026-06-30 19:48 UTC (permalink / raw)
To: netdev
Cc: davem, edumazet, kuba, pabeni, horms, linux-kernel,
Shuangpeng Bai, stable
llc_ui_autobind() opens a SAP after choosing a dynamic LSAP.
llc_sap_open() returns a reference owned by the caller, and
llc_sap_add_socket() takes a second reference for the socket's
membership in the SAP hash tables.
llc_ui_bind() drops the caller's reference after adding the socket,
but llc_ui_autobind() keeps it. When the socket is closed,
llc_sap_remove_socket() releases only the socket reference, leaving
the SAP on llc_sap_list with sk_count == 0.
This is user-visible because repeated autobind and close cycles can consume
all dynamic SAP values and make later autobinds fail with -EUSERS.
Drop the caller's reference after a successful autobind, matching
llc_ui_bind()'s ownership model.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Shuangpeng Bai <shuangpeng.kernel@gmail.com>
---
net/llc/af_llc.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index 8ed1be1ecccc..b0447c33dbf0 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -312,6 +312,7 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
/* assign new connection to its SAP */
llc_sap_add_socket(sap, sk);
sock_reset_flag(sk, SOCK_ZAPPED);
+ llc_sap_put(sap);
rc = 0;
out:
dev_put(dev);
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v1 net-next 07/10] net: fib_rules: Drop RTNL assertions.
From: Kuniyuki Iwashima @ 2026-06-30 19:52 UTC (permalink / raw)
To: David Ahern, Ido Schimmel, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Kuniyuki Iwashima, netdev
In-Reply-To: <20260629181226.1929658-8-kuniyu@google.com>
Replying to Sashiko review.
On Mon, Jun 29, 2026 at 11:12 AM Kuniyuki Iwashima <kuniyu@google.com> wrote:
>
> Now, fib_rule structs are protected by per-fib_rules_ops mutex.
>
> Let's drop ASSERT_RTNL_NET() and rtnl_dereference().
>
> Note that fib_rules_event() iterates over net->rules_ops without
> net->rules_mod_lock, but this is fine because all fib_rule users
> are built-in and concurrent fib_rules_unregister() does not happen.
---8<---
Is this description accurate?
---8<---
Yes.
---8<---
It appears that unprivileged users can trigger a race here via user
namespaces. If a user creates two network namespaces with a veth pair, moving
one interface to each, and then triggers netns destruction on one namespace
while concurrently deleting the veth interface from the other namespace:
...
---8<---
Sashiko somehow thinks it's possible to remove a netdev and dismantle
another netns, both of which require RTNL, so false-positive.
>
> Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
> ---
> net/core/fib_rules.c | 9 +++------
> 1 file changed, 3 insertions(+), 6 deletions(-)
>
> diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
> index 25a3fd997782..5eef5d6ace82 100644
> --- a/net/core/fib_rules.c
> +++ b/net/core/fib_rules.c
> @@ -387,7 +387,6 @@ static int call_fib_rule_notifiers(struct net *net,
> .rule = rule,
> };
>
> - ASSERT_RTNL_NET(net);
> lockdep_assert_held(&ops->lock);
>
> /* Paired with READ_ONCE() in fib_rules_seq() */
> @@ -955,7 +954,7 @@ int fib_newrule(struct net *net, struct sk_buff *skb, struct nlmsghdr *nlh,
> list_for_each_entry(r, &ops->rules_list, list) {
> if (r->action == FR_ACT_GOTO &&
> r->target == rule->pref &&
> - rtnl_dereference(r->ctarget) == NULL) {
> + !rcu_access_pointer(r->ctarget)) {
> rcu_assign_pointer(r->ctarget, rule);
> if (--ops->unresolved_rules == 0)
> break;
> @@ -1064,7 +1063,7 @@ int fib_delrule(struct net *net, struct sk_buff *skb, struct nlmsghdr *nlh,
>
> if (rule->action == FR_ACT_GOTO) {
> ops->nr_goto_rules--;
> - if (rtnl_dereference(rule->ctarget) == NULL)
> + if (!rcu_access_pointer(rule->ctarget))
> ops->unresolved_rules--;
> }
>
> @@ -1082,7 +1081,7 @@ int fib_delrule(struct net *net, struct sk_buff *skb, struct nlmsghdr *nlh,
> if (&n->list == &ops->rules_list || n->pref != rule->pref)
> n = NULL;
> list_for_each_entry(r, &ops->rules_list, list) {
> - if (rtnl_dereference(r->ctarget) != rule)
> + if (rcu_access_pointer(r->ctarget) != rule)
> continue;
> rcu_assign_pointer(r->ctarget, n);
> if (!n)
> @@ -1400,8 +1399,6 @@ static int fib_rules_event(struct notifier_block *this, unsigned long event,
> struct net *net = dev_net(dev);
> struct fib_rules_ops *ops;
>
> - ASSERT_RTNL();
> -
> switch (event) {
> case NETDEV_REGISTER:
> list_for_each_entry(ops, &net->rules_ops, list) {
> --
> 2.55.0.rc0.799.gd6f94ed593-goog
>
^ permalink raw reply
* Re: [PATCH v1 net-next 10/10] ipv6: fib_rules: Convert fib6_rules_net_exit_rtnl() to ->exit().
From: Kuniyuki Iwashima @ 2026-06-30 19:56 UTC (permalink / raw)
To: David Ahern, Ido Schimmel, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Kuniyuki Iwashima, netdev
In-Reply-To: <20260629181226.1929658-11-kuniyu@google.com>
Replying to Sashiko review
On Mon, Jun 29, 2026 at 11:12 AM Kuniyuki Iwashima <kuniyu@google.com> wrote:
>
> Now fib_rule is protected by per-ops mutex.
>
> fib6_rules_net_exit_batch() no longer needs RTNL.
>
> Let's convert it to ->exit() and drop RTNL.
>
> Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
> ---
> net/ipv6/fib6_rules.c | 13 +++----------
> 1 file changed, 3 insertions(+), 10 deletions(-)
>
> diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
> index 5ab4dde07225..04dab9329d0c 100644
> --- a/net/ipv6/fib6_rules.c
> +++ b/net/ipv6/fib6_rules.c
> @@ -635,21 +635,14 @@ static int __net_init fib6_rules_net_init(struct net *net)
> goto out;
> }
>
> -static void __net_exit fib6_rules_net_exit_batch(struct list_head *net_list)
> +static void __net_exit fib6_rules_net_exit(struct net *net)
> {
> - struct net *net;
> -
> - rtnl_lock();
> - list_for_each_entry(net, net_list, exit_list) {
> - fib_rules_unregister(net->ipv6.fib6_rules_ops);
> - cond_resched();
> - }
> - rtnl_unlock();
> + fib_rules_unregister(net->ipv6.fib6_rules_ops);
> }
---8<---
Does removing the rtnl_lock() here introduce a use-after-free and list
corruption regression with the netdev notifier fib_rules_event()?
When a veth interface is deleted while its peer is in a network namespace
undergoing teardown, the cleanup_net workqueue can execute this locklessly.
---8<---
Again, Sashiko misunderstands that a veth device can be removed
while the netns of its paired veth is being destroyed, which cannot
happen.
Even if it's possible, the concerned net->rules_ops is namespacified,
so no race can happen.
>
> static struct pernet_operations fib6_rules_net_ops = {
> .init = fib6_rules_net_init,
> - .exit_batch = fib6_rules_net_exit_batch,
> + .exit = fib6_rules_net_exit,
> };
>
> int __init fib6_rules_init(void)
> --
> 2.55.0.rc0.799.gd6f94ed593-goog
>
^ permalink raw reply
* Re: [PATCH v6 1/9] block: partitions: of: Skip child nodes without reg property
From: Loic Poulain @ 2026-06-30 19:59 UTC (permalink / raw)
To: Rob Herring
Cc: Ulf Hansson, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Konrad Dybcio, Jens Axboe, Johannes Berg, Jeff Johnson,
Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
Balakrishna Godavarthi, Rocky Liao, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Srinivas Kandagatla,
Andrew Lunn, Heiner Kallweit, Russell King, Saravana Kannan,
Christian Marangi, linux-mmc, devicetree, linux-kernel,
linux-arm-msm, linux-block, linux-wireless, ath10k,
linux-bluetooth, netdev, daniel, stable, Bartosz Golaszewski
In-Reply-To: <20260630180219.GA4139943-robh@kernel.org>
Hi Rob,
On Tue, Jun 30, 2026 at 8:02 PM Rob Herring <robh@kernel.org> wrote:
>
> On Mon, Jun 29, 2026 at 10:55:20AM +0200, Loic Poulain wrote:
> > Child nodes of a fixed-partitions node are not necessarily partition
> > entries, for example an nvmem-layout node has no reg property. The
> > current code passes a NULL reg pointer and uninitialized len to the
> > length check, which can result in a kernel panic or silent failure to
> > register any partitions.
>
> That does not sound right to me. A fixed-partitions node should only be
> defining partitions with address ranges. I would expect a partition node
> could be nvmem-layout, but not the whole address range. If you wanted
> the latter, then just do:
>
> partitions {
> ...
> };
>
> nvmem-layout {
> ...
> };
In our case, the nvmem-layout needs to be associated with a specific
eMMC hardware partition, nvmem cells can be a simple sub-range within
the global eMMC, each hardware partition (boot0, boot1, user...)
having its own address spaces.
That said, your point about not abusing fixed-partitions is valid. I
initially dropped the compatible = "fixed-partitions" from the
partitions-boot1 node when it only carries an nvmem-layout and no
actual partition entries, making it a plain named container node. But
it's a bit fragile if we want to support both nvmem-layout and
fixed-partitions.
Regarding your expectation of a partition node being a nvmem-layout,
do you mean that the nvmem-layout should live under a fixed-partitions
node? Something along these lines:
partitions-boot1 {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
nvmem@4400 {
reg = <0x4400 0x1000>;
nvmem-layout {
compatible = "fixed-layout";
#address-cells = <1>;
#size-cells = <1>;
wifi_mac_addr: mac-addr@0 {
compatible = "mac-base";
reg = <0x0 0x6>;
#nvmem-cell-cells = <1>;
};
[...]
That makes some sense, this would require extra work for the
emmc/block layer to also associate fwnodes with logical partitions,
not just the whole disk/hw (hw part), Is that the direction you'd like
us to go?
Also, Note that regardless of which approach we settle on, this
specific fix/patch remains necessary to validate the partition node
and prevent NULL-deref.
Regards,
Loic
^ permalink raw reply
* Re: [PATCH net] selftests: net: bump default cmd() timeout to 20 seconds
From: Nimrod Oren @ 2026-06-30 19:59 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms, shuah,
petrm, leitao, dw, gal, linux-kselftest
In-Reply-To: <20260629233348.2145841-1-kuba@kernel.org>
On 30/06/2026 2:33, Jakub Kicinski wrote:
> We always used 5 sec as the default command timeout. But soon after
> it was introduced, David effectively made us ignore the timeout
> (it was passed to process.communicate() as the wrong argument).
> Gal recently fixed that, but turns out the 5 sec is not enough
> for a lot of tests and setups. The fix regressed regressions.
>
> In particular running reconfig commands (e.g. XDP attach) on mlx5
> with 32 rings and 9k MTU, on a heavily-debug-enabled kernel takes
> more than 5 sec. The XDP installation command will time out after
> 5 sec but since the sleeps in the kernel are non interruptible
> the command finishes anyway, leaving the XDP program attached,
> but with non-zero exit code. defer()ed cleanups are not installed,
> breaking the environment for subsequent tests.
>
> Since "install XDP" is a pretty normal command a "point fix"
> does not seem appropriate. 32 rings is a fairly reasonable
> config, too, so we should just increase the timeout to 20 sec.
>
> There's no real reason behind the value of 20.
>
> Fixes: 1cf270424218 ("net: selftest: add test for netdev netlink queue-get API")
> Fixes: f0bd19316663 ("selftests: net: fix timeout passed as positional argument to communicate()")
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> ---
> CC: shuah@kernel.org
> CC: petrm@nvidia.com
> CC: leitao@debian.org
> CC: dw@davidwei.uk
> CC: noren@nvidia.com
> CC: gal@nvidia.com
> CC: linux-kselftest@vger.kernel.org
> ---
> tools/testing/selftests/net/lib/py/utils.py | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
Reviewed-by: Nimrod Oren <noren@nvidia.com>
> diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/selftests/net/lib/py/utils.py
> index 308c91833239..9b40049e2dbb 100644
> --- a/tools/testing/selftests/net/lib/py/utils.py
> +++ b/tools/testing/selftests/net/lib/py/utils.py
> @@ -44,7 +44,7 @@ import time
> Use bkg() instead to run a command in the background.
> """
> def __init__(self, comm, shell=None, fail=True, expect_fail=False, ns=None,
> - background=False, host=None, timeout=5, ksft_ready=None,
> + background=False, host=None, timeout=20, ksft_ready=None,
> ksft_wait=None):
> if ns:
> if hasattr(ns, 'user_ns_path'):
> @@ -113,7 +113,7 @@ import time
>
> return stdout, stderr
>
> - def process(self, terminate=True, fail=None, expect_fail=False, timeout=5):
> + def process(self, terminate=True, fail=None, expect_fail=False, timeout=20):
> if fail is None:
> fail = not terminate
>
^ permalink raw reply
* Re: Please backport bridge multicast exponential field encoding fix series to stable kernels
From: Ujjal Roy @ 2026-06-30 20:03 UTC (permalink / raw)
To: Sasha Levin
Cc: 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, stable, Greg KH,
Greg Kroah-Hartman, Ujjal Roy, bridge, Kernel, Kernel,
linux-kselftest
In-Reply-To: <CAE2MWkn=azz3gUKGBYc1jjvVnLxDHuHk9M7wAJHdAW8v=dP5GA@mail.gmail.com>
On Thu, Jun 25, 2026 at 8:20 PM Ujjal Roy <royujjal@gmail.com> wrote:
>
> On Thu, Jun 25, 2026 at 4:12 PM Sasha Levin <sashal@kernel.org> wrote:
> >
> > > Please backport the 5-patch bridge multicast exponential field
> > > encoding series (726fa7da2d8c, 12cfb4ecc471, 95bfd196f0dc,
> > > e51560f4220a, 529dbe762de0) to the stable kernels.
> >
> > I tried, but it doesn't apply to 7.1. Could you provide a backport please?
> >
> > --
> > Thanks,
> > Sasha
>
> I will create patches on top of 7.1. But tell me what about all other
> stable releases? I have to create patches to all stables and how to
> share the patches to you? Via this email or any other process? I am a
> fresh on backporting my changes to all stables.
I have prepared the patches for stable releases mentioned in kernel.org.
And I am waiting for your response so that I can send you the patchset.
^ permalink raw reply
* Re: [PATCH v2 5/7] pci: make pci_match_one_device match on ID instead of device
From: Danilo Krummrich @ 2026-06-30 20:04 UTC (permalink / raw)
To: Gary Guo
Cc: Bjorn Helgaas, Zhenzhong Duan, Greg Kroah-Hartman,
Rafael J. Wysocki, Damien Le Moal, Niklas Cassel, GOTO Masanori,
YOKOTA Hiroshi, James E.J. Bottomley, Martin K. Petersen,
Vaibhav Gupta, Jens Taprogge, Ido Schimmel, Petr Machata,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, linux-pci, driver-core, linux-kernel, linux-ide,
linux-scsi, industrypack-devel, netdev
In-Reply-To: <20260630-pci_id_fix-v2-5-b834a98c0af2@garyguo.net>
On Tue Jun 30, 2026 at 1:09 PM CEST, Gary Guo wrote:
> There is a need to match just IDs instead of against devices. Thus rename
> this function to pci_match_one_id, and add a pci_id_from_device helper to
> make it easy to convert users.
>
> Similar convert pci_match_id to do_pci_match_id, however the existing API
> is kept due to quite a few users.
>
> Signed-off-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Danilo Krummrich <dakr@kernel.org>
^ permalink raw reply
* [PATCH 5.10] net: cpsw_new: Fix potential unregister of netdev that has not been registered yet
From: Elizaveta Tereshkina @ 2026-06-30 20:07 UTC (permalink / raw)
To: stable, Greg Kroah-Hartman
Cc: Elizaveta Tereshkina, Grygorii Strashko, David S. Miller,
Jakub Kicinski, Sasha Levin, Kevin Hao, Alexander Sverdlin,
Wenshan Lan, Ilias Apalodimas, Murali Karicheri, linux-omap,
netdev, linux-kernel, lvc-project
From: Kevin Hao <haokexin@gmail.com>
commit 9d724b34fbe13b71865ad0906a4be97571f19cf5 upstream.
If an error occurs during register_netdev() for the first MAC in
cpsw_register_ports(), even though cpsw->slaves[0].ndev is set to NULL,
cpsw->slaves[1].ndev would remain unchanged. This could later cause
cpsw_unregister_ports() to attempt unregistering the second MAC.
To address this, add a check for ndev->reg_state before calling
unregister_netdev(). With this change, setting cpsw->slaves[i].ndev
to NULL becomes unnecessary and can be removed accordingly.
Fixes: ed3525eda4c4 ("net: ethernet: ti: introduce cpsw switchdev based driver part 1 - dual-emac")
Signed-off-by: Kevin Hao <haokexin@gmail.com>
Cc: stable@vger.kernel.org
Reviewed-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
Link: https://patch.msgid.link/20260205-cpsw-error-path-v1-2-6e58bae6b299@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Wenshan Lan <jetlan9@163.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Elizaveta Tereshkina <etereshkina@astralinux.ru>
---
Backport fix for CVE-2026-43219
drivers/net/ethernet/ti/cpsw_new.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c
index 66b1620b6f5b..cc276241f391 100644
--- a/drivers/net/ethernet/ti/cpsw_new.c
+++ b/drivers/net/ethernet/ti/cpsw_new.c
@@ -1456,7 +1456,8 @@ static void cpsw_unregister_ports(struct cpsw_common *cpsw)
int i = 0;
for (i = 0; i < cpsw->data.slaves; i++) {
- if (!cpsw->slaves[i].ndev)
+ if (!cpsw->slaves[i].ndev ||
+ cpsw->slaves[i].ndev->reg_state != NETREG_REGISTERED)
continue;
unregister_netdev(cpsw->slaves[i].ndev);
@@ -1476,7 +1477,6 @@ static int cpsw_register_ports(struct cpsw_common *cpsw)
if (ret) {
dev_err(cpsw->dev,
"cpsw: err registering net device%d\n", i);
- cpsw->slaves[i].ndev = NULL;
break;
}
}
--
2.39.2
^ permalink raw reply related
* Re: [PATCH v2 6/7] pci: fix dyn_id add TOCTOU
From: Danilo Krummrich @ 2026-06-30 20:16 UTC (permalink / raw)
To: Gary Guo
Cc: Bjorn Helgaas, Zhenzhong Duan, Greg Kroah-Hartman,
Rafael J. Wysocki, Damien Le Moal, Niklas Cassel, GOTO Masanori,
YOKOTA Hiroshi, James E.J. Bottomley, Martin K. Petersen,
Vaibhav Gupta, Jens Taprogge, Ido Schimmel, Petr Machata,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, linux-pci, driver-core, linux-kernel, linux-ide,
linux-scsi, industrypack-devel, netdev
In-Reply-To: <20260630-pci_id_fix-v2-6-b834a98c0af2@garyguo.net>
On Tue Jun 30, 2026 at 1:09 PM CEST, Gary Guo wrote:
> +static int do_pci_add_dynid(struct pci_driver *drv, const struct pci_device_id *id, bool check_dup)
> +{
> + struct pci_dynid *dynid, *existing_dynid;
> +
> + dynid = kzalloc_obj(*dynid);
> + if (!dynid)
> + return -ENOMEM;
> +
> + dynid->id = *id;
> +
> + {
> + guard(spinlock)(&drv->dynids.lock);
> + if (check_dup) {
> + list_for_each_entry(existing_dynid, &drv->dynids.list, node) {
> + if (pci_match_one_id(&existing_dynid->id, id)) {
> + kfree(dynid);
> + return -EEXIST;
> + }
> + }
> + }
> + list_add_tail(&dynid->node, &drv->dynids.list);
> + }
This should use scoped_guard(spinlock, &drv->dynids.lock) instead.
> static const struct pci_device_id *do_pci_match_id(const struct pci_device_id *ids,
> - const struct pci_device_id *dev_id)
> + const struct pci_device_id *dev_id,
> + bool match_override_only)
Maybe something along the lines of include_override_only? At a quick glance
match_override_only could be read as "match override-only entries exclusively".
^ permalink raw reply
* Re: [RFC] connectat()/bindat() or an alternative design
From: John Ericson @ 2026-06-30 20:22 UTC (permalink / raw)
To: Cong Wang
Cc: Li Chen, Andy Lutomirski, Christian Brauner, Jens Axboe,
network dev, linux-fsdevel
In-Reply-To: <66eb8227-85b6-4684-a4fa-e3e17ac2fa45@app.fastmail.com>
I'm bumping this and adding new recipients again in light of the
discussion happening elsewhere in
<https://lore.kernel.org/all/a49ce818-f38d-41b0-bbf7-80b8aad998b1@app.fastmail.com/>.
I don't want to count my chickens before they are hatched, but it is
looking to me like a consensus in that thread is building around the
ability to opt into intentionally empty/unusable root and working
directories (at least with nullfs, maybe but less likely with other
mechanisms instead).
That new functionality concretizes the motivation for what I am
proposing in this thread: in such a world, there is little to no point
binding listening sockets in the file system, because the containing
directory would have to be conveyed by file descriptor anyways --- might
as well just directly convey the socket to connect to by file
descriptor. Likewise, abstract sockets are not appealing, because the
abstract socket namespace is either too coarse-grained (leaking info in
the same way root/cwd would), or too cumbersome to keep it from leaking.
To recap (with some slight changes, like renames), my latest proposal (a
new version, not either of the two variations in the original email) is
new syscalls `bind_unix_anon` and `connectat`, supporting a workflow
like this:
/* server */
int lfd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
int addrfd = bind_unix_anon(
lfd,
/*flags, for the future*/0);
listen(lfd, 64);
/* client, handed `addrfd` */
int cfd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
connectat(addrfd, cfd, AT_EMPTY_PATH);
Or, more radically, `bind_unix_anon` and `connectat` could let one skip
the initial `socket` calls by returning those new sockets directly:
/* server */
int fds[2];
bind_unix_anon(
SOCK_STREAM | SOCK_CLOEXEC,
/*flags, for the future*/0,
fds);
int lfd = fds[0], addrfd = fds[1];
listen(lfd, 64);
/* client, handed `addrfd` */
int cfd = connectat(
addrfd,
SOCK_STREAM | SOCK_CLOEXEC,
AT_EMPTY_PATH);
(Note that in this variation `bind_unix_anon` would return *two* file
descriptors: one for the server, with the permission to listen, and the
other for clients, with just the privilege to `connectat`.) (Maybe
`bind_unix_anon` should furthermore `listen` right away on `lfd` too?)
Of course, it would be nice to have io_uring versions of these too. But
I don't know what the usual process is for that (regular first? io_uring
first? both at the same time?)
Thanks,
John
P.S. For anyone just getting CC'd now, the first message in this thread
is
<https://lore.kernel.org/all/b1af80fc-a57c-408d-bdfe-fa6bae26eaca@app.fastmail.com/>.
Hope that might save people a few keypresses :).
^ permalink raw reply
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