LCOV - code coverage report
Current view: top level - tests - test-csum.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 102 102 100.0 %
Date: 2016-09-14 01:02:56 Functions: 7 7 100.0 %
Branches: 48 66 72.7 %

           Branch data     Line data    Source code
       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 <netinet/ip.h>
      24                 :            : #include <stdio.h>
      25                 :            : #include <stdlib.h>
      26                 :            : #include <string.h>
      27                 :            : #include "crc32c.h"
      28                 :            : #include "ovstest.h"
      29                 :            : #include "packets.h"
      30                 :            : #include "random.h"
      31                 :            : #include "unaligned.h"
      32                 :            : #include "util.h"
      33                 :            : 
      34                 :            : struct test_case {
      35                 :            :     char *data;
      36                 :            :     size_t size;                /* Test requires a multiple of 4. */
      37                 :            :     uint16_t csum;
      38                 :            : };
      39                 :            : 
      40                 :            : #define TEST_CASE(DATA, CSUM) { DATA, (sizeof DATA) - 1, CSUM }
      41                 :            : 
      42                 :            : static const struct test_case test_cases[] = {
      43                 :            :     /* RFC 1071 section 3. */
      44                 :            :     TEST_CASE("\x00\x01\xf2\x03"
      45                 :            :               "\xf4\xf5\xf6\xf7",
      46                 :            :               0xffff - 0xddf2 /* ~0xddf2 */),
      47                 :            : 
      48                 :            :     /* http://www.sbprojects.com/projects/tcpip/theory/theory14.htm */
      49                 :            :     TEST_CASE("\x45\x00\x00\x28"
      50                 :            :               "\x1F\xFD\x40\x00"
      51                 :            :               "\x80\x06\x00\x00"
      52                 :            :               "\xC0\xA8\x3B\x0A"
      53                 :            :               "\xC0\xA8\x3B\x32",
      54                 :            :               0xe345),
      55                 :            : 
      56                 :            :     /* http://mathforum.org/library/drmath/view/54379.html */
      57                 :            :     TEST_CASE("\x86\x5e\xac\x60"
      58                 :            :               "\x71\x2a\x81\xb5",
      59                 :            :               0xda60),
      60                 :            : };
      61                 :            : 
      62                 :            : static void
      63                 :         84 : mark(char c)
      64                 :            : {
      65                 :         84 :     putchar(c);
      66                 :         84 :     fflush(stdout);
      67                 :         84 : }
      68                 :            : 
      69                 :            : #if 0
      70                 :            : /* This code is useful for generating new test cases for RFC 1624 section 4. */
      71                 :            : static void
      72                 :            : generate_rfc1624_test_case(void)
      73                 :            : {
      74                 :            :     int i;
      75                 :            : 
      76                 :            :     for (i = 0; i < 10000000; i++) {
      77                 :            :         uint32_t data[8];
      78                 :            :         int j;
      79                 :            : 
      80                 :            :         for (j = 0; j < 8; j++) {
      81                 :            :             data[j] = random_uint32();
      82                 :            :         }
      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);
      87                 :            :             exit(0);
      88                 :            :         }
      89                 :            :     }
      90                 :            : }
      91                 :            : #endif
      92                 :            : 
      93                 :            : 
      94                 :            : 
      95                 :            : /* Make sure we get the calculation in RFC 1624 section 4 correct. */
      96                 :            : static void
      97                 :          1 : test_rfc1624(void)
      98                 :            : {
      99                 :            :     /* "...an IP packet header in which a 16-bit field m = 0x5555..." */
     100                 :          1 :     uint8_t data[32] = {
     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
     105                 :            :     };
     106                 :            : 
     107                 :            :     /* "...the one's complement sum of all other header octets is 0xCD7A." */
     108         [ -  + ]:          1 :     assert(ntohs(csum(data, sizeof data - 2)) == 0xffff - 0xcd7a);
     109                 :            : 
     110                 :            :     /* "...the header checksum would be:
     111                 :            : 
     112                 :            :           HC = ~(0xCD7A + 0x5555)
     113                 :            :              = ~0x22D0
     114                 :            :              =  0xDD2F"
     115                 :            :     */
     116         [ -  + ]:          1 :     assert(ntohs(csum(data, sizeof data)) == 0xdd2f);
     117                 :            : 
     118                 :            :     /* "a 16-bit field m = 0x5555 changes to m' = 0x3285..." */
     119                 :          1 :     data[30] = 0x32;
     120                 :          1 :     data[31] = 0x85;
     121                 :            : 
     122                 :            :     /* "The new checksum via recomputation is:
     123                 :            : 
     124                 :            :           HC' = ~(0xCD7A + 0x3285)
     125                 :            :               = ~0xFFFF
     126                 :            :               =  0x0000"
     127                 :            :     */
     128         [ -  + ]:          1 :     assert(ntohs(csum(data, sizeof data)) == 0x0000);
     129                 :            : 
     130                 :            :     /* "Applying [Eqn. 3] to the example above, we get the correct result:
     131                 :            : 
     132                 :            :           HC' = ~(C + (-m) + m')
     133                 :            :               = ~(0x22D0 + ~0x5555 + 0x3285)
     134                 :            :               = ~0xFFFF
     135                 :            :               =  0x0000" */
     136         [ -  + ]:          1 :     assert(recalc_csum16(htons(0xdd2f), htons(0x5555), htons(0x3285))
     137                 :            :            == htons(0x0000));
     138                 :            : 
     139                 :          1 :     mark('#');
     140                 :          1 : }
     141                 :            : 
     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/ */
     145                 :            : static void
     146                 :          1 : test_crc32c(void)
     147                 :            : {
     148                 :            :     int i;
     149                 :          1 :     uint8_t data[48] = {
     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
     156                 :            :     };
     157                 :            : 
     158                 :            :     /* iSCSI Read PDU */
     159         [ -  + ]:          1 :     assert(ntohl(crc32c(data, 48)) == 0x563a96d9L);
     160                 :            : 
     161                 :            :     /* 32 bytes of all zeroes */
     162         [ +  + ]:         33 :     for (i = 0; i < 32; i++) data[i] = 0x00;
     163         [ -  + ]:          1 :     assert(ntohl(crc32c(data, 32)) == 0xaa36918aL);
     164                 :            : 
     165                 :            :     /* 32 bytes of all ones */
     166         [ +  + ]:         33 :     for (i = 0; i < 32; i++) data[i] = 0xff;
     167         [ -  + ]:          1 :     assert(ntohl(crc32c(data, 32)) == 0x43aba862L);
     168                 :            : 
     169                 :            :     /* 32 bytes of incrementing 00..1f */
     170         [ +  + ]:         33 :     for (i = 0; i < 32; i++) data[i] = i;
     171         [ -  + ]:          1 :     assert(ntohl(crc32c(data, 32)) == 0x4e79dd46L);
     172                 :            : 
     173                 :            :     /* 32 bytes of decrementing 1f..00 */
     174         [ +  + ]:         33 :     for (i  = 0; i < 32; i++) data[i] = 31 - i;
     175         [ -  + ]:          1 :     assert(ntohl(crc32c(data, 32)) == 0x5cdb3f11L);
     176                 :            : 
     177                 :          1 :     mark('#');
     178                 :          1 : }
     179                 :            : 
     180                 :            : /* Check the IP pseudoheader calculation. */
     181                 :            : static void
     182                 :          1 : test_pseudo(void)
     183                 :            : {
     184                 :            :     ovs_be16 csum;
     185                 :            :     /* Try an IP header similar to one that the tunnel code
     186                 :            :      * might generate. */
     187                 :          8 :     struct ip_header ip = {
     188                 :            :         .ip_ihl_ver = IP_IHL_VER(5, 4),
     189                 :            :         .ip_tos = 0,
     190                 :          1 :         .ip_tot_len = htons(134),
     191                 :            :         .ip_id = 0,
     192                 :          1 :         .ip_frag_off = htons(IP_DF),
     193                 :            :         .ip_ttl = 64,
     194                 :            :         .ip_proto = IPPROTO_UDP,
     195                 :          1 :         .ip_csum = htons(0x1265),
     196                 :          1 :         .ip_src = { .hi = htons(0x1400), .lo = htons(0x0002) },
     197                 :          1 :         .ip_dst = { .hi = htons(0x1400), .lo = htons(0x0001) }
     198                 :            :     };
     199                 :            : 
     200                 :          1 :     csum = csum_finish(packet_csum_pseudoheader(&ip));
     201         [ -  + ]:          1 :     assert(csum == htons(0xd779));
     202                 :            : 
     203                 :            :     /* And also test something totally different to check for
     204                 :            :      * corner cases. */
     205                 :          1 :     memset(&ip, 0xff, sizeof ip);
     206                 :          1 :     csum = csum_finish(packet_csum_pseudoheader(&ip));
     207         [ -  + ]:          1 :     assert(csum == htons(0xff3c));
     208                 :            : 
     209                 :          1 :     mark('#');
     210                 :          1 : }
     211                 :            : 
     212                 :            : static void
     213                 :          1 : test_csum_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
     214                 :            : {
     215                 :            :     const struct test_case *tc;
     216                 :            :     int i;
     217                 :            : 
     218         [ +  + ]:          4 :     for (tc = test_cases; tc < &test_cases[ARRAY_SIZE(test_cases)]; tc++) {
     219                 :          3 :         const void *data = tc->data;
     220                 :          3 :         const ovs_be16 *data16 = (OVS_FORCE const ovs_be16 *) data;
     221                 :          3 :         const ovs_be32 *data32 = (OVS_FORCE const ovs_be32 *) data;
     222                 :            :         uint32_t partial;
     223                 :            : 
     224                 :            :         /* Test csum(). */
     225         [ -  + ]:          3 :         assert(ntohs(csum(tc->data, tc->size)) == tc->csum);
     226                 :          3 :         mark('.');
     227                 :            : 
     228                 :            :         /* Test csum_add16(). */
     229                 :          3 :         partial = 0;
     230         [ +  + ]:         21 :         for (i = 0; i < tc->size / 2; i++) {
     231                 :         18 :             partial = csum_add16(partial, get_unaligned_be16(&data16[i]));
     232                 :            :         }
     233         [ -  + ]:          3 :         assert(ntohs(csum_finish(partial)) == tc->csum);
     234                 :          3 :         mark('.');
     235                 :            : 
     236                 :            :         /* Test csum_add32(). */
     237                 :          3 :         partial = 0;
     238         [ +  + ]:         12 :         for (i = 0; i < tc->size / 4; i++) {
     239                 :          9 :             partial = csum_add32(partial, get_unaligned_be32(&data32[i]));
     240                 :            :         }
     241         [ -  + ]:          3 :         assert(ntohs(csum_finish(partial)) == tc->csum);
     242                 :          3 :         mark('.');
     243                 :            : 
     244                 :            :         /* Test alternating csum_add16() and csum_add32(). */
     245                 :          3 :         partial = 0;
     246         [ +  + ]:         12 :         for (i = 0; i < tc->size / 4; i++) {
     247         [ +  + ]:          9 :             if (i % 2) {
     248                 :          4 :                 partial = csum_add32(partial, get_unaligned_be32(&data32[i]));
     249                 :            :             } else {
     250                 :          5 :                 ovs_be16 u0 = get_unaligned_be16(&data16[i * 2]);
     251                 :          5 :                 ovs_be16 u1 = get_unaligned_be16(&data16[i * 2 + 1]);
     252                 :          5 :                 partial = csum_add16(partial, u0);
     253                 :          5 :                 partial = csum_add16(partial, u1);
     254                 :            :             }
     255                 :            :         }
     256         [ -  + ]:          3 :         assert(ntohs(csum_finish(partial)) == tc->csum);
     257                 :          3 :         mark('.');
     258                 :            : 
     259                 :            :         /* Test csum_continue(). */
     260                 :          3 :         partial = 0;
     261         [ +  + ]:         12 :         for (i = 0; i < tc->size / 4; i++) {
     262         [ +  + ]:          9 :             if (i) {
     263                 :          6 :                 partial = csum_continue(partial, &data32[i], 4);
     264                 :            :             } else {
     265                 :          3 :                 partial = csum_continue(partial, &data16[i * 2], 2);
     266                 :          3 :                 partial = csum_continue(partial, &data16[i * 2 + 1], 2);
     267                 :            :             }
     268                 :            :         }
     269         [ -  + ]:          3 :         assert(ntohs(csum_finish(partial)) == tc->csum);
     270                 :          3 :         mark('#');
     271                 :            :     }
     272                 :            : 
     273                 :          1 :     test_rfc1624();
     274                 :          1 :     test_crc32c();
     275                 :          1 :     test_pseudo();
     276                 :            : 
     277                 :            :     /* Test recalc_csum16(). */
     278         [ +  + ]:         33 :     for (i = 0; i < 32; i++) {
     279                 :            :         ovs_be16 old_u16, new_u16;
     280                 :            :         ovs_be16 old_csum;
     281                 :            :         ovs_be16 data[16];
     282                 :            :         int j, index;
     283                 :            : 
     284         [ +  + ]:        544 :         for (j = 0; j < ARRAY_SIZE(data); j++) {
     285                 :        512 :             data[j] = (OVS_FORCE ovs_be16) random_uint32();
     286                 :            :         }
     287                 :         32 :         old_csum = csum(data, sizeof data);
     288                 :         32 :         index = random_range(ARRAY_SIZE(data));
     289                 :         32 :         old_u16 = data[index];
     290                 :         32 :         new_u16 = data[index] = (OVS_FORCE ovs_be16) random_uint32();
     291         [ -  + ]:         32 :         assert(csum(data, sizeof data)
     292                 :            :                == recalc_csum16(old_csum, old_u16, new_u16));
     293                 :         32 :         mark('.');
     294                 :            :     }
     295                 :          1 :     mark('#');
     296                 :            : 
     297                 :            :     /* Test recalc_csum32(). */
     298         [ +  + ]:         33 :     for (i = 0; i < 32; i++) {
     299                 :            :         ovs_be32 old_u32, new_u32;
     300                 :            :         ovs_be16 old_csum;
     301                 :            :         ovs_be32 data[16];
     302                 :            :         int j, index;
     303                 :            : 
     304         [ +  + ]:        544 :         for (j = 0; j < ARRAY_SIZE(data); j++) {
     305                 :        512 :             data[j] = (OVS_FORCE ovs_be32) random_uint32();
     306                 :            :         }
     307                 :         32 :         old_csum = csum(data, sizeof data);
     308                 :         32 :         index = random_range(ARRAY_SIZE(data));
     309                 :         32 :         old_u32 = data[index];
     310                 :         32 :         new_u32 = data[index] = (OVS_FORCE ovs_be32) random_uint32();
     311         [ -  + ]:         32 :         assert(csum(data, sizeof data)
     312                 :            :                == recalc_csum32(old_csum, old_u32, new_u32));
     313                 :         32 :         mark('.');
     314                 :            :     }
     315                 :          1 :     mark('#');
     316                 :            : 
     317                 :          1 :     putchar('\n');
     318                 :          1 : }
     319                 :            : 
     320                 :       1176 : OVSTEST_REGISTER("test-csum", test_csum_main);

Generated by: LCOV version 1.12