]> git.proxmox.com Git - mirror_ovs.git/commitdiff
netdev-provider: Apply batch object to netdev provider.
authorWilliam Tu <u9012063@gmail.com>
Tue, 19 Jul 2016 00:05:35 +0000 (17:05 -0700)
committerDaniele Di Proietto <diproiettod@vmware.com>
Thu, 21 Jul 2016 23:46:32 +0000 (16:46 -0700)
Commit 1895cc8dbb64 ("dpif-netdev: create batch object") introduces
batch process functions and 'struct dp_packet_batch' to associate with
batch-level metadata.  This patch applies the packet batch object to
the netdev provider interface (dummy, Linux, BSD, and DPDK) so that
batch APIs can be used in providers.  With batch metadata visible in
providers, optimizations can be introduced at per-batch level instead
of per-packet.

Tested-at: https://travis-ci.org/williamtu/ovs-travis/builds/145694197
Signed-off-by: William Tu <u9012063@gmail.com>
Signed-off-by: Daniele Di Proietto <diproiettod@vmware.com>
lib/netdev-bsd.c
lib/netdev-dpdk.c
lib/netdev-dummy.c
lib/netdev-linux.c
lib/netdev-provider.h
lib/netdev.c

index 2e92d976801288f31c82e81fea49e3aa866a794a..869d54d350644aa0f3e98925ead8b6cdfc6922cf 100644 (file)
@@ -618,8 +618,7 @@ netdev_rxq_bsd_recv_tap(struct netdev_rxq_bsd *rxq, struct dp_packet *buffer)
 }
 
 static int
-netdev_bsd_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet **packets,
-                    int *c)
+netdev_bsd_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet_batch *batch)
 {
     struct netdev_rxq_bsd *rxq = netdev_rxq_bsd_cast(rxq_);
     struct netdev *netdev = rxq->up.netdev;
@@ -641,8 +640,8 @@ netdev_bsd_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet **packets,
         dp_packet_delete(packet);
     } else {
         dp_packet_pad(packet);
-        packets[0] = packet;
-        *c = 1;
+        batch->packets[0] = packet;
+        batch->count = 1;
     }
     return retval;
 }
@@ -681,7 +680,7 @@ netdev_bsd_rxq_drain(struct netdev_rxq *rxq_)
  */
 static int
 netdev_bsd_send(struct netdev *netdev_, int qid OVS_UNUSED,
-                struct dp_packet **pkts, int cnt, bool may_steal)
+                struct dp_packet_batch *batch, bool may_steal)
 {
     struct netdev_bsd *dev = netdev_bsd_cast(netdev_);
     const char *name = netdev_get_name(netdev_);
@@ -695,12 +694,12 @@ netdev_bsd_send(struct netdev *netdev_, int qid OVS_UNUSED,
         error = 0;
     }
 
-    for (i = 0; i < cnt; i++) {
-        const void *data = dp_packet_data(pkts[i]);
-        size_t size = dp_packet_size(pkts[i]);
+    for (i = 0; i < batch->count; i++) {
+        const void *data = dp_packet_data(batch->packets[i]);
+        size_t size = dp_packet_size(batch->packets[i]);
 
         /* Truncate the packet if it is configured. */
-        size -= dp_packet_get_cutlen(pkts[i]);
+        size -= dp_packet_get_cutlen(batch->packets[i]);
 
         while (!error) {
             ssize_t retval;
@@ -731,11 +730,7 @@ netdev_bsd_send(struct netdev *netdev_, int qid OVS_UNUSED,
     }
 
     ovs_mutex_unlock(&dev->mutex);
-    if (may_steal) {
-        for (i = 0; i < cnt; i++) {
-            dp_packet_delete(pkts[i]);
-        }
-    }
+    dp_packet_delete_batch(batch, may_steal);
 
     return error;
 }
index 85b18fd5e13361401c778876b32ba6803af174cb..7fb6457af42e9c74a07427d1039063b4f9b26bb2 100644 (file)
@@ -478,7 +478,8 @@ dpdk_mp_get(int socket_id, int mtu) OVS_REQUIRES(dpdk_mutex)
     dmp->mtu = mtu;
     dmp->refcount = 1;
     mbp_priv.mbuf_data_room_size = MBUF_SIZE(mtu) - sizeof(struct dp_packet);
-    mbp_priv.mbuf_priv_size = sizeof (struct dp_packet) - sizeof (struct rte_mbuf);
+    mbp_priv.mbuf_priv_size = sizeof (struct dp_packet) -
+                              sizeof (struct rte_mbuf);
 
     mp_size = MAX_NB_MBUF;
     do {
@@ -1215,7 +1216,7 @@ netdev_dpdk_vhost_update_rx_counters(struct netdev_stats *stats,
  */
 static int
 netdev_dpdk_vhost_rxq_recv(struct netdev_rxq *rxq,
-                           struct dp_packet **packets, int *c)
+                           struct dp_packet_batch *batch)
 {
     struct netdev_dpdk *dev = netdev_dpdk_cast(rxq->netdev);
     struct virtio_net *virtio_dev = netdev_dpdk_get_virtio(dev);
@@ -1231,7 +1232,7 @@ netdev_dpdk_vhost_rxq_recv(struct netdev_rxq *rxq,
 
     nb_rx = rte_vhost_dequeue_burst(virtio_dev, qid * VIRTIO_QNUM + VIRTIO_TXQ,
                                     dev->dpdk_mp->mp,
-                                    (struct rte_mbuf **)packets,
+                                    (struct rte_mbuf **) batch->packets,
                                     NETDEV_MAX_BURST);
     if (!nb_rx) {
         return EAGAIN;
@@ -1239,21 +1240,23 @@ netdev_dpdk_vhost_rxq_recv(struct netdev_rxq *rxq,
 
     if (policer) {
         dropped = nb_rx;
-        nb_rx = ingress_policer_run(policer, (struct rte_mbuf **)packets, nb_rx);
+        nb_rx = ingress_policer_run(policer,
+                                    (struct rte_mbuf **) batch->packets,
+                                    nb_rx);
         dropped -= nb_rx;
     }
 
     rte_spinlock_lock(&dev->stats_lock);
-    netdev_dpdk_vhost_update_rx_counters(&dev->stats, packets, nb_rx, dropped);
+    netdev_dpdk_vhost_update_rx_counters(&dev->stats, batch->packets,
+                                         nb_rx, dropped);
     rte_spinlock_unlock(&dev->stats_lock);
 
-    *c = (int) nb_rx;
+    batch->count = (int) nb_rx;
     return 0;
 }
 
 static int
-netdev_dpdk_rxq_recv(struct netdev_rxq *rxq, struct dp_packet **packets,
-                     int *c)
+netdev_dpdk_rxq_recv(struct netdev_rxq *rxq, struct dp_packet_batch *batch)
 {
     struct netdev_rxq_dpdk *rx = netdev_rxq_dpdk_cast(rxq);
     struct netdev_dpdk *dev = netdev_dpdk_cast(rxq->netdev);
@@ -1262,7 +1265,7 @@ netdev_dpdk_rxq_recv(struct netdev_rxq *rxq, struct dp_packet **packets,
     int dropped = 0;
 
     nb_rx = rte_eth_rx_burst(rx->port_id, rxq->queue_id,
-                             (struct rte_mbuf **) packets,
+                             (struct rte_mbuf **) batch->packets,
                              NETDEV_MAX_BURST);
     if (!nb_rx) {
         return EAGAIN;
@@ -1270,7 +1273,9 @@ netdev_dpdk_rxq_recv(struct netdev_rxq *rxq, struct dp_packet **packets,
 
     if (policer) {
         dropped = nb_rx;
-        nb_rx = ingress_policer_run(policer, (struct rte_mbuf **) packets, nb_rx);
+        nb_rx = ingress_policer_run(policer,
+                                    (struct rte_mbuf **)batch->packets,
+                                    nb_rx);
         dropped -= nb_rx;
     }
 
@@ -1281,7 +1286,7 @@ netdev_dpdk_rxq_recv(struct netdev_rxq *rxq, struct dp_packet **packets,
         rte_spinlock_unlock(&dev->stats_lock);
     }
 
-    *c = nb_rx;
+    batch->count = nb_rx;
 
     return 0;
 }
@@ -1384,12 +1389,11 @@ out:
 
 /* Tx function. Transmit packets indefinitely */
 static void
-dpdk_do_tx_copy(struct netdev *netdev, int qid, struct dp_packet **pkts,
-                int cnt)
+dpdk_do_tx_copy(struct netdev *netdev, int qid, struct dp_packet_batch *batch)
     OVS_NO_THREAD_SAFETY_ANALYSIS
 {
 #if !defined(__CHECKER__) && !defined(_WIN32)
-    const size_t PKT_ARRAY_SIZE = cnt;
+    const size_t PKT_ARRAY_SIZE = batch->count;
 #else
     /* Sparse or MSVC doesn't like variable length array. */
     enum { PKT_ARRAY_SIZE = NETDEV_MAX_BURST };
@@ -1407,8 +1411,8 @@ dpdk_do_tx_copy(struct netdev *netdev, int qid, struct dp_packet **pkts,
         ovs_mutex_lock(&nonpmd_mempool_mutex);
     }
 
-    for (i = 0; i < cnt; i++) {
-        int size = dp_packet_size(pkts[i]);
+    for (i = 0; i < batch->count; i++) {
+        int size = dp_packet_size(batch->packets[i]);
 
         if (OVS_UNLIKELY(size > dev->max_packet_len)) {
             VLOG_WARN_RL(&rl, "Too big size %d max_packet_len %d",
@@ -1421,16 +1425,17 @@ dpdk_do_tx_copy(struct netdev *netdev, int qid, struct dp_packet **pkts,
         mbufs[newcnt] = rte_pktmbuf_alloc(dev->dpdk_mp->mp);
 
         if (!mbufs[newcnt]) {
-            dropped += cnt - i;
+            dropped += batch->count - i;
             break;
         }
 
         /* Cut the size so only the truncated size is copied. */
-        size -= dp_packet_get_cutlen(pkts[i]);
-        dp_packet_reset_cutlen(pkts[i]);
+        size -= dp_packet_get_cutlen(batch->packets[i]);
+        dp_packet_reset_cutlen(batch->packets[i]);
 
         /* We have to do a copy for now */
-        memcpy(rte_pktmbuf_mtod(mbufs[newcnt], void *), dp_packet_data(pkts[i]), size);
+        memcpy(rte_pktmbuf_mtod(mbufs[newcnt], void *),
+               dp_packet_data(batch->packets[i]), size);
 
         rte_pktmbuf_data_len(mbufs[newcnt]) = size;
         rte_pktmbuf_pkt_len(mbufs[newcnt]) = size;
@@ -1439,7 +1444,8 @@ dpdk_do_tx_copy(struct netdev *netdev, int qid, struct dp_packet **pkts,
     }
 
     if (dev->type == DPDK_DEV_VHOST) {
-        __netdev_dpdk_vhost_send(netdev, qid, (struct dp_packet **) mbufs, newcnt, true);
+        __netdev_dpdk_vhost_send(netdev, qid, (struct dp_packet **) mbufs,
+                                 newcnt, true);
     } else {
         unsigned int qos_pkts = newcnt;
 
@@ -1462,84 +1468,69 @@ dpdk_do_tx_copy(struct netdev *netdev, int qid, struct dp_packet **pkts,
 }
 
 static int
-netdev_dpdk_vhost_send(struct netdev *netdev, int qid, struct dp_packet **pkts,
-                 int cnt, bool may_steal)
+netdev_dpdk_vhost_send(struct netdev *netdev, int qid,
+                       struct dp_packet_batch *batch,
+                       bool may_steal)
 {
-    if (OVS_UNLIKELY(pkts[0]->source != DPBUF_DPDK)) {
-        int i;
 
-        dpdk_do_tx_copy(netdev, qid, pkts, cnt);
-        if (may_steal) {
-            for (i = 0; i < cnt; i++) {
-                dp_packet_delete(pkts[i]);
-            }
-        }
+    if (OVS_UNLIKELY(batch->packets[0]->source != DPBUF_DPDK)) {
+        dpdk_do_tx_copy(netdev, qid, batch);
+        dp_packet_delete_batch(batch, may_steal);
     } else {
-        int i;
-
-        for (i = 0; i < cnt; i++) {
-            int cutlen = dp_packet_get_cutlen(pkts[i]);
-
-            dp_packet_set_size(pkts[i], dp_packet_size(pkts[i]) - cutlen);
-            dp_packet_reset_cutlen(pkts[i]);
-        }
-        __netdev_dpdk_vhost_send(netdev, qid, pkts, cnt, may_steal);
+        dp_packet_batch_apply_cutlen(batch);
+        __netdev_dpdk_vhost_send(netdev, qid, batch->packets, batch->count,
+                                 may_steal);
     }
     return 0;
 }
 
 static inline void
 netdev_dpdk_send__(struct netdev_dpdk *dev, int qid,
-                   struct dp_packet **pkts, int cnt, bool may_steal)
+                   struct dp_packet_batch *batch, bool may_steal)
 {
-    int i;
-
     if (OVS_UNLIKELY(dev->txq_needs_locking)) {
         qid = qid % dev->up.n_txq;
         rte_spinlock_lock(&dev->tx_q[qid].tx_lock);
     }
 
     if (OVS_UNLIKELY(!may_steal ||
-                     pkts[0]->source != DPBUF_DPDK)) {
+                     batch->packets[0]->source != DPBUF_DPDK)) {
         struct netdev *netdev = &dev->up;
 
-        dpdk_do_tx_copy(netdev, qid, pkts, cnt);
-
-        if (may_steal) {
-            for (i = 0; i < cnt; i++) {
-                dp_packet_delete(pkts[i]);
-            }
-        }
+        dpdk_do_tx_copy(netdev, qid, batch);
+        dp_packet_delete_batch(batch, may_steal);
     } else {
         int next_tx_idx = 0;
         int dropped = 0;
         unsigned int qos_pkts = 0;
         unsigned int temp_cnt = 0;
+        int cnt = batch->count;
 
-        for (i = 0; i < cnt; i++) {
-            int size = dp_packet_size(pkts[i]);
+        for (int i = 0; i < cnt; i++) {
+            int size = dp_packet_size(batch->packets[i]);
 
-            size -= dp_packet_get_cutlen(pkts[i]);
-            dp_packet_set_size(pkts[i], size);
+            size -= dp_packet_get_cutlen(batch->packets[i]);
+            dp_packet_set_size(batch->packets[i], size);
 
             if (OVS_UNLIKELY(size > dev->max_packet_len)) {
                 if (next_tx_idx != i) {
                     temp_cnt = i - next_tx_idx;
                     qos_pkts = temp_cnt;
 
-                    temp_cnt = netdev_dpdk_qos_run__(dev, (struct rte_mbuf**)pkts,
-                                                temp_cnt);
+                    temp_cnt = netdev_dpdk_qos_run__(dev,
+                                        (struct rte_mbuf**)batch->packets,
+                                        temp_cnt);
                     dropped += qos_pkts - temp_cnt;
                     netdev_dpdk_eth_tx_burst(dev, qid,
-                                    (struct rte_mbuf **)&pkts[next_tx_idx],
-                                    temp_cnt);
+                            (struct rte_mbuf **)&batch->packets[next_tx_idx],
+                            temp_cnt);
 
                 }
 
                 VLOG_WARN_RL(&rl, "Too big size %d max_packet_len %d",
                              (int)size , dev->max_packet_len);
 
-                dp_packet_delete(pkts[i]);
+                dp_packet_delete(batch->packets[i]);
                 dropped++;
                 next_tx_idx = i + 1;
             }
@@ -1548,11 +1539,12 @@ netdev_dpdk_send__(struct netdev_dpdk *dev, int qid,
             cnt -= next_tx_idx;
             qos_pkts = cnt;
 
-            cnt = netdev_dpdk_qos_run__(dev, (struct rte_mbuf**)pkts, cnt);
+            cnt = netdev_dpdk_qos_run__(dev,
+                    (struct rte_mbuf**)batch->packets, cnt);
             dropped += qos_pkts - cnt;
             netdev_dpdk_eth_tx_burst(dev, qid,
-                                     (struct rte_mbuf **)&pkts[next_tx_idx],
-                                     cnt);
+                             (struct rte_mbuf **)&batch->packets[next_tx_idx],
+                             cnt);
         }
 
         if (OVS_UNLIKELY(dropped)) {
@@ -1569,11 +1561,11 @@ netdev_dpdk_send__(struct netdev_dpdk *dev, int qid,
 
 static int
 netdev_dpdk_eth_send(struct netdev *netdev, int qid,
-                     struct dp_packet **pkts, int cnt, bool may_steal)
+                     struct dp_packet_batch *batch, bool may_steal)
 {
     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
 
-    netdev_dpdk_send__(dev, qid, pkts, cnt, may_steal);
+    netdev_dpdk_send__(dev, qid, batch, may_steal);
     return 0;
 }
 
@@ -2011,7 +2003,8 @@ netdev_dpdk_set_miimon(struct netdev *netdev OVS_UNUSED,
 static int
 netdev_dpdk_update_flags__(struct netdev_dpdk *dev,
                            enum netdev_flags off, enum netdev_flags on,
-                           enum netdev_flags *old_flagsp) OVS_REQUIRES(dev->mutex)
+                           enum netdev_flags *old_flagsp)
+    OVS_REQUIRES(dev->mutex)
 {
     int err;
 
@@ -2518,7 +2511,8 @@ dpdk_ring_create(const char dev_name[], unsigned int port_no,
 }
 
 static int
-dpdk_ring_open(const char dev_name[], unsigned int *eth_port_id) OVS_REQUIRES(dpdk_mutex)
+dpdk_ring_open(const char dev_name[], unsigned int *eth_port_id)
+    OVS_REQUIRES(dpdk_mutex)
 {
     struct dpdk_ring *ivshmem;
     unsigned int port_no;
@@ -2544,7 +2538,7 @@ dpdk_ring_open(const char dev_name[], unsigned int *eth_port_id) OVS_REQUIRES(dp
 
 static int
 netdev_dpdk_ring_send(struct netdev *netdev, int qid,
-                      struct dp_packet **pkts, int cnt, bool may_steal)
+                      struct dp_packet_batch *batch, bool may_steal)
 {
     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
     unsigned i;
@@ -2553,11 +2547,11 @@ netdev_dpdk_ring_send(struct netdev *netdev, int qid,
      * rss hash field is clear. This is because the same mbuf may be modified by
      * the consumer of the ring and return into the datapath without recalculating
      * the RSS hash. */
-    for (i = 0; i < cnt; i++) {
-        dp_packet_rss_invalidate(pkts[i]);
+    for (i = 0; i < batch->count; i++) {
+        dp_packet_rss_invalidate(batch->packets[i]);
     }
 
-    netdev_dpdk_send__(dev, qid, pkts, cnt, may_steal);
+    netdev_dpdk_send__(dev, qid, batch, may_steal);
     return 0;
 }
 
index 9ea765b33209740cacf0f7ae6b7ac5ec916cead8..37c6b0226995238090380589c568ef28e9771d9f 100644 (file)
@@ -947,8 +947,7 @@ netdev_dummy_rxq_dealloc(struct netdev_rxq *rxq_)
 }
 
 static int
-netdev_dummy_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet **arr,
-                      int *c)
+netdev_dummy_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet_batch *batch)
 {
     struct netdev_rxq_dummy *rx = netdev_rxq_dummy_cast(rxq_);
     struct netdev_dummy *netdev = netdev_dummy_cast(rx->up.netdev);
@@ -991,8 +990,8 @@ netdev_dummy_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet **arr,
 
     dp_packet_pad(packet);
 
-    arr[0] = packet;
-    *c = 1;
+    batch->packets[0] = packet;
+    batch->count = 1;
     return 0;
 }
 
@@ -1030,17 +1029,17 @@ netdev_dummy_rxq_drain(struct netdev_rxq *rxq_)
 
 static int
 netdev_dummy_send(struct netdev *netdev, int qid OVS_UNUSED,
-                  struct dp_packet **pkts, int cnt, bool may_steal)
+                  struct dp_packet_batch *batch, bool may_steal)
 {
     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
     int error = 0;
     int i;
 
-    for (i = 0; i < cnt; i++) {
-        const void *buffer = dp_packet_data(pkts[i]);
-        size_t size = dp_packet_size(pkts[i]);
+    for (i = 0; i < batch->count; i++) {
+        const void *buffer = dp_packet_data(batch->packets[i]);
+        size_t size = dp_packet_size(batch->packets[i]);
 
-        size -= dp_packet_get_cutlen(pkts[i]);
+        size -= dp_packet_get_cutlen(batch->packets[i]);
 
         if (size < ETH_HEADER_LEN) {
             error = EMSGSIZE;
@@ -1096,11 +1095,7 @@ netdev_dummy_send(struct netdev *netdev, int qid OVS_UNUSED,
         ovs_mutex_unlock(&dev->mutex);
     }
 
-    if (may_steal) {
-        for (i = 0; i < cnt; i++) {
-            dp_packet_delete(pkts[i]);
-        }
-    }
+    dp_packet_delete_batch(batch, may_steal);
 
     return error;
 }
index 486910ab464df37ee1ad6a64ae8aba47365e3d7a..60ad38b9e361bcc199506f466aaafce3447686b8 100644 (file)
@@ -1091,8 +1091,7 @@ netdev_linux_rxq_recv_tap(int fd, struct dp_packet *buffer)
 }
 
 static int
-netdev_linux_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet **packets,
-                      int *c)
+netdev_linux_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet_batch *batch)
 {
     struct netdev_rxq_linux *rx = netdev_rxq_linux_cast(rxq_);
     struct netdev *netdev = rx->up.netdev;
@@ -1118,8 +1117,8 @@ netdev_linux_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet **packets,
         dp_packet_delete(buffer);
     } else {
         dp_packet_pad(buffer);
-        packets[0] = buffer;
-        *c = 1;
+        batch->packets[0] = buffer;
+        batch->count = 1;
     }
 
     return retval;
@@ -1161,19 +1160,19 @@ netdev_linux_rxq_drain(struct netdev_rxq *rxq_)
  * expected to do additional queuing of packets. */
 static int
 netdev_linux_send(struct netdev *netdev_, int qid OVS_UNUSED,
-                  struct dp_packet **pkts, int cnt, bool may_steal)
+                  struct dp_packet_batch *batch, bool may_steal)
 {
     int i;
     int error = 0;
 
     /* 'i' is incremented only if there's no error */
-    for (i = 0; i < cnt;) {
-        const void *data = dp_packet_data(pkts[i]);
-        size_t size = dp_packet_size(pkts[i]);
+    for (i = 0; i < batch->count;) {
+        const void *data = dp_packet_data(batch->packets[i]);
+        size_t size = dp_packet_size(batch->packets[i]);
         ssize_t retval;
 
         /* Truncate the packet if it is configured. */
-        size -= dp_packet_get_cutlen(pkts[i]);
+        size -= dp_packet_get_cutlen(batch->packets[i]);
 
         if (!is_tap_netdev(netdev_)) {
             /* Use our AF_PACKET socket to send to this device. */
@@ -1249,11 +1248,7 @@ netdev_linux_send(struct netdev *netdev_, int qid OVS_UNUSED,
         i++;
     }
 
-    if (may_steal) {
-        for (i = 0; i < cnt; i++) {
-            dp_packet_delete(pkts[i]);
-        }
-    }
+    dp_packet_delete_batch(batch, may_steal);
 
     if (error && error != EAGAIN) {
             VLOG_WARN_RL(&rl, "error sending Ethernet packet on %s: %s",
index 5da377f99991295b0848f8a95df4aa7f2681419b..c62dbd5a1e2d5e6beb421b92795bf66baf882f0f 100644 (file)
@@ -340,8 +340,8 @@ struct netdev_class {
      * network device from being usefully used by the netdev-based "userspace
      * datapath".  It will also prevent the OVS implementation of bonding from
      * working properly over 'netdev'.) */
-    int (*send)(struct netdev *netdev, int qid, struct dp_packet **buffers,
-                int cnt, bool may_steal);
+    int (*send)(struct netdev *netdev, int qid, struct dp_packet_batch *batch,
+                bool may_steal);
 
     /* Registers with the poll loop to wake up from the next call to
      * poll_block() when the packet transmission queue for 'netdev' has
@@ -727,25 +727,24 @@ struct netdev_class {
     void (*rxq_destruct)(struct netdev_rxq *);
     void (*rxq_dealloc)(struct netdev_rxq *);
 
-    /* Attempts to receive a batch of packets from 'rx'.  The caller supplies
-     * 'pkts' as the pointer to the beginning of an array of MAX_RX_BATCH
-     * pointers to dp_packet.  If successful, the implementation stores
-     * pointers to up to MAX_RX_BATCH dp_packets into the array, transferring
-     * ownership of the packets to the caller, stores the number of received
-     * packets into '*cnt', and returns 0.
+    /* Attempts to receive a batch of packets from 'rx'.  In 'batch', the
+     * caller supplies 'packets' as the pointer to the beginning of an array
+     * of MAX_RX_BATCH pointers to dp_packet.  If successful, the
+     * implementation stores pointers to up to MAX_RX_BATCH dp_packets into
+     * the array, transferring ownership of the packets to the caller, stores
+     * the number of received packets into 'count', and returns 0.
      *
      * The implementation does not necessarily initialize any non-data members
-     * of 'pkts'.  That is, the caller must initialize layer pointers and
-     * metadata itself, if desired, e.g. with pkt_metadata_init() and
-     * miniflow_extract().
+     * of 'packets' in 'batch'.  That is, the caller must initialize layer
+     * pointers and metadata itself, if desired, e.g. with pkt_metadata_init()
+     * and miniflow_extract().
      *
      * Implementations should allocate buffers with DP_NETDEV_HEADROOM bytes of
      * headroom.
      *
      * Returns EAGAIN immediately if no packet is ready to be received or
      * another positive errno value if an error was encountered. */
-    int (*rxq_recv)(struct netdev_rxq *rx, struct dp_packet **pkts,
-                    int *cnt);
+    int (*rxq_recv)(struct netdev_rxq *rx, struct dp_packet_batch *batch);
 
     /* Registers with the poll loop to wake up from the next call to
      * poll_block() when a packet is ready to be received with
index 66511731d96b1726f9f9d2b2f1285e1784c3a098..405bf41ef71399235ae1beef0304772d53f26b05 100644 (file)
@@ -625,7 +625,7 @@ netdev_rxq_recv(struct netdev_rxq *rx, struct dp_packet_batch *batch)
 {
     int retval;
 
-    retval = rx->netdev->netdev_class->rxq_recv(rx, batch->packets, &batch->count);
+    retval = rx->netdev->netdev_class->rxq_recv(rx,  batch);
     if (!retval) {
         COVERAGE_INC(netdev_received);
     } else {
@@ -711,9 +711,7 @@ netdev_send(struct netdev *netdev, int qid, struct dp_packet_batch *batch,
         return EOPNOTSUPP;
     }
 
-    int error = netdev->netdev_class->send(netdev, qid,
-                                           batch->packets, batch->count,
-                                           may_steal);
+    int error = netdev->netdev_class->send(netdev, qid, batch, may_steal);
     if (!error) {
         COVERAGE_INC(netdev_sent);
         if (!may_steal) {