[ovs-dev] [dpdk patch v2 2/6] netdev: Add n_txq to 'struct netdev'.

Alex Wang alexw at nicira.com
Mon Sep 8 18:28:05 UTC 2014


This commit adds new variable n_txq to 'struct netdev' for recording
the number of tx queues.  Correspondingly, the send_*() functions are
extended to accept queue id as input argument.

All 'netdev-*' implementation will ignore the queue id since having
multiple tx queues is not supported.  Upcomping patches will start
using it and create multiple tx queues for dpdk netdev by default.

Signed-off-by: Alex Wang <alexw at nicira.com>

---
PATCH -> V2
- rebase and refactor the code.
---
 lib/dpif-netdev.c     |    2 +-
 lib/dpif-netdev.h     |    2 ++
 lib/netdev-bsd.c      |    6 +++---
 lib/netdev-dpdk.c     |    6 +++---
 lib/netdev-dummy.c    |    4 ++--
 lib/netdev-linux.c    |    6 +++---
 lib/netdev-provider.h |   27 ++++++++++++++++-----------
 lib/netdev.c          |   41 +++++++++++++++++++++++++----------------
 lib/netdev.h          |    5 +++--
 9 files changed, 58 insertions(+), 41 deletions(-)

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 869fb55..098f5e7 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -2447,7 +2447,7 @@ dp_execute_cb(void *aux_, struct dpif_packet **packets, int cnt,
     case OVS_ACTION_ATTR_OUTPUT:
         p = dp_netdev_lookup_port(dp, u32_to_odp(nl_attr_get_u32(a)));
         if (OVS_LIKELY(p)) {
-            netdev_send(p->netdev, packets, cnt, may_steal);
+            netdev_send(p->netdev, NETDEV_QID_NONE, packets, cnt, may_steal);
         } else if (may_steal) {
             for (i = 0; i < cnt; i++) {
                 dpif_packet_delete(packets[i]);
diff --git a/lib/dpif-netdev.h b/lib/dpif-netdev.h
index 410fcfa..fb9d0e2 100644
--- a/lib/dpif-netdev.h
+++ b/lib/dpif-netdev.h
@@ -40,6 +40,8 @@ static inline void dp_packet_pad(struct ofpbuf *b)
     }
 }
 
+#define NETDEV_QID_NONE INT_MAX
+
 #define NR_QUEUE   1
 #define NR_PMD_THREADS 1
 
diff --git a/lib/netdev-bsd.c b/lib/netdev-bsd.c
index dd1893c..32c04a3 100644
--- a/lib/netdev-bsd.c
+++ b/lib/netdev-bsd.c
@@ -687,8 +687,8 @@ netdev_bsd_rxq_drain(struct netdev_rxq *rxq_)
  * system or a tap device.
  */
 static int
-netdev_bsd_send(struct netdev *netdev_, struct dpif_packet **pkts, int cnt,
-                bool may_steal)
+netdev_bsd_send(struct netdev *netdev_, int qid OVS_UNUSED,
+                struct dpif_packet **pkts, int cnt, bool may_steal)
 {
     struct netdev_bsd *dev = netdev_bsd_cast(netdev_);
     const char *name = netdev_get_name(netdev_);
@@ -750,7 +750,7 @@ netdev_bsd_send(struct netdev *netdev_, struct dpif_packet **pkts, int cnt,
  * with netdev_send().
  */
 static void
-netdev_bsd_send_wait(struct netdev *netdev_)
+netdev_bsd_send_wait(struct netdev *netdev_, int qid OVS_UNUSED)
 {
     struct netdev_bsd *dev = netdev_bsd_cast(netdev_);
 
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index 70ee8db..4f9c5c2 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -495,6 +495,7 @@ netdev_dpdk_init(struct netdev *netdev_, unsigned int port_no) OVS_REQUIRES(dpdk
     if (err) {
         goto unlock;
     }
+    netdev_->n_txq = NR_QUEUE;
     netdev_->n_rxq = NR_QUEUE;
 
     list_push_back(&dpdk_list, &netdev->list_node);
@@ -792,8 +793,8 @@ dpdk_do_tx_copy(struct netdev *netdev, struct dpif_packet ** pkts, int cnt)
 }
 
 static int
-netdev_dpdk_send(struct netdev *netdev, struct dpif_packet **pkts, int cnt,
-                 bool may_steal)
+netdev_dpdk_send(struct netdev *netdev, int qid, struct dpif_packet **pkts,
+                 int cnt, bool may_steal)
 {
     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
     int ret;
@@ -808,7 +809,6 @@ netdev_dpdk_send(struct netdev *netdev, struct dpif_packet **pkts, int cnt,
             }
         }
     } else {
-        int qid;
         int next_tx_idx = 0;
         int dropped = 0;
 
diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
index 14239f1..050bad8 100644
--- a/lib/netdev-dummy.c
+++ b/lib/netdev-dummy.c
@@ -847,8 +847,8 @@ netdev_dummy_rxq_drain(struct netdev_rxq *rxq_)
 }
 
 static int
-netdev_dummy_send(struct netdev *netdev, struct dpif_packet **pkts, int cnt,
-                  bool may_steal)
+netdev_dummy_send(struct netdev *netdev, int qid OVS_UNUSED,
+                  struct dpif_packet **pkts, int cnt, bool may_steal)
 {
     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
     int error = 0;
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index 298ccd6..e311122 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -1057,8 +1057,8 @@ netdev_linux_rxq_drain(struct netdev_rxq *rxq_)
  * The kernel maintains a packet transmission queue, so the caller is not
  * expected to do additional queuing of packets. */
 static int
-netdev_linux_send(struct netdev *netdev_, struct dpif_packet **pkts, int cnt,
-                  bool may_steal)
+netdev_linux_send(struct netdev *netdev_, int qid OVS_UNUSED,
+                  struct dpif_packet **pkts, int cnt, bool may_steal)
 {
     int i;
     int error = 0;
@@ -1161,7 +1161,7 @@ netdev_linux_send(struct netdev *netdev_, struct dpif_packet **pkts, int cnt,
  * expected to do additional queuing of packets.  Thus, this function is
  * unlikely to ever be used.  It is included for completeness. */
 static void
-netdev_linux_send_wait(struct netdev *netdev)
+netdev_linux_send_wait(struct netdev *netdev, int qid OVS_UNUSED)
 {
     if (is_tap_netdev(netdev)) {
         /* TAP device always accepts packets.*/
diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h
index e8f2ebe..c08ef35 100644
--- a/lib/netdev-provider.h
+++ b/lib/netdev-provider.h
@@ -52,6 +52,7 @@ struct netdev {
     uint64_t change_seq;
 
     /* The following are protected by 'netdev_mutex' (internal to netdev.c). */
+    int n_txq;
     int n_rxq;
     int ref_cnt;                        /* Times this devices was opened. */
     struct shash_node *node;            /* Pointer to element in global map. */
@@ -258,8 +259,8 @@ struct netdev_class {
     int (*get_numa_id)(const struct netdev *netdev);
 
     /* Sends buffers on 'netdev'.
-     * Returns 0 if successful (for every buffer), otherwise a positive errno value.
-     * Returns EAGAIN without blocking if one or more packets cannot be
+     * Returns 0 if successful (for every buffer), otherwise a positive errno
+     * value.  Returns EAGAIN without blocking if one or more packets cannot be
      * queued immediately. Returns EMSGSIZE if a partial packet was transmitted
      * or if a packet is too big or too small to transmit on the device.
      *
@@ -268,9 +269,11 @@ struct netdev_class {
      *
      * To retain ownership of 'buffers' caller can set may_steal to false.
      *
-     * The network device is expected to maintain a packet transmission queue,
-     * so that the caller does not ordinarily have to do additional queuing of
-     * packets.
+     * The network device is expected to maintain one or more packet
+     * transmission queues, so that the caller does not ordinarily have to
+     * do additional queuing of packets.  'qid' specifies the queue to use
+     * and can be ignored if the implementation does not support multiple
+     * queues.
      *
      * May return EOPNOTSUPP if a network device does not implement packet
      * transmission through this interface.  This function may be set to null
@@ -278,20 +281,22 @@ 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, struct dpif_packet **buffers, int cnt,
-                bool may_steal);
+    int (*send)(struct netdev *netdev, int qid, struct dpif_packet **buffers,
+                int cnt, 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
      * sufficient room to transmit a packet with netdev_send().
      *
-     * The network device is expected to maintain a packet transmission queue,
-     * so that the caller does not ordinarily have to do additional queuing of
-     * packets.  Thus, this function is unlikely to ever be useful.
+     * The network device is expected to maintain one or more packet
+     * transmission queues, so that the caller does not ordinarily have to
+     * do additional queuing of packets.  'qid' specifies the queue to use
+     * and can be ignored if the implementation does not support multiple
+     * queues.
      *
      * May be null if not needed, such as for a network device that does not
      * implement packet transmission through the 'send' member function. */
-    void (*send_wait)(struct netdev *netdev);
+    void (*send_wait)(struct netdev *netdev, int qid);
 
     /* Sets 'netdev''s Ethernet address to 'mac' */
     int (*set_etheraddr)(struct netdev *netdev, const uint8_t mac[6]);
diff --git a/lib/netdev.c b/lib/netdev.c
index 444ae85..0d065e7 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -92,6 +92,12 @@ static void restore_all_flags(void *aux OVS_UNUSED);
 void update_device_args(struct netdev *, const struct shash *args);
 
 int
+netdev_n_txq(const struct netdev *netdev)
+{
+    return netdev->n_txq;
+}
+
+int
 netdev_n_rxq(const struct netdev *netdev)
 {
     return netdev->n_rxq;
@@ -355,12 +361,10 @@ netdev_open(const char *name, const char *type, struct netdev **netdevp)
                 netdev->change_seq = 1;
                 netdev->node = shash_add(&netdev_shash, name, netdev);
 
-                /* By default enable one rx queue per netdev. */
-                if (netdev->netdev_class->rxq_alloc) {
-                    netdev->n_rxq = 1;
-                } else {
-                    netdev->n_rxq = 0;
-                }
+                /* By default enable one tx and rx queue per netdev. */
+                netdev->n_txq = netdev->netdev_class->send ? 1 : 0;
+                netdev->n_rxq = netdev->netdev_class->rxq_alloc ? 1 : 0;
+
                 list_init(&netdev->saved_flags_list);
 
                 error = rc->class->construct(netdev);
@@ -670,19 +674,22 @@ netdev_rxq_drain(struct netdev_rxq *rx)
  *
  * To retain ownership of 'buffer' caller can set may_steal to false.
  *
- * The kernel maintains a packet transmission queue, so the caller is not
- * expected to do additional queuing of packets.
+ * The network device is expected to maintain one or more packet
+ * transmission queues, so that the caller does not ordinarily have to
+ * do additional queuing of packets.  'qid' specifies the queue to use
+ * and can be ignored if the implementation does not support multiple
+ * queues.
  *
  * Some network devices may not implement support for this function.  In such
  * cases this function will always return EOPNOTSUPP. */
 int
-netdev_send(struct netdev *netdev, struct dpif_packet **buffers, int cnt,
-            bool may_steal)
+netdev_send(struct netdev *netdev, int qid, struct dpif_packet **buffers,
+            int cnt, bool may_steal)
 {
     int error;
 
     error = (netdev->netdev_class->send
-             ? netdev->netdev_class->send(netdev, buffers, cnt, may_steal)
+             ? netdev->netdev_class->send(netdev, qid, buffers, cnt, may_steal)
              : EOPNOTSUPP);
     if (!error) {
         COVERAGE_INC(netdev_sent);
@@ -694,14 +701,16 @@ netdev_send(struct netdev *netdev, struct dpif_packet **buffers, int cnt,
  * when the packet transmission queue has sufficient room to transmit a packet
  * with netdev_send().
  *
- * The kernel maintains a packet transmission queue, so the client is not
- * expected to do additional queuing of packets.  Thus, this function is
- * unlikely to ever be used.  It is included for completeness. */
+ * The network device is expected to maintain one or more packet
+ * transmission queues, so that the caller does not ordinarily have to
+ * do additional queuing of packets.  'qid' specifies the queue to use
+ * and can be ignored if the implementation does not support multiple
+ * queues. */
 void
-netdev_send_wait(struct netdev *netdev)
+netdev_send_wait(struct netdev *netdev, int qid)
 {
     if (netdev->netdev_class->send_wait) {
-        netdev->netdev_class->send_wait(netdev);
+        netdev->netdev_class->send_wait(netdev, qid);
     }
 }
 
diff --git a/lib/netdev.h b/lib/netdev.h
index f429bc6..c6249c4 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -135,6 +135,7 @@ void netdev_wait(void);
 void netdev_enumerate_types(struct sset *types);
 bool netdev_is_reserved_name(const char *name);
 
+int netdev_n_txq(const struct netdev *netdev);
 int netdev_n_rxq(const struct netdev *netdev);
 bool netdev_is_pmd(const struct netdev *netdev);
 
@@ -174,9 +175,9 @@ void netdev_rxq_wait(struct netdev_rxq *);
 int netdev_rxq_drain(struct netdev_rxq *);
 
 /* Packet transmission. */
-int netdev_send(struct netdev *, struct dpif_packet **, int cnt,
+int netdev_send(struct netdev *, int qid, struct dpif_packet **, int cnt,
                 bool may_steal);
-void netdev_send_wait(struct netdev *);
+void netdev_send_wait(struct netdev *, int qid);
 
 /* Hardware address. */
 int netdev_set_etheraddr(struct netdev *, const uint8_t mac[6]);
-- 
1.7.9.5




More information about the dev mailing list