aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2015-10-19 23:40:17 -0400
committerDavid S. Miller <davem@davemloft.net>2015-10-21 22:36:11 -0400
commitfeec0cb3f20b837f8ca36e974267918d7a4497f8 (patch)
tree053b9100b5c0d224d7de0ff48dd9de994efc0e42
parent8f3af27786913851e720bc9466d1abffcfa7aff6 (diff)
ipv6: gro: support sit protocol
Tom Herbert added SIT support to GRO with commit 19424e052fb4 ("sit: Add gro callbacks to sit_offload"), later reverted by Herbert Xu. The problem came because Tom patch was building GRO packets without proper meta data : If packets were locally delivered, we would not care. But if packets needed to be forwarded, GSO engine was not able to segment individual segments. With the following patch, we correctly set skb->encapsulation and inner network header. We also update gso_type. Tested: Server : netserver modprobe dummy ifconfig dummy0 8.0.0.1 netmask 255.255.255.0 up arp -s 8.0.0.100 4e:32:51:04:47:e5 iptables -I INPUT -s 10.246.7.151 -j TEE --gateway 8.0.0.100 ifconfig sixtofour0 sixtofour0 Link encap:IPv6-in-IPv4 inet6 addr: 2002:af6:798::1/128 Scope:Global inet6 addr: 2002:af6:798::/128 Scope:Global UP RUNNING NOARP MTU:1480 Metric:1 RX packets:411169 errors:0 dropped:0 overruns:0 frame:0 TX packets:409414 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:20319631739 (20.3 GB) TX bytes:29529556 (29.5 MB) Client : netperf -H 2002:af6:798::1 -l 1000 & Checked on server traffic copied on dummy0 and verify segments were properly rebuilt, with proper IP headers, TCP checksums... tcpdump on eth0 shows proper GRO aggregation takes place. Signed-off-by: Eric Dumazet <edumazet@google.com> Acked-by: Tom Herbert <tom@herbertland.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv6/ip6_offload.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index 08b62047c67f..eeca943f12dc 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -264,6 +264,9 @@ static int ipv6_gro_complete(struct sk_buff *skb, int nhoff)
264 struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + nhoff); 264 struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + nhoff);
265 int err = -ENOSYS; 265 int err = -ENOSYS;
266 266
267 if (skb->encapsulation)
268 skb_set_inner_network_header(skb, nhoff);
269
267 iph->payload_len = htons(skb->len - nhoff - sizeof(*iph)); 270 iph->payload_len = htons(skb->len - nhoff - sizeof(*iph));
268 271
269 rcu_read_lock(); 272 rcu_read_lock();
@@ -280,6 +283,13 @@ out_unlock:
280 return err; 283 return err;
281} 284}
282 285
286static int sit_gro_complete(struct sk_buff *skb, int nhoff)
287{
288 skb->encapsulation = 1;
289 skb_shinfo(skb)->gso_type |= SKB_GSO_SIT;
290 return ipv6_gro_complete(skb, nhoff);
291}
292
283static struct packet_offload ipv6_packet_offload __read_mostly = { 293static struct packet_offload ipv6_packet_offload __read_mostly = {
284 .type = cpu_to_be16(ETH_P_IPV6), 294 .type = cpu_to_be16(ETH_P_IPV6),
285 .callbacks = { 295 .callbacks = {
@@ -292,6 +302,8 @@ static struct packet_offload ipv6_packet_offload __read_mostly = {
292static const struct net_offload sit_offload = { 302static const struct net_offload sit_offload = {
293 .callbacks = { 303 .callbacks = {
294 .gso_segment = ipv6_gso_segment, 304 .gso_segment = ipv6_gso_segment,
305 .gro_receive = ipv6_gro_receive,
306 .gro_complete = sit_gro_complete,
295 }, 307 },
296}; 308};
297 309