Change code base to Nicira's master branch

This commit is contained in:
Mikio Hara committed 2009-06-29 05:03:42 -07:00
1 parent 695db2964e
commit 5ff6ec248d
199 files changed
+10152 -1817

No files matched your search

+2 -2
View File
@@ -3,5 +3,5 @@
/controller-lite
/ctlpath-lite
/dpctl-lite
/secchan
/secchan.8
/ofprotocol
/ofprotocol.8
+7 -7
View File
@@ -1,7 +1,7 @@
bin_PROGRAMS += secchan/secchan
man_MANS += secchan/secchan.8
bin_PROGRAMS += secchan/ofprotocol
man_MANS += secchan/ofprotocol.8
secchan_secchan_SOURCES = \
secchan_ofprotocol_SOURCES = \
secchan/discovery.c \
secchan/discovery.h \
secchan/executer.c \
@@ -24,13 +24,13 @@ secchan_secchan_SOURCES = \
secchan/stp-secchan.c \
secchan/stp-secchan.h
if SUPPORT_SNAT
secchan_secchan_SOURCES += \
secchan_ofprotocol_SOURCES += \
secchan/snat.c \
secchan/snat.h
endif
secchan_secchan_LDADD = lib/libopenflow.a $(FAULT_LIBS) $(SSL_LIBS)
secchan_ofprotocol_LDADD = lib/libopenflow.a $(FAULT_LIBS) $(SSL_LIBS)
EXTRA_DIST += secchan/secchan.8.in
DISTCLEANFILES += secchan/secchan.8
EXTRA_DIST += secchan/ofprotocol.8.in
DISTCLEANFILES += secchan/ofprotocol.8
include secchan/commands/automake.mk
+4 -4
View File
@@ -1,4 +1,4 @@
/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford
* Junior University
*
* We are making the OpenFlow specification and associated documentation
@@ -203,12 +203,12 @@ discovery_run(struct discovery *d, char **controller_name)
if (dhclient_is_bound(d->dhcp)) {
*controller_name = dhcp_msg_get_string(dhclient_get_config(d->dhcp),
DHCP_CODE_OFP_CONTROLLER_VCONN);
VLOG_WARN("%s: discovered controller", *controller_name);
VLOG_INFO("%s: discovered controller", *controller_name);
d->n_changes++;
} else {
*controller_name = NULL;
if (d->n_changes) {
VLOG_WARN("discovered controller no longer available");
VLOG_INFO("discovered controller no longer available");
d->n_changes++;
}
}
@@ -224,7 +224,7 @@ discovery_wait(struct discovery *d)
}
static void
modify_dhcp_request(struct dhcp_msg *msg, void *aux)
modify_dhcp_request(struct dhcp_msg *msg, void *aux UNUSED)
{
dhcp_msg_put_string(msg, DHCP_CODE_VENDOR_CLASS, "OpenFlow");
}
+4 -4
View File
@@ -1,4 +1,4 @@
/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford
* Junior University
*
* We are making the OpenFlow specification and associated documentation
@@ -126,7 +126,7 @@ executer_is_permitted(const char *acl_, const char *cmd)
/* Check the command white/blacklisted state. */
if (allowed && !denied) {
VLOG_WARN("permitting command execution: \"%s\" is whitelisted", cmd);
VLOG_INFO("permitting command execution: \"%s\" is whitelisted", cmd);
} else if (allowed && denied) {
VLOG_WARN("denying command execution: \"%s\" is both blacklisted "
"and whitelisted", cmd);
@@ -252,7 +252,7 @@ executer_remote_packet_cb(struct relay *r, void *e_)
/* Running in parent. */
struct child *child;
VLOG_WARN("started \"%s\" subprocess", argv[0]);
VLOG_INFO("started \"%s\" subprocess", argv[0]);
send_child_status(r, request->header.xid, NXT_STATUS_STARTED, NULL, 0);
child = &e->children[e->n_children++];
child->name = xstrdup(argv[0]);
@@ -330,7 +330,7 @@ child_terminated(struct child *child, int status)
if (WCOREDUMP(status)) {
ds_put_cstr(&ds, " (core dumped)");
}
VLOG_WARN("child process \"%s\" with pid %ld terminated %s",
VLOG_INFO("child process \"%s\" with pid %ld terminated %s",
child->name, (long int) child->pid, ds_cstr(&ds));
ds_destroy(&ds);
+2 -2
View File
@@ -1,4 +1,4 @@
/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford
* Junior University
*
* We are making the OpenFlow specification and associated documentation
@@ -84,7 +84,7 @@ fail_open_periodic_cb(void *fail_open_)
fail_open->last_disconn_secs = disconn_secs;
}
} else if (open && disconn_secs > fail_open->last_disconn_secs + 60) {
VLOG_WARN("Still in fail-open mode after %d seconds disconnected "
VLOG_INFO("Still in fail-open mode after %d seconds disconnected "
"from controller", disconn_secs);
fail_open->last_disconn_secs = disconn_secs;
}
+20 -6
View File
@@ -130,7 +130,7 @@ static void
in_band_learn_mac(struct in_band_data *in_band,
uint16_t in_port, const uint8_t src_mac[ETH_ADDR_LEN])
{
if (mac_learning_learn(in_band->ml, src_mac, in_port)) {
if (mac_learning_learn(in_band->ml, src_mac, 0, in_port)) {
VLOG_DBG_RL(&rl, "learned that "ETH_ADDR_FMT" is on port %"PRIu16,
ETH_ADDR_ARGS(src_mac), in_port);
}
@@ -158,7 +158,7 @@ in_band_local_packet_cb(struct relay *r, void *in_band_)
/* Deal with local stuff. */
if (in_port == OFPP_LOCAL) {
/* Sent by secure channel. */
out_port = mac_learning_lookup(in_band->ml, eth->eth_dst);
out_port = mac_learning_lookup(in_band->ml, eth->eth_dst, 0);
} else if (eth_addr_equals(eth->eth_dst,
netdev_get_etheraddr(in_band->of_device))) {
/* Sent to secure channel. */
@@ -179,7 +179,7 @@ in_band_local_packet_cb(struct relay *r, void *in_band_)
|| flow.tp_dst == htons(OFP_SSL_PORT))) {
/* Traffic to or from controller. Switch it by hand. */
in_band_learn_mac(in_band, in_port, eth->eth_src);
out_port = mac_learning_lookup(in_band->ml, eth->eth_dst);
out_port = mac_learning_lookup(in_band->ml, eth->eth_dst, 0);
} else {
const uint8_t *controller_mac;
controller_mac = get_controller_mac(in_band);
@@ -190,7 +190,7 @@ in_band_local_packet_cb(struct relay *r, void *in_band_)
out_port = OFPP_FLOOD;
} else if (is_controller_mac(eth->eth_dst, in_band)
&& in_port == mac_learning_lookup(in_band->ml,
controller_mac)) {
controller_mac, 0)) {
/* Drop controller traffic that arrives on the controller port. */
out_port = -1;
} else {
@@ -290,11 +290,25 @@ in_band_local_port_cb(const struct ofp_phy_port *port, void *in_band_)
}
}
static void
in_band_periodic_cb(void *in_band_)
{
struct in_band_data *in_band = in_band_;
mac_learning_run(in_band->ml, NULL);
}
static void
in_band_wait_cb(void *in_band_)
{
struct in_band_data *in_band = in_band_;
mac_learning_wait(in_band->ml);
}
static struct hook_class in_band_hook_class = {
in_band_local_packet_cb, /* local_packet_cb */
NULL, /* remote_packet_cb */
NULL, /* periodic_cb */
NULL, /* wait_cb */
in_band_periodic_cb, /* periodic_cb */
in_band_wait_cb, /* wait_cb */
NULL, /* closing_cb */
};
@@ -1,15 +1,16 @@
.TH secchan 8 "October 2008" "OpenFlow" "OpenFlow Manual"
.ds PN ofprotocol
.TH ofprotocol 8 "October 2008" "OpenFlow" "OpenFlow Manual"
.SH NAME
secchan \- secure channel connecting an OpenFlow datapath to a controller
ofprotocol \- secure channel connecting an OpenFlow datapath to a controller
.SH SYNOPSIS
.B secchan
.B ofprotocol
[\fIoptions\fR] \fIdatapath\fR [\fIcontroller\fR]
.SH DESCRIPTION
The \fBsecchan\fR program sets up a secure channel between a local
OpenFlow datapath and a remote controller. \fBsecchan\fR connects to
The \fBofprotocol\fR program sets up a secure channel between a local
OpenFlow datapath and a remote controller. \fBofprotocol\fR connects to
the local datapath over Netlink and to the controller over TCP or SSL,
and then forwards OpenFlow messages from one endpoint to the other.
@@ -24,9 +25,9 @@ The \fIdp_idx\fR argument is the number of a datapath created with
.TP
\fBunix:\fIfile\fR
Attach to the userspace datapath implemented by \fBudatapath\fR(8).
Attach to the userspace datapath implemented by \fBofdatapath\fR(8).
The \fIfile\fR argument must the same one specified on the
\fBudatapath\fR command line.
\fBofdatapath\fR command line.
.PP
The optional \fIcontroller\fR argument specifies how to connect to
@@ -48,7 +49,7 @@ The specified TCP \fIport\fR (default: 6633) on the given remote
The Unix domain server socket named \fIfile\fR.
.PP
If \fIcontroller\fR is omitted, \fBsecchan\fR attempts to discover the
If \fIcontroller\fR is omitted, \fBofprotocol\fR attempts to discover the
location of the controller automatically (see below).
.SH "CONTACTING THE CONTROLLER"
@@ -61,9 +62,9 @@ the data traffic that it controls, that is, the switch does not use
any of the network devices added to the datapath with \fBdpctl
addif\fR in its communication with the controller.
To use \fBsecchan\fR in a network with out-of-band control, specify
\fB--out-of-band\fR on the \fBsecchan\fR command line. The control
network must be configured separately, before or after \fBsecchan\fR
To use \fBofprotocol\fR in a network with out-of-band control, specify
\fB--out-of-band\fR on the \fBofprotocol\fR command line. The control
network must be configured separately, before or after \fBofprotocol\fR
is started.
.IP in-band
@@ -74,7 +75,7 @@ addif\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 \fBsecchan\fR, so no special
In-band control is the default for \fBofprotocol\fR, so no special
command-line option is required.
With in-band control, the location of the controller can be configured
@@ -82,23 +83,23 @@ manually or discovered automatically:
.RS
.IP "controller discovery"
To make \fBsecchan\fR discover the location of the controller
To make \fBofprotocol\fR discover the location of the controller
automatically, do not specify the location of the controller on the
\fBsecchan\fR command line.
\fBofprotocol\fR command line.
In this mode, \fBsecchan\fR will broadcast a DHCP request with vendor
In this mode, \fBofprotocol\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
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 \fBofprotocol\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; \fBsecchan\fR does not use it at all.
switch setup; \fBofprotocol\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
@@ -152,12 +153,12 @@ subnet 192.168.0.0 netmask 255.255.255.0 {
.IP "manual configuration"
To configure in-band control manually, specify the location of the
controller on the \fBsecchan\fR command line as the \fIcontroller\fR
controller on the \fBofprotocol\fR command line as the \fIcontroller\fR
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
``local port'' to allow \fBofprotocol\fR to connect to that controller.
The OpenFlow local port is a virtual network port that \fBofprotocol\fR
bridges to the physical switch ports. Its network device name depends
on the \fIdatapath\fR specified on the \fBsecchan\fR command line:
on the \fIdatapath\fR specified on the \fBofprotocol\fR command line:
.RS
.TP
@@ -168,12 +169,12 @@ The local port network device for \fBnl:\fIdp_idx\fR is always named
.TP
\fBunix:\fIfile\fR
The local port network device name may be specified on the
\fBudatapath\fR command line, using the \fB--local-port\fR option. It
\fBofdatapath\fR command line, using the \fB--local-port\fR option. It
is often \fBtap0\fR.
.RE
.IP
Before \fBsecchan\fR starts, the local port network device is not
Before \fBofprotocol\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
@@ -183,19 +184,20 @@ with a command such as:
ifconfig of0 192.168.1.1
.RE
.IP
and then invoke \fBsecchan\fR.
and then invoke \fBofprotocol\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 secure channel
has started up. Thus, start \fBsecchan\fR without configuring
has started up. Thus, start \fBofprotocol\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 \fBsecchan\fR performs controller discovery (see \fBCONTACTING
When \fBofprotocol\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
@@ -214,7 +216,7 @@ When controller discovery is not performed, this option has no effect.
.TP
\fB--no-resolv-conf\fR
When \fBsecchan\fR performs controller discovery (see \fBCONTACTING
When \fBofprotocol\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
@@ -222,14 +224,15 @@ 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, \fBsecchan\fR
\fB/etc/resolv.conf\fR, when this option is specified, \fBofprotocol\fR
will not modify \fB/etc/resolv.conf\fR.
\fBsecchan\fR will only modify \fBresolv.conf\fR if the DHCP response
\fBofprotocol\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-F\fR, \fB--fail=\fR[\fBopen\fR|\fBclosed\fR]
The controller is, ordinarily, responsible for setting up all flows on
@@ -238,17 +241,17 @@ 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), \fBsecchan\fR will
If this option is set to \fBopen\fR (the default), \fBofprotocol\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, \fBsecchan\fR causes the datapath to act
like an ordinary MAC-learning switch. \fBsecchan\fR will continue to
In this ``fail open'' mode, \fBofprotocol\fR causes the datapath to act
like an ordinary MAC-learning switch. \fBofprotocol\fR will continue to
retry connection to the controller in the background and, when the
connection succeeds, it discontinues its fail-open behavior. The
secure channel enters the fail-open mode when
If this option is set to \fBclosed\fR, then \fBsecchan\fR will not
If this option is set to \fBclosed\fR, then \fBofprotocol\fR will not
set up flows on its own when the controller connection fails.
.TP
@@ -333,15 +336,15 @@ command. The \fImethod\fR must be given as one of the passive
OpenFlow connection methods listed above as acceptable for
\fB--listen\fR.
When \fBdpctl monitor\fR makes a monitoring connection, \fBsecchan\fR
When \fBdpctl monitor\fR makes a monitoring connection, \fBofprotocol\fR
sends it a copy of every OpenFlow message sent to or received from the
kernel in the normal course of its operations. It does not send a
copy of any messages sent to or from the OpenFlow connection to the
controller. Most of these messages will be seen anyhow, however,
because \fBsecchan\fR mainly acts as a relay between the controller
and the kernel. \fBsecchan\fR also does not send a copy of any
because \fBofprotocol\fR mainly acts as a relay between the controller
and the kernel. \fBofprotocol\fR also does not send a copy of any
messages sent to or from the OpenFlow connection to the controller.
Such messages will typically \fBnot\fR be seen, because \fBsecchan\fR
Such messages will typically \fBnot\fR be seen, because \fBofprotocol\fR
maintains a separate connection to the kernel for each management
connection.
@@ -351,7 +354,7 @@ connection fills up, some messages will be lost.
.TP
\fB--in-band\fR, \fB--out-of-band\fR
Configures \fBsecchan\fR to operate in in-band or out-of-band control
Configures \fBofprotocol\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.
@@ -362,6 +365,41 @@ at the switch. The default is \fB--no-stp\fR in this distribution,
because bugs in the STP implementation are still being worked out.
The default will change to \fB--stp\fR at some point in the future.
.TP
\fB--netflow=\fIhost\fB:\fIport\fR
When flows end on the switch, send NetFlow v5 messages to
\fIhost\fR on UDP \fIport\fR.
.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
@@ -378,7 +416,7 @@ 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, \fBsecchan\fR
When the whitelist and blacklist permit a command name, \fBofprotocol\fR
looks for a program with the same name as the command in the commands
directory (see below). Other directories are not searched.
@@ -388,6 +426,11 @@ 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--netflow=\fIhost\fB:\fIport\fR
When flows end on the switch, send NetFlow v5 messages to
@@ -412,7 +455,7 @@ 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 \fBsecchan\fR
\fB-C\fR or \fB--ca-cert\fR. If it does not exist, then \fBofprotocol\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
@@ -429,37 +472,11 @@ 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.
.TP
\fB-P\fR[\fIpidfile\fR], \fB--pidfile\fR[\fB=\fIpidfile\fR]
Causes a file (by default, \fBsecchan.pid\fR) to be created indicating
the PID of the running process. If \fIpidfile\fR is not specified, or
if it does not begin with \fB/\fR, then it is created in
\fB@RUNDIR@\fR.
.TP
\fB-f\fR, \fB--force\fR
By default, when \fB-P\fR or \fB--pidfile\fR is specified and the
specified pidfile already exists and is locked by a running process,
\fBsecchan\fR refuses to start. Specify \fB-f\fR or \fB--force\fR
to cause it to instead overwrite the pidfile.
When \fB-P\fR or \fB--pidfile\fR is not specified, this option has no
effect.
.TP
\fB-D\fR, \fB--detach\fR
Causes \fBsecchan\fR to detach itself from the foreground session and
run as a background process.
.TP
.BR \-h ", " \-\^\-help
Prints a brief help message to the console.
@VLOG_OPTIONS@
.TP
.BR \-V ", " \-\^\-version
Prints version information to the console.
.SS "Logging Options"
.so lib/vlog.man
.SS "Other Options"
.so lib/common.man
.so lib/leak-checker.man
.SH "SEE ALSO"
@@ -467,5 +484,5 @@ Prints version information to the console.
.BR ofp-discover (8),
.BR controller (8),
.BR ofp-pki (8),
.BR udatapath (8),
.BR ofdatapath (8),
.BR vlogconf (8)
+123 -4
View File
@@ -1,4 +1,4 @@
/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford
* Junior University
*
* We are making the OpenFlow specification and associated documentation
@@ -38,11 +38,14 @@
#include <inttypes.h>
#include <stdlib.h>
#include "dynamic-string.h"
#include "netdev.h"
#include "ofpbuf.h"
#include "openflow/openflow.h"
#include "poll-loop.h"
#include "port-array.h"
#include "rconn.h"
#include "shash.h"
#include "svec.h"
#include "timeval.h"
#include "vconn.h"
#include "xtoxll.h"
@@ -73,6 +76,8 @@ struct port_watcher {
struct port_watcher_local_cb local_cbs[4];
int n_local_cbs;
char local_port_name[OFP_MAX_PORT_NAME_LEN + 1];
struct netdev_monitor *mon;
struct shash port_by_name;
};
/* Returns the number of fields that differ from 'a' to 'b'. */
@@ -156,7 +161,7 @@ call_local_port_changed_callbacks(struct port_watcher *pw)
}
if (strcmp(pw->local_port_name, name)) {
if (name[0]) {
VLOG_WARN("Identified data path local port as \"%s\".", name);
VLOG_INFO("Identified data path local port as \"%s\".", name);
} else {
VLOG_WARN("Data path has no local port.");
}
@@ -202,6 +207,25 @@ update_phy_port(struct port_watcher *pw, struct ofp_phy_port *opp,
}
}
static void
update_netdev_monitor_devices(struct port_watcher *pw)
{
struct ofp_phy_port *p;
struct svec netdevs;
unsigned int port_no;
svec_init(&netdevs);
shash_clear(&pw->port_by_name);
for (p = port_array_first(&pw->ports, &port_no); p;
p = port_array_next(&pw->ports, &port_no)) {
const char *name = (const char *) p->name;
svec_add(&netdevs, name);
shash_add(&pw->port_by_name, name, p);
}
netdev_monitor_set_devices(pw->mon, netdevs.names, netdevs.n);
svec_destroy(&netdevs);
}
static bool
port_watcher_local_packet_cb(struct relay *r, void *pw_)
{
@@ -221,7 +245,7 @@ port_watcher_local_packet_cb(struct relay *r, void *pw_)
pw->got_feature_reply = true;
if (pw->datapath_id != osf->datapath_id) {
pw->datapath_id = osf->datapath_id;
VLOG_WARN("Datapath id is %012"PRIx64, ntohll(pw->datapath_id));
VLOG_INFO("Datapath id is %012"PRIx64, ntohll(pw->datapath_id));
}
/* Update each port included in the message. */
@@ -242,6 +266,8 @@ port_watcher_local_packet_cb(struct relay *r, void *pw_)
}
}
update_netdev_monitor_devices(pw);
call_local_port_changed_callbacks(pw);
} else if (oh->type == OFPT_PORT_STATUS
&& msg->size >= sizeof(struct ofp_port_status)) {
@@ -250,10 +276,38 @@ port_watcher_local_packet_cb(struct relay *r, void *pw_)
if (ops->desc.port_no == htons(OFPP_LOCAL)) {
call_local_port_changed_callbacks(pw);
}
if (ops->reason == OFPPR_ADD || OFPPR_DELETE) {
update_netdev_monitor_devices(pw);
}
}
return false;
}
static void
bring_netdev_up_or_down(const char *name, bool down)
{
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
struct netdev *netdev;
int retval;
retval = netdev_open(name, NETDEV_ETH_TYPE_NONE, &netdev);
if (!retval) {
if (down) {
retval = netdev_turn_flags_off(netdev, NETDEV_UP, true);
} else {
retval = netdev_turn_flags_on(netdev, NETDEV_UP, true);
}
if (retval) {
VLOG_WARN_RL(&rl, "failed to bring network device %s %s: %s",
name, down ? "down" : "up", strerror(retval));
}
netdev_close(netdev);
} else {
VLOG_WARN_RL(&rl, "failed to open network device %s: %s",
name, strerror(retval));
}
}
static bool
port_watcher_remote_packet_cb(struct relay *r, void *pw_)
{
@@ -274,15 +328,32 @@ port_watcher_remote_packet_cb(struct relay *r, void *pw_)
if (pw_opp->port_no == htons(OFPP_LOCAL)) {
call_local_port_changed_callbacks(pw);
}
if (opm->mask & htonl(OFPPC_PORT_DOWN)) {
bring_netdev_up_or_down((const char *) pw_opp->name,
opm->config & htonl(OFPPC_PORT_DOWN));
}
}
}
return false;
}
/* Sets 'bit' in '*word' to 0 or 1 according to 'value'. */
static void
set_bit(uint32_t bit, bool value, uint32_t *word)
{
if (value) {
*word |= bit;
} else {
*word &= ~bit;
}
}
static void
port_watcher_periodic_cb(void *pw_)
{
struct port_watcher *pw = pw_;
const char *name;
if (!pw->got_feature_reply
&& time_now() >= pw->last_feature_request + 5
@@ -292,6 +363,47 @@ port_watcher_periodic_cb(void *pw_)
rconn_send_with_limit(pw->local_rconn, b, &pw->n_txq, 1);
pw->last_feature_request = time_now();
}
netdev_monitor_run(pw->mon);
while ((name = netdev_monitor_poll(pw->mon)) != NULL) {
struct ofp_phy_port *opp;
struct ofp_phy_port new_opp;
enum netdev_flags flags;
int retval;
opp = shash_find_data(&pw->port_by_name, name);
if (!opp) {
continue;
}
retval = netdev_nodev_get_flags(name, &flags);
if (retval) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
VLOG_WARN_RL(&rl, "could not get flags for %s", name);
continue;
}
new_opp = *opp;
set_bit(htonl(OFPPC_PORT_DOWN), flags & NETDEV_UP, &new_opp.config);
set_bit(htonl(OFPPS_LINK_DOWN), flags & NETDEV_CARRIER,
&new_opp.state);
if (opp->config != new_opp.config || opp->state != new_opp.state) {
struct ofp_port_status *ops;
struct ofpbuf *b;
/* Notify other secchan modules. */
update_phy_port(pw, &new_opp, OFPPR_MODIFY);
if (new_opp.port_no == htons(OFPP_LOCAL)) {
call_local_port_changed_callbacks(pw);
}
/* Notify the controller that the flags changed. */
ops = make_openflow(sizeof *ops, OFPT_PORT_STATUS, &b);
ops->reason = OFPPR_MODIFY;
ops->desc = new_opp;
rconn_send(pw->remote_rconn, b, NULL);
}
}
}
static void
@@ -305,6 +417,7 @@ port_watcher_wait_cb(void *pw_)
poll_immediate_wake();
}
}
netdev_monitor_wait(pw->mon);
}
static void
@@ -352,7 +465,7 @@ static void
log_port_status(uint16_t port_no,
const struct ofp_phy_port *old,
const struct ofp_phy_port *new,
void *aux)
void *aux UNUSED)
{
if (VLOG_IS_DBG_ENABLED()) {
if (old && new && (opp_differs(old, new)
@@ -489,6 +602,7 @@ port_watcher_start(struct secchan *secchan,
struct port_watcher **pwp)
{
struct port_watcher *pw;
int retval;
pw = *pwp = xcalloc(1, sizeof *pw);
pw->local_rconn = local_rconn;
@@ -496,6 +610,11 @@ port_watcher_start(struct secchan *secchan,
pw->last_feature_request = TIME_MIN;
port_array_init(&pw->ports);
pw->local_port_name[0] = '\0';
retval = netdev_monitor_create(&pw->mon);
if (retval) {
ofp_fatal(retval, "failed to start network device monitoring");
}
shash_init(&pw->port_by_name);
port_watcher_register_callback(pw, log_port_status, NULL);
add_hook(secchan, &port_watcher_hook_class, pw);
}
+14 -10
View File
@@ -1,4 +1,4 @@
/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford
* Junior University
*
* We are making the OpenFlow specification and associated documentation
@@ -50,6 +50,7 @@
#include "fail-open.h"
#include "fault.h"
#include "in-band.h"
#include "leak-checker.h"
#include "list.h"
#include "ofpbuf.h"
#include "openflow/openflow.h"
@@ -153,8 +154,8 @@ main(int argc, char *argv[])
ofp_fatal(retval, "Could not listen for vlog connections");
}
VLOG_WARN("OpenFlow reference implementation version %s", VERSION BUILDNR);
VLOG_WARN("OpenFlow protocol version 0x%02x", OFP_VERSION);
VLOG_INFO("OpenFlow reference implementation version %s", VERSION BUILDNR);
VLOG_INFO("OpenFlow protocol version 0x%02x", OFP_VERSION);
/* Check datapath name, to try to catch command-line invocation errors. */
if (strncmp(s.dp_name, "nl:", 3) && strncmp(s.dp_name, "unix:", 5)
@@ -215,7 +216,7 @@ main(int argc, char *argv[])
#endif
flow_end_start(&secchan, s.netflow_dst, local_rconn, remote_rconn);
if (s.enable_stp) {
stp_start(&secchan, &s, pw, local_rconn, remote_rconn);
stp_start(&secchan, pw, local_rconn, remote_rconn);
}
if (s.in_band) {
in_band_start(&secchan, &s, switch_status, pw, remote_rconn);
@@ -231,7 +232,7 @@ main(int argc, char *argv[])
executer_start(&secchan, &s);
}
for (;;) {
while (s.discovery || rconn_is_alive(remote_rconn)) {
struct relay *r, *n;
size_t i;
@@ -331,10 +332,8 @@ add_hook(struct secchan *secchan, const struct hook_class *class, void *aux)
struct hook *hook;
if (secchan->n_hooks >= secchan->allocated_hooks) {
secchan->allocated_hooks = secchan->allocated_hooks * 2 + 1;
secchan->hooks = xrealloc(secchan->hooks,
(sizeof *secchan->hooks
* secchan->allocated_hooks));
secchan->hooks = x2nrealloc(secchan->hooks, &secchan->allocated_hooks,
sizeof *secchan->hooks);
}
hook = &secchan->hooks[secchan->n_hooks++];
hook->class = class;
@@ -592,7 +591,8 @@ parse_options(int argc, char *argv[], struct settings *s)
OPT_COMMAND_ACL,
OPT_COMMAND_DIR,
OPT_NETFLOW,
VLOG_OPTION_ENUMS
VLOG_OPTION_ENUMS,
LEAK_CHECKER_OPTION_ENUMS
};
static struct option long_options[] = {
{"accept-vconn", required_argument, 0, OPT_ACCEPT_VCONN},
@@ -617,6 +617,7 @@ parse_options(int argc, char *argv[], struct settings *s)
{"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},
@@ -777,6 +778,8 @@ parse_options(int argc, char *argv[], struct settings *s)
VLOG_OPTION_HANDLERS
LEAK_CHECKER_OPTION_HANDLERS
#ifdef HAVE_OPENSSL
VCONN_SSL_OPTION_HANDLERS
@@ -880,5 +883,6 @@ usage(void)
printf("\nOther options:\n"
" -h, --help display this help message\n"
" -V, --version display version information\n");
leak_checker_usage();
exit(EXIT_SUCCESS);
}
+2 -2
View File
@@ -1,4 +1,4 @@
/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford
* Junior University
*
* We are making the OpenFlow specification and associated documentation
@@ -243,7 +243,7 @@ snat_remote_packet_cb(struct relay *r, void *snat_)
}
static void
snat_port_changed_cb(uint16_t port_no,
snat_port_changed_cb(uint16_t port_no UNUSED,
const struct ofp_phy_port *old,
const struct ofp_phy_port *new,
void *snat_)
+3 -5
View File
@@ -58,7 +58,7 @@ struct switch_status {
const struct settings *s;
time_t booted;
struct switch_status_category *categories;
int n_categories, allocated_categories;
size_t n_categories, allocated_categories;
};
struct status_reply {
@@ -195,10 +195,8 @@ switch_status_register_category(struct switch_status *ss,
{
struct switch_status_category *c;
if (ss->n_categories >= ss->allocated_categories) {
ss->allocated_categories = 1 + ss->allocated_categories * 2;
ss->categories = xrealloc(ss->categories,
(sizeof *ss->categories
* ss->allocated_categories));
ss->categories = x2nrealloc(ss->categories, &ss->allocated_categories,
sizeof *ss->categories);
}
c = &ss->categories[ss->n_categories++];
c->cb = cb;
+22 -46
View File
@@ -1,4 +1,4 @@
/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford
* Junior University
*
* We are making the OpenFlow specification and associated documentation
@@ -54,7 +54,7 @@ struct stp_data {
struct port_watcher *pw;
struct rconn *local_rconn;
struct rconn *remote_rconn;
long long int last_tick_256ths;
long long int last_tick;
int n_txq;
};
@@ -126,18 +126,12 @@ stp_local_packet_cb(struct relay *r, void *stp_)
return true;
}
static long long int
time_256ths(void)
{
return time_msec() * 256 / 1000;
}
static void
stp_periodic_cb(void *stp_)
{
struct stp_data *stp = stp_;
long long int now_256ths = time_256ths();
long long int elapsed_256ths = now_256ths - stp->last_tick_256ths;
long long int now = time_msec();
long long int elapsed = now - stp->last_tick;
struct stp_port *p;
if (!port_watcher_is_ready(stp->pw)) {
@@ -145,19 +139,19 @@ stp_periodic_cb(void *stp_)
* disable STP. */
return;
}
if (elapsed_256ths <= 0) {
if (elapsed <= 0) {
return;
}
stp_tick(stp->stp, MIN(INT_MAX, elapsed_256ths));
stp->last_tick_256ths = now_256ths;
stp_tick(stp->stp, MIN(INT_MAX, elapsed));
stp->last_tick = now;
while (stp_get_changed_port(stp->stp, &p)) {
int port_no = stp_port_no(p);
enum stp_state s_state = stp_port_get_state(p);
if (s_state != STP_DISABLED) {
VLOG_WARN("STP: Port %d entered %s state",
VLOG_INFO("STP: Port %d entered %s state",
port_no, stp_state_name(s_state));
}
if (!(port_watcher_get_config(stp->pw, port_no) & OFPPC_NO_STP)) {
@@ -202,39 +196,22 @@ stp_wait_cb(void *stp_ UNUSED)
}
static void
send_bpdu(const void *bpdu, size_t bpdu_size, int port_no, void *stp_)
send_bpdu(struct ofpbuf *pkt, int port_no, void *stp_)
{
struct stp_data *stp = stp_;
const uint8_t *port_mac;
struct eth_header *eth;
struct llc_header *llc;
struct ofpbuf pkt, *opo;
const uint8_t *port_mac = port_watcher_get_hwaddr(stp->pw, port_no);
if (port_mac) {
struct eth_header *eth = pkt->l2;
struct ofpbuf *opo;
port_mac = port_watcher_get_hwaddr(stp->pw, port_no);
if (!port_mac) {
memcpy(eth->eth_src, port_mac, ETH_ADDR_LEN);
opo = make_unbuffered_packet_out(pkt, OFPP_NONE, port_no);
rconn_send_with_limit(stp->local_rconn, opo, &stp->n_txq, OFPP_MAX);
} else {
VLOG_WARN_RL(&rl, "cannot send BPDU on missing port %d", port_no);
return;
}
/* Packet skeleton. */
ofpbuf_init(&pkt, ETH_HEADER_LEN + LLC_HEADER_LEN + bpdu_size);
eth = ofpbuf_put_uninit(&pkt, sizeof *eth);
llc = ofpbuf_put_uninit(&pkt, sizeof *llc);
ofpbuf_put(&pkt, bpdu, bpdu_size);
/* 802.2 header. */
memcpy(eth->eth_dst, stp_eth_addr, ETH_ADDR_LEN);
memcpy(eth->eth_src, port_mac, ETH_ADDR_LEN);
eth->eth_type = htons(pkt.size - ETH_HEADER_LEN);
/* LLC header. */
llc->llc_dsap = STP_LLC_DSAP;
llc->llc_ssap = STP_LLC_SSAP;
llc->llc_cntl = STP_LLC_CNTL;
opo = make_unbuffered_packet_out(&pkt, OFPP_NONE, port_no);
ofpbuf_uninit(&pkt);
rconn_send_with_limit(stp->local_rconn, opo, &stp->n_txq, OFPP_MAX);
ofpbuf_delete(pkt);
}
static bool
@@ -245,7 +222,7 @@ stp_is_port_supported(uint16_t port_no)
static void
stp_port_changed_cb(uint16_t port_no,
const struct ofp_phy_port *old,
const struct ofp_phy_port *old UNUSED,
const struct ofp_phy_port *new,
void *stp_)
{
@@ -295,8 +272,7 @@ static struct hook_class stp_hook_class = {
};
void
stp_start(struct secchan *secchan, const struct settings *s,
struct port_watcher *pw,
stp_start(struct secchan *secchan, struct port_watcher *pw,
struct rconn *local, struct rconn *remote)
{
uint8_t dpid[ETH_ADDR_LEN];
@@ -308,7 +284,7 @@ stp_start(struct secchan *secchan, const struct settings *s,
stp->pw = pw;
stp->local_rconn = local;
stp->remote_rconn = remote;
stp->last_tick_256ths = time_256ths();
stp->last_tick = time_msec();
port_watcher_register_callback(pw, stp_port_changed_cb, stp);
port_watcher_register_local_port_callback(pw, stp_local_port_changed_cb,
+2 -4
View File
@@ -1,4 +1,4 @@
/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford
* Junior University
*
* We are making the OpenFlow specification and associated documentation
@@ -41,10 +41,8 @@
struct port_watcher;
struct rconn;
struct secchan;
struct settings;
void stp_start(struct secchan *, const struct settings *,
struct port_watcher *,
void stp_start(struct secchan *, struct port_watcher *,
struct rconn *local, struct rconn *remote);
#endif /* stp-secchan.h */