[ovs-dev] [PATCH v2 6/7] netdev-dummy: Add multiqueue support to dummy-pmd.

Ilya Maximets i.maximets at samsung.com
Fri May 27 13:32:53 UTC 2016


All previous multi-open logic preserved for rx queues.
Also, added new optional parameter '--qid' for 'netdev-dummy/receive'
in order to allow user to choose id of rx queue to which packet will
be sent.

Ex.:
	ovs-appctl netdev-dummy/receive p1 --qid 3 'in_port(1) ...'

Signed-off-by: Ilya Maximets <i.maximets at samsung.com>
---
 lib/netdev-dummy.c    | 127 +++++++++++++++++++++++++++++++++++++++++---------
 tests/ofproto-dpif.at |   6 +--
 2 files changed, 109 insertions(+), 24 deletions(-)

diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
index f0d5626..216956a 100644
--- a/lib/netdev-dummy.c
+++ b/lib/netdev-dummy.c
@@ -118,6 +118,12 @@ struct netdev_dummy {
     struct in_addr address, netmask;
     struct in6_addr ipv6, ipv6_mask;
     struct ovs_list rxes OVS_GUARDED; /* List of child "netdev_rxq_dummy"s. */
+
+    /* The following properties are for dummy-pmd and they cannot be changed
+     * when a device is running, so we remember the request and update them
+     * next time netdev_dummy_reconfigure() is called. */
+    int requested_n_txq;
+    int requested_n_rxq;
 };
 
 /* Max 'recv_queue_len' in struct netdev_dummy. */
@@ -133,7 +139,8 @@ struct netdev_rxq_dummy {
 
 static unixctl_cb_func netdev_dummy_set_admin_state;
 static int netdev_dummy_construct(struct netdev *);
-static void netdev_dummy_queue_packet(struct netdev_dummy *, struct dp_packet *);
+static void netdev_dummy_queue_packet(struct netdev_dummy *,
+                                      struct dp_packet *, int);
 
 static void dummy_packet_stream_close(struct dummy_packet_stream *);
 
@@ -260,7 +267,7 @@ dummy_packet_stream_run(struct netdev_dummy *dev, struct dummy_packet_stream *s)
             if (retval == n && dp_packet_size(&s->rxbuf) > 2) {
                 dp_packet_pull(&s->rxbuf, 2);
                 netdev_dummy_queue_packet(dev,
-                                          dp_packet_clone(&s->rxbuf));
+                                          dp_packet_clone(&s->rxbuf), 0);
                 dp_packet_clear(&s->rxbuf);
             }
         } else if (retval != -EAGAIN) {
@@ -661,6 +668,8 @@ netdev_dummy_construct(struct netdev *netdev_)
     netdev->mtu = 1500;
     netdev->flags = 0;
     netdev->ifindex = -EOPNOTSUPP;
+    netdev->requested_n_rxq = netdev_->n_rxq;
+    netdev->requested_n_txq = netdev_->n_txq;
 
     dummy_packet_conn_init(&netdev->conn);
 
@@ -700,9 +709,9 @@ netdev_dummy_dealloc(struct netdev *netdev_)
 }
 
 static int
-netdev_dummy_get_config(const struct netdev *netdev_, struct smap *args)
+netdev_dummy_get_config(const struct netdev *dev, struct smap *args)
 {
-    struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
+    struct netdev_dummy *netdev = netdev_dummy_cast(dev);
 
     ovs_mutex_lock(&netdev->mutex);
 
@@ -712,6 +721,16 @@ netdev_dummy_get_config(const struct netdev *netdev_, struct smap *args)
 
     dummy_packet_conn_get_config(&netdev->conn, args);
 
+    /* 'dummy-pmd' specific config. */
+    if (!dev->netdev_class->is_pmd) {
+        goto exit;
+    }
+    smap_add_format(args, "requested_rx_queues", "%d", netdev->requested_n_rxq);
+    smap_add_format(args, "configured_rx_queues", "%d", dev->n_rxq);
+    smap_add_format(args, "requested_tx_queues", "%d", netdev->requested_n_txq);
+    smap_add_format(args, "configured_tx_queues", "%d", dev->n_txq);
+
+exit:
     ovs_mutex_unlock(&netdev->mutex);
     return 0;
 }
@@ -798,6 +817,7 @@ netdev_dummy_set_config(struct netdev *netdev_, const struct smap *args)
 {
     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
     const char *pcap;
+    int new_n_rxq;
 
     ovs_mutex_lock(&netdev->mutex);
     netdev->ifindex = smap_get_int(args, "ifindex", -EOPNOTSUPP);
@@ -826,8 +846,21 @@ netdev_dummy_set_config(struct netdev *netdev_, const struct smap *args)
         }
     }
 
