forked from mirrors/linux
		
	net: introduce sk_skb_reason_drop function
Long used destructors kfree_skb and kfree_skb_reason do not pass receiving socket to packet drop tracepoints trace_kfree_skb. This makes it hard to track packet drops of a certain netns (container) or a socket (user application). The naming of these destructors are also not consistent with most sk/skb operating functions, i.e. functions named "sk_xxx" or "skb_xxx". Introduce a new functions sk_skb_reason_drop as drop-in replacement for kfree_skb_reason on local receiving path. Callers can now pass receiving sockets to the tracepoints. kfree_skb and kfree_skb_reason are still usable but they are now just inline helpers that call sk_skb_reason_drop. Note it is not feasible to do the same to consume_skb. Packets not dropped can flow through multiple receive handlers, and have multiple receiving sockets. Leave it untouched for now. Suggested-by: Eric Dumazet <edumazet@google.com> Signed-off-by: Yan Zhai <yan@cloudflare.com> Acked-by: Jesper Dangaard Brouer <hawk@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									c53795d48e
								
							
						
					
					
						commit
						ba8de796ba
					
				
					 2 changed files with 20 additions and 12 deletions
				
			
		| 
						 | 
					@ -1251,8 +1251,14 @@ static inline bool skb_data_unref(const struct sk_buff *skb,
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void __fix_address
 | 
					void __fix_address sk_skb_reason_drop(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason);
 | 
									      enum skb_drop_reason reason);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void
 | 
				
			||||||
 | 
					kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						sk_skb_reason_drop(NULL, skb, reason);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 *	kfree_skb - free an sk_buff with 'NOT_SPECIFIED' reason
 | 
					 *	kfree_skb - free an sk_buff with 'NOT_SPECIFIED' reason
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1190,7 +1190,8 @@ void __kfree_skb(struct sk_buff *skb)
 | 
				
			||||||
EXPORT_SYMBOL(__kfree_skb);
 | 
					EXPORT_SYMBOL(__kfree_skb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static __always_inline
 | 
					static __always_inline
 | 
				
			||||||
bool __kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason)
 | 
					bool __sk_skb_reason_drop(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
 | 
								  enum skb_drop_reason reason)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (unlikely(!skb_unref(skb)))
 | 
						if (unlikely(!skb_unref(skb)))
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
| 
						 | 
					@ -1203,26 +1204,27 @@ bool __kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason)
 | 
				
			||||||
	if (reason == SKB_CONSUMED)
 | 
						if (reason == SKB_CONSUMED)
 | 
				
			||||||
		trace_consume_skb(skb, __builtin_return_address(0));
 | 
							trace_consume_skb(skb, __builtin_return_address(0));
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		trace_kfree_skb(skb, __builtin_return_address(0), reason, NULL);
 | 
							trace_kfree_skb(skb, __builtin_return_address(0), reason, sk);
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 *	kfree_skb_reason - free an sk_buff with special reason
 | 
					 *	sk_skb_reason_drop - free an sk_buff with special reason
 | 
				
			||||||
 | 
					 *	@sk: the socket to receive @skb, or NULL if not applicable
 | 
				
			||||||
 *	@skb: buffer to free
 | 
					 *	@skb: buffer to free
 | 
				
			||||||
 *	@reason: reason why this skb is dropped
 | 
					 *	@reason: reason why this skb is dropped
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	Drop a reference to the buffer and free it if the usage count has
 | 
					 *	Drop a reference to the buffer and free it if the usage count has hit
 | 
				
			||||||
 *	hit zero. Meanwhile, pass the drop reason to 'kfree_skb'
 | 
					 *	zero. Meanwhile, pass the receiving socket and drop reason to
 | 
				
			||||||
 *	tracepoint.
 | 
					 *	'kfree_skb' tracepoint.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void __fix_address
 | 
					void __fix_address
 | 
				
			||||||
kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason)
 | 
					sk_skb_reason_drop(struct sock *sk, struct sk_buff *skb, enum skb_drop_reason reason)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (__kfree_skb_reason(skb, reason))
 | 
						if (__sk_skb_reason_drop(sk, skb, reason))
 | 
				
			||||||
		__kfree_skb(skb);
 | 
							__kfree_skb(skb);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(kfree_skb_reason);
 | 
					EXPORT_SYMBOL(sk_skb_reason_drop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define KFREE_SKB_BULK_SIZE	16
 | 
					#define KFREE_SKB_BULK_SIZE	16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1261,7 +1263,7 @@ kfree_skb_list_reason(struct sk_buff *segs, enum skb_drop_reason reason)
 | 
				
			||||||
	while (segs) {
 | 
						while (segs) {
 | 
				
			||||||
		struct sk_buff *next = segs->next;
 | 
							struct sk_buff *next = segs->next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (__kfree_skb_reason(segs, reason)) {
 | 
							if (__sk_skb_reason_drop(NULL, segs, reason)) {
 | 
				
			||||||
			skb_poison_list(segs);
 | 
								skb_poison_list(segs);
 | 
				
			||||||
			kfree_skb_add_bulk(segs, &sa, reason);
 | 
								kfree_skb_add_bulk(segs, &sa, reason);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue