]> git.proxmox.com Git - qemu.git/commitdiff
net: iovec checksum calculator
authorDmitry Fleytman <dmitry@daynix.com>
Sat, 9 Mar 2013 09:21:03 +0000 (11:21 +0200)
committerStefan Hajnoczi <stefanha@redhat.com>
Mon, 25 Mar 2013 10:13:10 +0000 (11:13 +0100)
Signed-off-by: Dmitry Fleytman <dmitry@daynix.com>
Signed-off-by: Yan Vugenfirer <yan@daynix.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
include/net/checksum.h
net/checksum.c

index 3e7b93d0949f1174339aa0f695ebea1bb0ff3ec9..80203fb6e0f2957ec4dc316da6e9c9332ad5f23b 100644 (file)
@@ -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 */
index 4fa5563e7c22d6f0ed97f7fb00ceaf0d97cd268c..14c08550e0c88535a944615e2068bb890e3ea78e 100644 (file)
@@ -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;
+}