Commit 6af3b428 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'skb-drop-reasons'



Menglong Dong says:

====================
net: dev: add skb drop reasons to net/core/dev.c

In the commit c504e5c2 ("net: skb: introduce kfree_skb_reason()"),
we added the support of reporting the reasons of skb drops to kfree_skb
tracepoint. And in this series patches, reasons for skb drops are added
to the link layer, which means that 'net/core/dev.c' is our target.

Following functions are processed:

sch_handle_egress()
__dev_xmit_skb()
enqueue_to_backlog()
do_xdp_generic()
sch_handle_ingress()
__netif_receive_skb_core()

and following new drop reasons are added (what they mean can be see in
the document of them):

SKB_DROP_REASON_QDISC_EGRESS
SKB_DROP_REASON_QDISC_DROP
SKB_DROP_REASON_CPU_BACKLOG
SKB_DROP_REASON_XDP
SKB_DROP_REASON_QDISC_INGRESS
SKB_DROP_REASON_PTYPE_ABSENT

In order to add skb drop reasons to kfree_skb_list(), the function
kfree_skb_list_reason() is introduced in the 2th patch, which will be
used in __dev_xmit_skb() in the 3th patch.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 9f9919f7 6c2728b7
Loading
Loading
Loading
Loading
+25 −1
Original line number Diff line number Diff line
@@ -394,6 +394,24 @@ enum skb_drop_reason {
						 * entry is full
						 */
	SKB_DROP_REASON_NEIGH_DEAD,	/* neigh entry is dead */
	SKB_DROP_REASON_TC_EGRESS,	/* dropped in TC egress HOOK */
	SKB_DROP_REASON_QDISC_DROP,	/* dropped by qdisc when packet
					 * outputting (failed to enqueue to
					 * current qdisc)
					 */
	SKB_DROP_REASON_CPU_BACKLOG,	/* failed to enqueue the skb to
					 * the per CPU backlog queue. This
					 * can be caused by backlog queue
					 * full (see netdev_max_backlog in
					 * net.rst) or RPS flow limit
					 */
	SKB_DROP_REASON_XDP,		/* dropped by XDP in input path */
	SKB_DROP_REASON_TC_INGRESS,	/* dropped in TC ingress HOOK */
	SKB_DROP_REASON_PTYPE_ABSENT,	/* not packet_type found to handle
					 * the skb. For an etner packet,
					 * this means that L3 protocol is
					 * not supported
					 */
	SKB_DROP_REASON_MAX,
};

@@ -1201,10 +1219,16 @@ static inline void kfree_skb(struct sk_buff *skb)
}

void skb_release_head_state(struct sk_buff *skb);
void kfree_skb_list(struct sk_buff *segs);
void kfree_skb_list_reason(struct sk_buff *segs,
			   enum skb_drop_reason reason);
void skb_dump(const char *level, const struct sk_buff *skb, bool full_pkt);
void skb_tx_error(struct sk_buff *skb);

static inline void kfree_skb_list(struct sk_buff *segs)
{
	kfree_skb_list_reason(segs, SKB_DROP_REASON_NOT_SPECIFIED);
}

#ifdef CONFIG_TRACEPOINTS
void consume_skb(struct sk_buff *skb);
#else
+6 −0
Original line number Diff line number Diff line
@@ -45,6 +45,12 @@
	EM(SKB_DROP_REASON_NEIGH_FAILED, NEIGH_FAILED)		\
	EM(SKB_DROP_REASON_NEIGH_QUEUEFULL, NEIGH_QUEUEFULL)	\
	EM(SKB_DROP_REASON_NEIGH_DEAD, NEIGH_DEAD)		\
	EM(SKB_DROP_REASON_TC_EGRESS, TC_EGRESS)		\
	EM(SKB_DROP_REASON_QDISC_DROP, QDISC_DROP)		\
	EM(SKB_DROP_REASON_CPU_BACKLOG, CPU_BACKLOG)		\
	EM(SKB_DROP_REASON_XDP, XDP)				\
	EM(SKB_DROP_REASON_TC_INGRESS, TC_INGRESS)		\
	EM(SKB_DROP_REASON_PTYPE_ABSENT, PTYPE_ABSENT)		\
	EMe(SKB_DROP_REASON_MAX, MAX)

