This commit adds a new appctl command "dpif/set-n-handler-threads"
in "ofproto-dpif.c". It is used to set the number of upcall handler
threads created by ofproto-dpif-upcall module.

Signed-off-by: Alex Wang <al...@nicira.com>
---
 ofproto/ofproto-dpif-unixctl.man |   18 ++++++++++
 ofproto/ofproto-dpif.c           |   68 +++++++++++++++++++++++++++++++++++---
 tests/ofproto-dpif.at            |   48 +++++++++++++++++++++++++--
 tests/tunnel.at                  |   26 +++++++--------
 4 files changed, 140 insertions(+), 20 deletions(-)

diff --git a/ofproto/ofproto-dpif-unixctl.man b/ofproto/ofproto-dpif-unixctl.man
index 0512b21..2165795 100644
--- a/ofproto/ofproto-dpif-unixctl.man
+++ b/ofproto/ofproto-dpif-unixctl.man
@@ -28,3 +28,21 @@ underlying datapath implementation (e.g., kernel datapath 
module).
 This command is primarily useful for debugging Open vSwitch.  As
 discussed in \fBdpif/dump\-flows\fR, these entries are
 not OpenFlow flow entries.
+.
+.IP "\fBdpif/set\-n\-handler\-threads\fR [\fIdp_type\fR] \
+\fIn_handler_threads\fR"
+This command sets the number of upcall handler threads created
+by \fBofproto-dpif-upcall\fR module. The arguments are:
+.
+.RS
+.IP "[\fIdp_type\fR]"
+\fIdp_type\fR is the type of the datapath. If all of your bridges
+have the same datapath type, which is the common case, then you
+can omit \fIdp_type\fR, but if you have bridges of different types
+(say, both \fInetdev\fR and \fIsystem\fR), then you need to specify
+a \fIdp_type\fR to disambiguate.
+.
+.IP "\fIn_handler_threads\fR"
+\fIn_handler_threads\fR is number of upcall handler threads that
+you want to have.
+.RE
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 229b16c..79f84c3 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -20,6 +20,7 @@
 #include "ofproto/ofproto-provider.h"
 
 #include <errno.h>
+#include <unistd.h>
 
 #include "bfd.h"
 #include "bond.h"
@@ -75,8 +76,6 @@ COVERAGE_DEFINE(subfacet_install_fail);
 COVERAGE_DEFINE(packet_in_overflow);
 COVERAGE_DEFINE(flow_mod_overflow);
 
-#define N_THREADS 16
-
 /* Number of implemented OpenFlow tables. */
 enum { N_TABLES = 255 };
 enum { TBL_INTERNAL = N_TABLES - 1 };    /* Used for internal hidden rules. */
@@ -431,6 +430,9 @@ struct dpif_backer {
     /* Number of subfacets added or deleted from 'created' to 'last_minute.' */
     unsigned long long int total_subfacet_add_count;
     unsigned long long int total_subfacet_del_count;
+
+    /* Number of upcall handler threads. */
+    unsigned int n_handler_threads;
 };
 
 /* All existing ofproto_backer instances, indexed by ofproto->up.type. */
@@ -700,7 +702,8 @@ type_run(const char *type)
             VLOG_ERR("Failed to enable receiving packets in dpif.");
             return error;
         }
-        udpif_recv_set(backer->udpif, N_THREADS, backer->recv_set_enable);
+        udpif_recv_set(backer->udpif, backer->n_handler_threads,
+                       backer->recv_set_enable);
         dpif_flow_flush(backer->dpif);
         backer->need_revalidate = REV_RECONFIGURE;
     }
@@ -1209,7 +1212,6 @@ open_dpif_backer(const char *type, struct dpif_backer 
**backerp)
         close_dpif_backer(backer);
         return error;
     }
-    udpif_recv_set(backer->udpif, N_THREADS, backer->recv_set_enable);
 
     backer->max_n_subfacet = 0;
     backer->created = time_msec();
@@ -1223,7 +1225,10 @@ open_dpif_backer(const char *type, struct dpif_backer 
**backerp)
     backer->total_subfacet_del_count = 0;
     backer->avg_n_subfacet = 0;
     backer->avg_subfacet_life = 0;
+    backer->n_handler_threads = MAX(sysconf(_SC_NPROCESSORS_ONLN) - 1, 1);
 
