From: Paolo Abeni <pabeni@redhat.com>
To: Willem de Bruijn <willemdebruijn.kernel@gmail.com>,
Mahdi Faramarzpour <mahdifrmx@gmail.com>,
netdev@vger.kernel.org
Cc: davem@davemloft.net, dsahern@kernel.org, edumazet@google.com,
kuba@kernel.org, horms@kernel.org, kshitiz.bartariya@zohomail.in
Subject: Re: [PATCH net-next] udp: add drop count for packets in udp_prod_queue
Date: Fri, 23 Jan 2026 09:14:06 +0100 [thread overview]
Message-ID: <60ed19a1-97e1-4342-8dfc-a5db684afa6f@redhat.com> (raw)
In-Reply-To: <willemdebruijn.kernel.1682586fd684e@gmail.com>
On 1/22/26 10:26 PM, Willem de Bruijn wrote:
> Mahdi Faramarzpour wrote:
>> This commit adds SNMP drop count increment for the packets in
>> per NUMA queues which were introduced in commit b650bf0977d3
>> ("udp: remove busylock and add per NUMA queues"). note that SNMP
>> counters are incremented currently by the caller for skb. And
>> that these skbs on the intermediate queue cannot be counted
>> there so need similar logic in their error path.
>>
>> Signed-off-by: Mahdi Faramarzpour <mahdifrmx@gmail.com>
>> ---
>> v5:
>> - check if drop counts are non-zero before increasing countrers
>> v4: https://lore.kernel.org/netdev/20260108102950.49417-1-mahdifrmx@gmail.com/
>> - move all changes to unlikely(to_drop) branch
>> v3: https://lore.kernel.org/netdev/20260105114732.140719-1-mahdifrmx@gmail.com/
>> - remove the unreachable UDP_MIB_RCVBUFERRORS code
>> v2: https://lore.kernel.org/netdev/20260105071218.10785-1-mahdifrmx@gmail.com/
>> - change ENOMEM to ENOBUFS
>> v1: https://lore.kernel.org/netdev/20260104105732.427691-1-mahdifrmx@gmail.com/
>> ---
>> net/ipv4/udp.c | 19 ++++++++++++++++++-
>> 1 file changed, 18 insertions(+), 1 deletion(-)
>>
>> diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
>> index ffe074cb5..41cf8f7ab 100644
>> --- a/net/ipv4/udp.c
>> +++ b/net/ipv4/udp.c
>> @@ -1793,14 +1793,31 @@ int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb)
>> }
>>
>> if (unlikely(to_drop)) {
>> + int err_ipv4 = 0;
>> + int err_ipv6 = 0;
>
> nit: whitespace between variable definition and code block
>
>> for (nb = 0; to_drop != NULL; nb++) {
>> skb = to_drop;
>> + if (skb->protocol == htons(ETH_P_IP))
>> + err_ipv4++;
>> + else
>> + err_ipv6++;
>
> No need for separate counters.
>
> All counters will either update IPv4 or IPv6 stats. Similar to how
> the caller of _udp_enqueue_schedule_sk is either __udp_queue_rcv_skb
> or __udpv6_queue_rcv_skb and chooses the SNMP stat based on that.
>
> Can check sk_family == PF_INET6 once.
I think that doing the SNMP accounting in __udp_enqueue_schedule_skb()
(for `to_drop`), __udp_queue_rcv_skb() and __udpv6_queue_rcv_skb() (for
`skb`) is a little confusing and possible error prone in the long run.
I'm wondering if something alike the following (completely untested, not
even built! just to give the idea) would be better?
Note that the additional argument in __udp_enqueue_schedule_skb() could
be avoided piggybacking the `to_drop` return argument into the
__udp_enqueue_schedule_skb() return value.
---
diff --git a/include/net/udp.h b/include/net/udp.h
index a061d1b22ddc..673497eb79b7 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -399,7 +399,8 @@ static inline bool udp_sk_bound_dev_eq(const struct
net *net, int bound_dev_if,
/* net/ipv4/udp.c */
void udp_destruct_common(struct sock *sk);
void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len);
-int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb);
+int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb,
+ struct sk_buff *to_drop);
void udp_skb_destructor(struct sock *sk, struct sk_buff *skb);
struct sk_buff *__skb_recv_udp(struct sock *sk, unsigned int flags, int
*off,
int *err);
@@ -411,6 +412,21 @@ static inline struct sk_buff *skb_recv_udp(struct
sock *sk, unsigned int flags,
return __skb_recv_udp(sk, flags, &off, err);
}
+static inline int udp_drop_skbs(struct sock *sk, struct sk_buff *to_drop)
+{
+ struct sk_buff *skb;
+ int nb;
+
+ for (nb = 0; to_drop != NULL; nb++) {
+ skb = to_drop;
+ to_drop = skb->next;
+ skb_mark_not_on_list(skb);
+ sk_skb_reason_drop(sk, skb, SKB_DROP_REASON_PROTO_MEM);
+ }
+ numa_drop_add(&udp_sk(sk)->drop_counters, nb);
+ return nb;
+}
+
enum skb_drop_reason udp_v4_early_demux(struct sk_buff *skb);
bool udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst);
int udp_err(struct sk_buff *, u32);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index ee63af0ef42c..0869e115c0d3 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1696,14 +1696,15 @@ static int udp_rmem_schedule(struct sock *sk,
int size)
return 0;
}
-int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb)
+int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb,
+ struct sk_buff **to_drop)
{
struct sk_buff_head *list = &sk->sk_receive_queue;
struct udp_prod_queue *udp_prod_queue;
- struct sk_buff *next, *to_drop = NULL;
struct llist_node *ll_list;
unsigned int rmem, rcvbuf;
int size, err = -ENOMEM;
+ struct sk_buff *next;
int total_size = 0;
int q_size = 0;
int dropcount;
@@ -1761,8 +1762,8 @@ int __udp_enqueue_schedule_skb(struct sock *sk,
struct sk_buff *skb)
err = udp_rmem_schedule(sk, size);
if (unlikely(err)) {
/* Free the skbs outside of locked section. */
- skb->next = to_drop;
- to_drop = skb;
+ skb->next = *to_drop;
+ *to_drop = skb;
continue;
}
@@ -1792,17 +1793,6 @@ int __udp_enqueue_schedule_skb(struct sock *sk,
struct sk_buff *skb)
}
}
- if (unlikely(to_drop)) {
- for (nb = 0; to_drop != NULL; nb++) {
- skb = to_drop;
- to_drop = skb->next;
- skb_mark_not_on_list(skb);
- /* TODO: update SNMP values. */
- sk_skb_reason_drop(sk, skb, SKB_DROP_REASON_PROTO_MEM);
- }
- numa_drop_add(&udp_sk(sk)->drop_counters, nb);
- }
-
atomic_sub(total_size, &udp_prod_queue->rmem_alloc);
return 0;
@@ -2333,6 +2323,7 @@ void udp_v4_rehash(struct sock *sk)
static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
+ struct sk_buff *to_drop = NULL;
int rc;
if (inet_sk(sk)->inet_daddr) {
@@ -2343,7 +2334,13 @@ static int __udp_queue_rcv_skb(struct sock *sk,
struct sk_buff *skb)
sk_mark_napi_id_once(sk, skb);
}
- rc = __udp_enqueue_schedule_skb(sk, skb);
+ rc = __udp_enqueue_schedule_skb(sk, skb, &to_drop);
+ if (unlikely(to_drop)) {
+ int cnt = udp_drop_skb_list(sk, to_drop);
+
+ SNMP_ADD_STATS(__UDPX_MIB(sk, true), UDP_MIB_MEMERRORS, cnt);
+ SNMP_ADD_STATS(__UDPX_MIB(sk, true), UDP_MIB_INERRORS, cnt);
+ }
if (rc < 0) {
int is_udplite = IS_UDPLITE(sk);
int drop_reason;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 794c13674e8a..5950ec699deb 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -782,6 +782,7 @@ int __udp6_lib_err(struct sk_buff *skb, struct
inet6_skb_parm *opt,
static int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
+ struct sk_buff *to_drop = NULL;
int rc;
if (!ipv6_addr_any(&sk->sk_v6_daddr)) {
@@ -792,7 +793,13 @@ static int __udpv6_queue_rcv_skb(struct sock *sk,
struct sk_buff *skb)
sk_mark_napi_id_once(sk, skb);
}
- rc = __udp_enqueue_schedule_skb(sk, skb);
+ rc = __udp_enqueue_schedule_skb(sk, skb, &to_drop);
+ if (unlikely(to_drop)) {
+ int cnt = udp_drop_skb_list(sk, to_drop);
+
+ SNMP_ADD_STATS(__UDPX_MIB(sk, true), UDP_MIB_MEMERRORS, cnt);
+ SNMP_ADD_STATS(__UDPX_MIB(sk, true), UDP_MIB_INERRORS, cnt);
+ }
if (rc < 0) {
int is_udplite = IS_UDPLITE(sk);
enum skb_drop_reason drop_reason;
next prev parent reply other threads:[~2026-01-23 8:14 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-22 18:53 [PATCH net-next] udp: add drop count for packets in udp_prod_queue Mahdi Faramarzpour
2026-01-22 21:26 ` Willem de Bruijn
2026-01-23 8:14 ` Paolo Abeni [this message]
2026-01-23 14:41 ` Willem de Bruijn
2026-01-23 15:25 ` Paolo Abeni
2026-01-24 15:36 ` Willem de Bruijn
2026-01-24 6:20 ` Mahdi Faramarzpour
2026-01-24 15:32 ` Willem de Bruijn
-- strict thread matches above, loose matches on Subject: below --
2026-01-29 8:38 Mahdi Faramarzpour
2026-01-29 17:17 ` Willem de Bruijn
2026-01-29 17:28 ` Eric Dumazet
2026-01-31 1:40 ` patchwork-bot+netdevbpf
2026-01-28 7:03 Mahdi Faramarzpour
2026-01-28 11:43 ` Eric Dumazet
2026-01-28 12:27 ` Mahdi Faramarzpour
2026-01-28 12:37 ` Eric Dumazet
2026-01-28 14:56 ` Mahdi Faramarzpour
2026-01-28 18:54 ` Willem de Bruijn
2026-01-08 10:29 Mahdi Faramarzpour
2026-01-08 15:05 ` Willem de Bruijn
2026-01-05 11:47 Mahdi Faramarzpour
2026-01-06 1:54 ` Jakub Kicinski
2026-01-06 6:11 ` Mahdi Faramarzpour
2026-01-06 19:22 ` Willem de Bruijn
2026-01-07 9:27 ` Mahdi Faramarzpour
2026-01-07 15:09 ` Willem de Bruijn
2026-01-07 21:46 ` Mahdi Faramarzpour
2026-01-07 22:37 ` Willem de Bruijn
2026-01-06 23:02 ` Jakub Kicinski
2026-01-05 7:12 Mahdi Faramarzpour
2026-01-04 10:57 Mahdi Faramarzpour
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=60ed19a1-97e1-4342-8dfc-a5db684afa6f@redhat.com \
--to=pabeni@redhat.com \
--cc=davem@davemloft.net \
--cc=dsahern@kernel.org \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kshitiz.bartariya@zohomail.in \
--cc=kuba@kernel.org \
--cc=mahdifrmx@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=willemdebruijn.kernel@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox