/*
 *  IP checksumming functions.
 *  (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; under version 2 of the License.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 */

#ifndef QEMU_NET_CHECKSUM_H
#define QEMU_NET_CHECKSUM_H

#include "qemu/bswap.h"
struct iovec;

uint32_t net_checksum_add_cont(int len, uint8_t *buf, int seq);
uint16_t net_checksum_finish(uint32_t sum);
uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto,
                             uint8_t *addrs, uint8_t *buf);
void net_checksum_calculate(uint8_t *data, int length);

static inline uint32_t
net_checksum_add(int len, uint8_t *buf)
{
    return net_checksum_add_cont(len, buf, 0);
}

static inline uint16_t
net_checksum_finish_nozero(uint32_t sum)
{
    return net_checksum_finish(sum) ?: 0xFFFF;
}

static inline uint16_t
net_raw_checksum(uint8_t *data, int length)
{
    return net_checksum_finish(net_checksum_add(length, data));
}

/**
 * net_checksum_add_iov: scatter-gather vector checksumming
 *
 * @iov: input scatter-gather array
 * @iov_cnt: number of array elements
 * @iov_off: starting iov offset for checksumming
 * @size: length of data to be checksummed
 * @csum_offset: offset of the checksum chunk
 */
uint32_t net_checksum_add_iov(const struct iovec *iov,
                              const unsigned int iov_cnt,
                              uint32_t iov_off, uint32_t size,
                              uint32_t csum_offset);

typedef struct toeplitz_key_st {
    uint32_t leftmost_32_bits;
    uint8_t *next_byte;
} net_toeplitz_key;

static inline
void net_toeplitz_key_init(net_toeplitz_key *key, uint8_t *key_bytes)
{
    key->leftmost_32_bits = be32_to_cpu(*(uint32_t *)key_bytes);
    key->next_byte = key_bytes + sizeof(uint32_t);
}

static inline
void net_toeplitz_add(uint32_t *result,
                      uint8_t *input,
                      uint32_t len,
                      net_toeplitz_key *key)
{
    register uint32_t accumulator = *result;
    register uint32_t leftmost_32_bits = key->leftmost_32_bits;
    register uint32_t byte;

    for (byte = 0; byte < len; byte++) {
        register uint8_t input_byte = input[byte];
        register uint8_t key_byte = *(key->next_byte++);
        register uint8_t bit;

        for (bit = 0; bit < 8; bit++) {
            if (input_byte & (1 << 7)) {
                accumulator ^= leftmost_32_bits;
            }

            leftmost_32_bits =
                (leftmost_32_bits << 1) | ((key_byte & (1 << 7)) >> 7);

            input_byte <<= 1;
            key_byte <<= 1;
        }
    }

    key->leftmost_32_bits = leftmost_32_bits;
    *result = accumulator;
}

#endif /* QEMU_NET_CHECKSUM_H */