+    udpif_recv_set(backer->udpif, backer->n_handler_threads,
+                   backer->recv_set_enable);
     return error;
 }
 
@@ -5654,6 +5659,8 @@ dpif_show_backer(const struct dpif_backer *backer, struct 
ds *ds)
 
     ds_put_format(ds, "%s: hit:%"PRIu64" missed:%"PRIu64"\n",
                   dpif_name(backer->dpif), n_hit, n_missed);
+    ds_put_format(ds, "\thandler threads: %u\n", backer->recv_set_enable ?
+                                            backer->n_handler_threads : 0);
     ds_put_format(ds, "\tflows: cur: %zu, avg: %u, max: %u,"
                   " life span: %lldms\n", hmap_count(&backer->subfacets),
                   backer->avg_n_subfacet, backer->max_n_subfacet,
@@ -5841,6 +5848,56 @@ ofproto_unixctl_dpif_enable_megaflows(struct 
unixctl_conn *conn,
     unixctl_command_reply(conn, "megaflows enabled");
 }
 
+/* Sets the n-hander-threads.
+ * If a new configuration is given, call udpif_recv_set() to update. */
+static void
+ofproto_unixctl_dpif_set_n_handler_threads(struct unixctl_conn *conn,
+                                           int argc,
+                                           const char *argv[],
+                                           void *aux OVS_UNUSED)
+{
+    struct dpif_backer *backer;
+    unsigned int n_handler_threads;
+
+    if (argc == 2) {
+        struct shash_node *node;
+        /* If datapath type is not specified, check whether there
+         * is only one datapath type. */
+        if (shash_count(&all_dpif_backers) != 1) {
+            unixctl_command_reply_error(conn, "Must specify datapath "
+                                              "type, there is more than "
+                                              "one type of datapath");
+            return;
+        }
+        node = shash_first(&all_dpif_backers);
+        backer = node->data;
+    } else {
+        /* If datapath type is given, try extracting the dpif_backer. */
+        backer = shash_find_data(&all_dpif_backers, argv[1]);
+        if (!backer) {
+            unixctl_command_reply_error(conn, "The specified datapath "
+                                              "type does not exist");
+            return;
+        }
+    }
+
+    /* Extracts the n_handler_threads. */
+    if (!str_to_uint(argv[argc - 1], 10, &n_handler_threads)) {
+        unixctl_command_reply_error(conn, "Cannot extract the specified "
+                                          "number of handler threads");
+        return;
+    }
+
+    /* Updates the n_handler_threads when it is different from current
+     * configuration. */
+    if (n_handler_threads && backer->n_handler_threads != n_handler_threads) {
+        udpif_recv_set(backer->udpif, n_handler_threads,
+                       backer->recv_set_enable);
+        backer->n_handler_threads = n_handler_threads;
+    }
+    unixctl_command_reply(conn, "n-handler-threads set");
+}
+
 static void
 ofproto_unixctl_dpif_dump_flows(struct unixctl_conn *conn,
                                 int argc OVS_UNUSED, const char *argv[],
@@ -5967,6 +6024,9 @@ ofproto_dpif_unixctl_init(void)
                              ofproto_unixctl_dpif_disable_megaflows, NULL);
     unixctl_command_register("dpif/enable-megaflows", "", 0, 0,
                              ofproto_unixctl_dpif_enable_megaflows, NULL);
+    unixctl_command_register("dpif/set-n-handler-threads",
+                             "[dp_type] n_handler_thread", 1, 2,
+                             ofproto_unixctl_dpif_set_n_handler_threads, NULL);
 }
 
 /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index b093998..ac71066 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -2062,7 +2062,7 @@ OVS_VSWITCHD_START([add-br br1 -- set bridge br1 
datapath-type=dummy])
 ADD_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 "/^.*handler threads:.*/d"], [0], [dnl
 dummy@ovs-dummy: hit:0 missed:0
        flows: cur: 0, avg: 0, max: 0, life span: 0ms
        overall avg: add rate: 0.000/min, del rate: 0.000/min
@@ -2155,7 +2155,7 @@ AT_CHECK([ovs-appctl time/warp 1000 && ovs-appctl 
time/warp 1000], [0], [warped
 warped
 ])
 
-AT_CHECK([ovs-appctl dpif/show], [0], [dnl
+AT_CHECK([ovs-appctl dpif/show  | sed "/^.*handler threads:.*/d"], [0], [dnl
 dummy@ovs-dummy: hit:13 missed:2
        flows: cur: 2, avg: 1, max: 2, life span: 1250ms
        overall avg: add rate: 0.000/min, del rate: 0.000/min
@@ -2207,7 +2207,7 @@ done
 AT_CHECK([ovs-appctl time/warp 10000], [0], [warped
 ])
 
-AT_CHECK([ovs-appctl dpif/show | sed 's/ 10[[0-9]]\{3\}(ms)$/ 10000(ms)/'], 
[0], [dnl
+AT_CHECK([ovs-appctl dpif/show | sed "/^.*handler threads:.*/d" | sed 's/ 
10[[0-9]]\{3\}(ms)$/ 10000(ms)/'], [0], [dnl
 dummy@ovs-dummy: hit:0 missed:61
        flows: cur: 0, avg: 0, max: 1, life span: 1666ms
        hourly avg: add rate: 0.641/min, del rate: 0.641/min
@@ -2689,3 +2689,45 @@ AT_CHECK([tail -1 stdout], [0], [Datapath actions: 5
 ])
 OVS_VSWITCHD_STOP
 AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - set-n-handler-threads])
+OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])
+ADD_OF_PORTS([br0], 1)
+
+# Tests the command without specifying the datapath type.
+AT_CHECK([ovs-appctl dpif/set-n-handler-threads 10], [0], [dnl
+n-handler-threads set
+])
+AT_CHECK([ovs-appctl dpif/show | sed -n -e "/^.*handler threads:.*/p"], [0], 
[dnl
+       handler threads: 10
+])
+
+# Tests the command by specifying the datapath type.
+AT_CHECK([ovs-appctl dpif/set-n-handler-threads dummy 15], [0], [dnl
+n-handler-threads set
+])
+AT_CHECK([ovs-appctl dpif/show | sed -n -e "/^.*handler threads:.*/p"], [0], 
[dnl
+       handler threads: 15
+])
+
+# Tests the command by specifying non-existed datapath type.
+AT_CHECK([ovs-appctl dpif/set-n-handler-threads system 15], [2], [], [stderr])
+AT_CHECK([cat stderr], [0], [dnl
+The specified datapath type does not exist
+ovs-appctl: ovs-vswitchd: server returned an error
+])
+
+# Tests the command by specifying invalid argument
+AT_CHECK([ovs-appctl dpif/set-n-handler-threads invalid], [2], [], [stderr])
+AT_CHECK([cat stderr], [0], [dnl
+Cannot extract the specified number of handler threads
+ovs-appctl: ovs-vswitchd: server returned an error
+])
+AT_CHECK([ovs-appctl dpif/set-n-handler-threads invalid invalid], [2], [], 
[stderr])
+AT_CHECK([cat stderr], [0], [dnl
+The specified datapath type does not exist
+ovs-appctl: ovs-vswitchd: server returned an error
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
diff --git a/tests/tunnel.at b/tests/tunnel.at
index 697c217..def7567 100644
--- a/tests/tunnel.at
+++ b/tests/tunnel.at
@@ -14,7 +14,7 @@ actions=IN_PORT
 
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
-AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+AT_CHECK([ovs-appctl dpif/show | tail -n +6], [0], [dnl
                br0 65534/100: (dummy)
                p1 1/1: (gre: remote_ip=1.1.1.1)
                p2 2/1: (gre: local_ip=2.2.2.2, remote_ip=1.1.1.1)
@@ -37,7 +37,7 @@ dnl reconfigure, local_ip, remote_ip
 AT_CHECK([ovs-vsctl set Interface p2 type=gre options:local_ip=2.2.2.3 \
           options:df_default=false options:ttl=1 options:csum=true \
           -- set Interface p3 type=gre64])
-AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+AT_CHECK([ovs-appctl dpif/show | tail -n +6], [0], [dnl
                br0 65534/100: (dummy)
                p1 1/1: (gre: remote_ip=1.1.1.1)
                p2 2/1: (gre: csum=true, df_default=false, local_ip=2.2.2.3, 
remote_ip=1.1.1.1, ttl=1)
@@ -72,7 +72,7 @@ actions=2
 
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
-AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+AT_CHECK([ovs-appctl dpif/show | tail -n +6], [0], [dnl
                br0 65534/100: (dummy)
                p1 1/1: (gre: remote_ip=1.1.1.1)
                p2 2/2: (dummy)
@@ -116,7 +116,7 @@ actions=output:1
 
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
-AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+AT_CHECK([ovs-appctl dpif/show | tail -n +6], [0], [dnl
                br0 65534/100: (dummy)
                p1 1/1: (gre: key=5, local_ip=2.2.2.2, remote_ip=1.1.1.1)
                p2 2/2: (dummy)
@@ -148,7 +148,7 @@ actions=output:1
 
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
-AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+AT_CHECK([ovs-appctl dpif/show | tail -n +6], [0], [dnl
                br0 65534/100: (dummy)
                p1 1/1: (gre: remote_ip=1.1.1.1, tos=inherit, ttl=inherit)
                p2 2/2: (dummy)
@@ -190,7 +190,7 @@ 
actions=set_tunnel:1,output:1,set_tunnel:2,output:2,set_tunnel:3,output:3,set_tu
 
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
-AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+AT_CHECK([ovs-appctl dpif/show | tail -n +6], [0], [dnl
                br0 65534/100: (dummy)
                p1 1/1: (gre: key=flow, remote_ip=1.1.1.1)
                p2 2/1: (gre: key=flow, remote_ip=2.2.2.2)
@@ -222,7 +222,7 @@ actions=IN_PORT,output:1,output:2,output:3
 
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
-AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+AT_CHECK([ovs-appctl dpif/show | tail -n +6], [0], [dnl
                br0 65534/100: (dummy)
                p1 1/1: (gre: key=1, remote_ip=1.1.1.1)
                p2 2/1: (gre: in_key=2, out_key=3, remote_ip=1.1.1.1)
@@ -274,7 +274,7 @@ tun_id=4,actions=output:5
 
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
-AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+AT_CHECK([ovs-appctl dpif/show | tail -n +6], [0], [dnl
                br0 65534/100: (dummy)
                p1 1/1: (gre: key=flow, remote_ip=1.1.1.1)
                p2 2/1: (gre: key=3, remote_ip=3.3.3.3)
@@ -310,7 +310,7 @@ AT_SETUP([tunnel - VXLAN])
 OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=vxlan \
                     options:remote_ip=1.1.1.1 ofport_request=1])
 
-AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+AT_CHECK([ovs-appctl dpif/show | tail -n +6], [0], [dnl
                br0 65534/100: (dummy)
                p1 1/1: (vxlan: remote_ip=1.1.1.1)
 ])
@@ -322,7 +322,7 @@ AT_SETUP([tunnel - LISP])
 OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=lisp \
                     options:remote_ip=1.1.1.1 ofport_request=1])
 
-AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+AT_CHECK([ovs-appctl dpif/show | tail -n +6], [0], [dnl
                br0 65534/100: (dummy)
                p1 1/1: (lisp: remote_ip=1.1.1.1)
 ])
@@ -334,7 +334,7 @@ AT_SETUP([tunnel - different VXLAN UDP port])
 OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=vxlan \
                     options:remote_ip=1.1.1.1 ofport_request=1 
options:dst_port=4341])
 
-AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+AT_CHECK([ovs-appctl dpif/show | tail -n +6], [0], [dnl
                br0 65534/100: (dummy)
                p1 1/1: (vxlan: dst_port=4341, remote_ip=1.1.1.1)
 ])
@@ -343,7 +343,7 @@ dnl change UDP port
 
 AT_CHECK([ovs-vsctl -- set Interface p1 options:dst_port=5000])
 
-AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+AT_CHECK([ovs-appctl dpif/show | tail -n +6], [0], [dnl
                br0 65534/100: (dummy)
                p1 1/2: (vxlan: dst_port=5000, remote_ip=1.1.1.1)
 ])
@@ -352,7 +352,7 @@ dnl change UDP port to default
 
 AT_CHECK([ovs-vsctl -- set Interface p1 options:dst_port=4789])
 
-AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+AT_CHECK([ovs-appctl dpif/show | tail -n +6], [0], [dnl
                br0 65534/100: (dummy)
                p1 1/1: (vxlan: remote_ip=1.1.1.1)
 ])
-- 
1.7.9.5

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to