Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ip4ip6: Support for GSO/GRO

Signed-off-by: Tom Herbert <tom@herbertland.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Tom Herbert and committed by
David S. Miller
b8921ca8 815d22e5

+49 -6
+5
include/net/inet_common.h
··· 39 39 int inet_recv_error(struct sock *sk, struct msghdr *msg, int len, 40 40 int *addr_len); 41 41 42 + struct sk_buff **inet_gro_receive(struct sk_buff **head, struct sk_buff *skb); 43 + int inet_gro_complete(struct sk_buff *skb, int nhoff); 44 + struct sk_buff *inet_gso_segment(struct sk_buff *skb, 45 + netdev_features_t features); 46 + 42 47 static inline void inet_ctl_sock_destroy(struct sock *sk) 43 48 { 44 49 if (sk)
+7 -5
net/ipv4/af_inet.c
··· 1192 1192 } 1193 1193 EXPORT_SYMBOL(inet_sk_rebuild_header); 1194 1194 1195 - static struct sk_buff *inet_gso_segment(struct sk_buff *skb, 1196 - netdev_features_t features) 1195 + struct sk_buff *inet_gso_segment(struct sk_buff *skb, 1196 + netdev_features_t features) 1197 1197 { 1198 1198 bool udpfrag = false, fixedid = false, encap; 1199 1199 struct sk_buff *segs = ERR_PTR(-EINVAL); ··· 1280 1280 out: 1281 1281 return segs; 1282 1282 } 1283 + EXPORT_SYMBOL(inet_gso_segment); 1283 1284 1284 - static struct sk_buff **inet_gro_receive(struct sk_buff **head, 1285 - struct sk_buff *skb) 1285 + struct sk_buff **inet_gro_receive(struct sk_buff **head, struct sk_buff *skb) 1286 1286 { 1287 1287 const struct net_offload *ops; 1288 1288 struct sk_buff **pp = NULL; ··· 1398 1398 1399 1399 return pp; 1400 1400 } 1401 + EXPORT_SYMBOL(inet_gro_receive); 1401 1402 1402 1403 static struct sk_buff **ipip_gro_receive(struct sk_buff **head, 1403 1404 struct sk_buff *skb) ··· 1450 1449 return -EINVAL; 1451 1450 } 1452 1451 1453 - static int inet_gro_complete(struct sk_buff *skb, int nhoff) 1452 + int inet_gro_complete(struct sk_buff *skb, int nhoff) 1454 1453 { 1455 1454 __be16 newlen = htons(skb->len - nhoff); 1456 1455 struct iphdr *iph = (struct iphdr *)(skb->data + nhoff); ··· 1480 1479 1481 1480 return err; 1482 1481 } 1482 + EXPORT_SYMBOL(inet_gro_complete); 1483 1483 1484 1484 static int ipip_gro_complete(struct sk_buff *skb, int nhoff) 1485 1485 {
+32 -1
net/ipv6/ip6_offload.c
··· 16 16 17 17 #include <net/protocol.h> 18 18 #include <net/ipv6.h> 19 + #include <net/inet_common.h> 19 20 20 21 #include "ip6_offload.h" 21 22 ··· 269 268 return ipv6_gro_receive(head, skb); 270 269 } 271 270 271 + static struct sk_buff **ip4ip6_gro_receive(struct sk_buff **head, 272 + struct sk_buff *skb) 273 + { 274 + /* Common GRO receive for SIT and IP6IP6 */ 275 + 276 + if (NAPI_GRO_CB(skb)->encap_mark) { 277 + NAPI_GRO_CB(skb)->flush = 1; 278 + return NULL; 279 + } 280 + 281 + NAPI_GRO_CB(skb)->encap_mark = 1; 282 + 283 + return inet_gro_receive(head, skb); 284 + } 285 + 272 286 static int ipv6_gro_complete(struct sk_buff *skb, int nhoff) 273 287 { 274 288 const struct net_offload *ops; ··· 323 307 return ipv6_gro_complete(skb, nhoff); 324 308 } 325 309 310 + static int ip4ip6_gro_complete(struct sk_buff *skb, int nhoff) 311 + { 312 + skb->encapsulation = 1; 313 + skb_shinfo(skb)->gso_type |= SKB_GSO_IPXIP6; 314 + return inet_gro_complete(skb, nhoff); 315 + } 316 + 326 317 static struct packet_offload ipv6_packet_offload __read_mostly = { 327 318 .type = cpu_to_be16(ETH_P_IPV6), 328 319 .callbacks = { ··· 347 324 }, 348 325 }; 349 326 327 + static const struct net_offload ip4ip6_offload = { 328 + .callbacks = { 329 + .gso_segment = inet_gso_segment, 330 + .gro_receive = ip4ip6_gro_receive, 331 + .gro_complete = ip4ip6_gro_complete, 332 + }, 333 + }; 334 + 350 335 static const struct net_offload ip6ip6_offload = { 351 336 .callbacks = { 352 337 .gso_segment = ipv6_gso_segment, ··· 362 331 .gro_complete = ip6ip6_gro_complete, 363 332 }, 364 333 }; 365 - 366 334 static int __init ipv6_offload_init(void) 367 335 { 368 336 ··· 374 344 375 345 inet_add_offload(&sit_offload, IPPROTO_IPV6); 376 346 inet6_add_offload(&ip6ip6_offload, IPPROTO_IPV6); 347 + inet6_add_offload(&ip4ip6_offload, IPPROTO_IPIP); 377 348 378 349 return 0; 379 350 }
+5
net/ipv6/ip6_tunnel.c
··· 1188 1188 if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) 1189 1189 fl6.flowi6_mark = skb->mark; 1190 1190 1191 + if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) 1192 + return -1; 1193 + 1194 + skb_set_inner_ipproto(skb, IPPROTO_IPIP); 1195 + 1191 1196 err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, 1192 1197 IPPROTO_IPIP); 1193 1198 if (err != 0) {