diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index fffa6b399995..aa1685f72397 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2932,6 +2932,7 @@ static inline struct sk_buff *napi_alloc_skb(struct napi_struct *napi, return __napi_alloc_skb(napi, length, GFP_ATOMIC); } void napi_consume_skb(struct sk_buff *skb, int budget); +void napi_kfree_skb(struct sk_buff *skb, int budget); void napi_skb_free_stolen_head(struct sk_buff *skb); void __kfree_skb_defer(struct sk_buff *skb); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 7f5c02085438..294bf2068ab6 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -951,11 +951,14 @@ void napi_skb_free_stolen_head(struct sk_buff *skb) napi_skb_cache_put(skb); } -void napi_consume_skb(struct sk_buff *skb, int budget) +static void napi_release_skb(struct sk_buff *skb, int budget, bool consume) { /* Zero budget indicate non-NAPI context called us, like netpoll */ if (unlikely(!budget)) { - dev_consume_skb_any(skb); + if (consume) + dev_consume_skb_any(skb); + else + dev_kfree_skb_any(skb); return; } @@ -965,7 +968,10 @@ void napi_consume_skb(struct sk_buff *skb, int budget) return; /* if reaching here SKB is ready to free */ - trace_consume_skb(skb); + if (consume) + trace_consume_skb(skb); + else + trace_kfree_skb(skb); /* if SKB is a clone, don't handle this case */ if (skb->fclone != SKB_FCLONE_UNAVAILABLE) { @@ -976,8 +982,20 @@ void napi_consume_skb(struct sk_buff *skb, int budget) skb_release_all(skb); napi_skb_cache_put(skb); } + + +void napi_consume_skb(struct sk_buff *skb, int budget) +{ + napi_release_skb(skb, budget, true); +} EXPORT_SYMBOL(napi_consume_skb); +void napi_kfree_skb(struct sk_buff *skb, int budget) +{ + napi_release_skb(skb, budget, false); +} +EXPORT_SYMBOL(napi_kfree_skb); + /* Make sure a field is enclosed inside headers_start/headers_end section */ #define CHECK_SKB_FIELD(field) \ BUILD_BUG_ON(offsetof(struct sk_buff, field) < \