Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

core: add tracepoints for queueing skb to rcvbuf

This patch adds 2 tracepoints to get a status of a socket receive queue
and related parameter.

One tracepoint is added to sock_queue_rcv_skb. It records rcvbuf size
and its usage. The other tracepoint is added to __sk_mem_schedule and
it records limitations of memory for sockets and current usage.

By using these tracepoints we're able to know detailed reason why kernel
drop the packet.

Signed-off-by: Satoru Moriya <satoru.moriya@hds.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Satoru Moriya and committed by
David S. Miller
3847ce32 296f7ea7

+74
+68
include/trace/events/sock.h
··· 1 + #undef TRACE_SYSTEM 2 + #define TRACE_SYSTEM sock 3 + 4 + #if !defined(_TRACE_SOCK_H) || defined(TRACE_HEADER_MULTI_READ) 5 + #define _TRACE_SOCK_H 6 + 7 + #include <net/sock.h> 8 + #include <linux/tracepoint.h> 9 + 10 + TRACE_EVENT(sock_rcvqueue_full, 11 + 12 + TP_PROTO(struct sock *sk, struct sk_buff *skb), 13 + 14 + TP_ARGS(sk, skb), 15 + 16 + TP_STRUCT__entry( 17 + __field(int, rmem_alloc) 18 + __field(unsigned int, truesize) 19 + __field(int, sk_rcvbuf) 20 + ), 21 + 22 + TP_fast_assign( 23 + __entry->rmem_alloc = atomic_read(&sk->sk_rmem_alloc); 24 + __entry->truesize = skb->truesize; 25 + __entry->sk_rcvbuf = sk->sk_rcvbuf; 26 + ), 27 + 28 + TP_printk("rmem_alloc=%d truesize=%u sk_rcvbuf=%d", 29 + __entry->rmem_alloc, __entry->truesize, __entry->sk_rcvbuf) 30 + ); 31 + 32 + TRACE_EVENT(sock_exceed_buf_limit, 33 + 34 + TP_PROTO(struct sock *sk, struct proto *prot, long allocated), 35 + 36 + TP_ARGS(sk, prot, allocated), 37 + 38 + TP_STRUCT__entry( 39 + __array(char, name, 32) 40 + __field(long *, sysctl_mem) 41 + __field(long, allocated) 42 + __field(int, sysctl_rmem) 43 + __field(int, rmem_alloc) 44 + ), 45 + 46 + TP_fast_assign( 47 + strncpy(__entry->name, prot->name, 32); 48 + __entry->sysctl_mem = prot->sysctl_mem; 49 + __entry->allocated = allocated; 50 + __entry->sysctl_rmem = prot->sysctl_rmem[0]; 51 + __entry->rmem_alloc = atomic_read(&sk->sk_rmem_alloc); 52 + ), 53 + 54 + TP_printk("proto:%s sysctl_mem=%ld,%ld,%ld allocated=%ld " 55 + "sysctl_rmem=%d rmem_alloc=%d", 56 + __entry->name, 57 + __entry->sysctl_mem[0], 58 + __entry->sysctl_mem[1], 59 + __entry->sysctl_mem[2], 60 + __entry->allocated, 61 + __entry->sysctl_rmem, 62 + __entry->rmem_alloc) 63 + ); 64 + 65 + #endif /* _TRACE_SOCK_H */ 66 + 67 + /* This part must be outside protection */ 68 + #include <trace/define_trace.h>
+1
net/core/net-traces.c
··· 28 28 #include <trace/events/skb.h> 29 29 #include <trace/events/net.h> 30 30 #include <trace/events/napi.h> 31 + #include <trace/events/sock.h> 31 32 #include <trace/events/udp.h> 32 33 33 34 EXPORT_TRACEPOINT_SYMBOL_GPL(kfree_skb);
+5
net/core/sock.c
··· 128 128 129 129 #include <linux/filter.h> 130 130 131 + #include <trace/events/sock.h> 132 + 131 133 #ifdef CONFIG_INET 132 134 #include <net/tcp.h> 133 135 #endif ··· 294 292 if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= 295 293 (unsigned)sk->sk_rcvbuf) { 296 294 atomic_inc(&sk->sk_drops); 295 + trace_sock_rcvqueue_full(sk, skb); 297 296 return -ENOMEM; 298 297 } 299 298 ··· 1738 1735 if (sk->sk_wmem_queued + size >= sk->sk_sndbuf) 1739 1736 return 1; 1740 1737 } 1738 + 1739 + trace_sock_exceed_buf_limit(sk, prot, allocated); 1741 1740 1742 1741 /* Alas. Undo changes. */ 1743 1742 sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM;