*
* 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.
+ * the Free Software Foundation; under version 2 or later 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
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu-common.h"
#include "net/checksum.h"
#define PROTO_TCP 6
#define PROTO_UDP 17
-uint32_t net_checksum_add(int len, uint8_t *buf)
+uint32_t net_checksum_add_cont(int len, uint8_t *buf, int seq)
{
uint32_t sum = 0;
int i;
- for (i = 0; i < len; i++) {
- if (i & 1)
- sum += (uint32_t)buf[i];
- else
- sum += (uint32_t)buf[i] << 8;
+ for (i = seq; i < seq + len; i++) {
+ if (i & 1) {
+ sum += (uint32_t)buf[i - seq];
+ } else {
+ sum += (uint32_t)buf[i - seq] << 8;
+ }
}
return sum;
}
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;
+}