@@ -88,10 +88,6 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
#define MTU_TO_MAX_FRAME_LEN(mtu) ((mtu) + ETHER_HDR_MAX_LEN)
#define FRAME_LEN_TO_MTU(frame_len) ((frame_len) \
- ETHER_HDR_LEN - ETHER_CRC_LEN)
-#define MBUF_SIZE(mtu) ROUND_UP((MTU_TO_MAX_FRAME_LEN(mtu) \
- + sizeof(struct dp_packet) \
- + RTE_PKTMBUF_HEADROOM), \
- RTE_CACHE_LINE_SIZE)
#define NETDEV_DPDK_MBUF_ALIGN 1024
#define NETDEV_DPDK_MAX_PKT_LEN 9728
@@ -641,6 +637,7 @@ dpdk_mp_create(struct netdev_dpdk *dev, int mtu, uint32_t mbuf_size,
uint32_t n_mbufs;
uint32_t hash = hash_string(netdev_name, 0);
struct dpdk_mp *dmp = NULL;
+ uint16_t pkt_size, aligned_mbuf_size, mbuf_priv_data_len;
int ret;
dmp = dpdk_rte_mzalloc(sizeof *dmp);
@@ -662,8 +659,8 @@ dpdk_mp_create(struct netdev_dpdk *dev, int mtu, uint32_t mbuf_size,
* so this is not an issue for tasks such as debugging.
*/
ret = snprintf(mp_name, RTE_MEMPOOL_NAMESIZE,
- "ovs%08x%02d%05d%07u",
- hash, socket_id, mtu, n_mbufs);
+ "ovs%08x%02d%05d%07u",
+ hash, socket_id, mtu, n_mbufs);
if (ret < 0 || ret >= RTE_MEMPOOL_NAMESIZE) {
VLOG_DBG("snprintf returned %d. "
"Failed to generate a mempool name for \"%s\". "
@@ -675,16 +672,33 @@ dpdk_mp_create(struct netdev_dpdk *dev, int mtu, uint32_t mbuf_size,
}
VLOG_DBG("Port %s: Requesting a mempool of %u mbufs of size %u "
- "on socket %d for %d Rx and %d Tx queues.",
+ "on socket %d for %d Rx and %d Tx queues, "
+ "cache line size of %u",
netdev_name, n_mbufs, mbuf_size, socket_id,
- dev->requested_n_rxq, dev->requested_n_txq);
-
- dmp->mp = rte_pktmbuf_pool_create(mp_name, n_mbufs,
- MP_CACHE_SZ,
- sizeof (struct dp_packet)
- - sizeof (struct rte_mbuf),
- MBUF_SIZE(mbuf_size)
- - sizeof(struct dp_packet),
+ dev->requested_n_rxq, dev->requested_n_txq,
+ RTE_CACHE_LINE_SIZE);
+
+ mbuf_priv_data_len = sizeof(struct dp_packet) -
+ sizeof(struct rte_mbuf);
+ /* The size of the entire dp_packet. */
+ pkt_size = sizeof (struct dp_packet) +
+ mbuf_size + RTE_PKTMBUF_HEADROOM;
+ /* mbuf size, rounded up to cacheline size. */
+ aligned_mbuf_size = ROUND_UP(pkt_size, RTE_CACHE_LINE_SIZE);
+ /* If there is a size discrepancy, add padding to mbuf_priv_data_len.
+ * This maintains mbuf size cache alignment, while also honoring RX
+ * buffer alignment in the data portion of the mbuf. If this adjustment
+ * is not made, there is a possiblity later on that for an element of
+ * the mempool, buf, buf->data_len < (buf->buf_len - buf->data_off).
+ * This is problematic in the case of multi-segment mbufs, particularly
+ * when an mbuf segment needs to be resized (when [push|popp]ing a VLAN
+ * header, for example.
+ */
+ mbuf_priv_data_len += (aligned_mbuf_size - pkt_size);
+
+ dmp->mp = rte_pktmbuf_pool_create(mp_name, n_mbufs, MP_CACHE_SZ,
+ mbuf_priv_data_len,
+ mbuf_size + RTE_PKTMBUF_HEADROOM,
socket_id);
if (dmp->mp) {