]> git.proxmox.com Git - ovs.git/blob - tests/test-csum.c
lib: Move vconn.h to <openvswitch/vconn.h>
[ovs.git] / tests / test-csum.c
1 /*
2 * Copyright (c) 2009, 2010, 2011, 2014 Nicira, Inc.
3 *
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:
7 *
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.
15 */
16
17 #include <config.h>
18 #undef NDEBUG
19 #include "csum.h"
20 #include <assert.h>
21 #include <inttypes.h>
22 #include <netinet/in.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include "crc32c.h"
27 #include "ovstest.h"
28 #include "random.h"
29 #include "unaligned.h"
30 #include "util.h"
31
32 struct test_case {
33 char *data;
34 size_t size; /* Test requires a multiple of 4. */
35 uint16_t csum;
36 };
37
38 #define TEST_CASE(DATA, CSUM) { DATA, (sizeof DATA) - 1, CSUM }
39
40 static const struct test_case test_cases[] = {
41 /* RFC 1071 section 3. */
42 TEST_CASE("\x00\x01\xf2\x03"
43 "\xf4\xf5\xf6\xf7",
44 0xffff - 0xddf2 /* ~0xddf2 */),
45
46 /* http://www.sbprojects.com/projects/tcpip/theory/theory14.htm */
47 TEST_CASE("\x45\x00\x00\x28"
48 "\x1F\xFD\x40\x00"
49 "\x80\x06\x00\x00"
50 "\xC0\xA8\x3B\x0A"
51 "\xC0\xA8\x3B\x32",
52 0xe345),
53
54 /* http://mathforum.org/library/drmath/view/54379.html */
55 TEST_CASE("\x86\x5e\xac\x60"
56 "\x71\x2a\x81\xb5",
57 0xda60),
58 };
59
60 static void
61 mark(char c)
62 {
63 putchar(c);
64 fflush(stdout);
65 }
66
67 #if 0
68 /* This code is useful for generating new test cases for RFC 1624 section 4. */
69 static void
70 generate_rfc1624_test_case(void)
71 {
72 int i;
73
74 for (i = 0; i < 10000000; i++) {
75 uint32_t data[8];
76 int j;
77
78 for (j = 0; j < 8; j++) {
79 data[j] = random_uint32();
80 }
81 data[7] &= 0x0000ffff;
82 data[7] |= 0x55550000;
83 if (ntohs(~csum(data, sizeof data - 2)) == 0xcd7a) {
84 ovs_hex_dump(stdout, data, sizeof data, 0, false);
85 exit(0);
86 }
87 }
88 }
89 #endif
90
91
92
93 /* Make sure we get the calculation in RFC 1624 section 4 correct. */
94 static void
95 test_rfc1624(void)
96 {
97 /* "...an IP packet header in which a 16-bit field m = 0x5555..." */
98 uint8_t data[32] = {
99 0xfe, 0x8f, 0xc1, 0x14, 0x4b, 0x6f, 0x70, 0x2a,
100 0x80, 0x29, 0x78, 0xc0, 0x58, 0x81, 0x77, 0xaa,
101 0x66, 0x64, 0xfc, 0x96, 0x63, 0x97, 0x64, 0xee,
102 0x12, 0x53, 0x1d, 0xa9, 0x2d, 0xa9, 0x55, 0x55
103 };
104
105 /* "...the one's complement sum of all other header octets is 0xCD7A." */
106 assert(ntohs(csum(data, sizeof data - 2)) == 0xffff - 0xcd7a);
107
108 /* "...the header checksum would be:
109
110 HC = ~(0xCD7A + 0x5555)
111 = ~0x22D0
112 = 0xDD2F"
113 */
114 assert(ntohs(csum(data, sizeof data)) == 0xdd2f);
115
116 /* "a 16-bit field m = 0x5555 changes to m' = 0x3285..." */
117 data[30] = 0x32;
118 data[31] = 0x85;
119
120 /* "The new checksum via recomputation is:
121
122 HC' = ~(0xCD7A + 0x3285)
123 = ~0xFFFF
124 = 0x0000"
125 */
126 assert(ntohs(csum(data, sizeof data)) == 0x0000);
127
128 /* "Applying [Eqn. 3] to the example above, we get the correct result:
129
130 HC' = ~(C + (-m) + m')
131 = ~(0x22D0 + ~0x5555 + 0x3285)
132 = ~0xFFFF
133 = 0x0000" */
134 assert(recalc_csum16(htons(0xdd2f), htons(0x5555), htons(0x3285))
135 == htons(0x0000));
136
137 mark('#');
138 }
139
140 /* CRC32C checksum tests, based on Intel IPPs, Chapter 13,
141 * ippsCRC32C_8u() example, found at the following location:
142 * http://software.intel.com/sites/products/documentation/hpc/ipp/ipps/ */
143 static void
144 test_crc32c(void)
145 {
146 int i;
147 uint8_t data[48] = {
148 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
151 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18,
152 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
154 };
155
156 /* iSCSI Read PDU */
157 assert(ntohl(crc32c(data, 48)) == 0x563a96d9L);
158
159 /* 32 bytes of all zeroes */
160 for (i = 0; i < 32; i++) data[i] = 0x00;
161 assert(ntohl(crc32c(data, 32)) == 0xaa36918aL);
162
163 /* 32 bytes of all ones */
164 for (i = 0; i < 32; i++) data[i] = 0xff;
165 assert(ntohl(crc32c(data, 32)) == 0x43aba862L);
166
167 /* 32 bytes of incrementing 00..1f */
168 for (i = 0; i < 32; i++) data[i] = i;
169 assert(ntohl(crc32c(data, 32)) == 0x4e79dd46L);
170
171 /* 32 bytes of decrementing 1f..00 */
172 for (i = 0; i < 32; i++) data[i] = 31 - i;
173 assert(ntohl(crc32c(data, 32)) == 0x5cdb3f11L);
174
175 mark('#');
176 }
177
178
179 static void
180 test_csum_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
181 {
182 const struct test_case *tc;
183 int i;
184
185 for (tc = test_cases; tc < &test_cases[ARRAY_SIZE(test_cases)]; tc++) {
186 const void *data = tc->data;
187 const ovs_be16 *data16 = (OVS_FORCE const ovs_be16 *) data;
188 const ovs_be32 *data32 = (OVS_FORCE const ovs_be32 *) data;
189 uint32_t partial;
190
191 /* Test csum(). */
192 assert(ntohs(csum(tc->data, tc->size)) == tc->csum);
193 mark('.');
194
195 /* Test csum_add16(). */
196 partial = 0;
197 for (i = 0; i < tc->size / 2; i++) {
198 partial = csum_add16(partial, get_unaligned_be16(&data16[i]));
199 }
200 assert(ntohs(csum_finish(partial)) == tc->csum);
201 mark('.');
202
203 /* Test csum_add32(). */
204 partial = 0;
205 for (i = 0; i < tc->size / 4; i++) {
206 partial = csum_add32(partial, get_unaligned_be32(&data32[i]));
207 }
208 assert(ntohs(csum_finish(partial)) == tc->csum);
209 mark('.');
210
211 /* Test alternating csum_add16() and csum_add32(). */
212 partial = 0;
213 for (i = 0; i < tc->size / 4; i++) {
214 if (i % 2) {
215 partial = csum_add32(partial, get_unaligned_be32(&data32[i]));
216 } else {
217 ovs_be16 u0 = get_unaligned_be16(&data16[i * 2]);
218 ovs_be16 u1 = get_unaligned_be16(&data16[i * 2 + 1]);
219 partial = csum_add16(partial, u0);
220 partial = csum_add16(partial, u1);
221 }
222 }
223 assert(ntohs(csum_finish(partial)) == tc->csum);
224 mark('.');
225
226 /* Test csum_continue(). */
227 partial = 0;
228 for (i = 0; i < tc->size / 4; i++) {
229 if (i) {
230 partial = csum_continue(partial, &data32[i], 4);
231 } else {
232 partial = csum_continue(partial, &data16[i * 2], 2);
233 partial = csum_continue(partial, &data16[i * 2 + 1], 2);
234 }
235 }
236 assert(ntohs(csum_finish(partial)) == tc->csum);
237 mark('#');
238 }
239
240 test_rfc1624();
241 test_crc32c();
242
243 /* Test recalc_csum16(). */
244 for (i = 0; i < 32; i++) {
245 ovs_be16 old_u16, new_u16;
246 ovs_be16 old_csum;
247 ovs_be16 data[16];
248 int j, index;
249
250 for (j = 0; j < ARRAY_SIZE(data); j++) {
251 data[j] = (OVS_FORCE ovs_be16) random_uint32();
252 }
253 old_csum = csum(data, sizeof data);
254 index = random_range(ARRAY_SIZE(data));
255 old_u16 = data[index];
256 new_u16 = data[index] = (OVS_FORCE ovs_be16) random_uint32();
257 assert(csum(data, sizeof data)
258 == recalc_csum16(old_csum, old_u16, new_u16));
259 mark('.');
260 }
261 mark('#');
262
263 /* Test recalc_csum32(). */
264 for (i = 0; i < 32; i++) {
265 ovs_be32 old_u32, new_u32;
266 ovs_be16 old_csum;
267 ovs_be32 data[16];
268 int j, index;
269
270 for (j = 0; j < ARRAY_SIZE(data); j++) {
271 data[j] = (OVS_FORCE ovs_be32) random_uint32();
272 }
273 old_csum = csum(data, sizeof data);
274 index = random_range(ARRAY_SIZE(data));
275 old_u32 = data[index];
276 new_u32 = data[index] = (OVS_FORCE ovs_be32) random_uint32();
277 assert(csum(data, sizeof data)
278 == recalc_csum32(old_csum, old_u32, new_u32));
279 mark('.');
280 }
281 mark('#');
282
283 putchar('\n');
284 }
285
286 OVSTEST_REGISTER("test-csum", test_csum_main);