This function can be used to calculate the checksum of data embedded in
mbuf, that can be composed of several segments.

This function will be used by the virtio pmd in next commits to calculate
the checksum in software in case the protocol is not recognized.

Signed-off-by: Olivier Matz <olivier.matz at 6wind.com>
---
 doc/guides/rel_notes/release_16_11.rst |  5 ++++
 lib/librte_mbuf/rte_mbuf.c             | 55 ++++++++++++++++++++++++++++++++--
 lib/librte_mbuf/rte_mbuf.h             | 13 ++++++++
 lib/librte_mbuf/rte_mbuf_version.map   |  1 +
 4 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/doc/guides/rel_notes/release_16_11.rst 
b/doc/guides/rel_notes/release_16_11.rst
index 6a591e2..da70f3b 100644
--- a/doc/guides/rel_notes/release_16_11.rst
+++ b/doc/guides/rel_notes/release_16_11.rst
@@ -53,6 +53,11 @@ New Features
   Added two new functions ``rte_get_rx_ol_flag_list()`` and
   ``rte_get_tx_ol_flag_list()`` to dump offload flags as a string.

+* **Added a functions to calculate the checksum of data in a mbuf.**
+
+  Added a new function ``rte_pktmbuf_cksum()`` to process the checksum of
+  data embedded in an mbuf chain.
+
 Resolved Issues
 ---------------

diff --git a/lib/librte_mbuf/rte_mbuf.c b/lib/librte_mbuf/rte_mbuf.c
index 56f37e6..0304245 100644
--- a/lib/librte_mbuf/rte_mbuf.c
+++ b/lib/librte_mbuf/rte_mbuf.c
@@ -60,6 +60,7 @@
 #include <rte_hexdump.h>
 #include <rte_errno.h>
 #include <rte_memcpy.h>
+#include <rte_ip.h>

 /*
  * ctrlmbuf constructor, given as a callback function to
@@ -273,8 +274,7 @@ const void *__rte_pktmbuf_read(const struct rte_mbuf *m, 
uint32_t off,
        if (off + len > rte_pktmbuf_pkt_len(m))
                return NULL;

-       while (off >= rte_pktmbuf_data_len(seg) &&
-                       rte_pktmbuf_data_len(seg) != 0) {
+       while (off >= rte_pktmbuf_data_len(seg)) {
                off -= rte_pktmbuf_data_len(seg);
                seg = seg->next;
        }
@@ -432,3 +432,54 @@ int rte_get_tx_ol_flag_list(uint64_t mask, char *buf, 
size_t buflen)

        return 0;
 }
+
+/* compute the raw (non complemented) checksum of a packet */
+uint16_t
+rte_pktmbuf_cksum(const struct rte_mbuf *m, uint32_t off, uint32_t len)
+{
+       const struct rte_mbuf *seg;
+       const char *buf;
+       uint32_t sum, tmp;
+       uint32_t seglen, done;
+
+       /* easy case: all data in the first segment */
+       if (off + len <= rte_pktmbuf_data_len(m))
+               return rte_raw_cksum(rte_pktmbuf_mtod_offset(m,
+                               const char *, off), len);
+
+       if (off + len > rte_pktmbuf_pkt_len(m))
+               return 0; /* invalid params, return a dummy value */
+
+       /* else browse the segment to find offset */
+       seglen = 0;
+       for (seg = m; seg != NULL; seg = seg->next) {
+               seglen = rte_pktmbuf_data_len(seg);
+               if (off < seglen)
+                       break;
+               off -= seglen;
+       }
+       seglen -= off;
+       buf = rte_pktmbuf_mtod_offset(seg, const char *, off);
+       if (seglen >= len) /* all in one segment */
+               return rte_raw_cksum(buf, len);
+
+       /* hard case: process checksum of several segments */
+       sum = 0;
+       done = 0;
+       for (;;) {
+               tmp = __rte_raw_cksum(buf, seglen, 0);
+               if (done & 1)
+                       tmp = rte_bswap16(tmp);
+               sum += tmp;
+               done += seglen;
+               if (done == len)
+                       break;
+               seg = seg->next;
+               buf = rte_pktmbuf_mtod(seg, const char *);
+               seglen = rte_pktmbuf_data_len(seg);
+               if (seglen > len - done)
+                       seglen = len - done;
+       }
+
+       return __rte_raw_cksum_reduce(sum);
+}
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index 3c21c71..7bbe096 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -1581,6 +1581,19 @@ static inline int rte_pktmbuf_chain(struct rte_mbuf 
*head, struct rte_mbuf *tail
  */
 void rte_pktmbuf_dump(FILE *f, const struct rte_mbuf *m, unsigned dump_len);

+/**
+ * Compute the raw (non complemented) checksum of a packet.
+ *
+ * @param m
+ *   The pointer to the mbuf.
+ * @param off
+ *   The offset in bytes to start the checksum.
+ * @param len
+ *   The length in bytes of the data to ckecksum.
+ */
+uint16_t
+rte_pktmbuf_cksum(const struct rte_mbuf *m, uint32_t off, uint32_t len);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_mbuf/rte_mbuf_version.map 
b/lib/librte_mbuf/rte_mbuf_version.map
index 6f83745..7b85dad 100644
--- a/lib/librte_mbuf/rte_mbuf_version.map
+++ b/lib/librte_mbuf/rte_mbuf_version.map
@@ -33,6 +33,7 @@ DPDK_16.11 {
        rte_get_ptype_tunnel_name;
        rte_get_rx_ol_flag_list;
        rte_get_tx_ol_flag_list;
+       rte_pktmbuf_cksum;
        rte_pktmbuf_get_ptype;

 } DPDK_2.1;
-- 
2.8.1

Reply via email to