]>
git.proxmox.com Git - 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 <netinet/in.h>
23 #include <netinet/ip.h>
31 #include "unaligned.h"
36 size_t size
; /* Test requires a multiple of 4. */
40 #define TEST_CASE(DATA, CSUM) { DATA, (sizeof DATA) - 1, CSUM }
42 static const struct test_case test_cases
[] = {
43 /* RFC 1071 section 3. */
44 TEST_CASE("\x00\x01\xf2\x03"
46 0xffff - 0xddf2 /* ~0xddf2 */),
48 /* http://www.sbprojects.com/projects/tcpip/theory/theory14.htm */
49 TEST_CASE("\x45\x00\x00\x28"
56 /* http://mathforum.org/library/drmath/view/54379.html */
57 TEST_CASE("\x86\x5e\xac\x60"
70 /* This code is useful for generating new test cases for RFC 1624 section 4. */
72 generate_rfc1624_test_case(void)
76 for (i
= 0; i
< 10000000; i
++) {
80 for (j
= 0; j
< 8; j
++) {
81 data
[j
] = random_uint32();
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);
95 /* Make sure we get the calculation in RFC 1624 section 4 correct. */
99 /* "...an IP packet header in which a 16-bit field m = 0x5555..." */
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
107 /* "...the one's complement sum of all other header octets is 0xCD7A." */
108 assert(ntohs(csum(data
, sizeof data
- 2)) == 0xffff - 0xcd7a);
110 /* "...the header checksum would be:
112 HC = ~(0xCD7A + 0x5555)
116 assert(ntohs(csum(data
, sizeof data
)) == 0xdd2f);
118 /* "a 16-bit field m = 0x5555 changes to m' = 0x3285..." */
122 /* "The new checksum via recomputation is:
124 HC' = ~(0xCD7A + 0x3285)
128 assert(ntohs(csum(data
, sizeof data
)) == 0x0000);
130 /* "Applying [Eqn. 3] to the example above, we get the correct result:
132 HC' = ~(C + (-m) + m')
133 = ~(0x22D0 + ~0x5555 + 0x3285)
136 assert(recalc_csum16(htons(0xdd2f), htons(0x5555), htons(0x3285))
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/ */
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
159 assert(ntohl(crc32c(data
, 48)) == 0x563a96d9L
);
161 /* 32 bytes of all zeroes */
162 for (i
= 0; i
< 32; i
++) data
[i
] = 0x00;
163 assert(ntohl(crc32c(data
, 32)) == 0xaa36918aL
);
165 /* 32 bytes of all ones */
166 for (i
= 0; i
< 32; i
++) data
[i
] = 0xff;
167 assert(ntohl(crc32c(data
, 32)) == 0x43aba862L
);
169 /* 32 bytes of incrementing 00..1f */
170 for (i
= 0; i
< 32; i
++) data
[i
] = i
;
171 assert(ntohl(crc32c(data
, 32)) == 0x4e79dd46L
);
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
);
180 /* Check the IP pseudoheader calculation. */
185 /* Try an IP header similar to one that the tunnel code
187 struct ip_header ip
= {
188 .ip_ihl_ver
= IP_IHL_VER(5, 4),
190 .ip_tot_len
= htons(134),
192 .ip_frag_off
= htons(IP_DF
),
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) }
200 csum
= csum_finish(packet_csum_pseudoheader(&ip
));
201 assert(csum
== htons(0xd779));
203 /* And also test something totally different to check for
205 memset(&ip
, 0xff, sizeof ip
);
206 csum
= csum_finish(packet_csum_pseudoheader(&ip
));
207 assert(csum
== htons(0xff3c));
213 test_csum_main(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
215 const struct test_case
*tc
;
218 for (tc
= test_cases
; tc
< &test_cases
[ARRAY_SIZE(test_cases
)]; tc
++) {
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
;
225 assert(ntohs(csum(tc
->data
, tc
->size
)) == tc
->csum
);
228 /* Test csum_add16(). */
230 for (i
= 0; i
< tc
->size
/ 2; i
++) {
231 partial
= csum_add16(partial
, get_unaligned_be16(&data16
[i
]));
233 assert(ntohs(csum_finish(partial
)) == tc
->csum
);
236 /* Test csum_add32(). */
238 for (i
= 0; i
< tc
->size
/ 4; i
++) {
239 partial
= csum_add32(partial
, get_unaligned_be32(&data32
[i
]));
241 assert(ntohs(csum_finish(partial
)) == tc
->csum
);
244 /* Test alternating csum_add16() and csum_add32(). */
246 for (i
= 0; i
< tc
->size
/ 4; i
++) {
248 partial
= csum_add32(partial
, get_unaligned_be32(&data32
[i
]));
250 ovs_be16 u0
= get_unaligned_be16(&data16
[i
* 2]);
251 ovs_be16 u1
= get_unaligned_be16(&data16
[i
* 2 + 1]);
252 partial
= csum_add16(partial
, u0
);
253 partial
= csum_add16(partial
, u1
);
256 assert(ntohs(csum_finish(partial
)) == tc
->csum
);
259 /* Test csum_continue(). */
261 for (i
= 0; i
< tc
->size
/ 4; i
++) {
263 partial
= csum_continue(partial
, &data32
[i
], 4);
265 partial
= csum_continue(partial
, &data16
[i
* 2], 2);
266 partial
= csum_continue(partial
, &data16
[i
* 2 + 1], 2);
269 assert(ntohs(csum_finish(partial
)) == tc
->csum
);
277 /* Test recalc_csum16(). */
278 for (i
= 0; i
< 32; i
++) {
279 ovs_be16 old_u16
, new_u16
;
284 for (j
= 0; j
< ARRAY_SIZE(data
); j
++) {
285 data
[j
] = (OVS_FORCE ovs_be16
) random_uint32();
287 old_csum
= csum(data
, sizeof data
);
288 index
= random_range(ARRAY_SIZE(data
));
289 old_u16
= data
[index
];
290 new_u16
= data
[index
] = (OVS_FORCE ovs_be16
) random_uint32();
291 assert(csum(data
, sizeof data
)
292 == recalc_csum16(old_csum
, old_u16
, new_u16
));
297 /* Test recalc_csum32(). */
298 for (i
= 0; i
< 32; i
++) {
299 ovs_be32 old_u32
, new_u32
;
304 for (j
= 0; j
< ARRAY_SIZE(data
); j
++) {
305 data
[j
] = (OVS_FORCE ovs_be32
) random_uint32();
307 old_csum
= csum(data
, sizeof data
);
308 index
= random_range(ARRAY_SIZE(data
));
309 old_u32
= data
[index
];
310 new_u32
= data
[index
] = (OVS_FORCE ovs_be32
) random_uint32();
311 assert(csum(data
, sizeof data
)
312 == recalc_csum32(old_csum
, old_u32
, new_u32
));
320 OVSTEST_REGISTER("test-csum", test_csum_main
);