aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2005-08-17 17:57:30 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 19:01:54 -0400
commitd179cd12928443f3ec29cfbc3567439644bd0afc (patch)
tree0bfc57e73f0bf9f7bb9d5c8ce7d3d5afe550f94e /include
parente92ae93a8aa66aea12935420cb22d4df1c18d023 (diff)
[NET]: Implement SKB fast cloning.
Protocols that make extensive use of SKB cloning, for example TCP, eat at least 2 allocations per packet sent as a result. To cut the kmalloc() count in half, we implement a pre-allocation scheme wherein we allocate 2 sk_buff objects in advance, then use a simple reference count to free up the memory at the correct time. Based upon an initial patch by Thomas Graf and suggestions from Herbert Xu. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r--include/linux/skbuff.h26
-rw-r--r--include/net/sock.h2
2 files changed, 24 insertions, 4 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index db10335e4192..42edce6abe23 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -162,6 +162,13 @@ struct skb_timeval {
162 u32 off_usec; 162 u32 off_usec;
163}; 163};
164 164
165
166enum {
167 SKB_FCLONE_UNAVAILABLE,
168 SKB_FCLONE_ORIG,
169 SKB_FCLONE_CLONE,
170};
171
165/** 172/**
166 * struct sk_buff - socket buffer 173 * struct sk_buff - socket buffer
167 * @next: Next buffer in list 174 * @next: Next buffer in list
@@ -255,7 +262,8 @@ struct sk_buff {
255 ip_summed:2, 262 ip_summed:2,
256 nohdr:1, 263 nohdr:1,
257 nfctinfo:3; 264 nfctinfo:3;
258 __u8 pkt_type; 265 __u8 pkt_type:3,
266 fclone:2;
259 __be16 protocol; 267 __be16 protocol;
260 268
261 void (*destructor)(struct sk_buff *skb); 269 void (*destructor)(struct sk_buff *skb);
@@ -295,8 +303,20 @@ struct sk_buff {
295#include <asm/system.h> 303#include <asm/system.h>
296 304
297extern void __kfree_skb(struct sk_buff *skb); 305extern void __kfree_skb(struct sk_buff *skb);
298extern struct sk_buff *alloc_skb(unsigned int size, 306extern struct sk_buff *__alloc_skb(unsigned int size,
299 unsigned int __nocast priority); 307 unsigned int __nocast priority, int fclone);
308static inline struct sk_buff *alloc_skb(unsigned int size,
309 unsigned int __nocast priority)
310{
311 return __alloc_skb(size, priority, 0);
312}
313
314static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
315 unsigned int __nocast priority)
316{
317 return __alloc_skb(size, priority, 1);
318}
319
300extern struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp, 320extern struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp,
301 unsigned int size, 321 unsigned int size,
302 unsigned int __nocast priority); 322 unsigned int __nocast priority);
diff --git a/include/net/sock.h b/include/net/sock.h
index 14183883e8e6..d57aece9492c 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1200,7 +1200,7 @@ static inline struct sk_buff *sk_stream_alloc_pskb(struct sock *sk,
1200 int hdr_len; 1200 int hdr_len;
1201 1201
1202 hdr_len = SKB_DATA_ALIGN(sk->sk_prot->max_header); 1202 hdr_len = SKB_DATA_ALIGN(sk->sk_prot->max_header);
1203 skb = alloc_skb(size + hdr_len, gfp); 1203 skb = alloc_skb_fclone(size + hdr_len, gfp);
1204 if (skb) { 1204 if (skb) {
1205 skb->truesize += mem; 1205 skb->truesize += mem;
1206 if (sk->sk_forward_alloc >= (int)skb->truesize || 1206 if (sk->sk_forward_alloc >= (int)skb->truesize ||