-    ovs_mutex_unlock(&netdev->mutex);
+    netdev_change_seq_changed(netdev_);
+
+    /* 'dummy-pmd' specific config. */
+    if (!netdev_->netdev_class->is_pmd) {
+        goto exit;
+    }
+
+    new_n_rxq = MAX(smap_get_int(args, "n_rxq", netdev->requested_n_rxq), 1);
+    if (new_n_rxq != netdev->requested_n_rxq) {
+        netdev->requested_n_rxq = new_n_rxq;
+        netdev_request_reconfigure(netdev_);
+    }
 
+exit:
+    ovs_mutex_unlock(&netdev->mutex);
     return 0;
 }
 
@@ -837,6 +870,41 @@ netdev_dummy_get_numa_id(const struct netdev *netdev_ OVS_UNUSED)
     return 0;
 }
 
+/* Requests the number of tx queues for the dummy PMD interface. */
+static int
+netdev_dummy_set_tx_multiq(struct netdev *netdev_, unsigned int n_txq)
+{
+    struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
+
+    ovs_mutex_lock(&netdev->mutex);
+
+    if (netdev_->n_txq == n_txq) {
+        goto out;
+    }
+
+    netdev->requested_n_txq = n_txq;
+    netdev_request_reconfigure(netdev_);
+
+out:
+    ovs_mutex_unlock(&netdev->mutex);
+    return 0;
+}
+
+/* Sets the number of tx queues and rx queues for the dummy PMD interface. */
+static int
+netdev_dummy_reconfigure(struct netdev *netdev_)
+{
+    struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
+
+    ovs_mutex_lock(&netdev->mutex);
+
+    netdev_->n_txq = netdev->requested_n_txq;
+    netdev_->n_rxq = netdev->requested_n_rxq;
+
+    ovs_mutex_unlock(&netdev->mutex);
+    return 0;
+}
+
 static struct netdev_rxq *
 netdev_dummy_rxq_alloc(void)
 {
@@ -1000,7 +1068,7 @@ netdev_dummy_send(struct netdev *netdev, int qid OVS_UNUSED,
                 struct dp_packet *reply = dp_packet_new(0);
                 compose_arp(reply, ARP_OP_REPLY, dev->hwaddr, flow.dl_src,
                             false, flow.nw_dst, flow.nw_src);
-                netdev_dummy_queue_packet(dev, reply);
+                netdev_dummy_queue_packet(dev, reply, 0);
             }
         }
 
