diff options
author | David S. Miller <davem@davemloft.net> | 2005-07-05 18:17:25 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-07-05 18:17:25 -0400 |
commit | c65f7f00c587828e3d50737805a78f74804972de (patch) | |
tree | 160f85e7d9ec1df2432b4dd3fae315812558bd10 | |
parent | b8259d9ad1d0f8d0c5ea0e37bb15080b0bd395b5 (diff) |
[TCP]: Simplify SKB data portion allocation with NETIF_F_SG.
The ideal and most optimal layout for an SKB when doing
scatter-gather is to put all the headers at skb->data, and
all the user data in the page array.
This makes SKB splitting and combining extremely simple,
especially before a packet goes onto the wire the first
time.
So, when sk_stream_alloc_pskb() is given a zero size, make
sure there is no skb_tailroom(). This is achieved by applying
SKB_DATA_ALIGN() to the header length used here.
Next, make select_size() in TCP output segmentation use a
length of zero when NETIF_F_SG is true on the outgoing
interface.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/sock.h | 7 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 13 |
2 files changed, 7 insertions, 13 deletions
diff --git a/include/net/sock.h b/include/net/sock.h index e593af5b1ecc..7b76f891ae2d 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -1134,13 +1134,16 @@ static inline void sk_stream_moderate_sndbuf(struct sock *sk) | |||
1134 | static inline struct sk_buff *sk_stream_alloc_pskb(struct sock *sk, | 1134 | static inline struct sk_buff *sk_stream_alloc_pskb(struct sock *sk, |
1135 | int size, int mem, int gfp) | 1135 | int size, int mem, int gfp) |
1136 | { | 1136 | { |
1137 | struct sk_buff *skb = alloc_skb(size + sk->sk_prot->max_header, gfp); | 1137 | struct sk_buff *skb; |
1138 | int hdr_len; | ||
1138 | 1139 | ||
1140 | hdr_len = SKB_DATA_ALIGN(sk->sk_prot->max_header); | ||
1141 | skb = alloc_skb(size + hdr_len, gfp); | ||
1139 | if (skb) { | 1142 | if (skb) { |
1140 | skb->truesize += mem; | 1143 | skb->truesize += mem; |
1141 | if (sk->sk_forward_alloc >= (int)skb->truesize || | 1144 | if (sk->sk_forward_alloc >= (int)skb->truesize || |
1142 | sk_stream_mem_schedule(sk, skb->truesize, 0)) { | 1145 | sk_stream_mem_schedule(sk, skb->truesize, 0)) { |
1143 | skb_reserve(skb, sk->sk_prot->max_header); | 1146 | skb_reserve(skb, hdr_len); |
1144 | return skb; | 1147 | return skb; |
1145 | } | 1148 | } |
1146 | __kfree_skb(skb); | 1149 | __kfree_skb(skb); |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 882436da9a3a..be354155b2f9 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -756,13 +756,9 @@ static inline int select_size(struct sock *sk, struct tcp_sock *tp) | |||
756 | { | 756 | { |
757 | int tmp = tp->mss_cache_std; | 757 | int tmp = tp->mss_cache_std; |
758 | 758 | ||
759 | if (sk->sk_route_caps & NETIF_F_SG) { | 759 | if (sk->sk_route_caps & NETIF_F_SG) |
760 | int pgbreak = SKB_MAX_HEAD(MAX_TCP_HEADER); | 760 | tmp = 0; |
761 | 761 | ||
762 | if (tmp >= pgbreak && | ||
763 | tmp <= pgbreak + (MAX_SKB_FRAGS - 1) * PAGE_SIZE) | ||
764 | tmp = pgbreak; | ||
765 | } | ||
766 | return tmp; | 762 | return tmp; |
767 | } | 763 | } |
768 | 764 | ||
@@ -872,11 +868,6 @@ new_segment: | |||
872 | tcp_mark_push(tp, skb); | 868 | tcp_mark_push(tp, skb); |
873 | goto new_segment; | 869 | goto new_segment; |
874 | } else if (page) { | 870 | } else if (page) { |
875 | /* If page is cached, align | ||
876 | * offset to L1 cache boundary | ||
877 | */ | ||
878 | off = (off + L1_CACHE_BYTES - 1) & | ||
879 | ~(L1_CACHE_BYTES - 1); | ||
880 | if (off == PAGE_SIZE) { | 871 | if (off == PAGE_SIZE) { |
881 | put_page(page); | 872 | put_page(page); |
882 | TCP_PAGE(sk) = page = NULL; | 873 | TCP_PAGE(sk) = page = NULL; |