#include <stddef.h>
#include <stdint.h>
-#include "list.h"
+
+#ifdef DPDK_NETDEV
+#include <rte_config.h>
+#include <rte_mbuf.h>
+#endif
+
+#include "netdev-dpdk.h"
+#include "openvswitch/list.h"
#include "packets.h"
#include "util.h"
-#include "netdev-dpdk.h"
#ifdef __cplusplus
extern "C" {
* ref to build_dp_packet() in netdev-dpdk. */
};
+#define DP_PACKET_CONTEXT_SIZE 64
+
/* Buffer for holding packet data. A dp_packet is automatically reallocated
* as necessary if it grows too large for the available memory.
*/
uint16_t data_ofs; /* First byte actually in use. */
uint32_t size_; /* Number of bytes in use. */
uint32_t rss_hash; /* Packet hash. */
+ bool rss_hash_valid; /* Is the 'rss_hash' valid? */
#endif
enum dp_packet_source source; /* Source of memory allocated as 'base'. */
uint8_t l2_pad_size; /* Detected l2 padding size.
* or UINT16_MAX. */
uint16_t l4_ofs; /* Transport-level header offset,
or UINT16_MAX. */
- struct pkt_metadata md;
+ uint32_t cutlen; /* length in bytes to cut from the end. */
+ union {
+ struct pkt_metadata md;
+ uint64_t data[DP_PACKET_CONTEXT_SIZE / 8];
+ };
};
static inline void *dp_packet_data(const struct dp_packet *);
void *dp_packet_steal_data(struct dp_packet *);
-char *dp_packet_to_string(const struct dp_packet *, size_t maxbytes);
static inline bool dp_packet_equal(const struct dp_packet *,
const struct dp_packet *);
}
#endif
+static inline void
+dp_packet_reset_cutlen(struct dp_packet *b)
+{
+ b->cutlen = 0;
+}
+
+static inline uint32_t
+dp_packet_set_cutlen(struct dp_packet *b, uint32_t max_len)
+{
+ if (max_len < ETH_HEADER_LEN) {
+ max_len = ETH_HEADER_LEN;
+ }
+
+ if (max_len >= dp_packet_size(b)) {
+ b->cutlen = 0;
+ } else {
+ b->cutlen = dp_packet_size(b) - max_len;
+ }
+ return b->cutlen;
+}
+
+static inline uint32_t
+dp_packet_get_cutlen(struct dp_packet *b)
+{
+ /* Always in valid range if user uses dp_packet_set_cutlen. */
+ return b->cutlen;
+}
+
static inline void *
dp_packet_data(const struct dp_packet *b)
{
{
dp_packet_set_size(b, dp_packet_size(b) - off);
dp_packet_set_data(b, ((unsigned char *) dp_packet_data(b) + off));
- b->l2_5_ofs = b->l3_ofs = b->l4_ofs = UINT16_MAX;
+ dp_packet_reset_offsets(b);
}
+/* Returns the RSS hash of the packet 'p'. Note that the returned value is
+ * correct only if 'dp_packet_rss_valid(p)' returns true */
static inline uint32_t
dp_packet_get_rss_hash(struct dp_packet *p)
{
{
#ifdef DPDK_NETDEV
p->mbuf.hash.rss = hash;
+ p->mbuf.ol_flags |= PKT_RX_RSS_HASH;
#else
p->rss_hash = hash;
+ p->rss_hash_valid = true;
#endif
}
+static inline bool
+dp_packet_rss_valid(struct dp_packet *p)
+{
+#ifdef DPDK_NETDEV
+ return p->mbuf.ol_flags & PKT_RX_RSS_HASH;
+#else
+ return p->rss_hash_valid;
+#endif
+}
+
+static inline void
+dp_packet_rss_invalidate(struct dp_packet *p)
+{
+#ifdef DPDK_NETDEV
+ p->mbuf.ol_flags &= ~PKT_RX_RSS_HASH;
+#else
+ p->rss_hash_valid = false;
+#endif
+}
+
+enum { NETDEV_MAX_BURST = 32 }; /* Maximum number packets in a batch. */
+
+struct dp_packet_batch {
+ int count;
+ bool trunc; /* true if the batch needs truncate. */
+ struct dp_packet *packets[NETDEV_MAX_BURST];
+};
+
+static inline void dp_packet_batch_init(struct dp_packet_batch *b)
+{
+ b->count = 0;
+ b->trunc = false;
+}
+
+static inline void
+dp_packet_batch_clone(struct dp_packet_batch *dst,
+ struct dp_packet_batch *src)
+{
+ int i;
+
+ for (i = 0; i < src->count; i++) {
+ dst->packets[i] = dp_packet_clone(src->packets[i]);
+ }
+ dst->count = src->count;
+ dst->trunc = src->trunc;
+}
+
+static inline void
+packet_batch_init_packet(struct dp_packet_batch *b, struct dp_packet *p)
+{
+ b->count = 1;
+ b->trunc = false;
+ b->packets[0] = p;
+}
+
+static inline void
+dp_packet_delete_batch(struct dp_packet_batch *batch, bool may_steal)
+{
+ if (may_steal) {
+ int i;
+
+ for (i = 0; i < batch->count; i++) {
+ dp_packet_delete(batch->packets[i]);
+ }
+ }
+}
+
+static inline void
+dp_packet_batch_apply_cutlen(struct dp_packet_batch *pktb)
+{
+ int i;
+
+ if (!pktb->trunc)
+ return;
+
+ for (i = 0; i < pktb->count; i++) {
+ uint32_t cutlen = dp_packet_get_cutlen(pktb->packets[i]);
+
+ dp_packet_set_size(pktb->packets[i],
+ dp_packet_size(pktb->packets[i]) - cutlen);
+ dp_packet_reset_cutlen(pktb->packets[i]);
+ }
+ pktb->trunc = false;
+}
+
+static inline void
+dp_packet_batch_reset_cutlen(struct dp_packet_batch *pktb)
+{
+ int i;
+
+ if (!pktb->trunc)
+ return;
+
+ pktb->trunc = false;
+ for (i = 0; i < pktb->count; i++) {
+ dp_packet_reset_cutlen(pktb->packets[i]);
+ }
+}
+
#ifdef __cplusplus
}
#endif