From 042bb01062a0c302e654bb925f60f522cd2e158b Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Fri, 15 May 2009 15:48:58 -0700 Subject: [PATCH] Break dpctl into two programs: ovs-ofctl and ovs-dpctl. The datapath and OpenFlow are fairly different and it seems wrong conceptually to work with both in a single program. So this commit breaks them up into two programs. --- INSTALL | 20 +- README | 5 +- debian/openvswitch-switch.init | 4 +- debian/openvswitch-switch.install | 3 +- debian/openvswitch-switch.manpages | 3 +- debian/openvswitch-switch.template | 2 +- debian/ovs-switch-setup.8 | 2 +- lib/vlog-modules.def | 1 + secchan/secchan.8.in | 21 +- utilities/.gitignore | 6 +- utilities/automake.mk | 21 +- utilities/ovs-appctl.8.in | 6 +- utilities/ovs-controller.8.in | 4 +- utilities/ovs-discover.8.in | 2 +- utilities/ovs-dpctl.8.in | 175 +++++++ utilities/ovs-dpctl.c | 593 +++++++++++++++++++++++ utilities/ovs-monitor | 2 +- utilities/{dpctl.8.in => ovs-ofctl.8.in} | 194 +------- utilities/{dpctl.c => ovs-ofctl.c} | 393 +-------------- utilities/ovs-pki.8.in | 1 - vswitchd/bridge.c | 2 +- vswitchd/vswitchd.8.in | 4 +- vswitchd/vswitchd.conf.5.in | 6 +- xenserver/etc_init.d_vswitch | 7 +- xenserver/etc_profile.d_vswitch.sh | 8 +- xenserver/vswitch-xen.spec | 6 +- 26 files changed, 867 insertions(+), 624 deletions(-) create mode 100644 utilities/ovs-dpctl.8.in create mode 100644 utilities/ovs-dpctl.c rename utilities/{dpctl.8.in => ovs-ofctl.8.in} (71%) rename utilities/{dpctl.c => ovs-ofctl.c} (79%) diff --git a/INSTALL b/INSTALL index dbab025f..5aa7073e 100644 --- a/INSTALL +++ b/INSTALL @@ -150,7 +150,7 @@ distribution in the ordinary way using "configure" and "make". - Bridge compatibility daemon: vswitchd/brcompatd - - Datapath administration utility: utilities/dpctl. + - Datapath administration utility: utilities/ovs-dpctl. Some less important binaries will be built also: @@ -321,10 +321,10 @@ The OpenVSwitch kernel module must be loaded, as described under program such as "su" to become root temporarily. 1. Create a datapath instance. The command below creates a datapath - identified as dp0 (see dpctl(8) for more detailed usage + identified as dp0 (see ovs-dpctl(8) for more detailed usage information). - # dpctl adddp dp0 + # ovs-dpctl adddp dp0 (dp0 is the first datapath within a host. openvswitch_mod supports multiple datapaths within the same host, which would be identified @@ -335,18 +335,18 @@ The OpenVSwitch kernel module must be loaded, as described under bridged to the physical switch ports by the secchan, for use in in-band control. -2. Use dpctl to attach the datapath to physical interfaces on the +2. Use ovs-dpctl to attach the datapath to physical interfaces on the machine. Say, for example, you want to create a trivial 2-port - switch using interfaces eth1 and eth2, you would issue the following - commands: + switch using interfaces eth1 and eth2, you would issue the + following commands: - # dpctl addif dp0 eth1 - # dpctl addif dp0 eth2 + # ovs-dpctl addif dp0 eth1 + # ovs-dpctl addif dp0 eth2 You can verify that the interfaces were successfully added by asking - dpctl to print the current status of datapath dp0: + ovs-dpctl to print the current status of datapath dp0: - # dpctl show dp0 + # ovs-dpctl show dp0 3. Arrange so that the switch can reach the controller over the network. diff --git a/README b/README index e4a7c714..737029a1 100644 --- a/README +++ b/README @@ -28,7 +28,7 @@ The most important components of this distribution are: - vswitchd, a daemon that implements the virtual switch. - - dpctl, a tool for configuring the kernel module and + - ovs-dpctl, a tool for configuring the kernel module and controlling OpenFlow switches. This distribution includes some additional software as well: @@ -39,6 +39,9 @@ This distribution includes some additional software as well: - ovs-controller, a simple OpenFlow switch + - ovs-ofctl, a utility for querying and controlling OpenFlow + switches and controllers. + - vlog-appctl, a utility that can control OpenVSwitch daemons, adjusting their logging levels among other uses. diff --git a/debian/openvswitch-switch.init b/debian/openvswitch-switch.init index 45a87d25..3f96c914 100755 --- a/debian/openvswitch-switch.init +++ b/debian/openvswitch-switch.init @@ -265,7 +265,7 @@ case "$1" in check_op "Removing IP address from $netdev" ifconfig $netdev 0.0.0.0 done - must_succeed "Creating datapath" dpctl adddp of0 $NETDEVS + must_succeed "Creating datapath" ovs-dpctl adddp of0 $NETDEVS xx='[0-9abcdefABCDEF][0-9abcdefABCDEF]' case $DATAPATH_ID in @@ -385,7 +385,7 @@ case "$1" in --exec $DAEMON echo "$NAME." - check_op "Deleting datapath" dpctl deldp of0 + check_op "Deleting datapath" ovs-dpctl deldp of0 check_op "Unloading kernel module" modprobe -r openvswitch_mod ;; force-stop) diff --git a/debian/openvswitch-switch.install b/debian/openvswitch-switch.install index a43c9c60..9fddacf0 100644 --- a/debian/openvswitch-switch.install +++ b/debian/openvswitch-switch.install @@ -1,6 +1,7 @@ _debian/secchan/secchan usr/sbin -_debian/utilities/dpctl usr/sbin +_debian/utilities/ovs-dpctl usr/sbin _debian/utilities/ovs-discover usr/sbin _debian/utilities/ovs-kill usr/sbin +_debian/utilities/ovs-ofctl usr/sbin debian/openvswitch/usr/share/openvswitch/commands/* usr/share/openvswitch/commands debian/commands/* usr/share/openvswitch/commands diff --git a/debian/openvswitch-switch.manpages b/debian/openvswitch-switch.manpages index 80bfd9fd..f789eba9 100644 --- a/debian/openvswitch-switch.manpages +++ b/debian/openvswitch-switch.manpages @@ -1,4 +1,5 @@ _debian/secchan/secchan.8 _debian/utilities/ovs-discover.8 +_debian/utilities/ovs-dpctl.8 _debian/utilities/ovs-kill.8 -_debian/utilities/dpctl.8 +_debian/utilities/ovs-ofctl.8 diff --git a/debian/openvswitch-switch.template b/debian/openvswitch-switch.template index 704a3bbd..739475bc 100644 --- a/debian/openvswitch-switch.template +++ b/debian/openvswitch-switch.template @@ -102,7 +102,7 @@ SWITCH_IP=dhcp #CACERT_MODE=secure # MGMT_VCONNS: List of vconns (space-separated) on which secchan -# should listen for management connections from dpctl, etc. +# should listen for management connections from ovs-ofctl, etc. # openvswitch-switchui by default connects to # unix:/var/run/secchan.mgmt, so do not disable this if you want to # use openvswitch-switchui. diff --git a/debian/ovs-switch-setup.8 b/debian/ovs-switch-setup.8 index f369587c..e34656d7 100644 --- a/debian/ovs-switch-setup.8 +++ b/debian/ovs-switch-setup.8 @@ -36,6 +36,6 @@ obtained from the OpenFlow PKI server. .SH "SEE ALSO" +.BR ovs\-dpctl (8), .BR ovs-pki (8), -.BR dpctl (8), .BR secchan (8) diff --git a/lib/vlog-modules.def b/lib/vlog-modules.def index e9221e0d..4ef458ab 100644 --- a/lib/vlog-modules.def +++ b/lib/vlog-modules.def @@ -29,6 +29,7 @@ VLOG_MODULE(mgmt) VLOG_MODULE(netdev) VLOG_MODULE(netflow) VLOG_MODULE(netlink) +VLOG_MODULE(ofctl) VLOG_MODULE(ovs_discover) VLOG_MODULE(ofproto) VLOG_MODULE(pktbuf) diff --git a/secchan/secchan.8.in b/secchan/secchan.8.in index e456c530..8a842947 100644 --- a/secchan/secchan.8.in +++ b/secchan/secchan.8.in @@ -50,7 +50,7 @@ over the network. It can do so in one of two ways: .IP out-of-band In this configuration, OpenFlow traffic uses a network separate from the data traffic that it controls, that is, the switch does not use -any of the network devices added to the datapath with \fBdpctl +any of the network devices added to the datapath with \fBovs\-dpctl addif\fR in its communication with the controller. To use \fBsecchan\fR in a network with out-of-band control, specify @@ -61,7 +61,7 @@ is started. .IP in-band In this configuration, a single network is used for OpenFlow traffic and other data traffic, that is, the switch contacts the controller -over one of the network devices added to the datapath with \fBdpctl +over one of the network devices added to the datapath with \fBovs\-dpctl addif\fR. This configuration is often more convenient than out-of-band control, because it is not necessary to maintain two independent networks. @@ -80,7 +80,7 @@ automatically, do not specify the location of the controller on the In this mode, \fBsecchan\fR will broadcast a DHCP request with vendor class identifier \fBOpenFlow\fR across the network devices added to -the datapath with \fBdpctl addif\fR. It will accept any valid DHCP +the datapath with \fBovs\-dpctl addif\fR. It will accept any valid DHCP reply that has the same vendor class identifier and includes a vendor-specific option with code 1 whose contents are a string specifying the location of the controller in the same format used on @@ -149,7 +149,7 @@ argument. You must also configure the network device for the OpenFlow ``local port'' to allow \fBsecchan\fR to connect to that controller. The OpenFlow local port is a virtual network port that \fBsecchan\fR bridges to the physical switch ports. The name of the local port for -a given \fIdatapath\fR may be seen by running \fBdpctl dp-show +a given \fIdatapath\fR may be seen by running \fBovs\-dpctl dp-show \fIdatapath\fR; the local port is listed as port 0 in \fBdp-show\fR's output. @@ -300,7 +300,7 @@ time is 15 seconds. .TP \fB-l\fR, \fB--listen=\fImethod\fR Configures the switch to additionally listen for incoming OpenFlow -connections for switch management with \fBdpctl\fR. The \fImethod\fR +connections for switch management with \fBovs\-ofctl\fR. The \fImethod\fR must be given as one of the passive OpenFlow connection methods listed below. This option may be specified multiple times to listen to multiple connection methods. @@ -329,7 +329,7 @@ be given as one of the passive OpenFlow connection methods listed under the \fB--listen\fR option above. This option may be specified multiple times to listen to multiple connection methods. -If \fBdpctl monitor\fR is used to connect to \fImethod\fR specified on +If \fBovs\-ofctl monitor\fR is used to connect to \fImethod\fR specified on \fB--snoop\fR, it will display all the OpenFlow messages traveling between the switch and its controller on the primary OpenFlow connection. This can be useful for debugging switch and controller @@ -382,7 +382,7 @@ This option takes effect only when \fB--rate-limit\fR is also specified. .TP \fB--command-acl=\fR[\fB!\fR]\fIglob\fR[\fB,\fR[\fB!\fR]\fIglob\fR...] Configures the commands that remote OpenFlow connections are allowed -to invoke using (e.g.) \fBdpctl execute\fR. The argument is a +to invoke using (e.g.) \fBovs\-ofctl execute\fR. The argument is a comma-separated sequence of shell glob patterns. A glob pattern specified without a leading \fB!\fR is a ``whitelist'' that specifies a set of commands that are that may be invoked, whereas a pattern that @@ -454,9 +454,10 @@ require the controller to send the CA certificate, but .SH "SEE ALSO" -.BR dpctl (8), .BR ovs\-appctl (8), -.BR ovs-discover (8), .BR ovs\-controller (8), -.BR ovs-pki (8), +.BR ovs\-discover (8), +.BR ovs\-dpctl (8), +.BR ovs\-ofctl (8), +.BR ovs\-pki (8), .BR vswitchd.conf (5) diff --git a/utilities/.gitignore b/utilities/.gitignore index 7cfc5c49..32a7f2eb 100644 --- a/utilities/.gitignore +++ b/utilities/.gitignore @@ -1,7 +1,5 @@ /Makefile /Makefile.in -/dpctl -/dpctl.8 /nlmon /ovs-appctl /ovs-appctl.8 @@ -11,8 +9,12 @@ /ovs-controller.8 /ovs-discover /ovs-discover.8 +/ovs-dpctl +/ovs-dpctl.8 /ovs-kill /ovs-kill.8 +/ovs-ofctl +/ovs-ofctl.8 /ovs-parse-leaks /ovs-pki /ovs-pki-cgi diff --git a/utilities/automake.mk b/utilities/automake.mk index 35c303c3..97b827ac 100644 --- a/utilities/automake.mk +++ b/utilities/automake.mk @@ -1,10 +1,11 @@ bin_PROGRAMS += \ - utilities/dpctl \ utilities/ovs-appctl \ utilities/ovs-cfg-mod \ utilities/ovs-controller \ utilities/ovs-discover \ + utilities/ovs-dpctl \ utilities/ovs-kill \ + utilities/ovs-ofctl \ utilities/ovs-wdt noinst_PROGRAMS += utilities/nlmon bin_SCRIPTS += utilities/ovs-pki @@ -12,40 +13,40 @@ noinst_SCRIPTS += utilities/ovs-pki-cgi utilities/ovs-parse-leaks dist_sbin_SCRIPTS += utilities/ovs-monitor EXTRA_DIST += \ - utilities/dpctl.8.in \ utilities/ovs-appctl.8.in \ utilities/ovs-cfg-mod.8.in \ utilities/ovs-controller.8.in \ utilities/ovs-discover.8.in \ + utilities/ovs-dpctl.8.in \ utilities/ovs-kill.8.in \ + utilities/ovs-ofctl.8.in \ utilities/ovs-parse-leaks.in \ utilities/ovs-pki-cgi.in \ utilities/ovs-pki.8.in \ utilities/ovs-pki.in DISTCLEANFILES += \ - utilities/dpctl.8 \ utilities/ovs-appctl.8 \ utilities/ovs-cfg-mod.8 \ utilities/ovs-controller.8 \ utilities/ovs-discover.8 \ + utilities/ovs-dpctl.8 \ utilities/ovs-kill.8 \ + utilities/ovs-ofctl.8 \ utilities/ovs-parse-leaks \ utilities/ovs-pki \ utilities/ovs-pki.8 \ utilities/ovs-pki-cgi man_MANS += \ - utilities/dpctl.8 \ utilities/ovs-appctl.8 \ utilities/ovs-cfg-mod.8 \ utilities/ovs-controller.8 \ utilities/ovs-discover.8 \ + utilities/ovs-dpctl.8 \ utilities/ovs-kill.8 \ + utilities/ovs-ofctl.8 \ utilities/ovs-pki.8 -utilities_dpctl_SOURCES = utilities/dpctl.c -utilities_dpctl_LDADD = lib/libopenvswitch.a $(FAULT_LIBS) $(SSL_LIBS) - utilities_ovs_appctl_SOURCES = utilities/ovs-appctl.c utilities_ovs_appctl_LDADD = lib/libopenvswitch.a @@ -58,9 +59,15 @@ utilities_ovs_controller_LDADD = lib/libopenvswitch.a $(FAULT_LIBS) $(SSL_LIBS) utilities_ovs_discover_SOURCES = utilities/ovs-discover.c utilities_ovs_discover_LDADD = lib/libopenvswitch.a +utilities_ovs_dpctl_SOURCES = utilities/ovs-dpctl.c +utilities_ovs_dpctl_LDADD = lib/libopenvswitch.a $(FAULT_LIBS) + utilities_ovs_kill_SOURCES = utilities/ovs-kill.c utilities_ovs_kill_LDADD = lib/libopenvswitch.a +utilities_ovs_ofctl_SOURCES = utilities/ovs-ofctl.c +utilities_ovs_ofctl_LDADD = lib/libopenvswitch.a $(FAULT_LIBS) $(SSL_LIBS) + utilities_ovs_wdt_SOURCES = utilities/ovs-wdt.c utilities_nlmon_SOURCES = utilities/nlmon.c diff --git a/utilities/ovs-appctl.8.in b/utilities/ovs-appctl.8.in index 5204a800..f4538179 100644 --- a/utilities/ovs-appctl.8.in +++ b/utilities/ovs-appctl.8.in @@ -161,6 +161,6 @@ error occurs. Use \fB-e help\fR to print a list of available commands. .SH "SEE ALSO" -.BR dpctl (8), -.BR secchan (8), -.BR ovs\-controller (8) +.BR ovs\-controller (8), +.BR ovs\-dpctl (8), +.BR secchan (8) diff --git a/utilities/ovs-controller.8.in b/utilities/ovs-controller.8.in index 0f8e775f..c28efac3 100644 --- a/utilities/ovs-controller.8.in +++ b/utilities/ovs-controller.8.in @@ -127,6 +127,6 @@ To bind locally to port 6633 (the default) and wait for incoming connections fro .SH "SEE ALSO" -.BR dpctl (8), .BR secchan (8), -.BR ovs\-appctl (8) +.BR ovs\-appctl (8), +.BR ovs\-dpctl (8) diff --git a/utilities/ovs-discover.8.in b/utilities/ovs-discover.8.in index 12a950e8..423fa42c 100644 --- a/utilities/ovs-discover.8.in +++ b/utilities/ovs-discover.8.in @@ -100,7 +100,7 @@ effect. .SH BUGS If the network devices specified on the command line have been added -to an OpenVSwitch datapath with \fBdpctl addif\fR, then controller +to an OpenVSwitch datapath with \fBovs\-dpctl addif\fR, then controller discovery will fail because \fBovs\-discover\fR will not be able to see DHCP responses, even though tools such as \fBtcpdump\fR(8) and \fBwireshark\fR(1) can see them on the wire. This is because of the diff --git a/utilities/ovs-dpctl.8.in b/utilities/ovs-dpctl.8.in new file mode 100644 index 00000000..61f2c694 --- /dev/null +++ b/utilities/ovs-dpctl.8.in @@ -0,0 +1,175 @@ +.TH ovs\-dpctl 8 "March 2009" "OpenVSwitch" "OpenVSwitch Manual" +.ds PN ovs\-dpctl + +.SH NAME +ovs\-dpctl \- administer OpenVSwitch datapaths + +.SH SYNOPSIS +.B ovs\-dpctl +[\fIoptions\fR] \fIcommand \fR[\fIswitch\fR] [\fIargs\fR\&...] + +.SH DESCRIPTION + +The \fBovs\-dpctl\fR program can create, modify, and delete OpenVSwitch +datapaths. A single machine may host up to 256 datapaths (numbered 0 +to 255). + +A newly created datapath is associated with only one network device, a +virtual network device sometimes called the datapath's ``local port''. +A newly created datapath is not, however, associated with any of the +host's other network devices. To intercept and process traffic on a +given network device, use the \fBaddif\fR command to explicitly add +that network device to the datapath. + +Do not use \fBovs\-dpctl\fR commands to modify datapaths if +\fBvswitchd\fR(8) is in use. Instead, modify the \fBvswitchd\fR +configuration file and send \fBSIGHUP\fR to the \fBvswitchd\fR +process. + +.PP +Most \fBovs\-dpctl\fR commands that work with datapaths take an argument +that specifies the name of the datapath, in one of the following +forms: + +.so lib/dpif.man + +.PP +The following commands manage datapaths. + +.TP +\fBadddp \fIdp\fR [\fInetdev\fR...] + +Creates datapath \fIdp\fR. The name of the new datapath's local port +depends on how \fIdp\fR is specified: if it takes the form +\fBdp\fIN\fR, the local port will be named \fBdp\fIN\fR; if \fIdp\fR +is \fBnl:\fI, the local port will be named \fBof\fIN\fR; otherwise, +the local port's name will be \fIdp\fR. + +This will fail if the host already has 256 datapaths, if a network +device with the same name as the new datapath's local port already +exists, or if \fIdp\fR is given in the form \fBdp\fIN\fR or +\fBnl:\fIN\fR and a datapath numbered \fIN\fR already exists. + +If \fInetdev\fRs are specified, \fBovs\-dpctl\fR adds them to the datapath. + +.TP +\fBdeldp \fIdp\fR +Deletes datapath \fIdp\fR. If \fIdp\fR is associated with any network +devices, they are automatically removed. + +.TP +\fBaddif \fIdp netdev\fR[\fIoption\fR...]... +Adds each \fInetdev\fR to the set of network devices datapath +\fIdp\fR monitors, where \fIdp\fR is the name of an existing +datapath, and \fInetdev\fR is the name of one of the host's +network devices, e.g. \fBeth0\fR. Once a network device has been added +to a datapath, the datapath has complete ownership of the network device's +traffic and the network device appears silent to the rest of the +system. + +A \fInetdev\fR may be followed by a comma-separated list of options. +The following options are currently supported: + +.RS +.IP "\fBport=\fIportno\fR" +Specifies \fIportno\fR (a number between 1 and 255) as the port number +at which \fInetdev\fR will be attached. By default, \fBaddif\fR +automatically selects the lowest available port number. + +.IP "\fBinternal\fR" +Instead of attaching an existing \fInetdev\fR, creates an internal +port (analogous to the local port) with that name. +.RE + +.TP +\fBdelif \fIdp netdev\fR... +Removes each \fInetdev\fR from the list of network devices datapath +\fIdp\fR monitors. + +.TP +\fBget-idx \fIdp\fR +Prints the datapath number of datapath \fIdp\fR. + +.TP +\fBget-name \fIdp\fR +Prints the name of datapath \fIdp\fR, that is, the name of the network +device acting as its local port. + +.TP +\fBdp-show \fR[\fIdp\fR...] +Prints a summary of configured datapaths, including their datapath +numbers and a list of ports connected to each datapath. (The local +port is identified as port 0.) + +If one or more datapaths are specified, information on only those +datapaths are displayed. Otherwise, \fBovs\-dpctl\fR displays information +about all configured datapaths. + +.IP "\fBdp-dump-flows \fIdp\fR" +Prints to the console all flow entries in datapath \fIdp\fR's +flow table. + +This command is primarily useful for debugging OpenVSwitch. The flow +table entries that it displays are not +OpenFlow flow entries. Instead, they are different and considerably +simpler flows maintained by the OpenVSwitch kernel module. + +.IP "\fBdp-del-flows \fIdp\fR" +Deletes all flow entries from datapath \fIdp\fR's flow table. + +This command is primarily useful for debugging OpenVSwitch. As +discussed in \fBdp-dump-flows\fR, these entries are +not OpenFlow flow entries. By deleting them, the process that set them +up may be confused about their disappearance. + +.IP "\fBdp-dump-groups \fIdp\fR" +Prints to the console the sets of port groups maintained by datapath +\fIdp\fR. Ordinarily there are at least 2 port groups in a datapath +that \fBsecchan\fR or \fBvswitch\fR is controlling: group 0 contains +all ports except those disabled by STP, and group 1 contains all +ports. Additional groups might be used in the future. + +This command is primarily useful for debugging OpenVSwitch. OpenFlow +does not have a concept of port groups. + +.SH OPTIONS +.TP +\fB-t\fR, \fB--timeout=\fIsecs\fR +Limits \fBovs\-dpctl\fR runtime to approximately \fIsecs\fR seconds. If +the timeout expires, \fBovs\-dpctl\fR will exit with a \fBSIGALRM\fR +signal. + +.so lib/vlog.man +.so lib/common.man + +.SH EXAMPLES + +A typical \fBovs\-dpctl\fR command sequence for controlling an +OpenVSwitch kernel module: + +.TP +\fBovs\-dpctl adddp dp0\fR +Creates datapath number 0. + +.TP +\fBovs\-dpctl addif dp0 eth0 eth1\fR +Adds two network devices to the new datapath. + +.PP +At this point one would ordinarily start \fBsecchan\fR(8) on +\fBdp0\fR, transforming \fBdp0\fR into an OpenFlow switch. Then, when +the switch and the datapath is no longer needed: + +.TP +\fBovs\-dpctl delif dp0 eth0 eth1\fR +Removes network devices from the datapath. + +.TP +\fBovs\-dpctl deldp dp0\fR +Deletes the datapath. + +.SH "SEE ALSO" + +.BR vswitchd (8), +.BR secchan (8), +.BR ovs\-appctl (8) diff --git a/utilities/ovs-dpctl.c b/utilities/ovs-dpctl.c new file mode 100644 index 00000000..a8c7b1be --- /dev/null +++ b/utilities/ovs-dpctl.c @@ -0,0 +1,593 @@ +/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford + * Junior University + * + * We are making the OpenFlow specification and associated documentation + * (Software) available for public use and benefit with the expectation + * that others will use, modify and enhance the Software and contribute + * those enhancements back to the community. However, since we would + * like to make the Software available for broadest use, with as few + * restrictions as possible permission is hereby granted, free of + * charge, to any person obtaining a copy of this Software to deal in + * the Software under the copyrights without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The name and trademarks of copyright holder(s) may NOT be used in + * advertising or publicity pertaining to the Software or any + * derivatives without specific, written prior permission. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "command-line.h" +#include "compiler.h" +#include "dirs.h" +#include "dpif.h" +#include "dynamic-string.h" +#include "netdev.h" +#include "odp-util.h" +#include "timeval.h" +#include "util.h" + +#include "vlog.h" +#define THIS_MODULE VLM_dpctl + +struct command { + const char *name; + int min_args; + int max_args; + void (*handler)(int argc, char *argv[]); +}; + +static struct command all_commands[]; + +static void usage(void) NO_RETURN; +static void parse_options(int argc, char *argv[]); + +int main(int argc, char *argv[]) +{ + struct command *p; + + set_program_name(argv[0]); + time_init(); + vlog_init(); + parse_options(argc, argv); + signal(SIGPIPE, SIG_IGN); + + argc -= optind; + argv += optind; + if (argc < 1) + ovs_fatal(0, "missing command name; use --help for help"); + + for (p = all_commands; p->name != NULL; p++) { + if (!strcmp(p->name, argv[0])) { + int n_arg = argc - 1; + if (n_arg < p->min_args) + ovs_fatal(0, "'%s' command requires at least %d arguments", + p->name, p->min_args); + else if (n_arg > p->max_args) + ovs_fatal(0, "'%s' command takes at most %d arguments", + p->name, p->max_args); + else { + p->handler(argc, argv); + if (ferror(stdout)) { + ovs_fatal(0, "write to stdout failed"); + } + if (ferror(stderr)) { + ovs_fatal(0, "write to stderr failed"); + } + exit(0); + } + } + } + ovs_fatal(0, "unknown command '%s'; use --help for help", argv[0]); + + return 0; +} + +static void +parse_options(int argc, char *argv[]) +{ + static struct option long_options[] = { + {"timeout", required_argument, 0, 't'}, + {"verbose", optional_argument, 0, 'v'}, + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {0, 0, 0, 0}, + }; + char *short_options = long_options_to_short_options(long_options); + + for (;;) { + unsigned long int timeout; + int c; + + c = getopt_long(argc, argv, short_options, long_options, NULL); + if (c == -1) { + break; + } + + switch (c) { + case 't': + timeout = strtoul(optarg, NULL, 10); + if (timeout <= 0) { + ovs_fatal(0, "value %s on -t or --timeout is not at least 1", + optarg); + } else { + time_alarm(timeout); + } + break; + + case 'h': + usage(); + + case 'V': + printf("%s %s compiled "__DATE__" "__TIME__"\n", + program_name, VERSION BUILDNR); + exit(EXIT_SUCCESS); + + case 'v': + vlog_set_verbosity(optarg); + break; + + case '?': + exit(EXIT_FAILURE); + + default: + abort(); + } + } + free(short_options); +} + +static void +usage(void) +{ + printf("%s: OpenVSwitch datapath management utility\n" + "usage: %s [OPTIONS] COMMAND [ARG...]\n" + " adddp DP [IFACE...] add new datapath DP (with IFACES)\n" + " deldp DP delete local datapath DP\n" + " addif DP IFACE... add each IFACE as a port on DP\n" + " delif DP IFACE... delete each IFACE from DP\n" + " dp-show show basic info on all datapaths\n" + " dp-show DP... show basic info on each DP\n" + " dp-dump-flows DP display flows in DP\n" + " dp-del-flows DP delete all flows from DP\n" + " dp-dump-groups DP display port groups in DP\n", + program_name, program_name); + vlog_usage(); + printf("\nOther options:\n" + " -t, --timeout=SECS give up after SECS seconds\n" + " -h, --help display this help message\n" + " -V, --version display version information\n"); + exit(EXIT_SUCCESS); +} + +static void run(int retval, const char *message, ...) + PRINTF_FORMAT(2, 3); + +static void run(int retval, const char *message, ...) +{ + if (retval) { + va_list args; + + fprintf(stderr, "%s: ", program_name); + va_start(args, message); + vfprintf(stderr, message, args); + va_end(args); + if (retval == EOF) { + fputs(": unexpected end of file\n", stderr); + } else { + fprintf(stderr, ": %s\n", strerror(retval)); + } + + exit(EXIT_FAILURE); + } +} + +static void do_add_port(int argc, char *argv[]); + +static int if_up(const char *netdev_name) +{ + struct netdev *netdev; + int retval; + + retval = netdev_open(netdev_name, NETDEV_ETH_TYPE_NONE, &netdev); + if (!retval) { + retval = netdev_turn_flags_on(netdev, NETDEV_UP, true); + netdev_close(netdev); + } + return retval; +} + +static void +do_get_idx(int argc UNUSED, char *argv[]) +{ + struct dpif dpif; + run(dpif_open(argv[1], &dpif), "opening datapath"); + printf("%u\n", dpif_id(&dpif)); + dpif_close(&dpif); +} + +static void +do_get_name(int argc UNUSED, char *argv[]) +{ + struct dpif dpif; + char name[IF_NAMESIZE + 1]; + + run(dpif_open(argv[1], &dpif), "opening datapath"); + run(dpif_get_name(&dpif, name, sizeof name), "getting datapath name"); + puts(name); + dpif_close(&dpif); +} + +static void +do_add_dp(int argc UNUSED, char *argv[]) +{ + struct dpif dpif; + run(dpif_create(argv[1], &dpif), "add_dp"); + dpif_close(&dpif); + if (argc > 2) { + do_add_port(argc, argv); + } +} + +static void +do_del_dp(int argc UNUSED, char *argv[]) +{ + struct dpif dpif; + run(dpif_open(argv[1], &dpif), "opening datapath"); + run(dpif_delete(&dpif), "del_dp"); + dpif_close(&dpif); +} + +static int +compare_ports(const void *a_, const void *b_) +{ + const struct odp_port *a = a_; + const struct odp_port *b = b_; + return a->port < b->port ? -1 : a->port > b->port; +} + +static void +query_ports(struct dpif *dpif, struct odp_port **ports, size_t *n_ports) +{ + run(dpif_port_list(dpif, ports, n_ports), "listing ports"); + qsort(*ports, *n_ports, sizeof **ports, compare_ports); +} + +static uint16_t +get_free_port(struct dpif *dpif) +{ + struct odp_port *ports; + size_t n_ports; + int port_no; + + query_ports(dpif, &ports, &n_ports); + for (port_no = 0; port_no <= UINT16_MAX; port_no++) { + size_t i; + for (i = 0; i < n_ports; i++) { + if (ports[i].port == port_no) { + goto next_portno; + } + } + free(ports); + return port_no; + + next_portno: ; + } + ovs_fatal(0, "no free datapath ports"); +} + +static void +do_add_port(int argc UNUSED, char *argv[]) +{ + bool failure = false; + struct dpif dpif; + int i; + + run(dpif_open(argv[1], &dpif), "opening datapath"); + for (i = 2; i < argc; i++) { + char *save_ptr = NULL; + char *devname, *suboptions; + int port = -1; + int flags = 0; + int error; + + devname = strtok_r(argv[i], ",,", &save_ptr); + if (!devname) { + ovs_error(0, "%s is not a valid network device name", argv[i]); + continue; + } + + suboptions = strtok_r(NULL, "", &save_ptr); + if (suboptions) { + enum { + AP_PORT, + AP_INTERNAL + }; + static char *options[] = { + "port", + "internal" + }; + + while (*suboptions != '\0') { + char *value; + + switch (getsubopt(&suboptions, options, &value)) { + case AP_PORT: + if (!value) { + ovs_error(0, "'port' suboption requires a value"); + } + port = atoi(value); + break; + + case AP_INTERNAL: + flags |= ODP_PORT_INTERNAL; + break; + + default: + ovs_error(0, "unknown suboption '%s'", value); + break; + } + } + } + if (port < 0) { + port = get_free_port(&dpif); + } + + error = dpif_port_add(&dpif, devname, port, flags); + if (error) { + ovs_error(error, "adding %s as port %"PRIu16" of %s failed", + devname, port, argv[1]); + failure = true; + } else if (if_up(devname)) { + failure = true; + } + } + dpif_close(&dpif); + if (failure) { + exit(EXIT_FAILURE); + } +} + +static bool +get_port_number(struct dpif *dpif, const char *name, uint16_t *port) +{ + struct odp_port *ports; + size_t n_ports; + size_t i; + + query_ports(dpif, &ports, &n_ports); + for (i = 0; i < n_ports; i++) { + if (!strcmp(name, ports[i].devname)) { + *port = ports[i].port; + free(ports); + return true; + } + } + free(ports); + ovs_error(0, "no port named %s", name); + return false; +} + +static void +do_del_port(int argc UNUSED, char *argv[]) +{ + bool failure = false; + struct dpif dpif; + int i; + + run(dpif_open(argv[1], &dpif), "opening datapath"); + for (i = 2; i < argc; i++) { + const char *name = argv[i]; + uint16_t port; + int error; + + if (!name[strspn(name, "0123456789")]) { + port = atoi(name); + } else if (!get_port_number(&dpif, name, &port)) { + failure = true; + continue; + } + + error = dpif_port_del(&dpif, port); + if (error) { + ovs_error(error, "deleting port %s from %s failed", name, argv[1]); + failure = true; + } + } + dpif_close(&dpif); + if (failure) { + exit(EXIT_FAILURE); + } +} + +static void +show_dpif(struct dpif *dpif) +{ + struct odp_port *ports; + struct odp_stats stats; + size_t n_ports; + size_t i; + + printf("dp%u:\n", dpif_id(dpif)); + if (!dpif_get_dp_stats(dpif, &stats)) { + printf("\tflows: cur:%"PRIu32", soft-max:%"PRIu32", " + "hard-max:%"PRIu32"\n", + stats.n_flows, stats.cur_capacity, stats.max_capacity); + printf("\tports: cur:%"PRIu32", max:%"PRIu32"\n", + stats.n_ports, stats.max_ports); + printf("\tgroups: max:%"PRIu16"\n", stats.max_groups); + printf("\tlookups: frags:%"PRIu64", hit:%"PRIu64", missed:%"PRIu64", " + "lost:%"PRIu64"\n", + stats.n_frags, stats.n_hit, stats.n_missed, stats.n_lost); + printf("\tqueues: max-miss:%"PRIu16", max-action:%"PRIu16"\n", + stats.max_miss_queue, stats.max_action_queue); + } + query_ports(dpif, &ports, &n_ports); + for (i = 0; i < n_ports; i++) { + printf("\tport %u: %s", ports[i].port, ports[i].devname); + if (ports[i].flags & ODP_PORT_INTERNAL) { + printf(" (internal)"); + } + printf("\n"); + } + free(ports); + dpif_close(dpif); +} + +static void +do_dp_show(int argc UNUSED, char *argv[]) +{ + bool failure = false; + if (argc > 1) { + int i; + for (i = 1; i < argc; i++) { + const char *name = argv[i]; + struct dpif dpif; + int error; + + error = dpif_open(name, &dpif); + if (!error) { + show_dpif(&dpif); + } else { + ovs_error(error, "opening datapath %s failed", name); + failure = true; + } + } + } else { + unsigned int i; + for (i = 0; i < ODP_MAX; i++) { + char name[128]; + struct dpif dpif; + int error; + + sprintf(name, "dp%u", i); + error = dpif_open(name, &dpif); + if (!error) { + show_dpif(&dpif); + } else if (error != ENODEV) { + ovs_error(error, "opening datapath %s failed", name); + failure = true; + } + } + } + if (failure) { + exit(EXIT_FAILURE); + } +} + +static void +do_dp_dump_flows(int argc UNUSED, char *argv[]) +{ + struct odp_flow *flows; + struct dpif dpif; + size_t n_flows; + struct ds ds; + size_t i; + + run(dpif_open(argv[1], &dpif), "opening datapath"); + run(dpif_flow_list_all(&dpif, &flows, &n_flows), "listing all flows"); + + ds_init(&ds); + for (i = 0; i < n_flows; i++) { + struct odp_flow *f = &flows[i]; + enum { MAX_ACTIONS = 4096 / sizeof(union odp_action) }; + union odp_action actions[MAX_ACTIONS]; + + f->actions = actions; + f->n_actions = MAX_ACTIONS; + dpif_flow_get(&dpif, f); + + ds_clear(&ds); + format_odp_flow(&ds, f); + printf("%s\n", ds_cstr(&ds)); + } + ds_destroy(&ds); + dpif_close(&dpif); +} + +static void +do_dp_del_flows(int argc UNUSED, char *argv[]) +{ + struct dpif dpif; + + run(dpif_open(argv[1], &dpif), "opening datapath"); + run(dpif_flow_flush(&dpif), "deleting all flows"); + dpif_close(&dpif); +} + +static void +do_dp_dump_groups(int argc UNUSED, char *argv[]) +{ + struct odp_stats stats; + struct dpif dpif; + unsigned int i; + + run(dpif_open(argv[1], &dpif), "opening datapath"); + run(dpif_get_dp_stats(&dpif, &stats), "get datapath stats"); + for (i = 0; i < stats.max_groups; i++) { + uint16_t ports[UINT16_MAX]; + size_t n_ports; + + if (!dpif_port_group_get(&dpif, i, ports, + ARRAY_SIZE(ports), &n_ports) && n_ports) { + size_t j; + + printf("group %u:", i); + for (j = 0; j < n_ports; j++) { + printf(" %"PRIu16, ports[j]); + } + printf("\n"); + } + } + dpif_close(&dpif); +} + +static void +do_help(int argc UNUSED, char *argv[] UNUSED) +{ + usage(); +} + +static struct command all_commands[] = { + { "adddp", 1, INT_MAX, do_add_dp }, + { "deldp", 1, 1, do_del_dp }, + { "addif", 2, INT_MAX, do_add_port }, + { "delif", 2, INT_MAX, do_del_port }, + { "get-idx", 1, 1, do_get_idx }, + { "get-name", 1, 1, do_get_name }, + { "dp-show", 0, INT_MAX, do_dp_show }, + { "dp-dump-flows", 1, 1, do_dp_dump_flows }, + { "dp-del-flows", 1, 1, do_dp_del_flows }, + { "dp-dump-groups", 1, 1, do_dp_dump_groups }, + { "help", 0, INT_MAX, do_help }, + { NULL, 0, 0, NULL }, +}; diff --git a/utilities/ovs-monitor b/utilities/ovs-monitor index 07a56c33..4e098612 100755 --- a/utilities/ovs-monitor +++ b/utilities/ovs-monitor @@ -99,7 +99,7 @@ while `/bin/true`; do if [ -d /proc/$pid ]; then # Check if the secchan and datapath still can communicate if [ -S $SECCHAN_SOCK ]; then - dpctl probe -t 2 unix:$SECCHAN_SOCK + ovs-ofctl probe -t 2 unix:$SECCHAN_SOCK if [ $? -ne 0 ]; then log "datapath probe failed" let DP_DOWN++ diff --git a/utilities/dpctl.8.in b/utilities/ovs-ofctl.8.in similarity index 71% rename from utilities/dpctl.8.in rename to utilities/ovs-ofctl.8.in index c88d3d3b..1243f04b 100644 --- a/utilities/dpctl.8.in +++ b/utilities/ovs-ofctl.8.in @@ -1,150 +1,23 @@ -.TH dpctl 8 "March 2009" "OpenVSwitch" "OpenVSwitch Manual" -.ds PN dpctl +.TH ovs\-ofctl 8 "March 2009" "OpenVSwitch" "OpenVSwitch Manual" +.ds PN ovs\-ofctl .SH NAME -dpctl \- administer OpenVSwitch datapaths and OpenFlow switches +ovs\-ofctl \- administer OpenFlow switches .SH SYNOPSIS -.B dpctl +.B ovs\-ofctl [\fIoptions\fR] \fIcommand \fR[\fIswitch\fR] [\fIargs\fR\&...] .SH DESCRIPTION The -.B dpctl +.B ovs\-ofctl program is a command line tool for monitoring and administering -OpenVSwitch datapaths and OpenFlow switches. -.B dpctl -can add, delete, and modify OpenVSwitch datapaths. It can also show -the current state of an OpenFlow switch, including features, -configuration, and table entries. - -.SS "OpenVSwitch Datapath Commands" - -The \fBdpctl\fR program can create, modify, and delete OpenVSwitch -datapaths. A single machine may host up to 256 datapaths (numbered 0 -to 255). - -A newly created datapath is associated with only one network device, a -virtual network device sometimes called the datapath's ``local port''. -A newly created datapath is not, however, associated with any of the -host's other network devices. To intercept and process traffic on a -given network device, use the \fBaddif\fR command to explicitly add -that network device to the datapath. - -Do not use \fBdpctl\fR commands to modify datapaths in conjunction -with \fBvswitchd\fR(8). Instead, modify the \fBvswitchd\fR -configuration file and send \fBSIGHUP\fR to the \fBvswitchd\fR -process. - -.PP -Most \fBdpctl\fR commands that work with datapaths take an argument -that specifies the name of the datapath, in one of the following -forms: - -.so lib/dpif.man - -.PP -The following commands manage datapaths. - -.TP -\fBadddp \fIdp\fR [\fInetdev\fR...] - -Creates datapath \fIdp\fR. The name of the new datapath's local port -depends on how \fIdp\fR is specified: if it takes the form -\fBdp\fIN\fR, the local port will be named \fBdp\fIN\fR; if \fIdp\fR -is \fBnl:\fI, the local port will be named \fBof\fIN\fR; otherwise, -the local port's name will be \fIdp\fR. - -This will fail if the host already has 256 datapaths, if a network -device with the same name as the new datapath's local port already -exists, or if \fIdp\fR is given in the form \fBdp\fIN\fR or -\fBnl:\fIN\fR and a datapath numbered \fIN\fR already exists. - -If \fInetdev\fRs are specified, \fBdpctl\fR adds them to the datapath. - -.TP -\fBdeldp \fIdp\fR -Deletes datapath \fIdp\fR. If \fIdp\fR is associated with any network -devices, they are automatically removed. - -.TP -\fBaddif \fIdp netdev\fR[\fIoption\fR...]... -Adds each \fInetdev\fR to the set of network devices datapath -\fIdp\fR monitors, where \fIdp\fR is the name of an existing -datapath, and \fInetdev\fR is the name of one of the host's -network devices, e.g. \fBeth0\fR. Once a network device has been added -to a datapath, the datapath has complete ownership of the network device's -traffic and the network device appears silent to the rest of the -system. - -A \fInetdev\fR may be followed by a comma-separated list of options. -The following options are currently supported: - -.RS -.IP "\fBport=\fIportno\fR" -Specifies \fIportno\fR (a number between 1 and 255) as the port number -at which \fInetdev\fR will be attached. By default, \fBaddif\fR -automatically selects the lowest available port number. - -.IP "\fBinternal\fR" -Instead of attaching an existing \fInetdev\fR, creates an internal -port (analogous to the local port) with that name. -.RE - -.TP -\fBdelif \fIdp netdev\fR... -Removes each \fInetdev\fR from the list of network devices datapath -\fIdp\fR monitors. - -.TP -\fBget-idx \fIdp\fR -Prints the datapath number of datapath \fIdp\fR. - -.TP -\fBget-name \fIdp\fR -Prints the name of datapath \fIdp\fR, that is, the name of the network -device acting as its local port. - -.TP -\fBdp-show \fR[\fIdp\fR...] -Prints a summary of configured datapaths, including their datapath -numbers and a list of ports connected to each datapath. (The local -port is identified as port 0.) - -If one or more datapaths are specified, information on only those -datapaths are displayed. Otherwise, \fBdpctl\fR displays information -about all configured datapaths. - -.IP "\fBdp-dump-flows \fIdp\fR" -Prints to the console all flow entries in datapath \fIdp\fR's -flow table. - -This command is primarily useful for debugging OpenVSwitch. The flow -table entries that it displays are not -OpenFlow flow entries. Instead, they are different and considerably -simpler flows maintained by the OpenVSwitch kernel module. - -.IP "\fBdp-del-flows \fIdp\fR" -Deletes all flow entries from datapath \fIdp\fR's flow table. - -This command is primarily useful for debugging OpenVSwitch. As -discussed in \fBdp-dump-flows\fR, these entries are -not OpenFlow flow entries. By deleting them, the process that set them -up may be confused about their disappearance. - -.IP "\fBdp-dump-groups \fIdp\fR" -Prints to the console the sets of port groups maintained by datapath -\fIdp\fR. Ordinarily there are at least 2 port groups in a datapath -that \fBsecchan\fR or \fBvswitch\fR is controlling: group 0 contains -all ports except those disabled by STP, and group 1 contains all -ports. Additional groups might be used in the future. - -This command is primarily useful for debugging OpenVSwitch. OpenFlow -does not have a concept of port groups. +OpenFlow switches. It can also show the current state of an OpenFlow +switch, including features, configuration, and table entries. .SS "OpenFlow Switch Management Commands" -These commands allow \fBdpctl\fR to monitor and administer an OpenFlow +These commands allow \fBovs\-ofctl\fR to monitor and administer an OpenFlow switch. It is able to show the current state of a switch, including features, configuration, and table entries. @@ -277,16 +150,16 @@ messages received. Usually, \fIswitch\fR should specify a connection named on \fBsecchan\fR(8)'s \fB-l\fR or \fB--listen\fR command line option. -If \fImiss-len\fR is provided, \fBdpctl\fR sends an OpenFlow ``set +If \fImiss-len\fR is provided, \fBovs\-ofctl\fR sends an OpenFlow ``set configuration'' message at connection setup time that requests \fImiss-len\fR bytes of each packet that misses the flow table. The OpenFlow reference implementation not send these messages to the -\fBdpctl monitor\fR client connection unless a nonzero value is +\fBovs\-ofctl monitor\fR client connection unless a nonzero value is specified on this argument. -If \fIsend-exp\fR is specified as \fB1\fR, \fBdpctl\fR will also +If \fIsend-exp\fR is specified as \fB1\fR, \fBovs\-ofctl\fR will also request to be sent flow expiration messages. If this argument is -omitted, or \fB0\fR is specified, then \fRdpctl\fR will not request +omitted, or \fB0\fR is specified, then \fRovs\-ofctl\fR will not request flow expirations. This command may be useful for debugging switch or controller @@ -332,7 +205,7 @@ messages. .SS "Flow Syntax" -Some \fBdpctl\fR commands accept an argument that describes a flow or +Some \fBovs\-ofctl\fR commands accept an argument that describes a flow or flows. Such flow descriptions comprise a series \fIfield\fB=\fIvalue\fR assignments, separated by commas or white space. (Embedding spaces into a flow description normally requires @@ -348,7 +221,7 @@ may be specified to explicitly mark any of these fields as a wildcard. .IP \fBin_port=\fIport_no\fR Matches physical port \fIport_no\fR. Switch ports are numbered as -displayed by \fBdpctl show\fR. +displayed by \fBovs\-ofctl show\fR. .IP \fBdl_vlan=\fIvlan\fR Matches IEEE 802.1q virtual LAN tag \fIvlan\fR. Specify \fB0xffff\fR @@ -483,7 +356,7 @@ Sets the destination Ethernet address to \fImac\fR. .RE .IP -(The OpenFlow protocol supports other actions that \fBdpctl\fR does +(The OpenFlow protocol supports other actions that \fBovs\-ofctl\fR does not yet expose to the user.) .PP @@ -569,8 +442,8 @@ Uses strict matching when running flow modification commands. .TP \fB-t\fR, \fB--timeout=\fIsecs\fR -Limits \fBdpctl\fR runtime to approximately \fIsecs\fR seconds. If -the timeout expires, \fBdpctl\fR will exit with a \fBSIGALRM\fR +Limits \fBovs\-ofctl\fR runtime to approximately \fIsecs\fR seconds. If +the timeout expires, \fBovs\-ofctl\fR will exit with a \fBSIGALRM\fR signal. .TP @@ -594,34 +467,6 @@ a switch is trustworthy. .SH EXAMPLES -.SS "Datapath Examples" - -A typical \fBdpctl\fR command sequence for controlling an OpenFlow -kernel module: - -.TP -\fBdpctl adddp dp0\fR -Creates datapath numbered 0. - -.TP -\fBdpctl addif dp0 eth0 eth1\fR -Adds two network devices to the new datapath. - -.PP -At this point one would ordinarily start \fBsecchan\fR(8) on -\fBdp0\fR, transforming \fBdp0\fR into an OpenFlow switch. Then, when -the switch and the datapath is no longer needed: - -.TP -\fBdpctl delif dp0 eth0 eth1\fR -Removes network devices from the datapath. - -.TP -\fBdpctl deldp dp0\fR -Deletes the datapath. - -.SS "OpenFlow Switch Examples" - The following examples assume that an OpenFlow switch on the local host has been configured to listen for management connections on a Unix domain socket named \fB@RUNDIR@/openflow.sock\fR, e.g. by @@ -629,17 +474,16 @@ specifying \fB--listen=punix:@RUNDIR@/openflow.sock\fR on the \fBsecchan\fR(8) command line. .TP -\fBdpctl dump-tables unix:@RUNDIR@/openflow.sock\fR +\fBovs\-ofctl dump-tables unix:@RUNDIR@/openflow.sock\fR Prints out the switch's table stats. (This is more interesting after some traffic has passed through.) .TP -\fBdpctl dump-flows unix:@RUNDIR@/openflow.sock\fR +\fBovs\-ofctl dump-flows unix:@RUNDIR@/openflow.sock\fR Prints the flow entries in the switch. .SH "SEE ALSO" .BR vswitchd (8), -.BR secchan (8), .BR ovs\-appctl (8), .BR ovs\-controller (8) diff --git a/utilities/dpctl.c b/utilities/ovs-ofctl.c similarity index 79% rename from utilities/dpctl.c rename to utilities/ovs-ofctl.c index 15ea4883..e5acffca 100644 --- a/utilities/dpctl.c +++ b/utilities/ovs-ofctl.c @@ -67,7 +67,7 @@ #include "vconn.h" #include "vlog.h" -#define THIS_MODULE VLM_dpctl +#define THIS_MODULE VLM_ofctl #define DEFAULT_IDLE_TIMEOUT 60 @@ -207,18 +207,8 @@ parse_options(int argc, char *argv[], struct settings *s) static void usage(void) { - printf("%s: OpenVSwitch datapath and OpenFlow switch management utility\n" + printf("%s: OpenFlow switch management utility\n" "usage: %s [OPTIONS] COMMAND [ARG...]\n" - "\nFor OpenVSwitch datapaths:\n" - " adddp DP [IFACE...] add new datapath DP (with IFACES)\n" - " deldp DP delete local datapath DP\n" - " addif DP IFACE... add each IFACE as a port on DP\n" - " delif DP IFACE... delete each IFACE from DP\n" - " dp-show show basic info on all datapaths\n" - " dp-show DP... show basic info on each DP\n" - " dp-dump-flows DP display flows in DP\n" - " dp-del-flows DP delete all flows from DP\n" - " dp-dump-groups DP display port groups in DP\n" "\nFor OpenFlow switches:\n" " show SWITCH show OpenFlow information\n" " status SWITCH [KEY] report statistics (about KEY)\n" @@ -278,369 +268,6 @@ static void run(int retval, const char *message, ...) } } -static void do_add_port(const struct settings *, int argc, char *argv[]); - -static int if_up(const char *netdev_name) -{ - struct netdev *netdev; - int retval; - - retval = netdev_open(netdev_name, NETDEV_ETH_TYPE_NONE, &netdev); - if (!retval) { - retval = netdev_turn_flags_on(netdev, NETDEV_UP, true); - netdev_close(netdev); - } - return retval; -} - -static void -do_get_idx(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) -{ - struct dpif dpif; - run(dpif_open(argv[1], &dpif), "opening datapath"); - printf("%u\n", dpif_id(&dpif)); - dpif_close(&dpif); -} - -static void -do_get_name(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) -{ - struct dpif dpif; - char name[IF_NAMESIZE + 1]; - - run(dpif_open(argv[1], &dpif), "opening datapath"); - run(dpif_get_name(&dpif, name, sizeof name), "getting datapath name"); - puts(name); - dpif_close(&dpif); -} - -static void -do_add_dp(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) -{ - struct dpif dpif; - run(dpif_create(argv[1], &dpif), "add_dp"); - dpif_close(&dpif); - if (argc > 2) { - do_add_port(s, argc, argv); - } -} - -static void -do_del_dp(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) -{ - struct dpif dpif; - run(dpif_open(argv[1], &dpif), "opening datapath"); - run(dpif_delete(&dpif), "del_dp"); - dpif_close(&dpif); -} - -static int -compare_ports(const void *a_, const void *b_) -{ - const struct odp_port *a = a_; - const struct odp_port *b = b_; - return a->port < b->port ? -1 : a->port > b->port; -} - -static void -query_ports(struct dpif *dpif, struct odp_port **ports, size_t *n_ports) -{ - run(dpif_port_list(dpif, ports, n_ports), "listing ports"); - qsort(*ports, *n_ports, sizeof **ports, compare_ports); -} - -static uint16_t -get_free_port(struct dpif *dpif) -{ - struct odp_port *ports; - size_t n_ports; - int port_no; - - query_ports(dpif, &ports, &n_ports); - for (port_no = 0; port_no <= UINT16_MAX; port_no++) { - size_t i; - for (i = 0; i < n_ports; i++) { - if (ports[i].port == port_no) { - goto next_portno; - } - } - free(ports); - return port_no; - - next_portno: ; - } - ovs_fatal(0, "no free datapath ports"); -} - -static void -do_add_port(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) -{ - bool failure = false; - struct dpif dpif; - int i; - - run(dpif_open(argv[1], &dpif), "opening datapath"); - for (i = 2; i < argc; i++) { - char *save_ptr = NULL; - char *devname, *suboptions; - int port = -1; - int flags = 0; - int error; - - devname = strtok_r(argv[i], ",,", &save_ptr); - if (!devname) { - ovs_error(0, "%s is not a valid network device name", argv[i]); - continue; - } - - suboptions = strtok_r(NULL, "", &save_ptr); - if (suboptions) { - enum { - AP_PORT, - AP_INTERNAL - }; - static char *options[] = { - "port", - "internal" - }; - - while (*suboptions != '\0') { - char *value; - - switch (getsubopt(&suboptions, options, &value)) { - case AP_PORT: - if (!value) { - ovs_error(0, "'port' suboption requires a value"); - } - port = atoi(value); - break; - - case AP_INTERNAL: - flags |= ODP_PORT_INTERNAL; - break; - - default: - ovs_error(0, "unknown suboption '%s'", value); - break; - } - } - } - if (port < 0) { - port = get_free_port(&dpif); - } - - error = dpif_port_add(&dpif, devname, port, flags); - if (error) { - ovs_error(error, "adding %s as port %"PRIu16" of %s failed", - devname, port, argv[1]); - failure = true; - } else if (if_up(devname)) { - failure = true; - } - } - dpif_close(&dpif); - if (failure) { - exit(EXIT_FAILURE); - } -} - -static bool -get_port_number(struct dpif *dpif, const char *name, uint16_t *port) -{ - struct odp_port *ports; - size_t n_ports; - size_t i; - - query_ports(dpif, &ports, &n_ports); - for (i = 0; i < n_ports; i++) { - if (!strcmp(name, ports[i].devname)) { - *port = ports[i].port; - free(ports); - return true; - } - } - free(ports); - ovs_error(0, "no port named %s", name); - return false; -} - -static void -do_del_port(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) -{ - bool failure = false; - struct dpif dpif; - int i; - - run(dpif_open(argv[1], &dpif), "opening datapath"); - for (i = 2; i < argc; i++) { - const char *name = argv[i]; - uint16_t port; - int error; - - if (!name[strspn(name, "0123456789")]) { - port = atoi(name); - } else if (!get_port_number(&dpif, name, &port)) { - failure = true; - continue; - } - - error = dpif_port_del(&dpif, port); - if (error) { - ovs_error(error, "deleting port %s from %s failed", name, argv[1]); - failure = true; - } - } - dpif_close(&dpif); - if (failure) { - exit(EXIT_FAILURE); - } -} - -static void -show_dpif(struct dpif *dpif) -{ - struct odp_port *ports; - struct odp_stats stats; - size_t n_ports; - size_t i; - - printf("dp%u:\n", dpif_id(dpif)); - if (!dpif_get_dp_stats(dpif, &stats)) { - printf("\tflows: cur:%"PRIu32", soft-max:%"PRIu32", " - "hard-max:%"PRIu32"\n", - stats.n_flows, stats.cur_capacity, stats.max_capacity); - printf("\tports: cur:%"PRIu32", max:%"PRIu32"\n", - stats.n_ports, stats.max_ports); - printf("\tgroups: max:%"PRIu16"\n", stats.max_groups); - printf("\tlookups: frags:%"PRIu64", hit:%"PRIu64", missed:%"PRIu64", " - "lost:%"PRIu64"\n", - stats.n_frags, stats.n_hit, stats.n_missed, stats.n_lost); - printf("\tqueues: max-miss:%"PRIu16", max-action:%"PRIu16"\n", - stats.max_miss_queue, stats.max_action_queue); - } - query_ports(dpif, &ports, &n_ports); - for (i = 0; i < n_ports; i++) { - printf("\tport %u: %s", ports[i].port, ports[i].devname); - if (ports[i].flags & ODP_PORT_INTERNAL) { - printf(" (internal)"); - } - printf("\n"); - } - free(ports); - dpif_close(dpif); -} - -static void -do_dp_show(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) -{ - bool failure = false; - if (argc > 1) { - int i; - for (i = 1; i < argc; i++) { - const char *name = argv[i]; - struct dpif dpif; - int error; - - error = dpif_open(name, &dpif); - if (!error) { - show_dpif(&dpif); - } else { - ovs_error(error, "opening datapath %s failed", name); - failure = true; - } - } - } else { - unsigned int i; - for (i = 0; i < ODP_MAX; i++) { - char name[128]; - struct dpif dpif; - int error; - - sprintf(name, "dp%u", i); - error = dpif_open(name, &dpif); - if (!error) { - show_dpif(&dpif); - } else if (error != ENODEV) { - ovs_error(error, "opening datapath %s failed", name); - failure = true; - } - } - } - if (failure) { - exit(EXIT_FAILURE); - } -} - -static void -do_dp_dump_flows(const struct settings *s UNUSED, - int argc UNUSED, char *argv[]) -{ - struct odp_flow *flows; - struct dpif dpif; - size_t n_flows; - struct ds ds; - size_t i; - - run(dpif_open(argv[1], &dpif), "opening datapath"); - run(dpif_flow_list_all(&dpif, &flows, &n_flows), "listing all flows"); - - ds_init(&ds); - for (i = 0; i < n_flows; i++) { - struct odp_flow *f = &flows[i]; - enum { MAX_ACTIONS = 4096 / sizeof(union odp_action) }; - union odp_action actions[MAX_ACTIONS]; - - f->actions = actions; - f->n_actions = MAX_ACTIONS; - dpif_flow_get(&dpif, f); - - ds_clear(&ds); - format_odp_flow(&ds, f); - printf("%s\n", ds_cstr(&ds)); - } - ds_destroy(&ds); - dpif_close(&dpif); -} - -static void -do_dp_del_flows(const struct settings *s UNUSED, - int argc UNUSED, char *argv[]) -{ - struct dpif dpif; - - run(dpif_open(argv[1], &dpif), "opening datapath"); - run(dpif_flow_flush(&dpif), "deleting all flows"); - dpif_close(&dpif); -} - -static void -do_dp_dump_groups(const struct settings *s UNUSED, - int argc UNUSED, char *argv[]) -{ - struct odp_stats stats; - struct dpif dpif; - unsigned int i; - - run(dpif_open(argv[1], &dpif), "opening datapath"); - run(dpif_get_dp_stats(&dpif, &stats), "get datapath stats"); - for (i = 0; i < stats.max_groups; i++) { - uint16_t ports[UINT16_MAX]; - size_t n_ports; - - if (!dpif_port_group_get(&dpif, i, ports, - ARRAY_SIZE(ports), &n_ports) && n_ports) { - size_t j; - - printf("group %u:", i); - for (j = 0; j < n_ports; j++) { - printf(" %"PRIu16, ports[j]); - } - printf("\n"); - } - } - dpif_close(&dpif); -} - /* Generic commands. */ static void @@ -1718,23 +1345,8 @@ do_help(const struct settings *s UNUSED, int argc UNUSED, char *argv[] UNUSED) } static struct command all_commands[] = { -#ifdef HAVE_NETLINK - { "adddp", 1, INT_MAX, do_add_dp }, - { "deldp", 1, 1, do_del_dp }, - { "addif", 2, INT_MAX, do_add_port }, - { "delif", 2, INT_MAX, do_del_port }, - { "get-idx", 1, 1, do_get_idx }, - { "get-name", 1, 1, do_get_name }, - { "dp-show", 0, INT_MAX, do_dp_show }, - { "dp-dump-flows", 1, 1, do_dp_dump_flows }, - { "dp-del-flows", 1, 1, do_dp_del_flows }, - { "dp-dump-groups", 1, 1, do_dp_dump_groups }, -#endif - { "show", 1, 1, do_show }, { "status", 1, 2, do_status }, - - { "help", 0, INT_MAX, do_help }, { "monitor", 1, 3, do_monitor }, { "dump-desc", 1, 1, do_dump_desc }, { "dump-tables", 1, 1, do_dump_tables }, @@ -1754,5 +1366,6 @@ static struct command all_commands[] = { { "ping", 1, 2, do_ping }, { "benchmark", 3, 3, do_benchmark }, { "execute", 2, INT_MAX, do_execute }, + { "help", 0, INT_MAX, do_help }, { NULL, 0, 0, NULL }, }; diff --git a/utilities/ovs-pki.8.in b/utilities/ovs-pki.8.in index aa58d3fc..fb3e4e42 100644 --- a/utilities/ovs-pki.8.in +++ b/utilities/ovs-pki.8.in @@ -319,6 +319,5 @@ Prints a help usage message and exits. .SH "SEE ALSO" .BR controller (8), -.BR dpctl (8), .BR ovs\-pki\-cgi (8), .BR secchan (8) diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index fa246376..6fb9ccde 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -1619,7 +1619,7 @@ process_flow(struct bridge *br, const flow_t *flow, * - We deleted an interface but there are still a few packets * queued up from it. * - * - Someone externally added an interface (e.g. with "dpctl + * - Someone externally added an interface (e.g. with "ovs-dpctl * addif") that we don't know about. * * - Packet arrived on the local port but the local port is not diff --git a/vswitchd/vswitchd.8.in b/vswitchd/vswitchd.8.in index 737ef364..24357004 100644 --- a/vswitchd/vswitchd.8.in +++ b/vswitchd/vswitchd.8.in @@ -50,10 +50,10 @@ A single \fBvswitchd\fR can manage any number of virtual switches, up to the maximum number of supported OpenVSwitch datapaths. .PP \fBvswitchd\fR does all the necessary management of OpenVSwitch datapaths -itself. Thus, external tools, such \fBdpctl\fR(8), are not needed for +itself. Thus, external tools, such \fBovs\-dpctl\fR(8), are not needed for managing datapaths in conjunction with \fBvswitchd\fR, and their use to modify datapaths when \fBvswitchd\fR is running can interfere with -its operation. (\fBdpctl\fR may still be useful for diagnostics.) +its operation. (\fBovs\-dpctl\fR may still be useful for diagnostics.) .PP An OpenVSwitch datapath kernel module must be loaded for \fBvswitchd\fR to be useful. Please refer to the \fBINSTALL\fR file included in the diff --git a/vswitchd/vswitchd.conf.5.in b/vswitchd/vswitchd.conf.5.in index 53bdcecc..7b61ece8 100644 --- a/vswitchd/vswitchd.conf.5.in +++ b/vswitchd/vswitchd.conf.5.in @@ -529,7 +529,7 @@ using the \fBmgmt.burst-limit\fR key. This option takes effect only when a rate-limit is specified. .ST "Remote Command Execution Settings" These settings configure the commands that remote OpenFlow connections -are allowed to invoke using (e.g.) \fBdpctl execute\fR. To be +are allowed to invoke using (e.g.) \fBovs\-ofctl execute\fR. To be permitted, a command name must be whitelisted and must not be blacklisted. When the whitelist and blacklist permit a command name, \fBvswitchd\fR looks for a program with the same name as the command @@ -597,7 +597,7 @@ require the controller to send the CA certificate, but By default, each bridge \fIname\fR listens for OpenFlow management connections on a Unix domain socket named \fB@RUNDIR@/\fIname\fB.mgmt\fR. This socket can be used to perform -local OpenFlow monitoring and administration, e.g., \fBdpctl dump-flows +local OpenFlow monitoring and administration, e.g., \fBovs\-ofctl dump-flows unix:@RUNDIR@/\fIname\fB.mgmt\fR to display the flows currently set up in bridge \fIname\fR. .PP @@ -622,7 +622,7 @@ To entirely disable listening for management connections, set By default, each bridge \fIname\fR listens for OpenFlow controller connection snooping connections on a Unix domain socket named \fB@RUNDIR@/\fIname\fB.snoop\fR. A client that connects to this -socket, e.g., \fBdpctl monitor unix:@RUNDIR@/\fIname\fB.snoop\fR, will +socket, e.g., \fBovs\-ofctl monitor unix:@RUNDIR@/\fIname\fB.snoop\fR, will receive a copy of every OpenFlow message sent by the switch to the controller, or vice versa, on the primary OpenFlow controller connection. diff --git a/xenserver/etc_init.d_vswitch b/xenserver/etc_init.d_vswitch index 8be18cb7..932ba7cb 100755 --- a/xenserver/etc_init.d_vswitch +++ b/xenserver/etc_init.d_vswitch @@ -62,8 +62,9 @@ BRCOMPATD_VALGRIND_OPT="${BRCOMPATD_VALGRIND_OPT:-}" # Full paths to executables & modules vswitchd="$VSWITCH_BASE/sbin/vswitchd" brcompatd="$VSWITCH_BASE/sbin/brcompatd" -dpctl="$VSWITCH_BASE/bin/dpctl" +dpctl="$VSWITCH_BASE/bin/ovs-dpctl" appctl="$VSWITCH_BASE/bin/ovs-appctl" +ofctl="$VSWITCH_BASE/bin/ovs-ofctl" if [ "$ENABLE_FAKE_PROC_NET" == "y" ]; then @@ -119,8 +120,8 @@ function allow_xen_mgmt_traffic { local mgmt_hwaddr=$(xen_pifdev_hwaddr "$mgmt_pifdev") test -n "$mgmt_hwaddr" || return action "Inserting dl_addr $mgmt_hwaddr flows for mgmt intf" true - "$dpctl" add-flow "$mgmt_intf" dl_src="$mgmt_hwaddr",idle_timeout=0,priority=0,action=normal - "$dpctl" add-flow "$mgmt_intf" dl_dst="$mgmt_hwaddr",idle_timeout=0,priority=0,action=normal + "$ofctl" add-flow "$mgmt_intf" dl_src="$mgmt_hwaddr",idle_timeout=0,priority=0,action=normal + "$ofctl" add-flow "$mgmt_intf" dl_dst="$mgmt_hwaddr",idle_timeout=0,priority=0,action=normal } function ifup_dp_intf { diff --git a/xenserver/etc_profile.d_vswitch.sh b/xenserver/etc_profile.d_vswitch.sh index 1b691791..7905491e 100644 --- a/xenserver/etc_profile.d_vswitch.sh +++ b/xenserver/etc_profile.d_vswitch.sh @@ -17,7 +17,7 @@ function watchconf { } function watchdp { - watch dpctl dp-show "$@" + watch ovs-dpctl dp-show "$@" } function watchdpflows { @@ -27,18 +27,18 @@ function watchdpflows { if [ $# -gt 0 ]; then grep="| grep $@" fi - watch "dpctl dp-dump-flows $dp $grep" + watch "ovs-dpctl dp-dump-flows $dp $grep" } function watchflows { local grep="" local dp=$1 shift - bridge=$(dpctl dp-show $dp | grep 'port 0:' | cut -d' ' -f 3) + bridge=$(ovs-dpctl dp-show $dp | grep 'port 0:' | cut -d' ' -f 3) if [ $# -gt 0 ]; then grep="| grep $@" fi - watch "dpctl dump-flows unix:/var/run/$bridge.mgmt $grep" + watch "ovs-ofctl dump-flows unix:/var/run/$bridge.mgmt $grep" } function monitorlogs { diff --git a/xenserver/vswitch-xen.spec b/xenserver/vswitch-xen.spec index 2199c95f..5640c85b 100644 --- a/xenserver/vswitch-xen.spec +++ b/xenserver/vswitch-xen.spec @@ -259,12 +259,14 @@ fi /root/vswitch/scripts/XSFeatureNiciraVSwitch.pyo /root/vswitch/sbin/brcompatd /root/vswitch/sbin/vswitchd -/root/vswitch/bin/dpctl /root/vswitch/bin/ovs-appctl /root/vswitch/bin/ovs-cfg-mod +/root/vswitch/bin/ovs-dpctl +/root/vswitch/bin/ovs-ofctl /root/vswitch/share/man/man5/vswitchd.conf.5 /root/vswitch/share/man/man8/brcompatd.8 /root/vswitch/share/man/man8/ovs-appctl.8 /root/vswitch/share/man/man8/ovs-cfg-mod.8 -/root/vswitch/share/man/man8/dpctl.8 +/root/vswitch/share/man/man8/ovs-dpctl.8 +/root/vswitch/share/man/man8/ovs-ofctl.8 /root/vswitch/share/man/man8/vswitchd.8 -- 2.30.2