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