ia64/xen-unstable

view patches/linux-2.6.16.13/net-gso-2-checksum-fix.patch @ 11154:bb37d167c82e

[XEND] xc_save/xc_restore open the libxc interface independently
of their parent. This is required now that the interface fd is
marked for close-on-exec.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Tue Aug 15 19:04:43 2006 +0100 (2006-08-15)
parents d48322cddd87
children
line source
1 diff -urp a/drivers/net/bnx2.c b/drivers/net/bnx2.c
2 --- a/drivers/net/bnx2.c 2006-07-25 14:41:00.905507519 +0100
3 +++ b/drivers/net/bnx2.c 2006-07-25 14:36:00.288561400 +0100
4 @@ -1593,7 +1593,7 @@ bnx2_tx_int(struct bnx2 *bp)
5 skb = tx_buf->skb;
6 #ifdef BCM_TSO
7 /* partial BD completions possible with TSO packets */
8 - if (skb_shinfo(skb)->gso_size) {
9 + if (skb_is_gso(skb)) {
10 u16 last_idx, last_ring_idx;
12 last_idx = sw_cons +
13 diff -urp a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
14 --- a/drivers/net/chelsio/sge.c 2006-07-25 14:41:00.908507183 +0100
15 +++ b/drivers/net/chelsio/sge.c 2006-07-25 14:36:00.291561087 +0100
16 @@ -1419,7 +1419,7 @@ int t1_start_xmit(struct sk_buff *skb, s
17 struct cpl_tx_pkt *cpl;
19 #ifdef NETIF_F_TSO
20 - if (skb_shinfo(skb)->gso_size) {
21 + if (skb_is_gso(skb)) {
22 int eth_type;
23 struct cpl_tx_pkt_lso *hdr;
25 diff -urp a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
26 --- a/drivers/net/e1000/e1000_main.c 2006-07-25 14:41:00.910506958 +0100
27 +++ b/drivers/net/e1000/e1000_main.c 2006-07-25 14:36:00.293560878 +0100
28 @@ -2526,7 +2526,7 @@ e1000_tso(struct e1000_adapter *adapter,
29 uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
30 int err;
32 - if (skb_shinfo(skb)->gso_size) {
33 + if (skb_is_gso(skb)) {
34 if (skb_header_cloned(skb)) {
35 err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
36 if (err)
37 @@ -2651,7 +2651,7 @@ e1000_tx_map(struct e1000_adapter *adapt
38 * tso gets written back prematurely before the data is fully
39 * DMAd to the controller */
40 if (!skb->data_len && tx_ring->last_tx_tso &&
41 - !skb_shinfo(skb)->gso_size) {
42 + !skb_is_gso(skb)) {
43 tx_ring->last_tx_tso = 0;
44 size -= 4;
45 }
46 @@ -2934,8 +2934,7 @@ e1000_xmit_frame(struct sk_buff *skb, st
48 #ifdef NETIF_F_TSO
49 /* Controller Erratum workaround */
50 - if (!skb->data_len && tx_ring->last_tx_tso &&
51 - !skb_shinfo(skb)->gso_size)
52 + if (!skb->data_len && tx_ring->last_tx_tso && !skb_is_gso(skb))
53 count++;
54 #endif
56 diff -urp a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
57 --- a/drivers/net/forcedeth.c 2006-07-25 14:41:00.912506734 +0100
58 +++ b/drivers/net/forcedeth.c 2006-07-25 14:36:00.295560669 +0100
59 @@ -1105,7 +1105,7 @@ static int nv_start_xmit(struct sk_buff
60 np->tx_skbuff[nr] = skb;
62 #ifdef NETIF_F_TSO
63 - if (skb_shinfo(skb)->gso_size)
64 + if (skb_is_gso(skb))
65 tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size << NV_TX2_TSO_SHIFT);
66 else
67 #endif
68 diff -urp a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
69 --- a/drivers/net/ixgb/ixgb_main.c 2006-07-25 14:41:00.915506397 +0100
70 +++ b/drivers/net/ixgb/ixgb_main.c 2006-07-25 14:36:00.298560355 +0100
71 @@ -1163,7 +1163,7 @@ ixgb_tso(struct ixgb_adapter *adapter, s
72 uint16_t ipcse, tucse, mss;
73 int err;
75 - if(likely(skb_shinfo(skb)->gso_size)) {
76 + if (likely(skb_is_gso(skb))) {
77 if (skb_header_cloned(skb)) {
78 err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
79 if (err)
80 diff -urp a/drivers/net/loopback.c b/drivers/net/loopback.c
81 --- a/drivers/net/loopback.c 2006-07-25 14:41:00.915506397 +0100
82 +++ b/drivers/net/loopback.c 2006-07-25 14:36:00.298560355 +0100
83 @@ -139,7 +139,7 @@ static int loopback_xmit(struct sk_buff
84 #endif
86 #ifdef LOOPBACK_TSO
87 - if (skb_shinfo(skb)->gso_size) {
88 + if (skb_is_gso(skb)) {
89 BUG_ON(skb->protocol != htons(ETH_P_IP));
90 BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP);
92 diff -urp a/drivers/net/sky2.c b/drivers/net/sky2.c
93 --- a/drivers/net/sky2.c 2006-07-25 14:41:00.924505388 +0100
94 +++ b/drivers/net/sky2.c 2006-07-25 14:36:00.306559519 +0100
95 @@ -1125,7 +1125,7 @@ static unsigned tx_le_req(const struct s
96 count = sizeof(dma_addr_t) / sizeof(u32);
97 count += skb_shinfo(skb)->nr_frags * count;
99 - if (skb_shinfo(skb)->gso_size)
100 + if (skb_is_gso(skb))
101 ++count;
103 if (skb->ip_summed == CHECKSUM_HW)
104 diff -urp a/drivers/net/typhoon.c b/drivers/net/typhoon.c
105 --- a/drivers/net/typhoon.c 2006-07-25 14:41:00.931504603 +0100
106 +++ b/drivers/net/typhoon.c 2006-07-25 14:36:00.314558683 +0100
107 @@ -805,7 +805,7 @@ typhoon_start_tx(struct sk_buff *skb, st
108 * If problems develop with TSO, check this first.
109 */
110 numDesc = skb_shinfo(skb)->nr_frags + 1;
111 - if(skb_tso_size(skb))
112 + if (skb_is_gso(skb))
113 numDesc++;
115 /* When checking for free space in the ring, we need to also
116 @@ -845,7 +845,7 @@ typhoon_start_tx(struct sk_buff *skb, st
117 TYPHOON_TX_PF_VLAN_TAG_SHIFT);
118 }
120 - if(skb_tso_size(skb)) {
121 + if (skb_is_gso(skb)) {
122 first_txd->processFlags |= TYPHOON_TX_PF_TCP_SEGMENT;
123 first_txd->numDesc++;
125 diff -urp a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
126 --- a/drivers/s390/net/qeth_main.c 2006-07-25 14:41:00.939503705 +0100
127 +++ b/drivers/s390/net/qeth_main.c 2006-07-25 14:36:00.321557952 +0100
128 @@ -4454,7 +4454,7 @@ qeth_send_packet(struct qeth_card *card,
129 queue = card->qdio.out_qs
130 [qeth_get_priority_queue(card, skb, ipv, cast_type)];
132 - if (skb_shinfo(skb)->gso_size)
133 + if (skb_is_gso(skb))
134 large_send = card->options.large_send;
136 /*are we able to do TSO ? If so ,prepare and send it from here */
137 @@ -4501,8 +4501,7 @@ qeth_send_packet(struct qeth_card *card,
138 card->stats.tx_packets++;
139 card->stats.tx_bytes += skb->len;
140 #ifdef CONFIG_QETH_PERF_STATS
141 - if (skb_shinfo(skb)->gso_size &&
142 - !(large_send == QETH_LARGE_SEND_NO)) {
143 + if (skb_is_gso(skb) && !(large_send == QETH_LARGE_SEND_NO)) {
144 card->perf_stats.large_send_bytes += skb->len;
145 card->perf_stats.large_send_cnt++;
146 }
147 diff -urp a/include/linux/netdevice.h b/include/linux/netdevice.h
148 --- a/include/linux/netdevice.h 2006-07-25 14:41:00.940503593 +0100
149 +++ b/include/linux/netdevice.h 2006-07-25 14:36:00.323557743 +0100
150 @@ -541,6 +541,7 @@ struct packet_type {
151 struct net_device *);
152 struct sk_buff *(*gso_segment)(struct sk_buff *skb,
153 int features);
154 + int (*gso_send_check)(struct sk_buff *skb);
155 void *af_packet_priv;
156 struct list_head list;
157 };
158 @@ -1001,14 +1002,15 @@ extern void linkwatch_run_queue(void);
160 static inline int skb_gso_ok(struct sk_buff *skb, int features)
161 {
162 - int feature = skb_shinfo(skb)->gso_size ?
163 - skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT : 0;
164 + int feature = skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT;
165 return (features & feature) == feature;
166 }
168 static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
169 {
170 - return !skb_gso_ok(skb, dev->features);
171 + return skb_is_gso(skb) &&
172 + (!skb_gso_ok(skb, dev->features) ||
173 + unlikely(skb->ip_summed != CHECKSUM_HW));
174 }
176 #endif /* __KERNEL__ */
177 diff -urp a/include/linux/skbuff.h b/include/linux/skbuff.h
178 --- a/include/linux/skbuff.h 2006-07-25 14:41:00.941503481 +0100
179 +++ b/include/linux/skbuff.h 2006-07-25 14:36:00.323557743 +0100
180 @@ -1403,5 +1403,10 @@ static inline void nf_bridge_get(struct
181 static inline void nf_reset(struct sk_buff *skb) {}
182 #endif /* CONFIG_NETFILTER */
184 +static inline int skb_is_gso(const struct sk_buff *skb)
185 +{
186 + return skb_shinfo(skb)->gso_size;
187 +}
188 +
189 #endif /* __KERNEL__ */
190 #endif /* _LINUX_SKBUFF_H */
191 diff -urp a/include/net/protocol.h b/include/net/protocol.h
192 --- a/include/net/protocol.h 2006-07-25 14:41:00.942503369 +0100
193 +++ b/include/net/protocol.h 2006-07-25 14:36:00.324557639 +0100
194 @@ -37,6 +37,7 @@
195 struct net_protocol {
196 int (*handler)(struct sk_buff *skb);
197 void (*err_handler)(struct sk_buff *skb, u32 info);
198 + int (*gso_send_check)(struct sk_buff *skb);
199 struct sk_buff *(*gso_segment)(struct sk_buff *skb,
200 int features);
201 int no_policy;
202 diff -urp a/include/net/tcp.h b/include/net/tcp.h
203 --- a/include/net/tcp.h 2006-07-25 14:41:00.943503256 +0100
204 +++ b/include/net/tcp.h 2006-07-25 14:36:00.325557534 +0100
205 @@ -1063,6 +1063,7 @@ extern struct request_sock_ops tcp_reque
207 extern int tcp_v4_destroy_sock(struct sock *sk);
209 +extern int tcp_v4_gso_send_check(struct sk_buff *skb);
210 extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features);
212 #ifdef CONFIG_PROC_FS
213 diff -urp a/net/bridge/br_forward.c b/net/bridge/br_forward.c
214 --- a/net/bridge/br_forward.c 2006-07-25 14:41:00.944503144 +0100
215 +++ b/net/bridge/br_forward.c 2006-07-25 14:36:00.326557430 +0100
216 @@ -32,7 +32,7 @@ static inline int should_deliver(const s
217 int br_dev_queue_push_xmit(struct sk_buff *skb)
218 {
219 /* drop mtu oversized packets except tso */
220 - if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->gso_size)
221 + if (skb->len > skb->dev->mtu && !skb_is_gso(skb))
222 kfree_skb(skb);
223 else {
224 #ifdef CONFIG_BRIDGE_NETFILTER
225 diff -urp a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
226 --- a/net/bridge/br_netfilter.c 2006-07-25 14:41:00.945503032 +0100
227 +++ b/net/bridge/br_netfilter.c 2006-07-25 14:36:00.327557325 +0100
228 @@ -743,7 +743,7 @@ static int br_nf_dev_queue_xmit(struct s
229 {
230 if (skb->protocol == htons(ETH_P_IP) &&
231 skb->len > skb->dev->mtu &&
232 - !skb_shinfo(skb)->gso_size)
233 + !skb_is_gso(skb))
234 return ip_fragment(skb, br_dev_queue_push_xmit);
235 else
236 return br_dev_queue_push_xmit(skb);
237 diff -urp a/net/core/dev.c b/net/core/dev.c
238 --- a/net/core/dev.c 2006-07-25 14:41:00.947502808 +0100
239 +++ b/net/core/dev.c 2006-07-25 14:36:00.329557116 +0100
240 @@ -1083,9 +1083,17 @@ int skb_checksum_help(struct sk_buff *sk
241 unsigned int csum;
242 int ret = 0, offset = skb->h.raw - skb->data;
244 - if (inward) {
245 - skb->ip_summed = CHECKSUM_NONE;
246 - goto out;
247 + if (inward)
248 + goto out_set_summed;
249 +
250 + if (unlikely(skb_shinfo(skb)->gso_size)) {
251 + static int warned;
252 +
253 + WARN_ON(!warned);
254 + warned = 1;
255 +
256 + /* Let GSO fix up the checksum. */
257 + goto out_set_summed;
258 }
260 if (skb_cloned(skb)) {
261 @@ -1102,6 +1110,8 @@ int skb_checksum_help(struct sk_buff *sk
262 BUG_ON(skb->csum + 2 > offset);
264 *(u16*)(skb->h.raw + skb->csum) = csum_fold(csum);
265 +
266 +out_set_summed:
267 skb->ip_summed = CHECKSUM_NONE;
268 out:
269 return ret;
270 @@ -1122,17 +1132,35 @@ struct sk_buff *skb_gso_segment(struct s
271 struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
272 struct packet_type *ptype;
273 int type = skb->protocol;
274 + int err;
276 BUG_ON(skb_shinfo(skb)->frag_list);
277 - BUG_ON(skb->ip_summed != CHECKSUM_HW);
279 skb->mac.raw = skb->data;
280 skb->mac_len = skb->nh.raw - skb->data;
281 __skb_pull(skb, skb->mac_len);
283 + if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
284 + static int warned;
285 +
286 + WARN_ON(!warned);
287 + warned = 1;
288 +
289 + if (skb_header_cloned(skb) &&
290 + (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
291 + return ERR_PTR(err);
292 + }
293 +
294 rcu_read_lock();
295 list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) {
296 if (ptype->type == type && !ptype->dev && ptype->gso_segment) {
297 + if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
298 + err = ptype->gso_send_check(skb);
299 + segs = ERR_PTR(err);
300 + if (err || skb_gso_ok(skb, features))
301 + break;
302 + __skb_push(skb, skb->data - skb->nh.raw);
303 + }
304 segs = ptype->gso_segment(skb, features);
305 break;
306 }
307 diff -urp a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
308 --- a/net/ipv4/af_inet.c 2006-07-25 14:41:00.952502247 +0100
309 +++ b/net/ipv4/af_inet.c 2006-07-25 14:36:00.334556594 +0100
310 @@ -1085,6 +1085,40 @@ int inet_sk_rebuild_header(struct sock *
312 EXPORT_SYMBOL(inet_sk_rebuild_header);
314 +static int inet_gso_send_check(struct sk_buff *skb)
315 +{
316 + struct iphdr *iph;
317 + struct net_protocol *ops;
318 + int proto;
319 + int ihl;
320 + int err = -EINVAL;
321 +
322 + if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
323 + goto out;
324 +
325 + iph = skb->nh.iph;
326 + ihl = iph->ihl * 4;
327 + if (ihl < sizeof(*iph))
328 + goto out;
329 +
330 + if (unlikely(!pskb_may_pull(skb, ihl)))
331 + goto out;
332 +
333 + skb->h.raw = __skb_pull(skb, ihl);
334 + iph = skb->nh.iph;
335 + proto = iph->protocol & (MAX_INET_PROTOS - 1);
336 + err = -EPROTONOSUPPORT;
337 +
338 + rcu_read_lock();
339 + ops = rcu_dereference(inet_protos[proto]);
340 + if (likely(ops && ops->gso_send_check))
341 + err = ops->gso_send_check(skb);
342 + rcu_read_unlock();
343 +
344 +out:
345 + return err;
346 +}
347 +
348 static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
349 {
350 struct sk_buff *segs = ERR_PTR(-EINVAL);
351 @@ -1142,6 +1176,7 @@ static struct net_protocol igmp_protocol
352 static struct net_protocol tcp_protocol = {
353 .handler = tcp_v4_rcv,
354 .err_handler = tcp_v4_err,
355 + .gso_send_check = tcp_v4_gso_send_check,
356 .gso_segment = tcp_tso_segment,
357 .no_policy = 1,
358 };
359 @@ -1188,6 +1223,7 @@ static int ipv4_proc_init(void);
360 static struct packet_type ip_packet_type = {
361 .type = __constant_htons(ETH_P_IP),
362 .func = ip_rcv,
363 + .gso_send_check = inet_gso_send_check,
364 .gso_segment = inet_gso_segment,
365 };
367 diff -urp a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
368 --- a/net/ipv4/ip_output.c 2006-07-25 14:41:00.953502135 +0100
369 +++ b/net/ipv4/ip_output.c 2006-07-25 14:36:00.335556489 +0100
370 @@ -210,7 +210,7 @@ static inline int ip_finish_output(struc
371 return dst_output(skb);
372 }
373 #endif
374 - if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size)
375 + if (skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb))
376 return ip_fragment(skb, ip_finish_output2);
377 else
378 return ip_finish_output2(skb);
379 @@ -1095,7 +1095,7 @@ ssize_t ip_append_page(struct sock *sk,
380 while (size > 0) {
381 int i;
383 - if (skb_shinfo(skb)->gso_size)
384 + if (skb_is_gso(skb))
385 len = size;
386 else {
388 diff -urp a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
389 --- a/net/ipv4/tcp_ipv4.c 2006-07-25 14:39:15.985080788 +0100
390 +++ b/net/ipv4/tcp_ipv4.c 2006-07-25 14:36:00.339556071 +0100
391 @@ -495,6 +495,24 @@ void tcp_v4_send_check(struct sock *sk,
392 }
393 }
395 +int tcp_v4_gso_send_check(struct sk_buff *skb)
396 +{
397 + struct iphdr *iph;
398 + struct tcphdr *th;
399 +
400 + if (!pskb_may_pull(skb, sizeof(*th)))
401 + return -EINVAL;
402 +
403 + iph = skb->nh.iph;
404 + th = skb->h.th;
405 +
406 + th->check = 0;
407 + th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0);
408 + skb->csum = offsetof(struct tcphdr, check);
409 + skb->ip_summed = CHECKSUM_HW;
410 + return 0;
411 +}
412 +
413 /*
414 * This routine will send an RST to the other tcp.
415 *
416 diff -urp a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
417 --- a/net/ipv4/xfrm4_output.c 2006-07-25 14:41:00.958501574 +0100
418 +++ b/net/ipv4/xfrm4_output.c 2006-07-25 14:36:00.341555862 +0100
419 @@ -189,7 +189,7 @@ static int xfrm4_output_finish(struct sk
420 }
421 #endif
423 - if (!skb_shinfo(skb)->gso_size)
424 + if (!skb_is_gso(skb))
425 return xfrm4_output_finish2(skb);
427 skb->protocol = htons(ETH_P_IP);
428 diff -urp a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
429 --- a/net/ipv6/ip6_output.c 2006-07-25 14:41:00.959501461 +0100
430 +++ b/net/ipv6/ip6_output.c 2006-07-25 14:36:00.341555862 +0100
431 @@ -147,7 +147,7 @@ static int ip6_output2(struct sk_buff *s
433 int ip6_output(struct sk_buff *skb)
434 {
435 - if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size) ||
436 + if ((skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb)) ||
437 dst_allfrag(skb->dst))
438 return ip6_fragment(skb, ip6_output2);
439 else
440 diff -urp a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
441 --- a/net/ipv6/xfrm6_output.c 2006-07-25 14:41:00.960501349 +0100
442 +++ b/net/ipv6/xfrm6_output.c 2006-07-25 14:36:00.342555758 +0100
443 @@ -179,7 +179,7 @@ static int xfrm6_output_finish(struct sk
444 {
445 struct sk_buff *segs;
447 - if (!skb_shinfo(skb)->gso_size)
448 + if (!skb_is_gso(skb))
449 return xfrm6_output_finish2(skb);
451 skb->protocol = htons(ETH_P_IP);