#undef EM
+15 −9
Original line number Diff line number Diff line
@@ -3759,7 +3759,8 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,

no_lock_out:
		if (unlikely(to_free))
			kfree_skb_list(to_free);
			kfree_skb_list_reason(to_free,
					      SKB_DROP_REASON_QDISC_DROP);
		return rc;
	}

@@ -3814,7 +3815,7 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
	}
	spin_unlock(root_lock);
	if (unlikely(to_free))
		kfree_skb_list(to_free);
		kfree_skb_list_reason(to_free, SKB_DROP_REASON_QDISC_DROP);
	if (unlikely(contended))
		spin_unlock(&q->busylock);
	return rc;
@@ -3889,7 +3890,7 @@ sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
	case TC_ACT_SHOT:
		mini_qdisc_qstats_cpu_drop(miniq);
		*ret = NET_XMIT_DROP;
		kfree_skb(skb);
		kfree_skb_reason(skb, SKB_DROP_REASON_TC_EGRESS);
		return NULL;
	case TC_ACT_STOLEN:
	case TC_ACT_QUEUED:
@@ -4569,10 +4570,12 @@ static bool skb_flow_limit(struct sk_buff *skb, unsigned int qlen)
static int enqueue_to_backlog(struct sk_buff *skb, int cpu,
			      unsigned int *qtail)
{
	enum skb_drop_reason reason;
	struct softnet_data *sd;
	unsigned long flags;
	unsigned int qlen;

	reason = SKB_DROP_REASON_NOT_SPECIFIED;
	sd = &per_cpu(softnet_data, cpu);

	rps_lock_irqsave(sd, &flags);
@@ -4595,13 +4598,14 @@ static int enqueue_to_backlog(struct sk_buff *skb, int cpu,
			napi_schedule_rps(sd);
		goto enqueue;
	}
	reason = SKB_DROP_REASON_CPU_BACKLOG;

drop:
	sd->dropped++;
	rps_unlock_irq_restore(sd, &flags);

	atomic_long_inc(&skb->dev->rx_dropped);
	kfree_skb(skb);
	kfree_skb_reason(skb, reason);
	return NET_RX_DROP;
}

@@ -4821,7 +4825,7 @@ int do_xdp_generic(struct bpf_prog *xdp_prog, struct sk_buff *skb)
	}
	return XDP_PASS;
out_redir:
	kfree_skb(skb);
	kfree_skb_reason(skb, SKB_DROP_REASON_XDP);
	return XDP_DROP;
}
EXPORT_SYMBOL_GPL(do_xdp_generic);
@@ -5037,7 +5041,7 @@ sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,
		break;
	case TC_ACT_SHOT:
		mini_qdisc_qstats_cpu_drop(miniq);
		kfree_skb(skb);
		kfree_skb_reason(skb, SKB_DROP_REASON_TC_INGRESS);
		return NULL;
	case TC_ACT_STOLEN:
	case TC_ACT_QUEUED:
@@ -5354,11 +5358,13 @@ static int __netif_receive_skb_core(struct sk_buff **pskb, bool pfmemalloc,
		*ppt_prev = pt_prev;
	} else {
drop:
		if (!deliver_exact)
		if (!deliver_exact) {
			atomic_long_inc(&skb->dev->rx_dropped);
		else
			kfree_skb_reason(skb, SKB_DROP_REASON_PTYPE_ABSENT);
		} else {
			atomic_long_inc(&skb->dev->rx_nohandler);
			kfree_skb(skb);
		}
		/* Jamal, now you will not able to escape explaining
		 * me how you were going to use this. :-)
		 */
+4 −3
Original line number Diff line number Diff line
@@ -777,16 +777,17 @@ void kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason)
}
EXPORT_SYMBOL(kfree_skb_reason);

void kfree_skb_list(struct sk_buff *segs)
void kfree_skb_list_reason(struct sk_buff *segs,
			   enum skb_drop_reason reason)
{
	while (segs) {
		struct sk_buff *next = segs->next;

		kfree_skb(segs);
		kfree_skb_reason(segs, reason);
		segs = next;
	}
}
EXPORT_SYMBOL(kfree_skb_list);
EXPORT_SYMBOL(kfree_skb_list_reason);

/* Dump skb information and contents.
 *