2 * Copyright (c) 2009, 2010, 2011 Nicira, Inc.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <netinet/in.h>
26 #include "unaligned.h"
34 size_t size; /* Test requires a multiple of 4. */
38 #define TEST_CASE(DATA, CSUM) { DATA, (sizeof DATA) - 1, CSUM }
40 static const struct test_case test_cases[] = {
41 /* RFC 1071 section 3. */
42 TEST_CASE("\x00\x01\xf2\x03"
44 0xffff - 0xddf2 /* ~0xddf2 */),
46 /* http://www.sbprojects.com/projects/tcpip/theory/theory14.htm */
47 TEST_CASE("\x45\x00\x00\x28"
54 /* http://mathforum.org/library/drmath/view/54379.html */
55 TEST_CASE("\x86\x5e\xac\x60"
68 /* This code is useful for generating new test cases for RFC 1624 section 4. */
70 generate_rfc1624_test_case(void)
74 for (i = 0; i < 10000000; i++) {
78 for (j = 0; j < 8; j++) {
79 data[j] = random_uint32();
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);
93 /* Make sure we get the calculation in RFC 1624 section 4 correct. */
97 /* "...an IP packet header in which a 16-bit field m = 0x5555..." */
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
105 /* "...the one's complement sum of all other header octets is 0xCD7A." */
106 assert(ntohs(csum(data, sizeof data - 2)) == 0xffff - 0xcd7a);
108 /* "...the header checksum would be:
110 HC = ~(0xCD7A + 0x5555)
114 assert(ntohs(csum(data, sizeof data)) == 0xdd2f);
116 /* "a 16-bit field m = 0x5555 changes to m' = 0x3285..." */
120 /* "The new checksum via recomputation is:
122 HC' = ~(0xCD7A + 0x3285)
126 assert(ntohs(csum(data, sizeof data)) == 0x0000);
128 /* "Applying [Eqn. 3] to the example above, we get the correct result:
130 HC' = ~(C + (-m) + m')
131 = ~(0x22D0 + ~0x5555 + 0x3285)
134 assert(recalc_csum16(htons(0xdd2f), htons(0x5555), htons(0x3285))
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/ */
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
157 assert(ntohl(crc32c(data, 48)) == 0x563a96d9L);
159 /* 32 bytes of all zeroes */
160 for (i = 0; i < 32; i++) data[i] = 0x00;
161 assert(ntohl(crc32c(data, 32)) == 0xaa36918aL);
163 /* 32 bytes of all ones */
164 for (i = 0; i < 32; i++) data[i] = 0xff;
165 assert(ntohl(crc32c(data, 32)) == 0x43aba862L);
167 /* 32 bytes of incrementing 00..1f */
168 for (i = 0; i < 32; i++) data[i] = i;
169 assert(ntohl(crc32c(data, 32)) == 0x4e79dd46L);
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);
181 const struct test_case *tc;
184 for (tc = test_cases; tc < &test_cases[ARRAY_SIZE(test_cases)]; tc++) {
185 const void *data = tc->data;
186 const ovs_be16 *data16 = (OVS_FORCE const ovs_be16 *) data;
187 const ovs_be32 *data32 = (OVS_FORCE const ovs_be32 *) data;
191 assert(ntohs(csum(tc->data, tc->size)) == tc->csum);
194 /* Test csum_add16(). */
196 for (i = 0; i < tc->size / 2; i++) {
197 partial = csum_add16(partial, get_unaligned_be16(&data16[i]));
199 assert(ntohs(csum_finish(partial)) == tc->csum);
202 /* Test csum_add32(). */
204 for (i = 0; i < tc->size / 4; i++) {
205 partial = csum_add32(partial, get_unaligned_be32(&data32[i]));
207 assert(ntohs(csum_finish(partial)) == tc->csum);
210 /* Test alternating csum_add16() and csum_add32(). */
212 for (i = 0; i < tc->size / 4; i++) {
214 partial = csum_add32(partial, get_unaligned_be32(&data32[i]));
216 ovs_be16 u0 = get_unaligned_be16(&data16[i * 2]);
217 ovs_be16 u1 = get_unaligned_be16(&data16[i * 2 + 1]);
218 partial = csum_add16(partial, u0);
219 partial = csum_add16(partial, u1);
222 assert(ntohs(csum_finish(partial)) == tc->csum);
225 /* Test csum_continue(). */
227 for (i = 0; i < tc->size / 4; i++) {
229 partial = csum_continue(partial, &data32[i], 4);
231 partial = csum_continue(partial, &data16[i * 2], 2);
232 partial = csum_continue(partial, &data16[i * 2 + 1], 2);
235 assert(ntohs(csum_finish(partial)) == tc->csum);
242 /* Test recalc_csum16(). */
243 for (i = 0; i < 32; i++) {
244 ovs_be16 old_u16, new_u16;
249 for (j = 0; j < ARRAY_SIZE(data); j++) {
250 data[j] = (OVS_FORCE ovs_be16) random_uint32();
252 old_csum = csum(data, sizeof data);
253 index = random_range(ARRAY_SIZE(data));
254 old_u16 = data[index];
255 new_u16 = data[index] = (OVS_FORCE ovs_be16) random_uint32();
256 assert(csum(data, sizeof data)
257 == recalc_csum16(old_csum, old_u16, new_u16));
262 /* Test recalc_csum32(). */
263 for (i = 0; i < 32; i++) {
264 ovs_be32 old_u32, new_u32;
269 for (j = 0; j < ARRAY_SIZE(data); j++) {
270 data[j] = (OVS_FORCE ovs_be32) random_uint32();
272 old_csum = csum(data, sizeof data);
273 index = random_range(ARRAY_SIZE(data));
274 old_u32 = data[index];
275 new_u32 = data[index] = (OVS_FORCE ovs_be32) random_uint32();
276 assert(csum(data, sizeof data)
277 == recalc_csum32(old_csum, old_u32, new_u32));