Add --max-idle option to secchan and controller.

This commit is contained in:
Ben Pfaff committed 2008-06-26 09:26:50 -07:00
1 parent 58dc4ead3b
commit 5aca80fab9
8 files changed
+105 -16

No files matched your search

+15
View File
@@ -73,6 +73,21 @@ in the network passes through the controller.
This option is most useful for debugging. It reduces switching
performance, so it should not be used in production.
.TP
\fB--max-idle=\fIsecs\fR|\fBpermanent\fR
Sets \fIsecs\fR as the number of seconds that a flow set up by the
controller will remain in the switch's flow table without any matching
packets being seen. If \fBpermanent\fR is specified, which is not
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 OpenFlow secure channel can set up some flows
on its own. To set the idle time for those flows, pass
\fB--max-idle\fR to \fBsecchan\fR(8).
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).
.TP
.BR \-H ", " \-\^\-hub
By default, the controller acts as an L2 MAC-learning switch. This
+22 -1
View File
@@ -33,6 +33,7 @@
#include <errno.h>
#include <getopt.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
@@ -42,6 +43,7 @@
#include "daemon.h"
#include "fault.h"
#include "learning-switch.h"
#include "openflow.h"
#include "poll-loop.h"
#include "rconn.h"
#include "util.h"
@@ -66,6 +68,9 @@ static bool learn_macs = true;
/* Set up flows? (If not, every packet is processed at the controller.) */
static bool setup_flows = true;
/* --max-idle: Maximum idle time, in seconds, before flows expire. */
static int max_idle = 60;
static int do_switching(struct switch_ *);
static void new_switch(struct switch_ *, struct vconn *, const char *name);
static void parse_options(int argc, char *argv[]);
@@ -189,7 +194,8 @@ static void
new_switch(struct switch_ *sw, struct vconn *vconn, const char *name)
{
sw->rconn = rconn_new_from_vconn(name, 128, vconn);
sw->lswitch = lswitch_create(sw->rconn, learn_macs, setup_flows);
sw->lswitch = lswitch_create(sw->rconn, learn_macs,
setup_flows ? max_idle : -1);
}
static int
@@ -215,11 +221,13 @@ do_switching(struct switch_ *sw)
static void
parse_options(int argc, char *argv[])
{
enum { OPT_MAX_IDLE = UCHAR_MAX + 1 };
static struct option long_options[] = {
{"detach", no_argument, 0, 'D'},
{"pidfile", optional_argument, 0, 'P'},
{"hub", no_argument, 0, 'H'},
{"noflow", no_argument, 0, 'n'},
{"max-idle", required_argument, 0, OPT_MAX_IDLE},
{"verbose", optional_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
@@ -254,6 +262,18 @@ parse_options(int argc, char *argv[])
setup_flows = false;
break;
case OPT_MAX_IDLE:
if (!strcmp(optarg, "permanent")) {
max_idle = OFP_FLOW_PERMANENT;
} else {
max_idle = atoi(optarg);
if (max_idle < 1 || max_idle > 65535) {
fatal(0, "--max-idle argument must be between 1 and "
"65535 or the word 'permanent'");
}
}
break;
case 'h':
usage();
@@ -290,6 +310,7 @@ usage(void)
" -P, --pidfile[=FILE] create pidfile (default: %s/controller.pid)\n"
" -H, --hub act as hub instead of learning switch\n"
" -n, --noflow pass traffic, but don't add flows\n"
" --max-idle=SECS max idle time for new flows\n"
" -v, --verbose=MODULE:FACILITY:LEVEL configure logging levels\n"
" -v, --verbose set maximum verbosity level\n"
" -h, --help display this help message\n"
+1 -2
View File
@@ -39,8 +39,7 @@
struct buffer;
struct rconn;
struct lswitch *lswitch_create(struct rconn *,
bool learn_macs, bool setup_flows);
struct lswitch *lswitch_create(struct rconn *, bool learn_macs, int max_idle);
void lswitch_destroy(struct lswitch *);
void lswitch_process_packet(struct lswitch *, struct rconn *,
const struct buffer *);
+2 -1
View File
@@ -75,7 +75,8 @@ void vconn_recv_wait(struct vconn *);
void vconn_send_wait(struct vconn *);
struct buffer *make_add_simple_flow(const struct flow *,
uint32_t buffer_id, uint16_t out_port);
uint32_t buffer_id, uint16_t out_port,
uint16_t max_idle);
struct buffer *make_buffered_packet_out(uint32_t buffer_id,
uint16_t in_port, uint16_t out_port);
struct buffer *make_unbuffered_packet_out(const struct buffer *packet,
+12 -7
View File
@@ -53,7 +53,11 @@
#include "vlog.h"
struct lswitch {
bool setup_flows; /* Set up flows? (or controller processes all packets) */
/* If nonnegative, the switch sets up flows that expire after the given
* number of seconds (or never expire, if the value is OFP_FLOW_PERMANENT).
* Otherwise, the switch processes every packet. */
int max_idle;
uint64_t datapath_id;
time_t last_features_request;
struct mac_learning *ml; /* NULL to act as hub instead of switch. */
@@ -69,16 +73,17 @@ static void process_packet_in(struct lswitch *, struct rconn *,
* If 'learn_macs' is true, the new switch will learn the ports on which MAC
* addresses appear. Otherwise, the new switch will flood all packets.
*
* If 'setup_flows' is true, the new switch will set up flows. Otherwise, the
* new switch will process every packet.
* If 'max_idle' is nonnegative, the new switch will set up flows that expire
* after the given number of seconds (or never expire, if 'max_idle' is
* OFP_FLOW_PERMANENT). Otherwise, the new switch will process every packet.
*
* 'rconn' is used to send out an OpenFlow features request. */
struct lswitch *
lswitch_create(struct rconn *rconn, bool learn_macs, bool setup_flows)
lswitch_create(struct rconn *rconn, bool learn_macs, int max_idle)
{
struct lswitch *sw = xmalloc(sizeof *sw);
memset(sw, 0, sizeof *sw);
sw->setup_flows = setup_flows;
sw->max_idle = max_idle;
sw->datapath_id = 0;
sw->last_features_request = 0;
sw->ml = learn_macs ? mac_learning_create() : NULL;
@@ -213,11 +218,11 @@ process_packet_in(struct lswitch *sw, struct rconn *rconn,
out_port = mac_learning_lookup(sw->ml, flow.dl_dst);
}
if (sw->setup_flows && (!sw->ml || out_port != OFPP_FLOOD)) {
if (sw->max_idle >= 0 && (!sw->ml || out_port != OFPP_FLOOD)) {
/* The output port is known, or we always flood everything, so add a
* new flow. */
queue_tx(sw, rconn, make_add_simple_flow(&flow, ntohl(opi->buffer_id),
out_port));
out_port, sw->max_idle));
/* If the switch didn't buffer the packet, we need to send a copy. */
if (ntohl(opi->buffer_id) == UINT32_MAX) {
+2 -2
View File
@@ -370,7 +370,7 @@ vconn_send_wait(struct vconn *vconn)
struct buffer *
make_add_simple_flow(const struct flow *flow,
uint32_t buffer_id, uint16_t out_port)
uint32_t buffer_id, uint16_t out_port, uint16_t max_idle)
{
struct ofp_flow_mod *ofm;
size_t size = sizeof *ofm + sizeof ofm->actions[0];
@@ -392,7 +392,7 @@ make_add_simple_flow(const struct flow *flow,
ofm->match.tp_src = flow->tp_src;
ofm->match.tp_dst = flow->tp_dst;
ofm->command = htons(OFPFC_ADD);
ofm->max_idle = htons(60);
ofm->max_idle = htons(max_idle);
ofm->buffer_id = htonl(buffer_id);
ofm->actions[0].type = htons(OFPAT_OUTPUT);
ofm->actions[0].arg.output.max_len = htons(0);
+29 -1
View File
@@ -115,7 +115,35 @@ seconds.
This option has no effect when \fB--fail=closed\fR is specified.
.TP
\fB-l\Fr, \Fb--listen=\fImethod\fR
\fB--max-idle=\fIsecs\fR|\fBpermanent\fR
Sets \fIsecs\fR as the number of seconds that a flow set up by the
secure channel 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 secure channel will never
expire. The default is 15 seconds.
Most flows are set up by the OpenFlow controller, not by the secure
channel. This option affects only the following flows, which the
secure channel sets up itself:
.RS
.IP \(bu
When \fB--fail=open\fR is specified, flows set up when the secure
channel 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=open\fR and in-band control are not
in use, this option has no effect.
.TP
\fB-l\fR, \fB--listen=\fImethod\fR
Configures the switch to additionally listen for incoming OpenFlow
connections for switch management with \fBdpctl\fR. The \fImethod\fR
must be given as one of the following passive OpenFlow connection
+22 -2
View File
@@ -107,6 +107,10 @@ static enum fail_mode fail_mode = FAIL_OPEN;
* fail_mode is FAIL_OPEN. */
static int fail_open_delay = 30;
/* --max-idle: Idle time to assign to flows created by learning switch when in
* fail-open mode. */
static int max_idle = 15;
static void parse_options(int argc, char *argv[]);
static void usage(void) NO_RETURN;
@@ -409,7 +413,8 @@ local_hook(struct relay *r)
/* Add new flow. */
if (out_port != OFPP_FLOOD) {
b = make_add_simple_flow(&flow, ntohl(opi->buffer_id), out_port);
b = make_add_simple_flow(&flow, ntohl(opi->buffer_id), out_port,
max_idle);
if (rconn_force_send(rc, b)) {
buffer_delete(b);
}
@@ -453,7 +458,7 @@ fail_open_hook(struct relay *r)
if (!r->lswitch) {
VLOG_WARN("Could not connect to controller for %d seconds, "
"failing open", disconnected_duration);
r->lswitch = lswitch_create(local, true, true);
r->lswitch = lswitch_create(local, true, max_idle);
}
/* Do switching. */
@@ -465,9 +470,11 @@ fail_open_hook(struct relay *r)
static void
parse_options(int argc, char *argv[])
{
enum { OPT_MAX_IDLE = UCHAR_MAX + 1 };
static struct option long_options[] = {
{"fail", required_argument, 0, 'f'},
{"fail-open-delay", required_argument, 0, 'd'},
{"max-idle", required_argument, 0, OPT_MAX_IDLE},
{"listen", required_argument, 0, 'l'},
{"detach", no_argument, 0, 'D'},
{"pidfile", optional_argument, 0, 'P'},
@@ -507,6 +514,18 @@ parse_options(int argc, char *argv[])
}
break;
case OPT_MAX_IDLE:
if (!strcmp(optarg, "permanent")) {
max_idle = OFP_FLOW_PERMANENT;
} else {
max_idle = atoi(optarg);
if (max_idle < 1 || max_idle > 65535) {
fatal(0, "--max-idle argument must be between 1 and "
"65535 or the word 'permanent'");
}
}
break;
case 'D':
set_detach();
break;
@@ -560,6 +579,7 @@ usage(void)
" open (default): act as learning switch\n"
" -d, --fail-open-delay=SECS number of seconds after which to\n"
" fail open if --fail=open (default: 30)\n"
" --max-idle=SECS max idle for flows set up by secchan\n"
" -l, --listen=METHOD allow management connections on METHOD\n"
" (a passive OpenFlow connection method)\n"
"\nOther options:\n"