From 6153047a0ed9d4ecbe8ed0f0c9a4e7726da54345 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Thu, 27 Oct 2011 15:53:39 -0400 Subject: [PATCH] net: Add & modify tracepoints to skb FCLONE_SCRATCH paths Since skbs that are fcloned via the FCLONE_SCRATCH method are opportunistic, it would be nice to have some feedback on how efficiently the path is acting. These tracepoints provide the infrastructure needed to create perf scripts that let us measure things like the number of skbs that are converted for FCLONE_SCRATCH use, the number of scratch skbs that actually get allocated, and the average per-packet time spent in the napi softirq context. Signed-off-by: Neil Horman CC: "David S. Miller" (committer note: made it apply to 2.6.33.9-rt31.64.el5rt kernel) Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/skbuff.h | 20 +------------------- include/trace/events/napi.h | 41 +++++++++++++++++++++++++++++++++++++++++ include/trace/events/skb.h | 41 +++++++++++++++++++++++++++++++++++++++++ net/core/dev.c | 3 +++ net/core/skbuff.c | 37 +++++++++++++++++++++++++++++++++---- 5 files changed, 119 insertions(+), 23 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index a2dba03..049ba07 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2114,25 +2114,7 @@ extern unsigned int skb_make_fclone_scratch(struct sk_buff *skb); /* * Allocates an skb out of our scratch space */ -static inline struct sk_buff *alloc_fscratch_skb(struct sk_buff *skb) -{ - struct skb_scr_control *sctl = skb_get_scratch_control(skb); - struct sk_buff *sskb; - - BUG_ON(skb->fclone != SKB_FCLONE_SCRATCH); - BUG_ON(!sctl); - BUG_ON(sctl->owner != skb); - if (skb_queue_empty(&sctl->scr_skbs)) - return NULL; - - sskb = __skb_dequeue(&sctl->scr_skbs); +extern struct sk_buff *alloc_fscratch_skb(struct sk_buff *skb); - /* - * Mark us as a scratch skb, so we get properly kfree-ed - */ - sskb->fclone = SKB_FCLONE_SCRATCH; - - return sskb; -} #endif /* __KERNEL__ */ #endif /* _LINUX_SKBUFF_H */ diff --git a/include/trace/events/napi.h b/include/trace/events/napi.h index a8989c4..ecaa3ab 100644 --- a/include/trace/events/napi.h +++ b/include/trace/events/napi.h @@ -3,9 +3,50 @@ #include #include +#include DECLARE_TRACE(napi_poll, TP_PROTO(struct napi_struct *napi), TP_ARGS(napi)); +TRACE_EVENT(napi_schedule, + + TP_PROTO(struct napi_struct *napi), + + TP_ARGS(napi), + + TP_STRUCT__entry( + __field( struct napi_struct *, napi) + __string( dev_name, napi->dev ? napi->dev->name : NO_DEV) + ), + + TP_fast_assign( + __entry->napi = napi; + __assign_str(dev_name, napi->dev ? napi->dev->name : NO_DEV); + ), + + TP_printk("napi schedule on napi struct %p for device %s", + __entry->napi, __get_str(dev_name)) +); + +TRACE_EVENT(napi_complete, + + TP_PROTO(struct napi_struct *napi), + + TP_ARGS(napi), + + TP_STRUCT__entry( + __field( struct napi_struct *, napi) + __string( dev_name, napi->dev ? napi->dev->name : NO_DEV) + ), + + TP_fast_assign( + __entry->napi = napi; + __assign_str(dev_name, napi->dev ? napi->dev->name : NO_DEV); + ), + + TP_printk("napi complete on napi struct %p for device %s", + __entry->napi, __get_str(dev_name)) +); + #endif diff --git a/include/trace/events/skb.h b/include/trace/events/skb.h index 4b2be6d..3c12c2c 100644 --- a/include/trace/events/skb.h +++ b/include/trace/events/skb.h @@ -54,6 +54,47 @@ TRACE_EVENT(skb_copy_datagram_iovec, TP_printk("skbaddr=%p len=%d", __entry->skbaddr, __entry->len) ); +TRACE_EVENT(skb_make_fclone_scratch, + + TP_PROTO(struct sk_buff *skb, int count), + + TP_ARGS(skb, count), + + TP_STRUCT__entry( + __field( const struct sk_buff *, skb) + __string( name, skb->dev ? skb->dev->name : "unknown") + __field( int, fccount) + ), + + TP_fast_assign( + __entry->skb = skb; + __assign_str(name, skb->dev ? skb->dev->name : "unknown"); + __entry->fccount = count; + ), + + TP_printk("skb= %p, dev=%s, count=%d", __entry->skb, + __get_str(name), __entry->fccount) +); + +TRACE_EVENT(alloc_fscratch_skb, + + TP_PROTO(const struct sk_buff *parent, const struct sk_buff *child), + + TP_ARGS(parent, child), + + TP_STRUCT__entry( + __field( const struct sk_buff *, parent) + __field( const struct sk_buff *, child) + ), + + TP_fast_assign( + __entry->parent = parent; + __entry->child = child; + ), + + TP_printk("parent=%p, child=%p", __entry->parent, __entry->child) +); + #endif /* _TRACE_SKB_H */ /* This part must be outside protection */ diff --git a/net/core/dev.c b/net/core/dev.c index de37604..5607bb0 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2899,6 +2899,8 @@ void __napi_schedule(struct napi_struct *n) { unsigned long flags; + trace_napi_schedule(n); + local_irq_save(flags); list_add_tail(&n->poll_list, &__get_cpu_var(softnet_data).poll_list); raise_softirq_irqoff(NET_RX_SOFTIRQ); @@ -2911,6 +2913,7 @@ void __napi_complete(struct napi_struct *n) BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state)); BUG_ON(n->gro_list); + trace_napi_complete(n); list_del(&n->poll_list); smp_mb__before_clear_bit(); clear_bit(NAPI_STATE_SCHED, &n->state); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index bc24c3d..c88e007 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3062,6 +3062,30 @@ void __skb_warn_lro_forwarding(const struct sk_buff *skb) } EXPORT_SYMBOL(__skb_warn_lro_forwarding); +/* + * Allocates an skb out of our scratch space + */ +struct sk_buff *alloc_fscratch_skb(struct sk_buff *skb) +{ + struct skb_scr_control *sctl = skb_get_scratch_control(skb); + struct sk_buff *sskb = NULL; + + BUG_ON(skb->fclone != SKB_FCLONE_SCRATCH); + BUG_ON(!sctl); + BUG_ON(sctl->owner != skb); + + sskb = __skb_dequeue(&sctl->scr_skbs); + + /* + * Mark us as a scratch skb, so we get properly kfree-ed + */ + sskb->fclone = SKB_FCLONE_SCRATCH; + + trace_alloc_fscratch_skb(skb, sskb); + return sskb; +} +EXPORT_SYMBOL(alloc_fscratch_skb); + unsigned int skb_make_fclone_scratch(struct sk_buff *skb) { size_t bufsz, totsz, scrsz, tmpsz; @@ -3069,15 +3093,16 @@ unsigned int skb_make_fclone_scratch(struct sk_buff *skb) struct sk_buff *scr_skb; struct skb_shared_info *old_info; bool format_tail = false; + int fclone_count = 0; if (skb_shared(skb)) - return 0; + goto out; /* * Cant do scratch space on fcloned skbs */ if (skb->fclone) - return 0; + goto out; if ((skb->end - skb->tail) > sizeof(struct skb_shared_info)) { old_info = skb_shinfo(skb); @@ -3098,7 +3123,7 @@ unsigned int skb_make_fclone_scratch(struct sk_buff *skb) sizeof(struct skb_shared_info); if ((bufsz + sizeof(struct skb_scr_control)) >= totsz) - return 0; + goto out; /* * And this is the leftover area, minus sizeof(int) to store the number @@ -3119,6 +3144,10 @@ unsigned int skb_make_fclone_scratch(struct sk_buff *skb) skb->fclone = SKB_FCLONE_SCRATCH; - return skb_queue_len(&sctl->scr_skbs); + fclone_count = skb_queue_len(&sctl->scr_skbs); +out: + trace_skb_make_fclone_scratch(skb, fclone_count); + return fclone_count; } +EXPORT_SYMBOL(skb_make_fclone_scratch); -- 1.7.1