Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / include / xen / net-util.h
1 #ifndef __XEN_NETUTIL_H__
2 #define __XEN_NETUTIL_H__
3
4 #include <linux/kernel.h>
5 #include <linux/skbuff.h>
6 #include <linux/tcp.h>
7 #include <linux/udp.h>
8 #include <net/ip.h>
9
10 static inline int skb_checksum_setup(struct sk_buff *skb,
11                                      unsigned long *fixup_counter)
12 {
13         struct iphdr *iph = (void *)skb->data;
14         unsigned char *th;
15         __be16 *csum = NULL;
16         int err = -EPROTO;
17
18         if (skb->ip_summed != CHECKSUM_PARTIAL) {
19                 /* A non-CHECKSUM_PARTIAL SKB does not require setup. */
20                 if (!skb_is_gso(skb))
21                         return 0;
22
23                 /*
24                  * A GSO SKB must be CHECKSUM_PARTIAL. However some buggy
25                  * peers can fail to set NETRXF_csum_blank when sending a GSO
26                  * frame. In this case force the SKB to CHECKSUM_PARTIAL and
27                  * recalculate the partial checksum.
28                  */
29                 ++*fixup_counter;
30                 --csum;
31         }
32
33         if (skb->protocol != htons(ETH_P_IP))
34                 goto out;
35
36         th = skb->data + 4 * iph->ihl;
37         if (th >= skb_tail_pointer(skb))
38                 goto out;
39
40         skb->csum_start = th - skb->head;
41         switch (iph->protocol) {
42         case IPPROTO_TCP:
43                 skb->csum_offset = offsetof(struct tcphdr, check);
44                 if (csum)
45                         csum = &((struct tcphdr *)th)->check;
46                 break;
47         case IPPROTO_UDP:
48                 skb->csum_offset = offsetof(struct udphdr, check);
49                 if (csum)
50                         csum = &((struct udphdr *)th)->check;
51                 break;
52         default:
53                 if (net_ratelimit())
54                         pr_err("Attempting to checksum a non-"
55                                "TCP/UDP packet, dropping a protocol"
56                                " %d packet\n", iph->protocol);
57                 goto out;
58         }
59
60         if ((th + skb->csum_offset + sizeof(*csum)) > skb_tail_pointer(skb))
61                 goto out;
62
63         if (csum) {
64                 *csum = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
65                                            skb->len - iph->ihl*4,
66                                            IPPROTO_TCP, 0);
67                 skb->ip_summed = CHECKSUM_PARTIAL;
68         }
69
70         err = 0;
71 out:
72         return err;
73 }
74
75 #endif /* __XEN_NETUTIL_H__ */