aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_offload.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/ip6_offload.c')
-rw-r--r--net/ipv6/ip6_offload.c34
1 files changed, 6 insertions, 28 deletions
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index 65eda2a8af48..9034f76ae013 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -53,31 +53,6 @@ static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto)
53 return proto; 53 return proto;
54} 54}
55 55
56static int ipv6_gso_send_check(struct sk_buff *skb)
57{
58 const struct ipv6hdr *ipv6h;
59 const struct net_offload *ops;
60 int err = -EINVAL;
61
62 if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
63 goto out;
64
65 ipv6h = ipv6_hdr(skb);
66 __skb_pull(skb, sizeof(*ipv6h));
67 err = -EPROTONOSUPPORT;
68
69 ops = rcu_dereference(inet6_offloads[
70 ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr)]);
71
72 if (likely(ops && ops->callbacks.gso_send_check)) {
73 skb_reset_transport_header(skb);
74 err = ops->callbacks.gso_send_check(skb);
75 }
76
77out:
78 return err;
79}
80
81static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, 56static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
82 netdev_features_t features) 57 netdev_features_t features)
83{ 58{
@@ -244,7 +219,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
244 continue; 219 continue;
245 220
246 iph2 = (struct ipv6hdr *)(p->data + off); 221 iph2 = (struct ipv6hdr *)(p->data + off);
247 first_word = *(__be32 *)iph ^ *(__be32 *)iph2 ; 222 first_word = *(__be32 *)iph ^ *(__be32 *)iph2;
248 223
249 /* All fields must match except length and Traffic Class. 224 /* All fields must match except length and Traffic Class.
250 * XXX skbs on the gro_list have all been parsed and pulled 225 * XXX skbs on the gro_list have all been parsed and pulled
@@ -261,6 +236,9 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
261 /* flush if Traffic Class fields are different */ 236 /* flush if Traffic Class fields are different */
262 NAPI_GRO_CB(p)->flush |= !!(first_word & htonl(0x0FF00000)); 237 NAPI_GRO_CB(p)->flush |= !!(first_word & htonl(0x0FF00000));
263 NAPI_GRO_CB(p)->flush |= flush; 238 NAPI_GRO_CB(p)->flush |= flush;
239
240 /* Clear flush_id, there's really no concept of ID in IPv6. */
241 NAPI_GRO_CB(p)->flush_id = 0;
264 } 242 }
265 243
266 NAPI_GRO_CB(skb)->flush |= flush; 244 NAPI_GRO_CB(skb)->flush |= flush;
@@ -303,7 +281,6 @@ out_unlock:
303static struct packet_offload ipv6_packet_offload __read_mostly = { 281static struct packet_offload ipv6_packet_offload __read_mostly = {
304 .type = cpu_to_be16(ETH_P_IPV6), 282 .type = cpu_to_be16(ETH_P_IPV6),
305 .callbacks = { 283 .callbacks = {
306 .gso_send_check = ipv6_gso_send_check,
307 .gso_segment = ipv6_gso_segment, 284 .gso_segment = ipv6_gso_segment,
308 .gro_receive = ipv6_gro_receive, 285 .gro_receive = ipv6_gro_receive,
309 .gro_complete = ipv6_gro_complete, 286 .gro_complete = ipv6_gro_complete,
@@ -312,8 +289,9 @@ static struct packet_offload ipv6_packet_offload __read_mostly = {
312 289
313static const struct net_offload sit_offload = { 290static const struct net_offload sit_offload = {
314 .callbacks = { 291 .callbacks = {
315 .gso_send_check = ipv6_gso_send_check,
316 .gso_segment = ipv6_gso_segment, 292 .gso_segment = ipv6_gso_segment,
293 .gro_receive = ipv6_gro_receive,
294 .gro_complete = ipv6_gro_complete,
317 }, 295 },
318}; 296};
319 297