2 * Copyright (c) 2009, 2010, 2011, 2014 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"
35 size_t size; /* Test requires a multiple of 4. */
39 #define TEST_CASE(DATA, CSUM) { DATA, (sizeof DATA) - 1, CSUM }
41 static const struct test_case test_cases[] = {
42 /* RFC 1071 section 3. */
43 TEST_CASE("\x00\x01\xf2\x03"
45 0xffff - 0xddf2 /* ~0xddf2 */),
47 /* http://www.sbprojects.com/projects/tcpip/theory/theory14.htm */
48 TEST_CASE("\x45\x00\x00\x28"
55 /* http://mathforum.org/library/drmath/view/54379.html */
56 TEST_CASE("\x86\x5e\xac\x60"
69 /* This code is useful for generating new test cases for RFC 1624 section 4. */
71 generate_rfc1624_test_case(void)
75 for (i = 0; i < 10000000; i++) {
79 for (j = 0; j < 8; j++) {
80 data[j] = random_uint32();
82 data[7] &= 0x0000ffff;
83 data[7] |= 0x55550000;
84 if (ntohs(~csum(data, sizeof data - 2)) == 0xcd7a) {
85 ovs_hex_dump(stdout, data, sizeof data, 0, false);
94 /* Make sure we get the calculation in RFC 1624 section 4 correct. */
98 /* "...an IP packet header in which a 16-bit field m = 0x5555..." */
100 0xfe, 0x8f, 0xc1, 0x14, 0x4b, 0x6f, 0x70, 0x2a,
101 0x80, 0x29, 0x78, 0xc0, 0x58, 0x81, 0x77, 0xaa,
102 0x66, 0x64, 0xfc, 0x96, 0x63, 0x97, 0x64, 0xee,
103 0x12, 0x53, 0x1d, 0xa9, 0x2d, 0xa9, 0x55, 0x55
106 /* "...the one's complement sum of all other header octets is 0xCD7A." */
107 assert(ntohs(csum(data, sizeof data - 2)) == 0xffff - 0xcd7a);
109 /* "...the header checksum would be:
111 HC = ~(0xCD7A + 0x5555)
115 assert(ntohs(csum(data, sizeof data)) == 0xdd2f);
117 /* "a 16-bit field m = 0x5555 changes to m' = 0x3285..." */
121 /* "The new checksum via recomputation is:
123 HC' = ~(0xCD7A + 0x3285)
127 assert(ntohs(csum(data, sizeof data)) == 0x0000);
129 /* "Applying [Eqn. 3] to the example above, we get the correct result:
131 HC' = ~(C + (-m) + m')
132 = ~(0x22D0 + ~0x5555 + 0x3285)
135 assert(recalc_csum16(htons(0xdd2f), htons(0x5555), htons(0x3285))
141 /* CRC32C checksum tests, based on Intel IPPs, Chapter 13,
142 * ippsCRC32C_8u() example, found at the following location:
143 * http://software.intel.com/sites/products/documentation/hpc/ipp/ipps/ */
149 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
152 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18,
153 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
158 assert(ntohl(crc32c(data, 48)) == 0x563a96d9L);
160 /* 32 bytes of all zeroes */
161 for (i = 0; i < 32; i++) data[i] = 0x00;
162 assert(ntohl(crc32c(data, 32)) == 0xaa36918aL);
164 /* 32 bytes of all ones */
165 for (i = 0; i < 32; i++) data[i] = 0xff;
166 assert(ntohl(crc32c(data, 32)) == 0x43aba862L);
168 /* 32 bytes of incrementing 00..1f */
169 for (i = 0; i < 32; i++) data[i] = i;
170 assert(ntohl(crc32c(data, 32)) == 0x4e79dd46L);
172 /* 32 bytes of decrementing 1f..00 */
173 for (i = 0; i < 32; i++) data[i] = 31 - i;
174 assert(ntohl(crc32c(data, 32)) == 0x5cdb3f11L);
181 test_csum_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
183 const struct test_case *tc;
186 for (tc = test_cases; tc < &test_cases[ARRAY_SIZE(test_cases)]; tc++) {
187 const void *data = tc->data;
188 const ovs_be16 *data16 = (OVS_FORCE const ovs_be16 *) data;
189 const ovs_be32 *data32 = (OVS_FORCE const ovs_be32 *) data;
193 assert(ntohs(csum(tc->data, tc->size)) == tc->csum);
196 /* Test csum_add16(). */
198 for (i = 0; i < tc->size / 2; i++) {
199 partial = csum_add16(partial, get_unaligned_be16(&data16[i]));
201 assert(ntohs(csum_finish(partial)) == tc->csum);
204 /* Test csum_add32(). */
206 for (i = 0; i < tc->size / 4; i++) {
207 partial = csum_add32(partial, get_unaligned_be32(&data32[i]));
209 assert(ntohs(csum_finish(partial)) == tc->csum);
212 /* Test alternating csum_add16() and csum_add32(). */
214 for (i = 0; i < tc->size / 4; i++) {
216 partial = csum_add32(partial, get_unaligned_be32(&data32[i]));
218 ovs_be16 u0 = get_unaligned_be16(&data16[i * 2]);
219 ovs_be16 u1 = get_unaligned_be16(&data16[i * 2 + 1]);
220 partial = csum_add16(partial, u0);
221 partial = csum_add16(partial, u1);
224 assert(ntohs(csum_finish(partial)) == tc->csum);
227 /* Test csum_continue(). */
229 for (i = 0; i < tc->size / 4; i++) {
231 partial = csum_continue(partial, &data32[i], 4);
233 partial = csum_continue(partial, &data16[i * 2], 2);
234 partial = csum_continue(partial, &data16[i * 2 + 1], 2);
237 assert(ntohs(csum_finish(partial)) == tc->csum);
244 /* Test recalc_csum16(). */
245 for (i = 0; i < 32; i++) {
246 ovs_be16 old_u16, new_u16;
251 for (j = 0; j < ARRAY_SIZE(data); j++) {
252 data[j] = (OVS_FORCE ovs_be16) random_uint32();
254 old_csum = csum(data, sizeof data);
255 index = random_range(ARRAY_SIZE(data));
256 old_u16 = data[index];
257 new_u16 = data[index] = (OVS_FORCE ovs_be16) random_uint32();
258 assert(csum(data, sizeof data)
259 == recalc_csum16(old_csum, old_u16, new_u16));
264 /* Test recalc_csum32(). */
265 for (i = 0; i < 32; i++) {
266 ovs_be32 old_u32, new_u32;
271 for (j = 0; j < ARRAY_SIZE(data); j++) {
272 data[j] = (OVS_FORCE ovs_be32) random_uint32();
274 old_csum = csum(data, sizeof data);
275 index = random_range(ARRAY_SIZE(data));
276 old_u32 = data[index];
277 new_u32 = data[index] = (OVS_FORCE ovs_be32) random_uint32();
278 assert(csum(data, sizeof data)
279 == recalc_csum32(old_csum, old_u32, new_u32));
287 OVSTEST_REGISTER("test-csum", test_csum_main);