@@ -1227,7 +1295,7 @@ netdev_dummy_update_flags(struct netdev *netdev_,
 
 /* Helper functions. */
 
-#define NETDEV_DUMMY_CLASS(NAME, PMD)                           \
+#define NETDEV_DUMMY_CLASS(NAME, PMD, TX_MULTIQ, RECOFIGURE)       \
 {                                                               \
     NAME,                                                       \
     PMD,                        /* is_pmd */                    \
@@ -1246,7 +1314,7 @@ netdev_dummy_update_flags(struct netdev *netdev_,
     NULL,                       /* push header */               \
     NULL,                       /* pop header */                \
     netdev_dummy_get_numa_id,                                   \
-    NULL,                       /* set_tx_multiq */             \
+    TX_MULTIQ,                                                  \
                                                                 \
     netdev_dummy_send,          /* send */                      \
     NULL,                       /* send_wait */                 \
@@ -1286,7 +1354,7 @@ netdev_dummy_update_flags(struct netdev *netdev_,
     NULL,                       /* arp_lookup */                \
                                                                 \
     netdev_dummy_update_flags,                                  \
-    NULL,                       /* reconfigure */               \
+    RECOFIGURE,                                                 \
                                                                 \
     netdev_dummy_rxq_alloc,                                     \
     netdev_dummy_rxq_construct,                                 \
@@ -1298,9 +1366,12 @@ netdev_dummy_update_flags(struct netdev *netdev_,
 }
 
 static const struct netdev_class dummy_class =
-    NETDEV_DUMMY_CLASS("dummy", false);
+    NETDEV_DUMMY_CLASS("dummy", false, NULL, NULL);
+
 static const struct netdev_class dummy_pmd_class =
-    NETDEV_DUMMY_CLASS("dummy-pmd", true);
+    NETDEV_DUMMY_CLASS("dummy-pmd", true,
+                       netdev_dummy_set_tx_multiq,
+                       netdev_dummy_reconfigure);
 
 static void
 pkt_list_delete(struct ovs_list *l)
@@ -1365,7 +1436,8 @@ netdev_dummy_queue_packet__(struct netdev_rxq_dummy *rx, struct dp_packet *packe
 }
 
 static void
-netdev_dummy_queue_packet(struct netdev_dummy *dummy, struct dp_packet *packet)
+netdev_dummy_queue_packet(struct netdev_dummy *dummy, struct dp_packet *packet,
+                          int queue_id)
     OVS_REQUIRES(dummy->mutex)
 {
     struct netdev_rxq_dummy *rx, *prev;
@@ -1376,7 +1448,8 @@ netdev_dummy_queue_packet(struct netdev_dummy *dummy, struct dp_packet *packet)
     }
     prev = NULL;
     LIST_FOR_EACH (rx, node, &dummy->rxes) {
-        if (rx->recv_queue_len < NETDEV_DUMMY_MAX_QUEUE) {
+        if (rx->up.queue_id == queue_id &&
+            rx->recv_queue_len < NETDEV_DUMMY_MAX_QUEUE) {
             if (prev) {
                 netdev_dummy_queue_packet__(prev, dp_packet_clone(packet));
             }
@@ -1396,16 +1469,27 @@ netdev_dummy_receive(struct unixctl_conn *conn,
 {
     struct netdev_dummy *dummy_dev;
     struct netdev *netdev;
-    int i;
+    int i, k = 1, rx_qid = 0;
 
-    netdev = netdev_from_name(argv[1]);
+    netdev = netdev_from_name(argv[k++]);
     if (!netdev || !is_dummy_class(netdev->netdev_class)) {
         unixctl_command_reply_error(conn, "no such dummy netdev");
-        goto exit;
+        goto exit_netdev;
     }
     dummy_dev = netdev_dummy_cast(netdev);
 
-    for (i = 2; i < argc; i++) {
+    ovs_mutex_lock(&dummy_dev->mutex);
+
+    if (argc > k + 1 && !strcmp(argv[k], "--qid")) {
+        rx_qid = strtol(argv[k + 1], NULL, 10);
+        if (rx_qid < 0 || rx_qid >= netdev->n_rxq) {
+            unixctl_command_reply_error(conn, "bad rx queue id.");
+            goto exit;
+        }
+        k += 2;
+    }
+
+    for (i = k; i < argc; i++) {
         struct dp_packet *packet;
 
         packet = eth_from_packet_or_flow(argv[i]);
@@ -1414,14 +1498,14 @@ netdev_dummy_receive(struct unixctl_conn *conn,
             goto exit;
         }
 
-        ovs_mutex_lock(&dummy_dev->mutex);
-        netdev_dummy_queue_packet(dummy_dev, packet);
-        ovs_mutex_unlock(&dummy_dev->mutex);
+        netdev_dummy_queue_packet(dummy_dev, packet, rx_qid);
     }
 
     unixctl_command_reply(conn, NULL);
 
 exit:
+    ovs_mutex_unlock(&dummy_dev->mutex);
+exit_netdev:
     netdev_close(netdev);
 }
 
@@ -1624,7 +1708,8 @@ netdev_dummy_override(const char *type)
 void
 netdev_dummy_register(enum dummy_level level)
 {
-    unixctl_command_register("netdev-dummy/receive", "name packet|flow...",
+    unixctl_command_register("netdev-dummy/receive",
+                             "name [--qid queue_id] packet|flow...",
                              2, INT_MAX, netdev_dummy_receive, NULL);
     unixctl_command_register("netdev-dummy/set-admin-state",
                              "[netdev] up|down", 1, 2,
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 1c081d5..a523e87 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -6011,12 +6011,12 @@ OVS_VSWITCHD_START([add-br br1 -- set bridge br1 datapath-type=dummy])
 add_pmd_of_ports br0 1 2
 add_of_ports br1 3
 
-AT_CHECK([ovs-appctl dpif/show], [0], [dnl
+AT_CHECK([ovs-appctl dpif/show | sed 's/\(dummy-pmd: \).*)/\1<cleared>)/'], [0], [dnl
 dummy at ovs-dummy: hit:0 missed:0
 	br0:
 		br0 65534/100: (dummy)
-		p1 1/1: (dummy-pmd)
-		p2 2/2: (dummy-pmd)
+		p1 1/1: (dummy-pmd: <cleared>)
+		p2 2/2: (dummy-pmd: <cleared>)
 	br1:
 		br1 65534/101: (dummy)
 		p3 3/3: (dummy)
-- 
2.5.0




More information about the dev mailing list