tizen 2.3.1 release
[external/qemu.git] / net / checksum.c
index 4046932..14c0855 100644 (file)
@@ -4,7 +4,7 @@
  *
  *  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;
 }
@@ -83,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;
+}