Change code base to Nicira's master branch
This commit is contained in:
1 parent
695db2964e
commit
5ff6ec248d
199 files changed
+10152
-1817
No files matched your search
+2
-2
@@ -3,5 +3,5 @@
|
||||
/controller-lite
|
||||
/ctlpath-lite
|
||||
/dpctl-lite
|
||||
/secchan
|
||||
/secchan.8
|
||||
/ofprotocol
|
||||
/ofprotocol.8
|
||||
+7
-7
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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,
|
||||
|
||||
@@ -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 */
|
||||
Reference in new issue
Block a user