[ovs-dev] [RFC v7 07/13] dp-packet: Handle multi-seg mubfs in shift() func.
Tiago Lam
tiago.lam at intel.com
Wed May 23 16:47:22 UTC 2018
In its current implementation dp_packet_shift() is also unaware of
multi-seg mbufs (that holds data in memory non-contiguously) and assumes
that data exists contiguously in memory, memmove'ing data to perform the
shift.
To add support for multi-seg mbuds a new set of functions was
introduced, dp_packet_mbuf_shift() and dp_packet_mbuf_write(). These
functions are used by dp_packet_shift(), when handling multi-seg mbufs,
to shift and write data within a chain of mbufs.
Signed-off-by: Tiago Lam <tiago.lam at intel.com>
---
lib/dp-packet.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 101 insertions(+), 1 deletion(-)
diff --git a/lib/dp-packet.c b/lib/dp-packet.c
index 1b39946..7b603c7 100644
--- a/lib/dp-packet.c
+++ b/lib/dp-packet.c
@@ -294,13 +294,113 @@ dp_packet_prealloc_headroom(struct dp_packet *b, size_t size)
}
}
+#ifdef DPDK_NETDEV
+/* XXX: Caller must provide the correct mbuf where the offset is located. It
+ must also guarantee that 'ofs' is within bounds */
+static void
+dp_packet_mbuf_write(struct rte_mbuf *mbuf, int16_t ofs, uint32_t len,
+ const void *data)
+{
+ char *dst_addr;
+ uint16_t data_len;
+ int len_copy;
+ while (mbuf) {
+ if (len == 0) {
+ break;
+ }
+
+ dst_addr = rte_pktmbuf_mtod_offset(mbuf, char *, ofs);
+ data_len = MBUF_BUF_END(mbuf->buf_addr, mbuf->buf_len) - dst_addr;
+
+ len_copy = MIN(len, data_len);
+ /* We don't know if 'data' is the result of a rte_pktmbuf_read call, in
+ * which case we may end up writing to the same region of memory we are
+ * reading from and overlapping. Thus, the use of memmove */
+ memmove(dst_addr, data, len_copy);
+
+ data = ((char *) data) + len_copy;
+ len -= len_copy;
+ ofs = 0;
+
+ mbuf = mbuf->next;
+ }
+}
+
+static void
+dp_packet_mbuf_shift_(struct rte_mbuf *dbuf, int16_t dst_ofs,
+ const struct rte_mbuf *sbuf, uint16_t src_ofs, int len)
+{
+ char rd[len];
+
+ const char *wd = rte_pktmbuf_read(sbuf, src_ofs, len, rd);
+ if (!wd) {
+ /* XXX: Log WARN here. */
+ return;
+ }
+
+ dp_packet_mbuf_write(dbuf, dst_ofs, len, wd);
+}
+
+/* XXX: Delta must fall within the bounds of an mbuf */
+static void
+dp_packet_mbuf_shift(struct dp_packet *b, int delta)
+{
+ struct rte_mbuf *sbuf, *dbuf;
+ uint16_t src_ofs;
+ int16_t dst_ofs;
+
+ struct rte_mbuf *mbuf = CONST_CAST(struct rte_mbuf *, &b->mbuf);
+ dbuf = mbuf;
+ sbuf = mbuf;
+
+ /* Set the destination address to copy to */
+ if (delta < 0) {
+ dst_ofs = delta;
+ src_ofs = 0;
+ } else {
+ dst_ofs = delta;
+ src_ofs = 0;
+ }
+
+ /* Shift data from src mbuf and offset to dst mbuf and offset */
+ dp_packet_mbuf_shift_(dbuf, dst_ofs, sbuf, src_ofs,
+ rte_pktmbuf_pkt_len(sbuf));
+
+ /* Update mbufs' properties, depending if there's one mbuf or more */
+ mbuf->data_off = mbuf->data_off + dst_ofs;
+
+ struct rte_mbuf *tmbuf = rte_pktmbuf_lastseg(mbuf);
+ if (dbuf != tmbuf) {
+ tmbuf->data_len += delta;
+ mbuf->data_len -= dst_ofs;
+ }
+}
+#endif
+
/* Shifts all of the data within the allocated space in 'b' by 'delta' bytes.
* For example, a 'delta' of 1 would cause each byte of data to move one byte
* forward (from address 'p' to 'p+1'), and a 'delta' of -1 would cause each
- * byte to move one byte backward (from 'p' to 'p-1'). */
+ * byte to move one byte backward (from 'p' to 'p-1').
+ * Note for DPBUF_DPDK(XXX): The shift can only move within the bounds of an
+ * mbuf since it assumes the source and destination offsets will be on the
+ * same mbuf. */
void
dp_packet_shift(struct dp_packet *b, int delta)
{
+#ifdef DPDK_NETDEV
+ if (b->source == DPBUF_DPDK) {
+ ovs_assert(delta > 0 ? delta <= dp_packet_tailroom(b)
+ : delta < 0 ? -delta <= dp_packet_headroom(b)
+ : true);
+
+
+ if (delta != 0) {
+ dp_packet_mbuf_shift(b, delta);
+ }
+
+ return;
+ }
+#endif
ovs_assert(delta > 0 ? delta <= dp_packet_tailroom(b)
: delta < 0 ? -delta <= dp_packet_headroom(b)
: true);
--
2.7.4
More information about the dev
mailing list