Commit 84026301 authored by Dmitry Fleytman's avatar Dmitry Fleytman Committed by Stefan Hajnoczi
Browse files

net: iovec checksum calculator

parent 5acf5ea4
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -38,4 +38,16 @@ 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
 */
uint32_t net_checksum_add_iov(const struct iovec *iov,
                              const unsigned int iov_cnt,
                              uint32_t iov_off, uint32_t size);

#endif /* QEMU_NET_CHECKSUM_H */
+29 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 */

#include "qemu-common.h"
#include "net/checksum.h"

#define PROTO_TCP  6
@@ -84,3 +85,31 @@ void net_checksum_calculate(uint8_t *data, int length)
    data[14+hlen+csum_offset]   = csum >> 8;
    data[14+hlen+csum_offset+1] = csum & 0xff;
}

uint32_t
net_checksum_add_iov(const struct iovec *iov, const unsigned int iov_cnt,
                     uint32_t iov_off, uint32_t size)
{
    size_t iovec_off, buf_off;
    unsigned int i;
    uint32_t res = 0;
    uint32_t seq = 0;

    iovec_off = 0;
    buf_off = 0;
    for (i = 0; i < iov_cnt && size; i++) {
        if (iov_off < (iovec_off + iov[i].iov_len)) {
            size_t len = MIN((iovec_off + iov[i].iov_len) - iov_off , size);
            void *chunk_buf = iov[i].iov_base + (iov_off - iovec_off);

            res += net_checksum_add_cont(len, chunk_buf, seq);
            seq += len;

            buf_off += len;
            iov_off += len;
            size -= len;
        }
        iovec_off += iov[i].iov_len;
    }
    return res;
}