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

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2008, 2009, 2010, 2011, 2013, 2015 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                 :            : #include "csum.h"
      19                 :            : #include "unaligned.h"
      20                 :            : 
      21                 :            : #ifndef __CHECKER__
      22                 :            : /* Returns the IP checksum of the 'n' bytes in 'data'.
      23                 :            :  *
      24                 :            :  * The return value has the same endianness as the data.  That is, if 'data'
      25                 :            :  * consists of a packet in network byte order, then the return value is a value
      26                 :            :  * in network byte order, and if 'data' consists of a data structure in host
      27                 :            :  * byte order, then the return value is in host byte order. */
      28                 :            : ovs_be16
      29                 :      12087 : csum(const void *data, size_t n)
      30                 :            : {
      31                 :      12087 :     return csum_finish(csum_continue(0, data, n));
      32                 :            : }
      33                 :            : 
      34                 :            : /* Adds the 'n' bytes in 'data' to the partial IP checksum 'partial' and
      35                 :            :  * returns the updated checksum.  (To start a new checksum, pass 0 for
      36                 :            :  * 'partial'.  To obtain the finished checksum, pass the return value to
      37                 :            :  * csum_finish().) */
      38                 :            : uint32_t
      39                 :      17388 : csum_continue(uint32_t partial, const void *data_, size_t n)
      40                 :            : {
      41                 :      17388 :     const ovs_be16 *data = data_;
      42                 :            : 
      43         [ +  + ]:     282468 :     for (; n > 1; n -= 2, data++) {
      44                 :     265080 :         partial = csum_add16(partial, get_unaligned_be16(data));
      45                 :            :     }
      46         [ +  + ]:      17388 :     if (n) {
      47                 :         94 :         partial += *(uint8_t *) data;
      48                 :            :     }
      49                 :      17388 :     return partial;
      50                 :            : }
      51                 :            : 
      52                 :            : /* Returns the IP checksum corresponding to 'partial', which is a value updated
      53                 :            :  * by some combination of csum_add16(), csum_add32(), and csum_continue().
      54                 :            :  *
      55                 :            :  * The return value has the same endianness as the checksummed data.  That is,
      56                 :            :  * if the data consist of a packet in network byte order, then the return value
      57                 :            :  * is a value in network byte order, and if the data are a data structure in
      58                 :            :  * host byte order, then the return value is in host byte order. */
      59                 :            : ovs_be16
      60                 :      21111 : csum_finish(uint32_t partial)
      61                 :            : {
      62         [ +  + ]:      40291 :     while (partial >> 16) {
      63                 :      19180 :         partial = (partial & 0xffff) + (partial >> 16);
      64                 :            :     }
      65                 :      21111 :     return ~partial;
      66                 :            : }
      67                 :            : 
      68                 :            : /* Returns the new checksum for a packet in which the checksum field previously
      69                 :            :  * contained 'old_csum' and in which a field that contained 'old_u16' was
      70                 :            :  * changed to contain 'new_u16'. */
      71                 :            : ovs_be16
      72                 :       3721 : recalc_csum16(ovs_be16 old_csum, ovs_be16 old_u16, ovs_be16 new_u16)
      73                 :            : {
      74                 :            :     /* Ones-complement arithmetic is endian-independent, so this code does not
      75                 :            :      * use htons() or ntohs().
      76                 :            :      *
      77                 :            :      * See RFC 1624 for formula and explanation. */
      78                 :       3721 :     uint16_t hc_complement = ~old_csum;
      79                 :       3721 :     uint16_t m_complement = ~old_u16;
      80                 :       3721 :     uint16_t m_prime = new_u16;
      81                 :       3721 :     uint32_t sum = hc_complement + m_complement + m_prime;
      82                 :       3721 :     return csum_finish(sum);
      83                 :            : }
      84                 :            : 
      85                 :            : /* Returns the new checksum for a packet in which the checksum field previously
      86                 :            :  * contained 'old_csum' and in which a field that contained 'old_u32' was
      87                 :            :  * changed to contain 'new_u32'. */
      88                 :            : ovs_be16
      89                 :        260 : recalc_csum32(ovs_be16 old_csum, ovs_be32 old_u32, ovs_be32 new_u32)
      90                 :            : {
      91                 :        260 :     return recalc_csum16(recalc_csum16(old_csum, old_u32, new_u32),
      92                 :        520 :                          old_u32 >> 16, new_u32 >> 16);
      93                 :            : }
      94                 :            : 
      95                 :            : /* Returns the new checksum for a packet in which the checksum field previously
      96                 :            :  * contained 'old_csum' and in which a field that contained the 6 bytes at
      97                 :            :  * 'old_mac' was changed to contain the 6 bytes at 'new_mac'. */
      98                 :            : ovs_be16
      99                 :          8 : recalc_csum48(ovs_be16 old_csum, const struct eth_addr old_mac,
     100                 :            :               const struct eth_addr new_mac)
     101                 :            : {
     102                 :          8 :     ovs_be16 new_csum = old_csum;
     103                 :            : 
     104         [ +  + ]:         32 :     for (int i = 0; i < 3; ++i) {
     105                 :         24 :         new_csum = recalc_csum16(new_csum, old_mac.be16[i], new_mac.be16[i]);
     106                 :            :     }
     107                 :            : 
     108                 :          8 :     return new_csum;
     109                 :            : }
     110                 :            : 
     111                 :            : /* Returns the new checksum for a packet in which the checksum field previously
     112                 :            :  * contained 'old_csum' and in which a field that contained 'old_u32[4]' was
     113                 :            :  * changed to contain 'new_u32[4]'. */
     114                 :            : ovs_be16
     115                 :         19 : recalc_csum128(ovs_be16 old_csum, ovs_16aligned_be32 old_u32[4],
     116                 :            :                const ovs_be32 new_u32[4])
     117                 :            : {
     118                 :         19 :     ovs_be16 new_csum = old_csum;
     119                 :            :     int i;
     120                 :            : 
     121         [ +  + ]:         95 :     for (i = 0; i < 4; ++i) {
     122                 :         76 :         new_csum = recalc_csum32(new_csum,
     123                 :        152 :                                  get_16aligned_be32(&old_u32[i]), new_u32[i]);
     124                 :            :     }
     125                 :         19 :     return new_csum;
     126                 :            : }
     127                 :            : #else  /* __CHECKER__ */
     128                 :            : /* Making sparse happy with these functions also makes them unreadable, so
     129                 :            :  * don't bother to show it their implementations. */
     130                 :            : #endif

Generated by: LCOV version 1.12