Skip to content

Commit c504e5c

Browse files
menglongdongkuba-moo
authored andcommitted
net: skb: introduce kfree_skb_reason()
Introduce the interface kfree_skb_reason(), which is able to pass the reason why the skb is dropped to 'kfree_skb' tracepoint. Add the 'reason' field to 'trace_kfree_skb', therefor user can get more detail information about abnormal skb with 'drop_monitor' or eBPF. All drop reasons are defined in the enum 'skb_drop_reason', and they will be print as string in 'kfree_skb' tracepoint in format of 'reason: XXX'. ( Maybe the reasons should be defined in a uapi header file, so that user space can use them? ) Signed-off-by: Menglong Dong <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 342402c commit c504e5c

File tree

5 files changed

+67
-17
lines changed

5 files changed

+67
-17
lines changed

include/linux/skbuff.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,17 @@ struct sk_buff_head {
305305

306306
struct sk_buff;
307307

308+
/* The reason of skb drop, which is used in kfree_skb_reason().
309+
* en...maybe they should be splited by group?
310+
*
311+
* Each item here should also be in 'TRACE_SKB_DROP_REASON', which is
312+
* used to translate the reason to string.
313+
*/
314+
enum skb_drop_reason {
315+
SKB_DROP_REASON_NOT_SPECIFIED,
316+
SKB_DROP_REASON_MAX,
317+
};
318+
308319
/* To allow 64K frame to be packed as single skb without frag_list we
309320
* require 64K/PAGE_SIZE pages plus 1 additional page to allow for
310321
* buffers which do not start on a page boundary.
@@ -1085,8 +1096,18 @@ static inline bool skb_unref(struct sk_buff *skb)
10851096
return true;
10861097
}
10871098

1099+
void kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason);
1100+
1101+
/**
1102+
* kfree_skb - free an sk_buff with 'NOT_SPECIFIED' reason
1103+
* @skb: buffer to free
1104+
*/
1105+
static inline void kfree_skb(struct sk_buff *skb)
1106+
{
1107+
kfree_skb_reason(skb, SKB_DROP_REASON_NOT_SPECIFIED);
1108+
}
1109+
10881110
void skb_release_head_state(struct sk_buff *skb);
1089-
void kfree_skb(struct sk_buff *skb);
10901111
void kfree_skb_list(struct sk_buff *segs);
10911112
void skb_dump(const char *level, const struct sk_buff *skb, bool full_pkt);
10921113
void skb_tx_error(struct sk_buff *skb);

include/trace/events/skb.h

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,51 @@
99
#include <linux/netdevice.h>
1010
#include <linux/tracepoint.h>
1111

12+
#define TRACE_SKB_DROP_REASON \
13+
EM(SKB_DROP_REASON_NOT_SPECIFIED, NOT_SPECIFIED) \
14+
EMe(SKB_DROP_REASON_MAX, MAX)
15+
16+
#undef EM
17+
#undef EMe
18+
19+
#define EM(a, b) TRACE_DEFINE_ENUM(a);
20+
#define EMe(a, b) TRACE_DEFINE_ENUM(a);
21+
22+
TRACE_SKB_DROP_REASON
23+
24+
#undef EM
25+
#undef EMe
26+
#define EM(a, b) { a, #b },
27+
#define EMe(a, b) { a, #b }
28+
1229
/*
1330
* Tracepoint for free an sk_buff:
1431
*/
1532
TRACE_EVENT(kfree_skb,
1633

17-
TP_PROTO(struct sk_buff *skb, void *location),
34+
TP_PROTO(struct sk_buff *skb, void *location,
35+
enum skb_drop_reason reason),
1836

19-
TP_ARGS(skb, location),
37+
TP_ARGS(skb, location, reason),
2038

2139
TP_STRUCT__entry(
22-
__field( void *, skbaddr )
23-
__field( void *, location )
24-
__field( unsigned short, protocol )
40+
__field(void *, skbaddr)
41+
__field(void *, location)
42+
__field(unsigned short, protocol)
43+
__field(enum skb_drop_reason, reason)
2544
),
2645

2746
TP_fast_assign(
2847
__entry->skbaddr = skb;
2948
__entry->location = location;
3049
__entry->protocol = ntohs(skb->protocol);
50+
__entry->reason = reason;
3151
),
3252

33-
TP_printk("skbaddr=%p protocol=%u location=%p",
34-
__entry->skbaddr, __entry->protocol, __entry->location)
53+
TP_printk("skbaddr=%p protocol=%u location=%p reason: %s",
54+
__entry->skbaddr, __entry->protocol, __entry->location,
55+
__print_symbolic(__entry->reason,
56+
TRACE_SKB_DROP_REASON))
3557
);
3658

3759
TRACE_EVENT(consume_skb,

net/core/dev.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4899,7 +4899,8 @@ static __latent_entropy void net_tx_action(struct softirq_action *h)
48994899
if (likely(get_kfree_skb_cb(skb)->reason == SKB_REASON_CONSUMED))
49004900
trace_consume_skb(skb);
49014901
else
4902-
trace_kfree_skb(skb, net_tx_action);
4902+
trace_kfree_skb(skb, net_tx_action,
4903+
SKB_DROP_REASON_NOT_SPECIFIED);
49034904

49044905
if (skb->fclone != SKB_FCLONE_UNAVAILABLE)
49054906
__kfree_skb(skb);

net/core/drop_monitor.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ static u32 net_dm_queue_len = 1000;
110110

111111
struct net_dm_alert_ops {
112112
void (*kfree_skb_probe)(void *ignore, struct sk_buff *skb,
113-
void *location);
113+
void *location,
114+
enum skb_drop_reason reason);
114115
void (*napi_poll_probe)(void *ignore, struct napi_struct *napi,
115116
int work, int budget);
116117
void (*work_item_func)(struct work_struct *work);
@@ -262,7 +263,9 @@ static void trace_drop_common(struct sk_buff *skb, void *location)
262263
spin_unlock_irqrestore(&data->lock, flags);
263264
}
264265

265-
static void trace_kfree_skb_hit(void *ignore, struct sk_buff *skb, void *location)
266+
static void trace_kfree_skb_hit(void *ignore, struct sk_buff *skb,
267+
void *location,
268+
enum skb_drop_reason reason)
266269
{
267270
trace_drop_common(skb, location);
268271
}
@@ -490,7 +493,8 @@ static const struct net_dm_alert_ops net_dm_alert_summary_ops = {
490493

491494
static void net_dm_packet_trace_kfree_skb_hit(void *ignore,
492495
struct sk_buff *skb,
493-
void *location)
496+
void *location,
497+
enum skb_drop_reason reason)
494498
{
495499
ktime_t tstamp = ktime_get_real();
496500
struct per_cpu_dm_data *data;

net/core/skbuff.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -759,21 +759,23 @@ void __kfree_skb(struct sk_buff *skb)
759759
EXPORT_SYMBOL(__kfree_skb);
760760

761761
/**
762-
* kfree_skb - free an sk_buff
762+
* kfree_skb_reason - free an sk_buff with special reason
763763
* @skb: buffer to free
764+
* @reason: reason why this skb is dropped
764765
*
765766
* Drop a reference to the buffer and free it if the usage count has
766-
* hit zero.
767+
* hit zero. Meanwhile, pass the drop reason to 'kfree_skb'
768+
* tracepoint.
767769
*/
768-
void kfree_skb(struct sk_buff *skb)
770+
void kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason)
769771
{
770772
if (!skb_unref(skb))
771773
return;
772774

773-
trace_kfree_skb(skb, __builtin_return_address(0));
775+
trace_kfree_skb(skb, __builtin_return_address(0), reason);
774776
__kfree_skb(skb);
775777
}
776-
EXPORT_SYMBOL(kfree_skb);
778+
EXPORT_SYMBOL(kfree_skb_reason);
777779

778780
void kfree_skb_list(struct sk_buff *segs)
779781
{

0 commit comments

Comments
 (0)