diff options
| author | Ben Pfaff <blp@nicira.com> | 2009-08-19 13:03:46 -0700 |
|---|---|---|
| committer | Ben Pfaff <blp@nicira.com> | 2009-08-19 13:03:46 -0700 |
| commit | 8fef8c7121222233075a03d57db7e0b48d5f6be5 (patch) | |
| tree | 5cb9822a490c41694be2c8af80ec6a5300ad7a28 /utilities | |
| parent | d2cd45db48e2713b74c3a31f746f923a72294e46 (diff) | |
| parent | 6dd3fad481b5d801695c2b0529c7d37cac2c9b19 (diff) | |
| download | openvswitch-8fef8c7121222233075a03d57db7e0b48d5f6be5.tar.gz | |
Merge citrix into master.
This was a somewhat difficult merge since there was a fair amount of
superficially divergent development on the two branches, especially in the
datapath.
This has been build-tested against XenServer 5.5.0 and XenServer 5.7.0
build 15122. It has been booted and connected to XenCenter on 5.5.0.
The merge revealed a couple of outstanding bugs, which will be fixed on
citrix and then merged back into master.
Diffstat (limited to 'utilities')
| -rw-r--r-- | utilities/.gitignore | 2 | ||||
| -rw-r--r-- | utilities/automake.mk | 11 | ||||
| -rw-r--r-- | utilities/ovs-appctl.8.in | 4 | ||||
| -rw-r--r-- | utilities/ovs-controller.8.in | 16 | ||||
| -rw-r--r-- | utilities/ovs-discover.8.in | 17 | ||||
| -rw-r--r-- | utilities/ovs-discover.c | 2 | ||||
| -rw-r--r-- | utilities/ovs-dpctl.8.in | 21 | ||||
| -rw-r--r-- | utilities/ovs-dpctl.c | 112 | ||||
| -rwxr-xr-x | utilities/ovs-monitor | 50 | ||||
| -rw-r--r-- | utilities/ovs-ofctl.8.in | 12 | ||||
| -rw-r--r-- | utilities/ovs-ofctl.c | 8 | ||||
| -rw-r--r-- | utilities/ovs-openflowd.8.in | 469 | ||||
| -rw-r--r-- | utilities/ovs-openflowd.c | 565 | ||||
| -rw-r--r-- | utilities/ovs-pki.8.in | 6 |
14 files changed, 1152 insertions, 143 deletions
diff --git a/utilities/.gitignore b/utilities/.gitignore index 32a7f2eb7..ebbd69167 100644 --- a/utilities/.gitignore +++ b/utilities/.gitignore @@ -15,6 +15,8 @@ /ovs-kill.8 /ovs-ofctl /ovs-ofctl.8 +/ovs-openflowd +/ovs-openflowd.8 /ovs-parse-leaks /ovs-pki /ovs-pki-cgi diff --git a/utilities/automake.mk b/utilities/automake.mk index 97b827acc..5bf3cbb7e 100644 --- a/utilities/automake.mk +++ b/utilities/automake.mk @@ -6,6 +6,7 @@ bin_PROGRAMS += \ utilities/ovs-dpctl \ utilities/ovs-kill \ utilities/ovs-ofctl \ + utilities/ovs-openflowd \ utilities/ovs-wdt noinst_PROGRAMS += utilities/nlmon bin_SCRIPTS += utilities/ovs-pki @@ -20,6 +21,7 @@ EXTRA_DIST += \ utilities/ovs-dpctl.8.in \ utilities/ovs-kill.8.in \ utilities/ovs-ofctl.8.in \ + utilities/ovs-openflowd.8.in \ utilities/ovs-parse-leaks.in \ utilities/ovs-pki-cgi.in \ utilities/ovs-pki.8.in \ @@ -32,6 +34,7 @@ DISTCLEANFILES += \ utilities/ovs-dpctl.8 \ utilities/ovs-kill.8 \ utilities/ovs-ofctl.8 \ + utilities/ovs-openflowd.8 \ utilities/ovs-parse-leaks \ utilities/ovs-pki \ utilities/ovs-pki.8 \ @@ -45,6 +48,7 @@ man_MANS += \ utilities/ovs-dpctl.8 \ utilities/ovs-kill.8 \ utilities/ovs-ofctl.8 \ + utilities/ovs-openflowd.8 \ utilities/ovs-pki.8 utilities_ovs_appctl_SOURCES = utilities/ovs-appctl.c @@ -68,6 +72,13 @@ 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_openflowd_SOURCES = utilities/ovs-openflowd.c +utilities_ovs_openflowd_LDADD = \ + ofproto/libofproto.a \ + 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 9bf97fd2f..d5e6b82ec 100644 --- a/utilities/ovs-appctl.8.in +++ b/utilities/ovs-appctl.8.in @@ -79,7 +79,7 @@ expanded as follows: .RS .IP \fB%A\fR -The name of the application logging the message, e.g. \fBsecchan\fR. +The name of the application logging the message, e.g. \fBovs-vswitchd\fR. .IP \fB%c\fR The name of the module (as shown by \fBovs\-appctl --list\fR) logging @@ -163,4 +163,4 @@ error occurs. Use \fB-e help\fR to print a list of available commands. .BR ovs\-controller (8), .BR ovs\-dpctl (8), -.BR secchan (8) +.BR ovs\-openflowd (8) diff --git a/utilities/ovs-controller.8.in b/utilities/ovs-controller.8.in index 750fcea5f..658cf131b 100644 --- a/utilities/ovs-controller.8.in +++ b/utilities/ovs-controller.8.in @@ -16,16 +16,22 @@ protocol, causing them to function as L2 MAC-learning switches or hub. one or more of the following OpenFlow connection methods: .TP -\fBpssl:\fR[\fIport\fR] +\fBpssl:\fR[\fIport\fR][\fB:\fIip\fR] Listens for SSL connections from remote OpenFlow switches on \fIport\fR (default: 6633). The \fB--private-key\fR, \fB--certificate\fR, and \fB--ca-cert\fR options are mandatory when this form is used. +By default, \fB\*(PN\fR listens for connections to any local IP +address, but \fIip\fR may be specified to listen only for connections +to the given \fIip\fR. .TP -\fBptcp:\fR[\fIport\fR] +\fBptcp:\fR[\fIport\fR][\fB:\fIip\fR] Listens for TCP connections from remote OpenFlow switches on \fIport\fR (default: 6633). +By default, \fB\*(PN\fR listens for connections to any local IP +address, but \fIip\fR may be specified to listen only for connections +to the given \fIip\fR. .TP \fBpunix:\fIfile\fR @@ -75,7 +81,7 @@ already have the controller CA certificate for it to have any confidence in the controller's identity. However, this option allows a newly installed switch to obtain the controller CA certificate on first boot using, e.g., the \fB--bootstrap-ca-cert\fR option to -\fBsecchan\fR(8). +\fBovs\-openflowd\fR(8). .IP "\fB-n\fR, \fB--noflow\fR" By default, \fBovs\-controller\fR sets up a flow in each OpenFlow switch @@ -96,7 +102,7 @@ recommended, flows will never expire. The default is 60 seconds. This option affects only flows set up by the OpenFlow controller. In some configurations, the switch can set up some flows on its own. To set the idle time for those flows, pass -\fB--max-idle\fR to \fBsecchan\fR (on the switch). +\fB--max-idle\fR to \fBovs\-openflowd\fR (on the switch). This option has no effect when \fB-n\fR (or \fB--noflow\fR) is in use (because the controller does not set up flows in that case). @@ -126,6 +132,6 @@ To bind locally to port 6633 (the default) and wait for incoming connections fro .SH "SEE ALSO" -.BR secchan (8), +.BR ovs\-openflowd (8), .BR ovs\-appctl (8), .BR ovs\-dpctl (8) diff --git a/utilities/ovs-discover.8.in b/utilities/ovs-discover.8.in index e9685d9e0..61e4b123f 100644 --- a/utilities/ovs-discover.8.in +++ b/utilities/ovs-discover.8.in @@ -17,7 +17,7 @@ receives an acceptable DHCP response. 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 -the \fBsecchan\fR command line (e.g. \fBssl:192.168.0.1\fR). +the \fBovs\-openflowd\fR command line (e.g. \fBssl:192.168.0.1\fR). When \fBovs\-discover\fR receives an acceptable response, it prints the details of the response on \fBstdout\fR. Then, by default, it @@ -28,15 +28,16 @@ itself to the background. .SH OPTIONS .TP \fB--accept-vconn=\fIregex\fR -By default, \fBovs\-discover\fR accepts any controller location -advertised over DHCP. With this option, only controllers whose names -match POSIX extended regular expression \fIregex\fR will be accepted. -Specifying \fBssl:.*\fR for \fIregex\fR, for example, would cause only -SSL controller connections to be accepted. +With this option, only controllers whose names match POSIX extended +regular expression \fIregex\fR will be accepted. Specifying +\fBssl:.*\fR for \fIregex\fR, for example, would cause only SSL +controller connections to be accepted. The \fIregex\fR is implicitly anchored at the beginning of the controller location string, as if it begins with \fB^\fR. +When this option is not given, the default \fIregex\fR is +\fBtcp:.*\fR. .TP \fB--exit-without-bind\fR By default, \fBovs\-discover\fR binds the network device that receives @@ -113,5 +114,5 @@ arriving IP packets, will not. .SH "SEE ALSO" -.BR secchan (8), -.BR ovs-pki (8) +.BR ovs\-openflowd (8), +.BR ovs\-pki (8) diff --git a/utilities/ovs-discover.c b/utilities/ovs-discover.c index 308c40531..dc91bce3d 100644 --- a/utilities/ovs-discover.c +++ b/utilities/ovs-discover.c @@ -48,7 +48,7 @@ static int n_ifaces; /* --accept-vconn: Regular expression specifying the class of controller vconns * that we will accept during autodiscovery. */ -static const char *accept_controller_re = ".*"; +static const char *accept_controller_re = "tcp:.*"; static regex_t accept_controller_regex; /* --exit-without-bind: Exit after discovering the controller, without binding diff --git a/utilities/ovs-dpctl.8.in b/utilities/ovs-dpctl.8.in index a1719f8ee..dc4d45681 100644 --- a/utilities/ovs-dpctl.8.in +++ b/utilities/ovs-dpctl.8.in @@ -41,14 +41,13 @@ The following commands manage datapaths. 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, +\fBdp\fIN\fR, the local port will be named \fBdp\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. +exists, or if \fIdp\fR is given in the form \fBdp\fIN\fR +and a datapath numbered \fIN\fR already exists. If \fInetdev\fRs are specified, \fBovs\-dpctl\fR adds them to the datapath. @@ -71,11 +70,6 @@ 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, \fBadd\-if\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. @@ -120,9 +114,10 @@ up may be confused about their disappearance. .IP "\fBdump-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 +that \fBovs\-openflowd\fR or \fBovs\-vswitch\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. +ports. Additional or different groups might be used in the future. This command is primarily useful for debugging Open vSwitch. OpenFlow does not have a concept of port groups. @@ -151,7 +146,7 @@ Creates datapath number 0. Adds two network devices to the new datapath. .PP -At this point one would ordinarily start \fBsecchan\fR(8) on +At this point one would ordinarily start \fBovs\-openflowd\fR(8) on \fBdp0\fR, transforming \fBdp0\fR into an OpenFlow switch. Then, when the switch and the datapath is no longer needed: @@ -165,6 +160,6 @@ Deletes the datapath. .SH "SEE ALSO" -.BR secchan (8), .BR ovs\-appctl (8), +.BR ovs\-openflowd (8), .BR ovs\-vswitchd (8) diff --git a/utilities/ovs-dpctl.c b/utilities/ovs-dpctl.c index 886cdb3ac..5a0da820c 100644 --- a/utilities/ovs-dpctl.c +++ b/utilities/ovs-dpctl.c @@ -213,9 +213,9 @@ static int if_up(const char *netdev_name) static void do_add_dp(int argc UNUSED, char *argv[]) { - struct dpif dpif; + struct dpif *dpif; run(dpif_create(argv[1], &dpif), "add_dp"); - dpif_close(&dpif); + dpif_close(dpif); if (argc > 2) { do_add_if(argc, argv); } @@ -224,10 +224,10 @@ do_add_dp(int argc UNUSED, char *argv[]) static void do_del_dp(int argc UNUSED, char *argv[]) { - struct dpif dpif; + struct dpif *dpif; run(dpif_open(argv[1], &dpif), "opening datapath"); - run(dpif_delete(&dpif), "del_dp"); - dpif_close(&dpif); + run(dpif_delete(dpif), "del_dp"); + dpif_close(dpif); } static int @@ -245,41 +245,17 @@ query_ports(struct dpif *dpif, struct odp_port **ports, size_t *n_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_if(int argc UNUSED, char *argv[]) { bool failure = false; - struct dpif dpif; + 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; @@ -292,11 +268,9 @@ do_add_if(int argc UNUSED, char *argv[]) suboptions = strtok_r(NULL, "", &save_ptr); if (suboptions) { enum { - AP_PORT, AP_INTERNAL }; static char *options[] = { - "port", "internal" }; @@ -304,13 +278,6 @@ do_add_if(int argc UNUSED, char *argv[]) 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; @@ -321,20 +288,16 @@ do_add_if(int argc UNUSED, char *argv[]) } } } - if (port < 0) { - port = get_free_port(&dpif); - } - error = dpif_port_add(&dpif, devname, port, flags); + error = dpif_port_add(dpif, devname, flags, NULL); if (error) { - ovs_error(error, "adding %s as port %"PRIu16" of %s failed", - devname, port, argv[1]); + ovs_error(error, "adding %s to %s failed", devname, argv[1]); failure = true; } else if (if_up(devname)) { failure = true; } } - dpif_close(&dpif); + dpif_close(dpif); if (failure) { exit(EXIT_FAILURE); } @@ -364,7 +327,7 @@ static void do_del_if(int argc UNUSED, char *argv[]) { bool failure = false; - struct dpif dpif; + struct dpif *dpif; int i; run(dpif_open(argv[1], &dpif), "opening datapath"); @@ -375,18 +338,18 @@ do_del_if(int argc UNUSED, char *argv[]) if (!name[strspn(name, "0123456789")]) { port = atoi(name); - } else if (!get_port_number(&dpif, name, &port)) { + } else if (!get_port_number(dpif, name, &port)) { failure = true; continue; } - error = dpif_port_del(&dpif, port); + 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); + dpif_close(dpif); if (failure) { exit(EXIT_FAILURE); } @@ -400,7 +363,7 @@ show_dpif(struct dpif *dpif) size_t n_ports; size_t i; - printf("dp%u:\n", dpif_id(dpif)); + printf("%s:\n", dpif_name(dpif)); if (!dpif_get_dp_stats(dpif, &stats)) { printf("\tflows: cur:%"PRIu32", soft-max:%"PRIu32", " "hard-max:%"PRIu32"\n", @@ -434,12 +397,12 @@ do_show(int argc, char *argv[]) int i; for (i = 1; i < argc; i++) { const char *name = argv[i]; - struct dpif dpif; + struct dpif *dpif; int error; error = dpif_open(name, &dpif); if (!error) { - show_dpif(&dpif); + show_dpif(dpif); } else { ovs_error(error, "opening datapath %s failed", name); failure = true; @@ -449,13 +412,13 @@ do_show(int argc, char *argv[]) unsigned int i; for (i = 0; i < ODP_MAX; i++) { char name[128]; - struct dpif dpif; + struct dpif *dpif; int error; sprintf(name, "dp%u", i); error = dpif_open(name, &dpif); if (!error) { - show_dpif(&dpif); + show_dpif(dpif); } else if (error != ENODEV) { ovs_error(error, "opening datapath %s failed", name); failure = true; @@ -478,16 +441,11 @@ do_dump_dps(int argc UNUSED, char *argv[] UNUSED) error = dp_enumerate(&all_dps); for (i = 0; i < all_dps.n; i++) { - struct dpif dpif; - char dpif_name[IF_NAMESIZE]; - - if (dpif_open(all_dps.names[i], &dpif)) { - continue; - } - if (!dpif_get_name(&dpif, dpif_name, sizeof dpif_name)) { - printf("%s\n", dpif_name); + struct dpif *dpif; + if (!dpif_open(all_dps.names[i], &dpif)) { + printf("%s\n", dpif_name(dpif)); + dpif_close(dpif); } - dpif_close(&dpif); } svec_destroy(&all_dps); @@ -500,13 +458,13 @@ static void do_dump_flows(int argc UNUSED, char *argv[]) { struct odp_flow *flows; - struct dpif dpif; + 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"); + run(dpif_flow_list_all(dpif, &flows, &n_flows), "listing all flows"); ds_init(&ds); for (i = 0; i < n_flows; i++) { @@ -516,41 +474,40 @@ do_dump_flows(int argc UNUSED, char *argv[]) f->actions = actions; f->n_actions = MAX_ACTIONS; - dpif_flow_get(&dpif, f); + 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); + dpif_close(dpif); } static void do_del_flows(int argc UNUSED, char *argv[]) { - struct dpif dpif; + struct dpif *dpif; run(dpif_open(argv[1], &dpif), "opening datapath"); - run(dpif_flow_flush(&dpif), "deleting all flows"); - dpif_close(&dpif); + run(dpif_flow_flush(dpif), "deleting all flows"); + dpif_close(dpif); } static void do_dump_groups(int argc UNUSED, char *argv[]) { struct odp_stats stats; - struct dpif dpif; + struct dpif *dpif; unsigned int i; run(dpif_open(argv[1], &dpif), "opening datapath"); - run(dpif_get_dp_stats(&dpif, &stats), "get datapath stats"); + run(dpif_get_dp_stats(dpif, &stats), "get datapath stats"); for (i = 0; i < stats.max_groups; i++) { - uint16_t ports[UINT16_MAX]; + uint16_t *ports; size_t n_ports; - if (!dpif_port_group_get(&dpif, i, ports, - ARRAY_SIZE(ports), &n_ports) && n_ports) { + if (!dpif_port_group_get(dpif, i, &ports, &n_ports) && n_ports) { size_t j; printf("group %u:", i); @@ -559,8 +516,9 @@ do_dump_groups(int argc UNUSED, char *argv[]) } printf("\n"); } + free(ports); } - dpif_close(&dpif); + dpif_close(dpif); } static void diff --git a/utilities/ovs-monitor b/utilities/ovs-monitor index 215032ae4..40ad64b30 100755 --- a/utilities/ovs-monitor +++ b/utilities/ovs-monitor @@ -16,8 +16,8 @@ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin -SECCHAN_PID=/var/run/secchan.pid -SECCHAN_SOCK=/var/run/secchan.mgmt +OPENFLOWD_PID=/var/run/ovs-openflowd.pid +OPENFLOWD_SOCK=/var/run/ovs-openflowd.mgmt LOG_FILE=/var/log/openflow/monitor INTERVAL=1 FAIL_THRESH=3 @@ -27,8 +27,8 @@ usage() { echo echo "OPTIONS:" echo " -h Show this message" - echo " -p PID file for secchan (default: $SECCHAN_PID)" - echo " -s Unix socket for secchan (default: $SECCHAN_SOCK)" + echo " -p PID file for ovs-openflowd (default: $OPENFLOWD_PID)" + echo " -s Unix socket for ovs-openflowd (default: $OPENFLOWD_SOCK)" echo " -l File to log messages (default: $LOG_FILE)" echo " -i Interval to send probes in seconds (default: $INTERVAL)" echo " -c Number of failed probes before reboot (default: $FAIL_THRESH)" @@ -48,11 +48,11 @@ while getopts "hp:s:l:i:c:" OPTION; do ;; p) - SECCHAN_PID=$OPTARG + OPENFLOWD_PID=$OPTARG ;; s) - SECCHAN_SOCK=$OPTARG + OPENFLOWD_SOCK=$OPTARG ;; l) @@ -73,14 +73,14 @@ while getopts "hp:s:l:i:c:" OPTION; do done -if [ ! -f $SECCHAN_PID ]; then - log "No secchan pid file: ${SECCHAN_PID}" - echo "No secchan pid file: ${SECCHAN_PID}" +if [ ! -f $OPENFLOWD_PID ]; then + log "No ovs-openflowd pid file: ${OPENFLOWD_PID}" + echo "No ovs-openflowd pid file: ${OPENFLOWD_PID}" fi -if [ ! -S $SECCHAN_SOCK ]; then - log "No secchan sock file: ${SECCHAN_SOCK}" - echo "No secchan sock file: ${SECCHAN_SOCK}" +if [ ! -S $OPENFLOWD_SOCK ]; then + log "No ovs-openflowd sock file: ${OPENFLOWD_SOCK}" + echo "No ovs-openflowd sock file: ${OPENFLOWD_SOCK}" fi if [ ! -d `dirname $LOG_FILE` ]; then @@ -88,17 +88,17 @@ if [ ! -d `dirname $LOG_FILE` ]; then fi let DP_DOWN=0 -let SECCHAN_DOWN=0 +let OPENFLOWD_DOWN=0 log "===== Starting Monitor ====" while `/bin/true`; do - # Only check for liveness if the secchan's PID file exists. The PID - # file is removed when secchan is brought down gracefully. - if [ -f $SECCHAN_PID ]; then - pid=`cat $SECCHAN_PID` + # Only check for liveness if ovs-openflowd's PID file exists. The PID + # file is removed when ovs-openflowd is brought down gracefully. + if [ -f $OPENFLOWD_PID ]; then + pid=`cat $OPENFLOWD_PID` if [ -d /proc/$pid ]; then - # Check if the secchan and datapath still can communicate - if [ -S $SECCHAN_SOCK ]; then - ovs-ofctl probe -t 2 unix:$SECCHAN_SOCK + # Check if the ovs-openflowd and datapath still can communicate + if [ -S $OPENFLOWD_SOCK ]; then + ovs-ofctl probe -t 2 unix:$OPENFLOWD_SOCK if [ $? -ne 0 ]; then log "datapath probe failed" let DP_DOWN++ @@ -106,15 +106,15 @@ while `/bin/true`; do let DP_DOWN=0 fi fi - let SECCHAN_DOWN=0 + let OPENFLOWD_DOWN=0 else - log "secchan probe failed" - let SECCHAN_DOWN++ + log "ovs-openflowd probe failed" + let OPENFLOWD_DOWN++ fi fi - if [ $SECCHAN_DOWN -ge $FAIL_THRESH ]; then - log "Failed to probe secchan after ${SECCHAN_DOWN} tries...rebooting!" + if [ $OPENFLOWD_DOWN -ge $FAIL_THRESH ]; then + log "Failed to probe ovs-openflowd after ${OPENFLOWD_DOWN} tries...rebooting!" reboot fi diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in index 6b39765cb..2e2b38b38 100644 --- a/utilities/ovs-ofctl.8.in +++ b/utilities/ovs-ofctl.8.in @@ -1,4 +1,4 @@ -.TH ovs\-ofctl 8 "March 2009" "Open vSwitch" "Open vSwitch Manual" +.TH ovs\-ofctl 8 "June 2009" "Open vSwitch" "Open vSwitch Manual" .ds PN ovs\-ofctl .SH NAME @@ -146,7 +146,7 @@ syntax of \fIflows\fR. \fBmonitor \fIswitch\fR [\fImiss-len\fR [\fIsend-exp]] Connects to \fIswitch\fR and prints to the console all OpenFlow messages received. Usually, \fIswitch\fR should specify a connection -named on \fBsecchan\fR(8)'s \fB-l\fR or \fB--listen\fR command line +named on \fBovs\-openflowd\fR(8)'s \fB-l\fR or \fB--listen\fR command line option. If \fImiss-len\fR is provided, \fBovs\-ofctl\fR sends an OpenFlow ``set @@ -223,8 +223,8 @@ Matches physical port \fIport_no\fR. Switch ports are numbered as displayed by \fBovs\-ofctl show\fR. .IP \fBdl_vlan=\fIvlan\fR -Matches IEEE 802.1q virtual LAN tag \fIvlan\fR. Specify \fB0xffff\fR -as \fIvlan\fR to match packets that are not tagged with a virtual LAN; +Matches IEEE 802.1q Virtual LAN tag \fIvlan\fR. Specify \fB0xffff\fR +as \fIvlan\fR to match packets that are not tagged with a Virtual LAN; otherwise, specify a number between 0 and 4095, inclusive, as the 12-bit VLAN ID to match. @@ -326,7 +326,7 @@ omitted, then the entire packet is sent. .IP \fBlocal\fR Outputs the packet on the ``local port,'' which corresponds to the \fBof\fIn\fR network device (see \fBCONTACTING THE CONTROLLER\fR in -\fBsecchan\fR(8) for information on the \fBof\fIn\fR network device). +\fBovs\-openflowd\fR(8) for information on the \fBof\fIn\fR network device). .IP \fBdrop\fR Discards the packet, so no further processing or forwarding takes place. @@ -470,7 +470,7 @@ 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 specifying \fB--listen=punix:@RUNDIR@/openflow.sock\fR on the -\fBsecchan\fR(8) command line. +\fBovs\-openflowd\fR(8) command line. .TP \fBovs\-ofctl dump-tables unix:@RUNDIR@/openflow.sock\fR diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 04a869a2f..e873ed7ba 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -251,7 +251,7 @@ static void run(int retval, const char *message, ...) static void open_vconn(const char *name, struct vconn **vconnp) { - struct dpif dpif; + struct dpif *dpif; struct stat s; if (strstr(name, ":")) { @@ -268,9 +268,9 @@ open_vconn(const char *name, struct vconn **vconnp) char *socket_name; char *vconn_name; - run(dpif_get_name(&dpif, dpif_name, sizeof dpif_name), + run(dpif_port_get_name(dpif, ODPP_LOCAL, dpif_name, sizeof dpif_name), "obtaining name of %s", dpif_name); - dpif_close(&dpif); + dpif_close(dpif); if (strcmp(dpif_name, name)) { VLOG_INFO("datapath %s is named %s", name, dpif_name); } @@ -617,6 +617,8 @@ str_to_action(char *str, struct ofpbuf *b) * packet to the controller. */ if (arg && (strspn(act, "0123456789") == strlen(act))) { oao->max_len = htons(str_to_u32(arg)); + } else { + oao->max_len = htons(UINT16_MAX); } } else if (parse_port_name(act, &port)) { put_output_action(b, port); diff --git a/utilities/ovs-openflowd.8.in b/utilities/ovs-openflowd.8.in new file mode 100644 index 000000000..3d255746d --- /dev/null +++ b/utilities/ovs-openflowd.8.in @@ -0,0 +1,469 @@ +.TH ovs\-openflowd 8 "March 2009" "Open vSwitch" "Open vSwitch Manual" +.ds PN ovs\-openflowd + +.SH NAME +ovs\-openflowd \- OpenFlow switch implementation + +.SH SYNOPSIS +.B ovs\-openflowd +[\fIoptions\fR] \fIdatapath\fR [\fIcontroller\fR] + +.SH DESCRIPTION +The \fBovs\-openflowd\fR program implements an OpenFlow switch using a +flow-based datapath. \fBovs\-openflowd\fR connects to an OpenFlow controller +over TCP or SSL. + +The mandatory \fIdatapath\fR argument argument specifies the local datapath +to relay. It takes one of the following forms: + +.so lib/dpif.man + +.PP +The optional \fIcontroller\fR argument specifies how to connect to +the OpenFlow controller. It takes one of the following forms: + +.RS +.IP "\fBssl:\fIip\fR[\fB:\fIport\fR]" +The specified SSL \fIport\fR (default: 6633) on the host at the given +\fIip\fR, which must be expressed as an IP address (not a DNS name). +The \fB--private-key\fR, \fB--certificate\fR, and \fB--ca-cert\fR +options are mandatory when this form is used. + +.IP "\fBtcp:\fIip\fR[\fB:\fIport\fR]" +The specified TCP \fIport\fR (default: 6633) on the host at the given +\fIip\fR, which must be expressed as an IP address (not a DNS name). + +.TP +\fBunix:\fIfile\fR +The Unix domain server socket named \fIfile\fR. +.RE + +.PP +If \fIcontroller\fR is omitted, \fBovs\-openflowd\fR attempts to discover the +location of the controller automatically (see below). + +.SS "Contacting the Controller" +The OpenFlow switch must be able to contact the OpenFlow controller +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 \fBovs\-dpctl +add\-if\fR in its communication with the controller. + +To use \fBovs\-openflowd\fR in a network with out-of-band control, specify +\fB--out-of-band\fR on the \fBovs\-openflowd\fR command line. The control +network must be configured separately, before or after \fBovs\-openflowd\fR +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 \fBovs\-dpctl +add\-if\fR. This configuration is often more convenient than +out-of-band control, because it is not necessary to maintain two +independent networks. + +In-band control is the default for \fBovs\-openflowd\fR, so no special +command-line option is required. + +With in-band control, the location of the controller can be configured +manually or discovered automatically: + +.RS +.IP "controller discovery" +To make \fBovs\-openflowd\fR discover the location of the controller +automatically, do not specify the location of the controller on the +\fBovs\-openflowd\fR command line. + +In this mode, \fBovs\-openflowd\fR will broadcast a DHCP request with vendor +class identifier \fBOpenFlow\fR across the network devices added to +the datapath with \fBovs\-dpctl add\-if\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 +the \fBovs\-openflowd\fR command line (e.g. \fBssl:192.168.0.1\fR). + +The DHCP reply may also, optionally, include a vendor-specific option +with code 2 whose contents are a string specifying the URI to the base +of the OpenFlow PKI (e.g. \fBhttp://192.168.0.1/openflow/pki\fR). +This URI is used only for bootstrapping the OpenFlow PKI at initial +switch setup; \fBovs\-openflowd\fR does not use it at all. + +The following ISC DHCP server configuration file assigns the IP +address range 192.168.0.20 through 192.168.0.30 to OpenFlow switches +that follow the switch protocol and addresses 192.168.0.1 through +192.168.0.10 to all other DHCP clients: + +default-lease-time 600; +.br +max-lease-time 7200; +.br +option space openflow; +.br +option openflow.controller-vconn code 1 = text; +.br +option openflow.pki-uri code 2 = text; +.br +class "OpenFlow" { +.br + match if option vendor-class-identifier = "OpenFlow"; +.br + vendor-option-space openflow; +.br + option openflow.controller-vconn "tcp:192.168.0.10"; +.br + option openflow.pki-uri "http://192.168.0.10/openflow/pki"; +.br + option vendor-class-identifier "OpenFlow"; +.br +} +.br +subnet 192.168.0.0 netmask 255.255.255.0 { +.br + pool { +.br + allow members of "OpenFlow"; +.br + range 192.168.0.20 192.168.0.30; +.br + } +.br + pool { +.br + deny members of "OpenFlow"; +.br + range 192.168.0.1 192.168.0.10; +.br + } +.br +} +.br + +.IP "manual configuration" +To configure in-band control manually, specify the location of the +controller on the \fBovs\-openflowd\fR command line as the \fIcontroller\fR +argument. You must also configure the network device for the OpenFlow +``local port'' to allow \fBovs\-openflowd\fR to connect to that controller. +The OpenFlow local port is a virtual network port that \fBovs\-openflowd\fR +bridges to the physical switch ports. The name of the local port for +a given \fIdatapath\fR may be seen by running \fBovs\-dpctl show +\fIdatapath\fR; the local port is listed as port 0 in \fBshow\fR's +output. + +.IP +Before \fBovs\-openflowd\fR starts, the local port network device is not +bridged to any physical network, so the next step depends on whether +connectivity is required to configure the device's IP address. If the +switch has a static IP address, you may configure its IP address now +with a command such as +.B ifconfig of0 192.168.1.1 +and then invoke \fBovs\-openflowd\fR. + +On the other hand, if the switch does not have a static IP address, +e.g. it obtains its IP address dynamically via DHCP, the DHCP client +will not be able to contact the DHCP server until the OpenFlow switch +has started up. Thus, start \fBovs\-openflowd\fR without configuring +the local port network device, and start the DHCP client afterward. +.RE + +.SH OPTIONS +.SS "Controller Discovery Options" +.TP +\fB--accept-vconn=\fIregex\fR +When \fBovs\-openflowd\fR performs controller discovery (see \fBContacting +the Controller\fR, above, for more information about controller +discovery), it validates the controller location obtained via DHCP +with a POSIX extended regular expression. Only controllers whose +names match the regular expression will be accepted. + +The default regular expression is \fBssl:.*\fR (meaning that only SSL +controller connections will be accepted) when any of the SSL +configuration options \fB--private-key\fR, \fB--certificate\fR, or +\fB--ca-cert\fR is specified. The default is \fB^tcp:.*\fR otherwise +(meaning that only TCP controller connections will be accepted). + +The \fIregex\fR is implicitly anchored at the beginning of the +controller location string, as if it begins with \fB^\fR. + +When controller discovery is not performed, this option has no effect. + +.TP +\fB--no-resolv-conf\fR +When \fBovs\-openflowd\fR performs controller discovery (see \fBContacting +the Controller\fR, above, for more information about controller +discovery), by default it overwrites the system's +\fB/etc/resolv.conf\fR with domain information and DNS servers +obtained via DHCP. If the location of the controller is specified +using a hostname, rather than an IP address, and the network's DNS +servers ever change, this behavior is essential. But because it also +interferes with any administrator or process that manages +\fB/etc/resolv.conf\fR, when this option is specified, \fBovs\-openflowd\fR +will not modify \fB/etc/resolv.conf\fR. + +\fBovs\-openflowd\fR will only modify \fBresolv.conf\fR if the DHCP response +that it receives specifies one or more DNS servers. + +When controller discovery is not performed, this option has no effect. + +.SS "Networking Options" +.TP +\fB--datapath-id=\fIdpid\fR +Sets \fIdpid\fR, which must consist of exactly 12 hexadecimal digits, +as the datapath ID that the switch will use to identify itself to the +OpenFlow controller. + +If this option is omitted, the default datapath ID is taken from the +Ethernet address of the datapath's local port (which is typically +randomly generated). + +.TP +\fB--mgmt-id=\fImgmtid\fR +Sets \fImgmtid\fR, which must consist of exactly 12 hexadecimal +digits, as the switch's management ID. + +If this option is omitted, the management ID defaults to 0, signaling +to the controller that management is supported but not configured. + +.TP +\fB--fail=\fR[\fBopen\fR|\fBclosed\fR] +The controller is, ordinarily, responsible for setting up all flows on +the OpenFlow switch. Thus, if the connection to the controller fails, +no new network connections can be set up. If the connection to the +controller stays down long enough, no packets can pass through the +switch at all. + +If this option is set to \fBopen\fR (the default), \fBovs\-openflowd\fR will +take over responsibility for setting up flows in the local datapath +when no message has been received from the controller for three times +the inactivity probe interval (see below), or 45 seconds by default. +In this ``fail open'' mode, \fBovs\-openflowd\fR causes the datapath to act +like an ordinary MAC-learning switch. \fBovs\-openflowd\fR will continue to +retry connection to the controller in the background and, when the +connection succeeds, it discontinues its fail-open behavior. + +If this option is set to \fBclosed\fR, then \fBovs\-openflowd\fR will not +set up flows on its own when the controller connection fails. + +.TP +\fB--inactivity-probe=\fIsecs\fR +When the OpenFlow switch is connected to the controller, the +switch waits for a message to be received from the controller for +\fIsecs\fR seconds before it sends a inactivity probe to the +controller. After sending the inactivity probe, if no response is +received for an additional \fIsecs\fR seconds, the switch +assumes that the connection has been broken and attempts to reconnect. +The default and the minimum value are both 5 seconds. + +When fail-open mode is configured, changing the inactivity probe +interval also changes the interval before entering fail-open mode (see +above). + +.TP +\fB--max-idle=\fIsecs\fR|\fBpermanent\fR +Sets \fIsecs\fR as the number of seconds that a flow set up by the +OpenFlow switch will remain in the switch's flow table without any +matching packets being seen. If \fBpermanent\fR is specified, which +is not recommended, flows set up by the switch will never +expire. The default is 15 seconds. + +Most flows are set up by the OpenFlow controller, not by the +switch. This option affects only the following flows, which the +OpenFlow switch sets up itself: + +.RS +.IP \(bu +When \fB--fail=open\fR is specified, flows set up when the +switch has not been able to contact the controller for the configured +fail-open delay. + +.IP \(bu +When in-band control is in use, flows set up to bootstrap contacting +the controller (see \fBContacting the Controller\fR, above, for +more information about in-band control). +.RE + +.IP +As a result, when both \fB--fail=closed\fR and \fB--out-of-band\fR are +specified, this option has no effect. + +.TP +\fB--max-backoff=\fIsecs\fR +Sets the maximum time between attempts to connect to the controller to +\fIsecs\fR, which must be at least 1. The actual interval between +connection attempts starts at 1 second and doubles on each failing +attempt until it reaches the maximum. The default maximum backoff +time is 8 seconds. + +.TP +\fB-l\fR, \fB--listen=\fImethod\fR +Configures the switch to additionally listen for incoming OpenFlow +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. + +.RS +.TP +\fBpssl:\fR[\fIport\fR][\fB:\fIip\fR] +Listens for SSL connections on \fIport\fR (default: 6633). The +\fB--private-key\fR, \fB--certificate\fR, and \fB--ca-cert\fR options +are mandatory when this form is used. +By default, \fB\*(PN\fR listens for connections to any local IP +address, but \fIip\fR may be specified to listen only for connections +to the given \fIip\fR. + +.TP +\fBptcp:\fR[\fIport\fR][\fB:\fIip\fR] +Listens for TCP connections on \fIport\fR (default: 6633). +By default, \fB\*(PN\fR listens for connections to any local IP +address, but \fIip\fR may be specified to listen only for connections +to the given \fIip\fR. + +.TP +\fBpunix:\fIfile\fR +Listens for connections on Unix domain server socket named \fIfile\fR. +.RE + +.TP +\fB--snoop=\fImethod\fR +Configures the switch to additionally listen for incoming OpenFlow +connections for controller connection snooping. The \fImethod\fR must +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 \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 +problems. + +.TP +\fB--in-band\fR, \fB--out-of-band\fR +Configures \fBovs\-openflowd\fR to operate in in-band or out-of-band control +mode (see \fBContacting the Controller\fR above). When neither option +is given, the default is in-band control. + +.TP +\fB--netflow=\fIip\fB:\fIport\fR +Configures the given UDP \fIport\fR on the specified IP \fIip\fR as +a recipient of NetFlow messages for expired flows. The \fIip\fR must +be specified numerically, not as a DNS name. + +This option may be specified multiple times to configure additional +NetFlow collectors. + +.SS "Rate-Limiting Options" + +These options configure how the switch applies a ``token bucket'' to +limit the rate at which packets in unknown flows are forwarded to an +OpenFlow controller for flow-setup processing. This feature prevents +a single OpenFlow switch from overwhelming a controller. + +.TP +\fB--rate-limit\fR[\fB=\fIrate\fR] +. +Limits the maximum rate at which packets will be forwarded to the +OpenFlow controller to \fIrate\fR packets per second. If \fIrate\fR +is not specified then the default of 1,000 packets per second is used. + +If \fB--rate-limit\fR is not used, then the switch does not limit the +rate at which packets are forwarded to the controller. + +.TP +\fB--burst-limit=\fIburst\fR +. +Sets the maximum number of unused packet credits that the switch will +allow to accumulate during time in which no packets are being +forwarded to the OpenFlow controller to \fIburst\fR (measured in +packets). The default \fIburst\fR is one-quarter of the \fIrate\fR +specified on \fB--rate-limit\fR. + +This option takes effect only when \fB--rate-limit\fR is also specified. + +.SS "Remote Command Execution Options" + +.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.) \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 +does begin with \fB!\fR is a ``blacklist'' that specifies commands +that may not be invoked. To be permitted, a command name must be +whitelisted and must not be blacklisted; +e.g. \fB--command-acl=up*,!upgrade\fR would allow any command whose name +begins with \fBup\fR except for the command named \fBupgrade\fR. +Command names that include characters other than upper- and lower-case +English letters, digits, and the underscore and hyphen characters are +unconditionally disallowed. + +When the whitelist and blacklist permit a command name, \fBovs\-openflowd\fR +looks for a program with the same name as the command in the commands +directory (see below). Other directories are not searched. + +.TP +\fB--command-dir=\fIdirectory\fR +Sets the directory searched for remote command execution to +\fBdirectory\fR. The default directory is +\fB@pkgdatadir@/commands\fR. + +.SS "Daemon Options" +.so lib/daemon.man + +.SS "Public Key Infrastructure Options" + +.TP +\fB-p\fR, \fB--private-key=\fIprivkey.pem\fR +Specifies a PEM file containing the private key used as the switch's +identity for SSL connections to the controller. + +.TP +\fB-c\fR, \fB--certificate=\fIcert.pem\fR +Specifies a PEM file containing a certificate, signed by the +controller's certificate authority (CA), that certifies the switch's +private key to identify a trustworthy switch. + +.TP +\fB-C\fR, \fB--ca-cert=\fIcacert.pem\fR +Specifies a PEM file containing the CA certificate used to verify that +the switch is connected to a trustworthy controller. + +.TP +\fB--bootstrap-ca-cert=\fIcacert.pem\fR +When \fIcacert.pem\fR exists, this option has the same effect as +\fB-C\fR or \fB--ca-cert\fR. If it does not exist, then \fBovs\-openflowd\fR +will attempt to obtain the CA certificate from the controller on its +first SSL connection and save it to the named PEM file. If it is +successful, it will immediately drop the connection and reconnect, and +from then on all SSL connections must be authenticated by a +certificate signed by the CA certificate thus obtained. + +\fBThis option exposes the SSL connection to a man-in-the-middle +attack obtaining the initial CA certificate\fR, but it may be useful +for bootstrapping. + +This option is only useful if the controller sends its CA certificate +as part of the SSL certificate chain. The SSL protocol does not +require the controller to send the CA certificate, but +\fBcontroller\fR(8) can be configured to do so with the +\fB--peer-ca-cert\fR option. + +.SS "Logging Options" +.so lib/vlog.man +.SS "Other Options" +.so lib/common.man +.so lib/leak-checker.man + +.SH "SEE ALSO" + +.BR ovs\-appctl (8), +.BR ovs\-controller (8), +.BR ovs\-discover (8), +.BR ovs\-dpctl (8), +.BR ovs\-ofctl (8), +.BR ovs\-pki (8), +.BR ovs\-vswitchd.conf (5) diff --git a/utilities/ovs-openflowd.c b/utilities/ovs-openflowd.c new file mode 100644 index 000000000..603e2587b --- /dev/null +++ b/utilities/ovs-openflowd.c @@ -0,0 +1,565 @@ +/* + * Copyright (c) 2008, 2009 Nicira Networks. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <getopt.h> +#include <inttypes.h> +#include <netinet/in.h> +#include <stdlib.h> +#include <signal.h> +#include <string.h> + +#include "command-line.h" +#include "compiler.h" +#include "daemon.h" +#include "dirs.h" +#include "dpif.h" +#include "fault.h" +#include "leak-checker.h" +#include "list.h" +#include "netdev.h" +#include "ofpbuf.h" +#include "ofproto/ofproto.h" +#include "openflow/openflow.h" +#include "packets.h" +#include "poll-loop.h" +#include "rconn.h" +#include "svec.h" +#include "timeval.h" +#include "unixctl.h" +#include "util.h" +#include "vconn-ssl.h" +#include "vconn.h" + +#include "vlog.h" +#define THIS_MODULE VLM_openflowd + +/* Behavior when the connection to the controller fails. */ +enum fail_mode { + FAIL_OPEN, /* Act as learning switch. */ + FAIL_CLOSED /* Drop all packets. */ +}; + +/* Settings that may be configured by the user. */ +struct ofsettings { + /* Overall mode of operation. */ + bool discovery; /* Discover the controller automatically? */ + bool in_band; /* Connect to controller in-band? */ + + /* Datapath. */ + uint64_t datapath_id; /* Datapath ID. */ + const char *dp_name; /* Name of local datapath. */ + + /* Description strings. */ + const char *mfr_desc; /* Manufacturer. */ + const char *hw_desc; /* Hardware. */ + const char *sw_desc; /* Software version. */ + const char *serial_desc; /* Serial number. */ + + /* Related vconns and network devices. */ + const char *controller_name; /* Controller (if not discovery mode). */ + struct svec listeners; /* Listen for management connections. */ + struct svec snoops; /* Listen for controller snooping conns. */ + + /* Failure behavior. */ + enum fail_mode fail_mode; /* Act as learning switch if no controller? */ + int max_idle; /* Idle time for flows in fail-open mode. */ + int probe_interval; /* # seconds idle before sending echo request. */ + int max_backoff; /* Max # seconds between connection attempts. */ + + /* Packet-in rate-limiting. */ + int rate_limit; /* Tokens added to bucket per second. */ + int burst_limit; /* Maximum number token bucket size. */ + + /* Discovery behavior. */ + const char *accept_controller_re; /* Controller vconns to accept. */ + bool update_resolv_conf; /* Update /etc/resolv.conf? */ + + /* Spanning tree protocol. */ + bool enable_stp; + + /* Remote command execution. */ + char *command_acl; /* Command white/blacklist, as shell globs. */ + char *command_dir; /* Directory that contains commands. */ + + /* Management. */ + uint64_t mgmt_id; /* Management ID. */ + + /* NetFlow. */ + struct svec netflow; /* NetFlow targets. */ +}; + +static void parse_options(int argc, char *argv[], struct ofsettings *); +static void usage(void) NO_RETURN; + +int +main(int argc, char *argv[]) +{ + struct unixctl_server *unixctl; + struct ofproto *ofproto; + struct ofsettings s; + int error; + + set_program_name(argv[0]); + register_fault_handlers(); + time_init(); + vlog_init(); + parse_options(argc, argv, &s); + signal(SIGPIPE, SIG_IGN); + + die_if_already_running(); + daemonize(); + + /* Start listening for ovs-appctl requests. */ + error = unixctl_server_create(NULL, &unixctl); + if (error) { + ovs_fatal(error, "Could not listen for unixctl connections"); + } + + VLOG_INFO("Open vSwitch version %s", VERSION BUILDNR); + VLOG_INFO("OpenFlow protocol version 0x%02x", OFP_VERSION); + + /* Start OpenFlow processing. */ + error = ofproto_create(s.dp_name, NULL, NULL, &ofproto); + if (error) { + ovs_fatal(error, "could not initialize openflow switch"); + } + error = ofproto_set_in_band(ofproto, s.in_band); + if (error) { + ovs_fatal(error, "failed to configure in-band control"); + } + error = ofproto_set_discovery(ofproto, s.discovery, s.accept_controller_re, + s.update_resolv_conf); + if (error) { + ovs_fatal(error, "failed to configure controller discovery"); + } + if (s.datapath_id) { + ofproto_set_datapath_id(ofproto, s.datapath_id); + } + if (s.mgmt_id) { + ofproto_set_mgmt_id(ofproto, s.mgmt_id); + } + ofproto_set_desc(ofproto, s.mfr_desc, s.hw_desc, s.sw_desc, s.serial_desc); + error = ofproto_set_listeners(ofproto, &s.listeners); + if (error) { + ovs_fatal(error, "failed to configure management connections"); + } + error = ofproto_set_snoops(ofproto, &s.snoops); + if (error) { + ovs_fatal(error, + "failed to configure controller snooping connections"); + } + error = ofproto_set_netflow(ofproto, &s.netflow, 0, 0, false); + if (error) { + ovs_fatal(error, "failed to configure NetFlow collectors"); + } + ofproto_set_failure(ofproto, s.fail_mode == FAIL_OPEN); + ofproto_set_probe_interval(ofproto, s.probe_interval); + ofproto_set_max_backoff(ofproto, s.max_backoff); + ofproto_set_rate_limit(ofproto, s.rate_limit, s.burst_limit); + error = ofproto_set_stp(ofproto, s.enable_stp); + if (error) { + ovs_fatal(error, "failed to configure STP"); + } + error = ofproto_set_remote_execution(ofproto, s.command_acl, + s.command_dir); + if (error) { + ovs_fatal(error, "failed to configure remote command execution"); + } + if (!s.discovery) { + error = ofproto_set_controller(ofproto, s.controller_name); + if (error) { + ovs_fatal(error, "failed to configure controller"); + } + } + + while (ofproto_is_alive(ofproto)) { + error = ofproto_run(ofproto); + if (error) { + ovs_fatal(error, "unrecoverable datapath error"); + } + unixctl_server_run(unixctl); + dp_run(); + netdev_run(); + + ofproto_wait(ofproto); + unixctl_server_wait(unixctl); + dp_wait(); + netdev_wait(); + poll_block(); + } + + return 0; +} + +/* User interface. */ + +static void +parse_options(int argc, char *argv[], struct ofsettings *s) +{ + enum { + OPT_DATAPATH_ID = UCHAR_MAX + 1, + OPT_MANUFACTURER, + OPT_HARDWARE, + OPT_SOFTWARE, + OPT_SERIAL, + OPT_ACCEPT_VCONN, + OPT_NO_RESOLV_CONF, + OPT_BR_NAME, + OPT_FAIL_MODE, + OPT_INACTIVITY_PROBE, + OPT_MAX_IDLE, + OPT_MAX_BACKOFF, + OPT_SNOOP, + OPT_RATE_LIMIT, + OPT_BURST_LIMIT, + OPT_BOOTSTRAP_CA_CERT, + OPT_STP, + OPT_NO_STP, + OPT_OUT_OF_BAND, + OPT_IN_BAND, + OPT_COMMAND_ACL, + OPT_COMMAND_DIR, + OPT_NETFLOW, + OPT_MGMT_ID, + VLOG_OPTION_ENUMS, + LEAK_CHECKER_OPTION_ENUMS + }; + static struct option long_options[] = { + {"datapath-id", required_argument, 0, OPT_DATAPATH_ID}, + {"manufacturer", required_argument, 0, OPT_MANUFACTURER}, + {"hardware", required_argument, 0, OPT_HARDWARE}, + {"software", required_argument, 0, OPT_SOFTWARE}, + {"serial", required_argument, 0, OPT_SERIAL}, + {"accept-vconn", required_argument, 0, OPT_ACCEPT_VCONN}, + {"no-resolv-conf", no_argument, 0, OPT_NO_RESOLV_CONF}, + {"config", required_argument, 0, 'F'}, + {"br-name", required_argument, 0, OPT_BR_NAME}, + {"fail", required_argument, 0, OPT_FAIL_MODE}, + {"inactivity-probe", required_argument, 0, OPT_INACTIVITY_PROBE}, + {"max-idle", required_argument, 0, OPT_MAX_IDLE}, + {"max-backoff", required_argument, 0, OPT_MAX_BACKOFF}, + {"listen", required_argument, 0, 'l'}, + {"snoop", required_argument, 0, OPT_SNOOP}, + {"rate-limit", optional_argument, 0, OPT_RATE_LIMIT}, + {"burst-limit", required_argument, 0, OPT_BURST_LIMIT}, + {"stp", no_argument, 0, OPT_STP}, + {"no-stp", no_argument, 0, OPT_NO_STP}, + {"out-of-band", no_argument, 0, OPT_OUT_OF_BAND}, + {"in-band", no_argument, 0, OPT_IN_BAND}, + {"command-acl", required_argument, 0, OPT_COMMAND_ACL}, + {"command-dir", required_argument, 0, OPT_COMMAND_DIR}, + {"netflow", required_argument, 0, OPT_NETFLOW}, + {"mgmt-id", required_argument, 0, OPT_MGMT_ID}, + {"verbose", optional_argument, 0, 'v'}, + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + DAEMON_LONG_OPTIONS, + VLOG_LONG_OPTIONS, + LEAK_CHECKER_LONG_OPTIONS, +#ifdef HAVE_OPENSSL + VCONN_SSL_LONG_OPTIONS + {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT}, +#endif + {0, 0, 0, 0}, + }; + char *short_options = long_options_to_short_options(long_options); + + /* Set defaults that we can figure out before parsing options. */ + s->datapath_id = 0; + s->mfr_desc = NULL; + s->hw_desc = NULL; + s->sw_desc = NULL; + s->serial_desc = NULL; + svec_init(&s->listeners); + svec_init(&s->snoops); + s->fail_mode = FAIL_OPEN; + s->max_idle = 0; + s->probe_interval = 0; + s->max_backoff = 8; + s->update_resolv_conf = true; + s->rate_limit = 0; + s->burst_limit = 0; + s->accept_controller_re = NULL; + s->enable_stp = false; + s->in_band = true; + s->command_acl = ""; + s->command_dir = NULL; + svec_init(&s->netflow); + s->mgmt_id = 0; + for (;;) { + int c; + + c = getopt_long(argc, argv, short_options, long_options, NULL); + if (c == -1) { + break; + } + + switch (c) { + case OPT_DATAPATH_ID: + if (strlen(optarg) != 12 + || strspn(optarg, "0123456789abcdefABCDEF") != 12) { + ovs_fatal(0, "argument to --datapath-id must be " + "exactly 12 hex digits"); + } + s->datapath_id = strtoll(optarg, NULL, 16); + if (!s->datapath_id) { + ovs_fatal(0, "argument to --datapath-id must be nonzero"); + } + break; + + case OPT_MANUFACTURER: + s->mfr_desc = optarg; + break; + + case OPT_HARDWARE: + s->hw_desc = optarg; + break; + + case OPT_SOFTWARE: + s->sw_desc = optarg; + break; + + case OPT_SERIAL: + s->serial_desc = optarg; + break; + + case OPT_ACCEPT_VCONN: + s->accept_controller_re = optarg; + break; + + case OPT_NO_RESOLV_CONF: + s->update_resolv_conf = false; + break; + + case OPT_FAIL_MODE: + if (!strcmp(optarg, "open")) { + s->fail_mode = FAIL_OPEN; + } else if (!strcmp(optarg, "closed")) { + s->fail_mode = FAIL_CLOSED; + } else { + ovs_fatal(0, "--fail argument must be \"open\" or \"closed\""); + } + break; + + case OPT_INACTIVITY_PROBE: + s->probe_interval = atoi(optarg); + if (s->probe_interval < 5) { + ovs_fatal(0, "--inactivity-probe argument must be at least 5"); + } + break; + + case OPT_MAX_IDLE: + if (!strcmp(optarg, "permanent")) { + s->max_idle = OFP_FLOW_PERMANENT; + } else { + s->max_idle = atoi(optarg); + if (s->max_idle < 1 || s->max_idle > 65535) { + ovs_fatal(0, "--max-idle argument must be between 1 and " + "65535 or the word 'permanent'"); + } + } + break; + + case OPT_MAX_BACKOFF: + s->max_backoff = atoi(optarg); + if (s->max_backoff < 1) { + ovs_fatal(0, "--max-backoff argument must be at least 1"); + } else if (s->max_backoff > 3600) { + s->max_backoff = 3600; + } + break; + + case OPT_RATE_LIMIT: + if (optarg) { + s->rate_limit = atoi(optarg); + if (s->rate_limit < 1) { + ovs_fatal(0, "--rate-limit argument must be at least 1"); + } + } else { + s->rate_limit = 1000; + } + break; + + case OPT_BURST_LIMIT: + s->burst_limit = atoi(optarg); + if (s->burst_limit < 1) { + ovs_fatal(0, "--burst-limit argument must be at least 1"); + } + break; + + case OPT_STP: + s->enable_stp = true; + break; + + case OPT_NO_STP: + s->enable_stp = false; + break; + + case OPT_OUT_OF_BAND: + s->in_band = false; + break; + + case OPT_IN_BAND: + s->in_band = true; + break; + + case OPT_COMMAND_ACL: + s->command_acl = (s->command_acl[0] + ? xasprintf("%s,%s", s->command_acl, optarg) + : optarg); + break; + + case OPT_COMMAND_DIR: + s->command_dir = optarg; + break; + + case OPT_NETFLOW: + svec_add(&s->netflow, optarg); + break; + + case OPT_MGMT_ID: + if (strlen(optarg) != 12 + || strspn(optarg, "0123456789abcdefABCDEF") != 12) { + ovs_fatal(0, "argument to --mgmt-id must be " + "exactly 12 hex digits"); + } + s->mgmt_id = strtoll(optarg, NULL, 16); + if (!s->mgmt_id) { + ovs_fatal(0, "argument to --mgmt-id must be nonzero"); + } + break; + + case 'l': + svec_add(&s->listeners, optarg); + break; + + case OPT_SNOOP: + svec_add(&s->snoops, optarg); + break; + + case 'h': + usage(); + + case 'V': + OVS_PRINT_VERSION(OFP_VERSION, OFP_VERSION); + exit(EXIT_SUCCESS); + + DAEMON_OPTION_HANDLERS + + VLOG_OPTION_HANDLERS + + LEAK_CHECKER_OPTION_HANDLERS + +#ifdef HAVE_OPENSSL + VCONN_SSL_OPTION_HANDLERS + + case OPT_BOOTSTRAP_CA_CERT: + vconn_ssl_set_ca_cert_file(optarg, true); + break; +#endif + + case '?': + exit(EXIT_FAILURE); + + default: + abort(); + } + } + free(short_options); + + argc -= optind; + argv += optind; + if (argc < 1 || argc > 2) { + ovs_fatal(0, "need one or two non-option arguments; " + "use --help for usage"); + } + + /* Local and remote vconns. */ + s->dp_name = argv[0]; + s->controller_name = argc > 1 ? xstrdup(argv[1]) : NULL; + + /* Set accept_controller_regex. */ + if (!s->accept_controller_re) { + s->accept_controller_re + = vconn_ssl_is_configured() ? "^ssl:.*" : "^tcp:.*"; + } + + /* Mode of operation. */ + s->discovery = s->controller_name == NULL; + if (s->discovery && !s->in_band) { + ovs_fatal(0, "Cannot perform discovery with out-of-band control"); + } + + /* Rate limiting. */ + if (s->rate_limit && s->rate_limit < 100) { + VLOG_WARN("Rate limit set to unusually low value %d", s->rate_limit); + } +} + +static void +usage(void) +{ + printf("%s: an OpenFlow switch implementation.\n" + "usage: %s [OPTIONS] DATAPATH [CONTROLLER]\n" + "DATAPATH is a local datapath (e.g. \"dp0\").\n" + "CONTROLLER is an active OpenFlow connection method; if it is\n" + "omitted, then ovs-openflowd performs controller discovery.\n", + program_name, program_name); + vconn_usage(true, true, true); + printf("\nOpenFlow options:\n" + " -d, --datapath-id=ID Use ID as the OpenFlow switch ID\n" + " (ID must consist of 12 hex digits)\n" + " --mgmt-id=ID Use ID as the management ID\n" + " (ID must consist of 12 hex digits)\n" + " --manufacturer=MFR Identify manufacturer as MFR\n" + " --hardware=HW Identify hardware as HW\n" + " --software=SW Identify software as SW\n" + " --serial=SERIAL Identify serial number as SERIAL\n" + "\nController discovery options:\n" + " --accept-vconn=REGEX accept matching discovered controllers\n" + " --no-resolv-conf do not update /etc/resolv.conf\n" + "\nNetworking options:\n" + " --fail=open|closed when controller connection fails:\n" + " closed: drop all packets\n" + " open (default): act as learning switch\n" + " --inactivity-probe=SECS time between inactivity probes\n" + " --max-idle=SECS max idle for flows set up by switch\n" + " --max-backoff=SECS max time between controller connection\n" + " attempts (default: 8 seconds)\n" + " -l, --listen=METHOD allow management connections on METHOD\n" + " (a passive OpenFlow connection method)\n" + " --snoop=METHOD allow controller snooping on METHOD\n" + " (a passive OpenFlow connection method)\n" + " --out-of-band controller connection is out-of-band\n" + " --netflow=HOST:PORT configure NetFlow output target\n" + "\nRate-limiting of \"packet-in\" messages to the controller:\n" + " --rate-limit[=PACKETS] max rate, in packets/s (default: 1000)\n" + " --burst-limit=BURST limit on packet credit for idle time\n" + "\nRemote command execution options:\n" + " --command-acl=[!]GLOB[,[!]GLOB...] set allowed/denied commands\n" + " --command-dir=DIR set command dir (default: %s/commands)\n", + ovs_pkgdatadir); + daemon_usage(); + vlog_usage(); + printf("\nOther options:\n" + " -h, --help display this help message\n" + " -V, --version display version information\n"); + leak_checker_usage(); + exit(EXIT_SUCCESS); +} diff --git a/utilities/ovs-pki.8.in b/utilities/ovs-pki.8.in index 27dfccfcf..0f1c4540f 100644 --- a/utilities/ovs-pki.8.in +++ b/utilities/ovs-pki.8.in @@ -325,6 +325,6 @@ Prints a help usage message and exits. .SH "SEE ALSO" -.BR controller (8), -.BR ovs\-pki\-cgi (8), -.BR secchan (8) +.BR ovs\-controller (8), +.BR ovs\-openflowd (8), +.BR ovs\-pki\-cgi (8) |
