diff options
author | Eric Dumazet <edumazet@google.com> | 2013-10-19 14:42:54 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-10-19 19:36:18 -0400 |
commit | 030737bcc3c404e273e97dbe06fe9561699a411b (patch) | |
tree | 95b56e3692c3f2704d7f41d70fb0627ae812ed2c /net/core | |
parent | b917eb155c56bbb766140b406979820e719e3f55 (diff) |
net: generalize skb_segment()
While implementing GSO/TSO support for IPIP, I found skb_segment()
was assuming network header was immediately following mac header.
Its not really true in the case inet_gso_segment() is stacked :
By the time tcp_gso_segment() is called, network header points
to the inner IP header.
Let's instead assume nothing and pick the current offsets found in
original skb, we have skb_headers_offset_update() helper for that.
Also move the csum_start update inside skb_headers_offset_update()
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/skbuff.c | 22 |
1 files changed, 5 insertions, 17 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 8ead744fcc94..0ab32faa520f 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -903,6 +903,9 @@ EXPORT_SYMBOL(skb_clone); | |||
903 | 903 | ||
904 | static void skb_headers_offset_update(struct sk_buff *skb, int off) | 904 | static void skb_headers_offset_update(struct sk_buff *skb, int off) |
905 | { | 905 | { |
906 | /* Only adjust this if it actually is csum_start rather than csum */ | ||
907 | if (skb->ip_summed == CHECKSUM_PARTIAL) | ||
908 | skb->csum_start += off; | ||
906 | /* {transport,network,mac}_header and tail are relative to skb->head */ | 909 | /* {transport,network,mac}_header and tail are relative to skb->head */ |
907 | skb->transport_header += off; | 910 | skb->transport_header += off; |
908 | skb->network_header += off; | 911 | skb->network_header += off; |
@@ -1109,9 +1112,6 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, | |||
1109 | #endif | 1112 | #endif |
1110 | skb->tail += off; | 1113 | skb->tail += off; |
1111 | skb_headers_offset_update(skb, nhead); | 1114 | skb_headers_offset_update(skb, nhead); |
1112 | /* Only adjust this if it actually is csum_start rather than csum */ | ||
1113 | if (skb->ip_summed == CHECKSUM_PARTIAL) | ||
1114 | skb->csum_start += nhead; | ||
1115 | skb->cloned = 0; | 1115 | skb->cloned = 0; |
1116 | skb->hdr_len = 0; | 1116 | skb->hdr_len = 0; |
1117 | skb->nohdr = 0; | 1117 | skb->nohdr = 0; |
@@ -1176,7 +1176,6 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb, | |||
1176 | NUMA_NO_NODE); | 1176 | NUMA_NO_NODE); |
1177 | int oldheadroom = skb_headroom(skb); | 1177 | int oldheadroom = skb_headroom(skb); |
1178 | int head_copy_len, head_copy_off; | 1178 | int head_copy_len, head_copy_off; |
1179 | int off; | ||
1180 | 1179 | ||
1181 | if (!n) | 1180 | if (!n) |
1182 | return NULL; | 1181 | return NULL; |
@@ -1200,11 +1199,7 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb, | |||
1200 | 1199 | ||
1201 | copy_skb_header(n, skb); | 1200 | copy_skb_header(n, skb); |
1202 | 1201 | ||
1203 | off = newheadroom - oldheadroom; | 1202 | skb_headers_offset_update(n, newheadroom - oldheadroom); |
1204 | if (n->ip_summed == CHECKSUM_PARTIAL) | ||
1205 | n->csum_start += off; | ||
1206 | |||
1207 | skb_headers_offset_update(n, off); | ||
1208 | 1203 | ||
1209 | return n; | 1204 | return n; |
1210 | } | 1205 | } |
@@ -2837,14 +2832,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) | |||
2837 | __copy_skb_header(nskb, skb); | 2832 | __copy_skb_header(nskb, skb); |
2838 | nskb->mac_len = skb->mac_len; | 2833 | nskb->mac_len = skb->mac_len; |
2839 | 2834 | ||
2840 | /* nskb and skb might have different headroom */ | 2835 | skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom); |
2841 | if (nskb->ip_summed == CHECKSUM_PARTIAL) | ||
2842 | nskb->csum_start += skb_headroom(nskb) - headroom; | ||
2843 | |||
2844 | skb_reset_mac_header(nskb); | ||
2845 | skb_set_network_header(nskb, skb->mac_len); | ||
2846 | nskb->transport_header = (nskb->network_header + | ||
2847 | skb_network_header_len(skb)); | ||
2848 | 2836 | ||
2849 | skb_copy_from_linear_data_offset(skb, -tnl_hlen, | 2837 | skb_copy_from_linear_data_offset(skb, -tnl_hlen, |
2850 | nskb->data - tnl_hlen, | 2838 | nskb->data - tnl_hlen, |