diff options
author | David S. Miller <davem@davemloft.net> | 2005-08-17 17:57:30 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 19:01:54 -0400 |
commit | d179cd12928443f3ec29cfbc3567439644bd0afc (patch) | |
tree | 0bfc57e73f0bf9f7bb9d5c8ce7d3d5afe550f94e /include | |
parent | e92ae93a8aa66aea12935420cb22d4df1c18d023 (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.h | 26 | ||||
-rw-r--r-- | include/net/sock.h | 2 |
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 | |||
166 | enum { | ||
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 | ||
297 | extern void __kfree_skb(struct sk_buff *skb); | 305 | extern void __kfree_skb(struct sk_buff *skb); |
298 | extern struct sk_buff *alloc_skb(unsigned int size, | 306 | extern struct sk_buff *__alloc_skb(unsigned int size, |
299 | unsigned int __nocast priority); | 307 | unsigned int __nocast priority, int fclone); |
308 | static inline struct sk_buff *alloc_skb(unsigned int size, | ||
309 | unsigned int __nocast priority) | ||
310 | { | ||
311 | return __alloc_skb(size, priority, 0); | ||
312 | } | ||
313 | |||
314 | static 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 | |||
300 | extern struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp, | 320 | extern 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 || |