@@ -41,11 +41,11 @@ static void
dp_packet_use__(struct dp_packet *b, void *base, size_t allocated,
enum dp_packet_source source)
{
+ dp_packet_init__(b, allocated, source);
+
dp_packet_set_base(b, base);
dp_packet_set_data(b, base);
dp_packet_set_size(b, 0);
-
- dp_packet_init__(b, allocated, source);
}
/* Initializes 'b' as an empty dp_packet that contains the 'allocated' bytes of
@@ -185,9 +185,25 @@ dp_packet_delete(struct dp_packet *b)
static inline void *
dp_packet_at(const struct dp_packet *b, size_t offset, size_t size)
{
- return offset + size <= dp_packet_size(b)
- ? (char *) dp_packet_data(b) + offset
- : NULL;
+ if (offset + size > dp_packet_size(b)) {
+ return NULL;
+ }
+
+#ifdef DPDK_NETDEV
+ if (b->source == DPBUF_DPDK) {
+ struct rte_mbuf *buf = CONST_CAST(struct rte_mbuf *, &b->mbuf);
+
+ while (buf && offset > buf->data_len) {
+ offset -= buf->data_len;
+
+ buf = buf->next;
+ }
+
+ return buf ? rte_pktmbuf_mtod_offset(buf, char *, offset) : NULL;
+ }
+#endif
+
+ return (char *) dp_packet_data(b) + offset;
}
/* Returns a pointer to byte 'offset' in 'b', which must contain at least
@@ -196,13 +212,23 @@ static inline void *
dp_packet_at_assert(const struct dp_packet *b, size_t offset, size_t size)
{
ovs_assert(offset + size <= dp_packet_size(b));
- return ((char *) dp_packet_data(b)) + offset;
+ return dp_packet_at(b, offset, size);
}
/* Returns a pointer to byte following the last byte of data in use in 'b'. */
static inline void *
dp_packet_tail(const struct dp_packet *b)
{
+#ifdef DPDK_NETDEV
+ if (b->source == DPBUF_DPDK) {
+ struct rte_mbuf *buf = CONST_CAST(struct rte_mbuf *, &b->mbuf);
+ /* Find last segment where data ends, meaning the tail of the chained
+ * mbufs must be there */
+ buf = rte_pktmbuf_lastseg(buf);
+
+ return rte_pktmbuf_mtod_offset(buf, void *, buf->data_len);
+ }
+#endif
return (char *) dp_packet_data(b) + dp_packet_size(b);
}
@@ -211,6 +237,15 @@ dp_packet_tail(const struct dp_packet *b)
static inline void *
dp_packet_end(const struct dp_packet *b)
{
+#ifdef DPDK_NETDEV
+ if (b->source == DPBUF_DPDK) {
+ struct rte_mbuf *buf = CONST_CAST(struct rte_mbuf *, &(b->mbuf));
+
+ buf = rte_pktmbuf_lastseg(buf);
+
+ return (char *) buf->buf_addr + buf->buf_len;
+ }
+#endif
return (char *) dp_packet_base(b) + dp_packet_get_allocated(b);
}
@@ -236,6 +271,15 @@ dp_packet_tailroom(const struct dp_packet *b)
static inline void
dp_packet_clear(struct dp_packet *b)
{
+#ifdef DPDK_NETDEV
+ if (b->source == DPBUF_DPDK) {
+ /* sets pkt_len and data_len to zero and frees unused mbufs */
+ dp_packet_set_size(b, 0);
+ rte_pktmbuf_reset(&b->mbuf);
+
+ return;
+ }
+#endif
dp_packet_set_data(b, dp_packet_base(b));
dp_packet_set_size(b, 0);
}
@@ -252,12 +296,33 @@ dp_packet_pull(struct dp_packet *b, size_t size)
return data;
}
+#ifdef DPDK_NETDEV
+/* Similar to dp_packet_try_pull() but doesn't actually pull any data, only
+ * checks if it could and returns true or false accordingly.
+ *
+ * Valid for dp_packets carrying mbufs only. */
+static inline bool
+dp_packet_mbuf_may_pull(const struct dp_packet *b, size_t size) {
+ if (size > b->mbuf.data_len) {
+ return false;
+ }
+
+ return true;
+}
+#endif
+
/* If 'b' has at least 'size' bytes of data, removes that many bytes from the
* head end of 'b' and returns the first byte removed. Otherwise, returns a
* null pointer without modifying 'b'. */
static inline void *
dp_packet_try_pull(struct dp_packet *b, size_t size)
{
+#ifdef DPDK_NETDEV
+ if (!dp_packet_mbuf_may_pull(b, size)) {
+ return NULL;
+ }
+#endif
+
return dp_packet_size(b) - dp_packet_l2_pad_size(b) >= size
? dp_packet_pull(b, size) : NULL;
}
@@ -311,6 +376,12 @@ dp_packet_set_l2_pad_size(struct dp_packet *b, uint8_t pad_size)
static inline void *
dp_packet_l2_5(const struct dp_packet *b)
{
+#ifdef DPDK_NETDEV
+ if (!dp_packet_mbuf_may_pull(b, b->l2_5_ofs)) {
+ return NULL;
+ }
+#endif
+
return b->l2_5_ofs != UINT16_MAX
? (char *) dp_packet_data(b) + b->l2_5_ofs
: NULL;
@@ -327,6 +398,12 @@ dp_packet_set_l2_5(struct dp_packet *b, void *l2_5)
static inline void *
dp_packet_l3(const struct dp_packet *b)
{
+#ifdef DPDK_NETDEV
+ if (!dp_packet_mbuf_may_pull(b, b->l3_ofs)) {
+ return NULL;
+ }
+#endif
+
return b->l3_ofs != UINT16_MAX
? (char *) dp_packet_data(b) + b->l3_ofs
: NULL;
@@ -341,6 +418,12 @@ dp_packet_set_l3(struct dp_packet *b, void *l3)
static inline void *
dp_packet_l4(const struct dp_packet *b)
{
+#ifdef DPDK_NETDEV
+ if (!dp_packet_mbuf_may_pull(b, b->l4_ofs)) {
+ return NULL;
+ }
+#endif
+
return b->l4_ofs != UINT16_MAX
? (char *) dp_packet_data(b) + b->l4_ofs
: NULL;
@@ -355,6 +438,27 @@ dp_packet_set_l4(struct dp_packet *b, void *l4)
static inline size_t
dp_packet_l4_size(const struct dp_packet *b)
{
+#ifdef DPDK_NETDEV
+ if (b->source == DPBUF_DPDK) {
+ if (!dp_packet_mbuf_may_pull(b, b->l4_ofs)) {
+ return 0;
+ }
+
+ struct rte_mbuf *mbuf = CONST_CAST(struct rte_mbuf *, &b->mbuf);
+ size_t l4_size = mbuf->data_len - b->l4_ofs;
+
+ mbuf = mbuf->next;
+ while (mbuf) {
+ l4_size += mbuf->data_len;
+
+ mbuf = mbuf->next;
+ }
+
+ l4_size -= dp_packet_l2_pad_size(b);
+
+ return l4_size;
+ }
+#endif
return b->l4_ofs != UINT16_MAX
? (const char *)dp_packet_tail(b) - (const char *)dp_packet_l4(b)
- dp_packet_l2_pad_size(b)
@@ -509,7 +613,7 @@ __packet_set_data(struct dp_packet *b, uint16_t v)
static inline uint16_t
dp_packet_get_allocated(const struct dp_packet *b)
{
- return b->mbuf.buf_len;
+ return b->mbuf.nb_segs * b->mbuf.buf_len;
}
static inline void