This patchset fixes the transmission of cloned mbufs when using virtio + TSO. The problem is we need to fix the L4 checksum in the packet, but it should be considered as read-only, as pointed-out by Stephen here: http://dpdk.org/ml/archives/dev/2016-October/048873.html
Unfortunatly the patchset is quite big, but I did not manage to find a shorter solution. The first patches add some mbuf helpers that are used in virtio in the last patch. This last patch adds a zone for each tx ring entry where headers can be copied, patched, and referenced by virtio descriptors in case the mbuf is read-only. If its not the case, the mbuf is modified as before. I tested with the same test plan than the one described in http://dpdk.org/ml/archives/dev/2016-October/048092.html (only the TSO test case). I also replayed the test with the following patches to validate the code path for: - segmented packets (it forces a local copy in virtio_tso_fix_cksum) --- a/lib/librte_mbuf/rte_mbuf.c +++ b/lib/librte_mbuf/rte_mbuf.c @@ -279,7 +279,7 @@ void *__rte_pktmbuf_read(const struct rte_mbuf *m, uint32_t off, seg = seg->next; } - if (off + len <= rte_pktmbuf_data_len(seg)) + if (0 && off + len <= rte_pktmbuf_data_len(seg)) return rte_pktmbuf_mtod_offset(seg, char *, off); /* rare case: header is split among several segments */ diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h index 9dc6f10..5a4312a 100644 --- a/lib/librte_mbuf/rte_mbuf.h +++ b/lib/librte_mbuf/rte_mbuf.h @@ -1671,7 +1671,7 @@ void *__rte_pktmbuf_read(const struct rte_mbuf *m, uint32_t off, static inline void *rte_pktmbuf_read(const struct rte_mbuf *m, uint32_t off, uint32_t len, void *buf) { - if (likely(off + len <= rte_pktmbuf_data_len(m))) + if (likely(0 && off + len <= rte_pktmbuf_data_len(m))) return rte_pktmbuf_mtod_offset(m, char *, off); else return __rte_pktmbuf_read(m, off, len, buf); - and for shared mbuf (force to use the buffer in virtio tx ring) --- a/drivers/net/virtio/virtio_rxtx.c +++ b/drivers/net/virtio/virtio_rxtx.c @@ -225,7 +225,7 @@ virtio_tso_fix_cksum(struct rte_mbuf *m, char *hdr, size_t hdr_sz) int shared = 0; /* mbuf is write-only, we need to copy the headers in a linear buffer */ - if (unlikely(rte_pktmbuf_data_is_shared(m, 0, hdrlen))) { + if (unlikely(1 || rte_pktmbuf_data_is_shared(m, 0, hdrlen))) { shared = 1; /* network headers are too big, there's nothing we can do */ Olivier Matz (5): mbuf: remove const attribute in mbuf read function mbuf: new helper to check if a mbuf is shared mbuf: new helper to write data in a mbuf chain mbuf: new helper to copy data from a mbuf net/virtio: fix Tso when mbuf is shared app/test/test_mbuf.c | 62 +++++++++++++- drivers/net/virtio/virtio_rxtx.c | 119 ++++++++++++++++++-------- drivers/net/virtio/virtqueue.h | 2 + lib/librte_mbuf/rte_mbuf.c | 46 +++++++++- lib/librte_mbuf/rte_mbuf.h | 157 ++++++++++++++++++++++++++++++++++- lib/librte_mbuf/rte_mbuf_version.map | 6 ++ 6 files changed, 347 insertions(+), 45 deletions(-) -- 2.8.1