2
0
mirror of https://github.com/openvswitch/ovs synced 2025-10-29 15:28:56 +00:00

netdev-dpdk: Remove alloc from packet recv.

On DPDK packet recv, ovs is given pointer to mbuf which has
information about a packet, for example pointer to data and size.
By moving mbuf to ofpbuf we can let dpdk allocate ofpbuf and
pass that to ovs for processing the packet.

Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
This commit is contained in:
Pravin Shelar
2014-03-31 13:17:24 -07:00
committed by Pravin B Shelar
parent 1005dd9a16
commit b3cd9f9d6a
3 changed files with 59 additions and 54 deletions

View File

@@ -209,16 +209,53 @@ dpdk_rte_mzalloc(size_t sz)
void
free_dpdk_buf(struct ofpbuf *b)
{
struct rte_mbuf *pkt;
pkt = b->private_p;
if (!pkt) {
return;
}
struct rte_mbuf *pkt = (struct rte_mbuf *) b;
rte_mempool_put(pkt->pool, pkt);
}
static void
__rte_pktmbuf_init(struct rte_mempool *mp,
void *opaque_arg OVS_UNUSED,
void *_m,
unsigned i OVS_UNUSED)
{
struct rte_mbuf *m = _m;
uint32_t buf_len = mp->elt_size - sizeof(struct ofpbuf);
RTE_MBUF_ASSERT(mp->elt_size >= sizeof(struct ofpbuf));
memset(m, 0, mp->elt_size);
/* start of buffer is just after mbuf structure */
m->buf_addr = (char *)m + sizeof(struct ofpbuf);
m->buf_physaddr = rte_mempool_virt2phy(mp, m) +
sizeof(struct ofpbuf);
m->buf_len = (uint16_t)buf_len;
/* keep some headroom between start of buffer and data */
m->pkt.data = (char*) m->buf_addr + RTE_MIN(RTE_PKTMBUF_HEADROOM, m->buf_len);
/* init some constant fields */
m->type = RTE_MBUF_PKT;
m->pool = mp;
m->pkt.nb_segs = 1;
m->pkt.in_port = 0xff;
}
static void
ovs_rte_pktmbuf_init(struct rte_mempool *mp,
void *opaque_arg OVS_UNUSED,
void *_m,
unsigned i OVS_UNUSED)
{
struct rte_mbuf *m = _m;
__rte_pktmbuf_init(mp, opaque_arg, _m, i);
ofpbuf_init_dpdk((struct ofpbuf *) m, m->buf_len);
}
static struct dpdk_mp *
dpdk_mp_get(int socket_id, int mtu) OVS_REQUIRES(dpdk_mutex)
{
@@ -242,7 +279,7 @@ dpdk_mp_get(int socket_id, int mtu) OVS_REQUIRES(dpdk_mutex)
MP_CACHE_SZ,
sizeof(struct rte_pktmbuf_pool_private),
rte_pktmbuf_pool_init, NULL,
rte_pktmbuf_init, NULL,
ovs_rte_pktmbuf_init, NULL,
socket_id, 0);
if (dmp->mp == NULL) {
@@ -550,47 +587,22 @@ dpdk_queue_flush(struct netdev_dpdk *dev, int qid)
rte_spinlock_unlock(&txq->tx_lock);
}
inline static struct ofpbuf *
build_ofpbuf(struct rte_mbuf *pkt)
{
struct ofpbuf *b;
b = ofpbuf_new(0);
b->private_p = pkt;
ofpbuf_set_data(b, pkt->pkt.data);
ofpbuf_set_base(b, (char *)ofpbuf_data(b) - DP_NETDEV_HEADROOM - VLAN_ETH_HEADER_LEN);
b->allocated = pkt->buf_len;
ofpbuf_set_size(b, rte_pktmbuf_data_len(pkt));
b->source = OFPBUF_DPDK;
dp_packet_pad(b);
return b;
}
static int
netdev_dpdk_rxq_recv(struct netdev_rxq *rxq_, struct ofpbuf **packet, int *c)
netdev_dpdk_rxq_recv(struct netdev_rxq *rxq_, struct ofpbuf **packets, int *c)
{
struct netdev_rxq_dpdk *rx = netdev_rxq_dpdk_cast(rxq_);
struct netdev *netdev = rx->up.netdev;
struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
struct rte_mbuf *burst_pkts[MAX_RX_QUEUE_LEN];
int nb_rx;
int i;
dpdk_queue_flush(dev, rxq_->queue_id);
nb_rx = rte_eth_rx_burst(rx->port_id, rxq_->queue_id,
burst_pkts, MAX_RX_QUEUE_LEN);
(struct rte_mbuf **) packets, MAX_RX_QUEUE_LEN);
if (!nb_rx) {
return EAGAIN;
}
for (i = 0; i < nb_rx; i++) {
packet[i] = build_ofpbuf(burst_pkts[i]);
}
*c = nb_rx;
return 0;
@@ -677,32 +689,23 @@ netdev_dpdk_send(struct netdev *netdev,
goto out;
}
rte_prefetch0(&ofpbuf->private_p);
if (!may_steal ||
!ofpbuf->private_p || ofpbuf->source != OFPBUF_DPDK) {
if (!may_steal || ofpbuf->source != OFPBUF_DPDK) {
dpdk_do_tx_copy(netdev, (char *) ofpbuf_data(ofpbuf), ofpbuf_size(ofpbuf));
} else {
struct rte_mbuf *pkt;
int qid;
pkt = ofpbuf->private_p;
ofpbuf->private_p = NULL;
rte_pktmbuf_data_len(pkt) = ofpbuf_size(ofpbuf);
rte_pktmbuf_pkt_len(pkt) = ofpbuf_size(ofpbuf);
if (may_steal) {
ofpbuf_delete(ofpbuf);
}
} else {
int qid;
qid = rte_lcore_id() % NR_QUEUE;
dpdk_queue_pkt(dev, qid, pkt);
dpdk_queue_pkt(dev, qid, (struct rte_mbuf *)ofpbuf);
ofpbuf->private_p = NULL;
}
ret = 0;
out:
if (may_steal) {
ofpbuf_delete(ofpbuf);
}
return ret;
}