Signed-off-by: Daniele Di Proietto <[email protected]>
---
lib/netdev-dpdk.c | 139 +++++++++++++++++++++++++++++++-----------------------
1 file changed, 80 insertions(+), 59 deletions(-)
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index ee811eb..0798a18 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -605,107 +605,128 @@ netdev_dpdk_rxq_recv(struct netdev_rxq *rxq_, struct
ofpbuf **packets, int *c)
}
inline static void
-dpdk_queue_pkt(struct netdev_dpdk *dev, int qid,
- struct rte_mbuf *pkt)
+dpdk_queue_pkts(struct netdev_dpdk *dev, int qid,
+ struct rte_mbuf **pkts, int c)
{
struct dpdk_tx_queue *txq = &dev->tx_q[qid];
uint64_t diff_tsc;
uint64_t cur_tsc;
uint32_t nb_tx;
+ int i = 0;
+
rte_spinlock_lock(&txq->tx_lock);
- txq->burst_pkts[txq->count++] = pkt;
- if (txq->count == MAX_TX_QUEUE_LEN) {
- goto flush;
- }
- cur_tsc = rte_get_timer_cycles();
- if (txq->count == 1) {
- txq->tsc = cur_tsc;
- }
- diff_tsc = cur_tsc - txq->tsc;
- if (diff_tsc >= DRAIN_TSC) {
- goto flush;
- }
- rte_spinlock_unlock(&txq->tx_lock);
- return;
+ while (i < c) {
+ int freeslots = MAX_TX_QUEUE_LEN - txq->count;
+ int tocopy = MIN(freeslots, c-i);
-flush:
- nb_tx = rte_eth_tx_burst(dev->port_id, qid, txq->burst_pkts, txq->count);
- if (nb_tx != txq->count) {
- /* free buffers if we couldn't transmit packets */
- rte_mempool_put_bulk(dev->dpdk_mp->mp,
- (void **) &txq->burst_pkts[nb_tx],
- (txq->count - nb_tx));
+ memcpy(&txq->burst_pkts[txq->count], &pkts[i], tocopy * sizeof (struct
rte_mbuf *));
+
+ txq->count += tocopy;
+ i += tocopy;
+
+ if (txq->count == MAX_TX_QUEUE_LEN) {
+ goto flush;
+ }
+ cur_tsc = rte_get_timer_cycles();
+ if (txq->count == 1) {
+ txq->tsc = cur_tsc;
+ }
+ diff_tsc = cur_tsc - txq->tsc;
+ if (diff_tsc >= DRAIN_TSC) {
+ goto flush;
+ }
+ continue;
+
+ flush:
+ nb_tx = rte_eth_tx_burst(dev->port_id, qid, txq->burst_pkts,
txq->count);
+ if (nb_tx != txq->count) {
+ /* free buffers if we couldn't transmit packets */
+ rte_mempool_put_bulk(dev->dpdk_mp->mp,
+ (void **) &txq->burst_pkts[nb_tx],
+ (txq->count - nb_tx));
+ }
+ txq->count = 0;
}
- txq->count = 0;
rte_spinlock_unlock(&txq->tx_lock);
}
/* Tx function. Transmit packets indefinitely */
static void
-dpdk_do_tx_copy(struct netdev *netdev, char *buf, int size)
+dpdk_do_tx_copy(struct netdev *netdev, struct ofpbuf ** ofpbufs, int c)
{
struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
- struct rte_mbuf *pkt;
+ struct rte_mbuf *pkts[c];
+ int i;
- pkt = rte_pktmbuf_alloc(dev->dpdk_mp->mp);
- if (!pkt) {
- ovs_mutex_lock(&dev->mutex);
- dev->stats.tx_dropped++;
- ovs_mutex_unlock(&dev->mutex);
- return;
- }
+ for (i = 0; i < c; i++) {
+ int size = ofpbuf_size(ofpbufs[i]);
+ if (size > dev->max_packet_len) {
+ VLOG_WARN_RL(&rl, "Too big size %d max_packet_len %d",
+ (int)size , dev->max_packet_len);
+
+ ovs_mutex_lock(&dev->mutex);
+ dev->stats.tx_dropped++;
+ ovs_mutex_unlock(&dev->mutex);
+ }
+
+ pkts[i] = rte_pktmbuf_alloc(dev->dpdk_mp->mp);
+
+ if (!pkts[i]) {
+ ovs_mutex_lock(&dev->mutex);
+ dev->stats.tx_dropped++;
+ ovs_mutex_unlock(&dev->mutex);
+ return;
+ }
- /* We have to do a copy for now */
- memcpy(pkt->pkt.data, buf, size);
+ /* We have to do a copy for now */
+ memcpy(pkts[i]->pkt.data, ofpbuf_data(ofpbufs[i]), size);
- rte_pktmbuf_data_len(pkt) = size;
- rte_pktmbuf_pkt_len(pkt) = size;
+ rte_pktmbuf_data_len(pkts[i]) = size;
+ rte_pktmbuf_pkt_len(pkts[i]) = size;
+ }
- dpdk_queue_pkt(dev, NON_PMD_THREAD_TX_QUEUE, pkt);
+ dpdk_queue_pkts(dev, NON_PMD_THREAD_TX_QUEUE, pkts, c);
dpdk_queue_flush(dev, NON_PMD_THREAD_TX_QUEUE);
}
static int
-netdev_dpdk_send(struct netdev *netdev,
- struct ofpbuf *ofpbuf, bool may_steal)
+netdev_dpdk_send_batch(struct netdev *netdev,
+ struct ofpbuf **ofpbufs, int c, bool may_steal)
{
struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
int ret;
+ int i;
- if (ofpbuf_size(ofpbuf) > dev->max_packet_len) {
- VLOG_WARN_RL(&rl, "Too big size %d max_packet_len %d",
- (int)ofpbuf_size(ofpbuf) , dev->max_packet_len);
-
- ovs_mutex_lock(&dev->mutex);
- dev->stats.tx_dropped++;
- ovs_mutex_unlock(&dev->mutex);
-
- ret = E2BIG;
- goto out;
- }
-
- if (!may_steal || ofpbuf->source != OFPBUF_DPDK) {
- dpdk_do_tx_copy(netdev, (char *) ofpbuf_data(ofpbuf),
ofpbuf_size(ofpbuf));
+ if (!may_steal || ofpbufs[0]->source != OFPBUF_DPDK) {
+ dpdk_do_tx_copy(netdev, ofpbufs, c);
if (may_steal) {
- ofpbuf_delete(ofpbuf);
+ for (i = 0; i < c; i++) {
+ ofpbuf_delete(ofpbufs[i]);
+ }
}
} else {
int qid;
qid = rte_lcore_id() % NR_QUEUE;
- dpdk_queue_pkt(dev, qid, (struct rte_mbuf *)ofpbuf);
-
+ /* TODO: warn if any packet bigger than dev->max_packet_len */
+ dpdk_queue_pkts(dev, qid, (struct rte_mbuf **)ofpbufs, c);
}
ret = 0;
-out:
return ret;
}
static int
+netdev_dpdk_send(struct netdev *netdev,
+ struct ofpbuf *ofpbuf, bool may_steal)
+{
+ return netdev_dpdk_send_batch(netdev, &ofpbuf, 1, may_steal);
+}
+
+static int
netdev_dpdk_set_etheraddr(struct netdev *netdev,
const uint8_t mac[ETH_ADDR_LEN])
{
@@ -1122,7 +1143,7 @@ static struct netdev_class netdev_dpdk_class = {
NULL, /* get_tunnel_config */
netdev_dpdk_send, /* send */
- NULL, /* send_batch */
+ netdev_dpdk_send_batch, /* send_batch */
NULL, /* send_wait */
netdev_dpdk_set_etheraddr,
--
2.0.0.rc0
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev