summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2022-03-04 12:17:11 +0000
committerDavid S. Miller <davem@davemloft.net>2022-03-04 12:17:11 +0000
commit6af3b428cd02b09db79f0ee0265dcb8799d9327c (patch)
treecd9c481d3a8436b3a1f1214084245dc37bbab61c
parent9f9919f73c94ae00af4e6ad45179282122f24988 (diff)
parent6c2728b7c14164928cb7cb9c847dead101b2d503 (diff)
Merge branch 'skb-drop-reasons'
Menglong Dong says: ==================== net: dev: add skb drop reasons to net/core/dev.c In the commit c504e5c2f964 ("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: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/skbuff.h26
-rw-r--r--include/trace/events/skb.h6
-rw-r--r--net/core/dev.c24
-rw-r--r--net/core/skbuff.c7
4 files changed, 50 insertions, 13 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 5445860e1ba6..2be263184d1e 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -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
diff --git a/include/trace/events/skb.h b/include/trace/events/skb.h
index 1977f301260d..c0769d943f8e 100644
--- a/include/trace/events/skb.h
+++ b/include/trace/events/skb.h
@@ -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
diff --git a/net/core/dev.c b/net/core/dev.c
index 96bcc003e018..ba69ddf85af6 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -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 @@ no_lock_out:
}
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 @@ enqueue:
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 @@ check_vlan_id:
*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);
+ kfree_skb(skb);
+ }
/* Jamal, now you will not able to escape explaining
* me how you were going to use this. :-)
*/
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 23f3ba343661..10bde7c6db44 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -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.
*