aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2013-10-19 14:42:54 -0400
committerDavid S. Miller <davem@davemloft.net>2013-10-19 19:36:18 -0400
commit030737bcc3c404e273e97dbe06fe9561699a411b (patch)
tree95b56e3692c3f2704d7f41d70fb0627ae812ed2c /net/core
parentb917eb155c56bbb766140b406979820e719e3f55 (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.c22
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
904static void skb_headers_offset_update(struct sk_buff *skb, int off) 904static 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,