]>
git.proxmox.com Git - mirror_ovs.git/blob - tests/test-csum.c
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.
22 #include <sys/types.h>
23 #include <netinet/in.h>
24 #include <netinet/ip.h>
32 #include "unaligned.h"
37 size_t size
; /* Test requires a multiple of 4. */
41 #define TEST_CASE(DATA, CSUM) { DATA, (sizeof DATA) - 1, CSUM }
43 static const struct test_case test_cases
[] = {
44 /* RFC 1071 section 3. */
45 TEST_CASE("\x00\x01\xf2\x03"
47 0xffff - 0xddf2 /* ~0xddf2 */),
49 /* http://www.sbprojects.com/projects/tcpip/theory/theory14.htm */
50 TEST_CASE("\x45\x00\x00\x28"
57 /* http://mathforum.org/library/drmath/view/54379.html */
58 TEST_CASE("\x86\x5e\xac\x60"
71 /* This code is useful for generating new test cases for RFC 1624 section 4. */
73 generate_rfc1624_test_case(void)
77 for (i
= 0; i
< 10000000; i
++) {
81 for (j
= 0; j
< 8; j
++) {
82 data
[j
] = random_uint32();
84 data
[7] &= 0x0000ffff;
85 data
[7] |= 0x55550000;
86 if (ntohs(~csum(data
, sizeof data
- 2)) == 0xcd7a) {
87 ovs_hex_dump(stdout
, data
, sizeof data
, 0, false);
96 /* Make sure we get the calculation in RFC 1624 section 4 correct. */
100 /* "...an IP packet header in which a 16-bit field m = 0x5555..." */
102 0xfe, 0x8f, 0xc1, 0x14, 0x4b, 0x6f, 0x70, 0x2a,
103 0x80, 0x29, 0x78, 0xc0, 0x58, 0x81, 0x77, 0xaa,
104 0x66, 0x64, 0xfc, 0x96, 0x63, 0x97, 0x64, 0xee,
105 0x12, 0x53, 0x1d, 0xa9, 0x2d, 0xa9, 0x55, 0x55
108 /* "...the one's complement sum of all other header octets is 0xCD7A." */
109 assert(ntohs(csum(data
, sizeof data
- 2)) == 0xffff - 0xcd7a);
111 /* "...the header checksum would be:
113 HC = ~(0xCD7A + 0x5555)
117 assert(ntohs(csum(data
, sizeof data
)) == 0xdd2f);
119 /* "a 16-bit field m = 0x5555 changes to m' = 0x3285..." */
123 /* "The new checksum via recomputation is:
125 HC' = ~(0xCD7A + 0x3285)
129 assert(ntohs(csum(data
, sizeof data
)) == 0x0000);
131 /* "Applying [Eqn. 3] to the example above, we get the correct result:
133 HC' = ~(C + (-m) + m')
134 = ~(0x22D0 + ~0x5555 + 0x3285)
137 assert(recalc_csum16(htons(0xdd2f), htons(0x5555), htons(0x3285))
143 /* CRC32C checksum tests, based on Intel IPPs, Chapter 13,
144 * ippsCRC32C_8u() example, found at the following location:
145 * http://software.intel.com/sites/products/documentation/hpc/ipp/ipps/ */
151 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
154 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18,
155 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
160 assert(ntohl(crc32c(data
, 48)) == 0x563a96d9L
);
162 /* 32 bytes of all zeroes */
163 for (i
= 0; i
< 32; i
++) data
[i
] = 0x00;
164 assert(ntohl(crc32c(data
, 32)) == 0xaa36918aL
);
166 /* 32 bytes of all ones */
167 for (i
= 0; i
< 32; i
++) data
[i
] = 0xff;
168 assert(ntohl(crc32c(data
, 32)) == 0x43aba862L
);
170 /* 32 bytes of incrementing 00..1f */
171 for (i
= 0; i
< 32; i
++) data
[i
] = i
;
172 assert(ntohl(crc32c(data
, 32)) == 0x4e79dd46L
);
174 /* 32 bytes of decrementing 1f..00 */
175 for (i
= 0; i
< 32; i
++) data
[i
] = 31 - i
;
176 assert(ntohl(crc32c(data
, 32)) == 0x5cdb3f11L
);
181 /* Check the IP pseudoheader calculation. */
186 /* Try an IP header similar to one that the tunnel code
188 struct ip_header ip
= {
189 .ip_ihl_ver
= IP_IHL_VER(5, 4),
191 .ip_tot_len
= htons(134),
193 .ip_frag_off
= htons(IP_DF
),
195 .ip_proto
= IPPROTO_UDP
,
196 .ip_csum
= htons(0x1265),
197 .ip_src
= { .hi
= htons(0x1400), .lo
= htons(0x0002) },
198 .ip_dst
= { .hi
= htons(0x1400), .lo
= htons(0x0001) }
201 csum
= csum_finish(packet_csum_pseudoheader(&ip
));
202 assert(csum
== htons(0xd779));
204 /* And also test something totally different to check for
206 memset(&ip
, 0xff, sizeof ip
);
207 csum
= csum_finish(packet_csum_pseudoheader(&ip
));
208 assert(csum
== htons(0xff3c));
214 test_csum_main(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
216 const struct test_case
*tc
;
219 for (tc
= test_cases
; tc
< &test_cases
[ARRAY_SIZE(test_cases
)]; tc
++) {
220 const void *data
= tc
->data
;
221 const ovs_be16
*data16
= (OVS_FORCE
const ovs_be16
*) data
;
222 const ovs_be32
*data32
= (OVS_FORCE
const ovs_be32
*) data
;
226 assert(ntohs(csum(tc
->data
, tc
->size
)) == tc
->csum
);
229 /* Test csum_add16(). */
231 for (i
= 0; i
< tc
->size
/ 2; i
++) {
232 partial
= csum_add16(partial
, get_unaligned_be16(&data16
[i
]));
234 assert(ntohs(csum_finish(partial
)) == tc
->csum
);
237 /* Test csum_add32(). */
239 for (i
= 0; i
< tc
->size
/ 4; i
++) {
240 partial
= csum_add32(partial
, get_unaligned_be32(&data32
[i
]));
242 assert(ntohs(csum_finish(partial
)) == tc
->csum
);
245 /* Test alternating csum_add16() and csum_add32(). */
247 for (i
= 0; i
< tc
->size
/ 4; i
++) {
249 partial
= csum_add32(partial
, get_unaligned_be32(&data32
[i
]));
251 ovs_be16 u0
= get_unaligned_be16(&data16
[i
* 2]);
252 ovs_be16 u1
= get_unaligned_be16(&data16
[i
* 2 + 1]);
253 partial
= csum_add16(partial
, u0
);
254 partial
= csum_add16(partial
, u1
);
257 assert(ntohs(csum_finish(partial
)) == tc
->csum
);
260 /* Test csum_continue(). */
262 for (i
= 0; i
< tc
->size
/ 4; i
++) {
264 partial
= csum_continue(partial
, &data32
[i
], 4);
266 partial
= csum_continue(partial
, &data16
[i
* 2], 2);
267 partial
= csum_continue(partial
, &data16
[i
* 2 + 1], 2);
270 assert(ntohs(csum_finish(partial
)) == tc
->csum
);
278 /* Test recalc_csum16(). */
279 for (i
= 0; i
< 32; i
++) {
280 ovs_be16 old_u16
, new_u16
;
285 for (j
= 0; j
< ARRAY_SIZE(data
); j
++) {
286 data
[j
] = (OVS_FORCE ovs_be16
) random_uint32();
288 old_csum
= csum(data
, sizeof data
);
289 index
= random_range(ARRAY_SIZE(data
));
290 old_u16
= data
[index
];
291 new_u16
= data
[index
] = (OVS_FORCE ovs_be16
) random_uint32();
292 assert(csum(data
, sizeof data
)
293 == recalc_csum16(old_csum
, old_u16
, new_u16
));
298 /* Test recalc_csum32(). */
299 for (i
= 0; i
< 32; i
++) {
300 ovs_be32 old_u32
, new_u32
;
305 for (j
= 0; j
< ARRAY_SIZE(data
); j
++) {
306 data
[j
] = (OVS_FORCE ovs_be32
) random_uint32();
308 old_csum
= csum(data
, sizeof data
);
309 index
= random_range(ARRAY_SIZE(data
));
310 old_u32
= data
[index
];
311 new_u32
= data
[index
] = (OVS_FORCE ovs_be32
) random_uint32();
312 assert(csum(data
, sizeof data
)
313 == recalc_csum32(old_csum
, old_u32
, new_u32
));
321 OVSTEST_REGISTER("test-csum", test_csum_main
);