diff options
Diffstat (limited to 'net/ipv6/ip6_offload.c')
-rw-r--r-- | net/ipv6/ip6_offload.c | 34 |
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 | ||
56 | static 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 | |||
77 | out: | ||
78 | return err; | ||
79 | } | ||
80 | |||
81 | static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | 56 | static 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: | |||
303 | static struct packet_offload ipv6_packet_offload __read_mostly = { | 281 | static 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 | ||
313 | static const struct net_offload sit_offload = { | 290 | static 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 | ||