@@ -312,27 +312,67 @@ dp_packet_shift(struct dp_packet *b, int delta)
}
}
-/* Appends 'size' bytes of data to the tail end of 'b', reallocating and
- * copying its data if necessary. Returns a pointer to the first byte of the
- * new data, which is left uninitialized. */
-void *
-dp_packet_put_uninit(struct dp_packet *b, size_t size)
+static void *
+dp_packet_put_uninit_(struct dp_packet *b, size_t size)
{
void *p;
dp_packet_prealloc_tailroom(b, size);
+#ifdef DPDK_NETDEV
+ p = dp_packet_mbuf_tail(b);
+ /* In the case of multi-segment mbufs, the data length of the last mbuf
+ * should be adjusted by 'size' bytes. The packet length of the entire
+ * mbuf chain (stored in the first mbuf of said chain) is adjusted in
+ * the normal execution path below.
+ */
+
+ struct rte_mbuf *tmbuf = (struct rte_mbuf *) p;
+ struct mbuf_tail *mbuf_tail = xmalloc(sizeof(*mbuf_tail));
+ size_t pkt_len = size;
+
+ mbuf_tail->mbuf = tmbuf;
+ mbuf_tail->ofs = tmbuf->data_len;
+
+ /* Adjust size of intermediate mbufs from current tail to end */
+ while (tmbuf && pkt_len > 0) {
+ tmbuf->data_len = MIN(pkt_len, (rte_pktmbuf_mtod(tmbuf, char *) +
+ tmbuf->buf_len) - rte_pktmbuf_mtod(tmbuf, char *));
+ pkt_len -= tmbuf->data_len;
+
+ tmbuf = tmbuf->next;
+ }
+
+ p = (void *) mbuf_tail;
+#else
p = dp_packet_tail(b);
+#endif
dp_packet_set_size(b, dp_packet_size(b) + size);
+
return p;
}
-/* Appends 'size' zeroed bytes to the tail end of 'b'. Data in 'b' is
- * reallocated and copied if necessary. Returns a pointer to the first byte of
- * the data's location in the dp_packet. */
+static void *
+dp_packet_tail_to_addr(struct dp_packet *b OVS_UNUSED, void *p) {
+#ifdef DPDK_NETDEV
+ struct mbuf_tail *mbuf_tail = (struct mbuf_tail *) p;
+ p = (void *) rte_pktmbuf_mtod_offset(mbuf_tail->mbuf, void *,
+ mbuf_tail->ofs);
+#endif
+
+ return p;
+}
+
+/* Appends 'size' bytes of data to the tail end of 'b', reallocating and
+ * copying its data if necessary. Returns a pointer to the first byte of the
+ * new data, which is left uninitialized. */
void *
-dp_packet_put_zeros(struct dp_packet *b, size_t size)
+dp_packet_put_uninit(struct dp_packet *b, size_t size)
{
- void *dst = dp_packet_put_uninit(b, size);
- memset(dst, 0, size);
+ void *tail = dp_packet_put_uninit_(b, size);
+
+ void *dst = dp_packet_tail_to_addr(b, tail);
+
+ free(tail);
+
return dst;
}
@@ -342,8 +382,40 @@ dp_packet_put_zeros(struct dp_packet *b, size_t size)
void *
dp_packet_put(struct dp_packet *b, const void *p, size_t size)
{
- void *dst = dp_packet_put_uninit(b, size);
- memcpy(dst, p, size);
+ void *tail = dp_packet_put_uninit_(b, size);
+#ifdef DPDK_NETDEV
+ struct mbuf_tail *mbuf_tail = (struct mbuf_tail *) tail;
+
+ dp_packet_mbuf_write(mbuf_tail->mbuf, mbuf_tail->ofs, size, p);
+#else
+ memcpy(tail, p, size);
+#endif
+
+ void *dst = dp_packet_tail_to_addr(b, tail);
+
+ free(tail);
+
+ return dst;
+}
+
+/* Appends 'size' zeroed bytes to the tail end of 'b'. Data in 'b' is
+ * reallocated and copied if necessary. Returns a pointer to the first byte of
+ * the data's location in the dp_packet. */
+void *
+dp_packet_put_zeros(struct dp_packet *b, size_t size)
+{
+ void *dst;
+#ifdef DPDK_NETDEV
+ char zeros[size];
+ memset(zeros, 0, size);
+
+ dst = dp_packet_put(b, zeros, size);
+
+ return dst;
+#endif
+ dst = dp_packet_put_uninit(b, size);
+ memset(dst, 0, size);
+
return dst;
}
@@ -80,6 +80,13 @@ struct dp_packet {
};
};
+#ifdef DPDK_NETDEV
+struct mbuf_tail {
+ struct rte_mbuf *mbuf;
+ uint16_t ofs;
+};
+#endif
+
static inline void *dp_packet_data(const struct dp_packet *);
static inline void dp_packet_set_data(struct dp_packet *, void *);
static inline void *dp_packet_base(const struct dp_packet *);