datapath: Avoid duplicate test in tnl_free_linked_skbs().
[openvswitch] / datapath / checksum.c
1 /*
2  * Copyright (c) 2010 Nicira Networks.
3  * Distributed under the terms of the GNU GPL version 2.
4  *
5  * Significant portions of this file may be copied from parts of the Linux
6  * kernel, by Linus Torvalds and others.
7  */
8
9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10
11 #include <linux/in.h>
12 #include <linux/ip.h>
13 #include <linux/tcp.h>
14 #include <linux/udp.h>
15
16 #include "checksum.h"
17 #include "datapath.h"
18
19  /* Types of checksums that we can receive (these all refer to L4 checksums):
20  * 1. CHECKSUM_NONE: Device that did not compute checksum, contains full
21  *      (though not verified) checksum in packet but not in skb->csum.  Packets
22  *      from the bridge local port will also have this type.
23  * 2. CHECKSUM_COMPLETE (CHECKSUM_HW): Good device that computes checksums,
24  *      also the GRE module.  This is the same as CHECKSUM_NONE, except it has
25  *      a valid skb->csum.  Importantly, both contain a full checksum (not
26  *      verified) in the packet itself.  The only difference is that if the
27  *      packet gets to L4 processing on this machine (not in DomU) we won't
28  *      have to recompute the checksum to verify.  Most hardware devices do not
29  *      produce packets with this type, even if they support receive checksum
30  *      offloading (they produce type #5).
31  * 3. CHECKSUM_PARTIAL (CHECKSUM_HW): Packet without full checksum and needs to
32  *      be computed if it is sent off box.  Unfortunately on earlier kernels,
33  *      this case is impossible to distinguish from #2, despite having opposite
34  *      meanings.  Xen adds an extra field on earlier kernels (see #4) in order
35  *      to distinguish the different states.
36  * 4. CHECKSUM_UNNECESSARY (with proto_csum_blank true): This packet was
37  *      generated locally by a Xen DomU and has a partial checksum.  If it is
38  *      handled on this machine (Dom0 or DomU), then the checksum will not be
39  *      computed.  If it goes off box, the checksum in the packet needs to be
40  *      completed.  Calling skb_checksum_setup converts this to CHECKSUM_HW
41  *      (CHECKSUM_PARTIAL) so that the checksum can be completed.  In later
42  *      kernels, this combination is replaced with CHECKSUM_PARTIAL.
43  * 5. CHECKSUM_UNNECESSARY (with proto_csum_blank false): Packet with a correct
44  *      full checksum or using a protocol without a checksum.  skb->csum is
45  *      undefined.  This is common from devices with receive checksum
46  *      offloading.  This is somewhat similar to CHECKSUM_NONE, except that
47  *      nobody will try to verify the checksum with CHECKSUM_UNNECESSARY.
48  *
49  * Note that on earlier kernels, CHECKSUM_COMPLETE and CHECKSUM_PARTIAL are
50  * both defined as CHECKSUM_HW.  Normally the meaning of CHECKSUM_HW is clear
51  * based on whether it is on the transmit or receive path.  After the datapath
52  * it will be intepreted as CHECKSUM_PARTIAL.  If the packet already has a
53  * checksum, we will panic.  Since we can receive packets with checksums, we
54  * assume that all CHECKSUM_HW packets have checksums and map them to
55  * CHECKSUM_NONE, which has a similar meaning (the it is only different if the
56  * packet is processed by the local IP stack, in which case it will need to
57  * be reverified).  If we receive a packet with CHECKSUM_HW that really means
58  * CHECKSUM_PARTIAL, it will be sent with the wrong checksum.  However, there
59  * shouldn't be any devices that do this with bridging.
60  */
61 #ifdef NEED_CSUM_NORMALIZE
62 void compute_ip_summed(struct sk_buff *skb, bool xmit)
63 {
64         /* For our convenience these defines change repeatedly between kernel
65          * versions, so we can't just copy them over...
66          */
67         switch (skb->ip_summed) {
68         case CHECKSUM_NONE:
69                 OVS_CB(skb)->ip_summed = OVS_CSUM_NONE;
70                 break;
71         case CHECKSUM_UNNECESSARY:
72                 OVS_CB(skb)->ip_summed = OVS_CSUM_UNNECESSARY;
73                 break;
74 #ifdef CHECKSUM_HW
75         /* In theory this could be either CHECKSUM_PARTIAL or CHECKSUM_COMPLETE.
76          * However, on the receive side we should only get CHECKSUM_PARTIAL
77          * packets from Xen, which uses some special fields to represent this
78          * (see below).  Since we can only make one type work, pick the one
79          * that actually happens in practice.
80          *
81          * On the transmit side (basically after skb_checksum_setup()
82          * has been run or on internal dev transmit), packets with
83          * CHECKSUM_COMPLETE aren't generated, so assume CHECKSUM_PARTIAL.
84          */
85         case CHECKSUM_HW:
86                 if (!xmit)
87                         OVS_CB(skb)->ip_summed = OVS_CSUM_COMPLETE;
88                 else
89                         OVS_CB(skb)->ip_summed = OVS_CSUM_PARTIAL;
90
91                 break;
92 #else
93         case CHECKSUM_COMPLETE:
94                 OVS_CB(skb)->ip_summed = OVS_CSUM_COMPLETE;
95                 break;
96         case CHECKSUM_PARTIAL:
97                 OVS_CB(skb)->ip_summed = OVS_CSUM_PARTIAL;
98                 break;
99 #endif
100         }
101
102 #if defined(CONFIG_XEN) && defined(HAVE_PROTO_DATA_VALID)
103         /* Xen has a special way of representing CHECKSUM_PARTIAL on older
104          * kernels. It should not be set on the transmit path though.
105          */
106         if (skb->proto_csum_blank)
107                 OVS_CB(skb)->ip_summed = OVS_CSUM_PARTIAL;
108
109         WARN_ON_ONCE(skb->proto_csum_blank && xmit);
110 #endif
111 }
112
113 u8 get_ip_summed(struct sk_buff *skb)
114 {
115         return OVS_CB(skb)->ip_summed;
116 }
117 #endif /* NEED_CSUM_NORMALIZE */
118
119 #if defined(CONFIG_XEN) && defined(HAVE_PROTO_DATA_VALID)
120 /* This code is based on skb_checksum_setup() from Xen's net/dev/core.c.  We
121  * can't call this function directly because it isn't exported in all
122  * versions. */
123 int vswitch_skb_checksum_setup(struct sk_buff *skb)
124 {
125         struct iphdr *iph;
126         unsigned char *th;
127         int err = -EPROTO;
128         __u16 csum_start, csum_offset;
129
130         if (!skb->proto_csum_blank)
131                 return 0;
132
133         if (skb->protocol != htons(ETH_P_IP))
134                 goto out;
135
136         if (!pskb_may_pull(skb, skb_network_header(skb) + sizeof(struct iphdr) - skb->data))
137                 goto out;
138
139         iph = ip_hdr(skb);
140         th = skb_network_header(skb) + 4 * iph->ihl;
141
142         csum_start = th - skb->head;
143         switch (iph->protocol) {
144         case IPPROTO_TCP:
145                 csum_offset = offsetof(struct tcphdr, check);
146                 break;
147         case IPPROTO_UDP:
148                 csum_offset = offsetof(struct udphdr, check);
149                 break;
150         default:
151                 if (net_ratelimit())
152                         pr_err("Attempting to checksum a non-TCP/UDP packet, "
153                                "dropping a protocol %d packet",
154                                iph->protocol);
155                 goto out;
156         }
157
158         if (!pskb_may_pull(skb, th + csum_offset + 2 - skb->data))
159                 goto out;
160
161         skb->ip_summed = CHECKSUM_PARTIAL;
162         skb->proto_csum_blank = 0;
163         set_skb_csum_pointers(skb, csum_start, csum_offset);
164
165         err = 0;
166
167 out:
168         return err;
169 }
170 #endif /* CONFIG_XEN && HAVE_PROTO_DATA_VALID */