]> git.proxmox.com Git - mirror_ovs.git/blame - tests/test-csum.c
odp-execute: Add missing break statement for CLONE action.
[mirror_ovs.git] / tests / test-csum.c
CommitLineData
21effc03 1/*
eadd1644 2 * Copyright (c) 2009, 2010, 2011, 2014 Nicira, Inc.
21effc03 3 *
a14bc59f
BP
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
21effc03 7 *
a14bc59f
BP
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21effc03
BP
15 */
16
17#include <config.h>
3f636c7e 18#undef NDEBUG
21effc03 19#include "csum.h"
3f636c7e 20#include <assert.h>
21effc03
BP
21#include <inttypes.h>
22#include <netinet/in.h>
0292a0c9 23#include <netinet/ip.h>
21effc03
BP
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
3f636c7e
JR
27#include "crc32c.h"
28#include "ovstest.h"
0292a0c9 29#include "packets.h"
21effc03 30#include "random.h"
80642190 31#include "unaligned.h"
21effc03 32#include "util.h"
21effc03
BP
33
34struct test_case {
35 char *data;
d932cf70 36 size_t size; /* Test requires a multiple of 4. */
21effc03
BP
37 uint16_t csum;
38};
39
40#define TEST_CASE(DATA, CSUM) { DATA, (sizeof DATA) - 1, CSUM }
41
42static const struct test_case test_cases[] = {
43 /* RFC 1071 section 3. */
d932cf70
BP
44 TEST_CASE("\x00\x01\xf2\x03"
45 "\xf4\xf5\xf6\xf7",
d84d4b88 46 0xffff - 0xddf2 /* ~0xddf2 */),
21effc03
BP
47
48 /* http://www.sbprojects.com/projects/tcpip/theory/theory14.htm */
d932cf70
BP
49 TEST_CASE("\x45\x00\x00\x28"
50 "\x1F\xFD\x40\x00"
51 "\x80\x06\x00\x00"
52 "\xC0\xA8\x3B\x0A"
53 "\xC0\xA8\x3B\x32",
21effc03
BP
54 0xe345),
55
56 /* http://mathforum.org/library/drmath/view/54379.html */
d932cf70
BP
57 TEST_CASE("\x86\x5e\xac\x60"
58 "\x71\x2a\x81\xb5",
59 0xda60),
21effc03
BP
60};
61
62static void
63mark(char c)
64{
65 putchar(c);
66 fflush(stdout);
67}
68
69#if 0
70/* This code is useful for generating new test cases for RFC 1624 section 4. */
71static void
72generate_rfc1624_test_case(void)
73{
74 int i;
75
76 for (i = 0; i < 10000000; i++) {
77 uint32_t data[8];
78 int j;
79
80 for (j = 0; j < 8; j++) {
81 data[j] = random_uint32();
82 }
83 data[7] &= 0x0000ffff;
84 data[7] |= 0x55550000;
85 if (ntohs(~csum(data, sizeof data - 2)) == 0xcd7a) {
86 ovs_hex_dump(stdout, data, sizeof data, 0, false);
87 exit(0);
88 }
89 }
90}
91#endif
92
93
94
95/* Make sure we get the calculation in RFC 1624 section 4 correct. */
96static void
97test_rfc1624(void)
98{
99 /* "...an IP packet header in which a 16-bit field m = 0x5555..." */
8d32c1d3
EJ
100 uint8_t data[32] = {
101 0xfe, 0x8f, 0xc1, 0x14, 0x4b, 0x6f, 0x70, 0x2a,
102 0x80, 0x29, 0x78, 0xc0, 0x58, 0x81, 0x77, 0xaa,
103 0x66, 0x64, 0xfc, 0x96, 0x63, 0x97, 0x64, 0xee,
104 0x12, 0x53, 0x1d, 0xa9, 0x2d, 0xa9, 0x55, 0x55
105 };
21effc03
BP
106
107 /* "...the one's complement sum of all other header octets is 0xCD7A." */
d84d4b88 108 assert(ntohs(csum(data, sizeof data - 2)) == 0xffff - 0xcd7a);
21effc03
BP
109
110 /* "...the header checksum would be:
111
112 HC = ~(0xCD7A + 0x5555)
113 = ~0x22D0
114 = 0xDD2F"
115 */
116 assert(ntohs(csum(data, sizeof data)) == 0xdd2f);
117
118 /* "a 16-bit field m = 0x5555 changes to m' = 0x3285..." */
119 data[30] = 0x32;
120 data[31] = 0x85;
121
122 /* "The new checksum via recomputation is:
123
124 HC' = ~(0xCD7A + 0x3285)
125 = ~0xFFFF
126 = 0x0000"
127 */
128 assert(ntohs(csum(data, sizeof data)) == 0x0000);
129
130 /* "Applying [Eqn. 3] to the example above, we get the correct result:
131
132 HC' = ~(C + (-m) + m')
133 = ~(0x22D0 + ~0x5555 + 0x3285)
134 = ~0xFFFF
135 = 0x0000" */
d84d4b88
BP
136 assert(recalc_csum16(htons(0xdd2f), htons(0x5555), htons(0x3285))
137 == htons(0x0000));
21effc03
BP
138
139 mark('#');
140}
141
97025b23
JS
142/* CRC32C checksum tests, based on Intel IPPs, Chapter 13,
143 * ippsCRC32C_8u() example, found at the following location:
144 * http://software.intel.com/sites/products/documentation/hpc/ipp/ipps/ */
145static void
146test_crc32c(void)
147{
148 int i;
149 uint8_t data[48] = {
150 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
153 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18,
154 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
156 };
157
158 /* iSCSI Read PDU */
159 assert(ntohl(crc32c(data, 48)) == 0x563a96d9L);
160
161 /* 32 bytes of all zeroes */
162 for (i = 0; i < 32; i++) data[i] = 0x00;
163 assert(ntohl(crc32c(data, 32)) == 0xaa36918aL);
164
165 /* 32 bytes of all ones */
166 for (i = 0; i < 32; i++) data[i] = 0xff;
167 assert(ntohl(crc32c(data, 32)) == 0x43aba862L);
168
169 /* 32 bytes of incrementing 00..1f */
170 for (i = 0; i < 32; i++) data[i] = i;
171 assert(ntohl(crc32c(data, 32)) == 0x4e79dd46L);
172
173 /* 32 bytes of decrementing 1f..00 */
174 for (i = 0; i < 32; i++) data[i] = 31 - i;
175 assert(ntohl(crc32c(data, 32)) == 0x5cdb3f11L);
176
177 mark('#');
178}
179
0292a0c9
JG
180/* Check the IP pseudoheader calculation. */
181static void
182test_pseudo(void)
183{
2f86335b 184 ovs_be16 csum;
0292a0c9
JG
185 /* Try an IP header similar to one that the tunnel code
186 * might generate. */
187 struct ip_header ip = {
188 .ip_ihl_ver = IP_IHL_VER(5, 4),
189 .ip_tos = 0,
190 .ip_tot_len = htons(134),
191 .ip_id = 0,
192 .ip_frag_off = htons(IP_DF),
193 .ip_ttl = 64,
194 .ip_proto = IPPROTO_UDP,
195 .ip_csum = htons(0x1265),
196 .ip_src = { .hi = htons(0x1400), .lo = htons(0x0002) },
197 .ip_dst = { .hi = htons(0x1400), .lo = htons(0x0001) }
198 };
199
2f86335b
FL
200 csum = csum_finish(packet_csum_pseudoheader(&ip));
201 assert(csum == htons(0xd779));
0292a0c9
JG
202
203 /* And also test something totally different to check for
204 * corner cases. */
205 memset(&ip, 0xff, sizeof ip);
2f86335b
FL
206 csum = csum_finish(packet_csum_pseudoheader(&ip));
207 assert(csum == htons(0xff3c));
0292a0c9
JG
208
209 mark('#');
210}
eadd1644
AZ
211
212static void
213test_csum_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
21effc03
BP
214{
215 const struct test_case *tc;
216 int i;
217
218 for (tc = test_cases; tc < &test_cases[ARRAY_SIZE(test_cases)]; tc++) {
e7b3e606
BP
219 const void *data = tc->data;
220 const ovs_be16 *data16 = (OVS_FORCE const ovs_be16 *) data;
221 const ovs_be32 *data32 = (OVS_FORCE const ovs_be32 *) data;
21effc03 222 uint32_t partial;
21effc03
BP
223
224 /* Test csum(). */
225 assert(ntohs(csum(tc->data, tc->size)) == tc->csum);
226 mark('.');
227
228 /* Test csum_add16(). */
229 partial = 0;
230 for (i = 0; i < tc->size / 2; i++) {
d84d4b88 231 partial = csum_add16(partial, get_unaligned_be16(&data16[i]));
21effc03
BP
232 }
233 assert(ntohs(csum_finish(partial)) == tc->csum);
234 mark('.');
235
236 /* Test csum_add32(). */
237 partial = 0;
238 for (i = 0; i < tc->size / 4; i++) {
d84d4b88 239 partial = csum_add32(partial, get_unaligned_be32(&data32[i]));
21effc03
BP
240 }
241 assert(ntohs(csum_finish(partial)) == tc->csum);
242 mark('.');
243
244 /* Test alternating csum_add16() and csum_add32(). */
245 partial = 0;
246 for (i = 0; i < tc->size / 4; i++) {
247 if (i % 2) {
d84d4b88 248 partial = csum_add32(partial, get_unaligned_be32(&data32[i]));
21effc03 249 } else {
d84d4b88
BP
250 ovs_be16 u0 = get_unaligned_be16(&data16[i * 2]);
251 ovs_be16 u1 = get_unaligned_be16(&data16[i * 2 + 1]);
80642190
BP
252 partial = csum_add16(partial, u0);
253 partial = csum_add16(partial, u1);
21effc03
BP
254 }
255 }
256 assert(ntohs(csum_finish(partial)) == tc->csum);
257 mark('.');
258
259 /* Test csum_continue(). */
260 partial = 0;
261 for (i = 0; i < tc->size / 4; i++) {
262 if (i) {
263 partial = csum_continue(partial, &data32[i], 4);
264 } else {
265 partial = csum_continue(partial, &data16[i * 2], 2);
266 partial = csum_continue(partial, &data16[i * 2 + 1], 2);
267 }
268 }
269 assert(ntohs(csum_finish(partial)) == tc->csum);
270 mark('#');
271 }
272
273 test_rfc1624();
97025b23 274 test_crc32c();
0292a0c9 275 test_pseudo();
21effc03
BP
276
277 /* Test recalc_csum16(). */
278 for (i = 0; i < 32; i++) {
d84d4b88
BP
279 ovs_be16 old_u16, new_u16;
280 ovs_be16 old_csum;
281 ovs_be16 data[16];
21effc03
BP
282 int j, index;
283
284 for (j = 0; j < ARRAY_SIZE(data); j++) {
d84d4b88 285 data[j] = (OVS_FORCE ovs_be16) random_uint32();
21effc03
BP
286 }
287 old_csum = csum(data, sizeof data);
288 index = random_range(ARRAY_SIZE(data));
289 old_u16 = data[index];
d84d4b88 290 new_u16 = data[index] = (OVS_FORCE ovs_be16) random_uint32();
21effc03
BP
291 assert(csum(data, sizeof data)
292 == recalc_csum16(old_csum, old_u16, new_u16));
293 mark('.');
294 }
295 mark('#');
296
297 /* Test recalc_csum32(). */
298 for (i = 0; i < 32; i++) {
d84d4b88
BP
299 ovs_be32 old_u32, new_u32;
300 ovs_be16 old_csum;
301 ovs_be32 data[16];
21effc03
BP
302 int j, index;
303
304 for (j = 0; j < ARRAY_SIZE(data); j++) {
d84d4b88 305 data[j] = (OVS_FORCE ovs_be32) random_uint32();
21effc03
BP
306 }
307 old_csum = csum(data, sizeof data);
308 index = random_range(ARRAY_SIZE(data));
309 old_u32 = data[index];
d84d4b88 310 new_u32 = data[index] = (OVS_FORCE ovs_be32) random_uint32();
21effc03
BP
311 assert(csum(data, sizeof data)
312 == recalc_csum32(old_csum, old_u32, new_u32));
313 mark('.');
314 }
315 mark('#');
316
317 putchar('\n');
21effc03 318}
eadd1644
AZ
319
320OVSTEST_REGISTER("test-csum", test_csum_main);