X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=controller%2Fcontroller.c;h=48420c8697ae9ae0ec2056ea327b38ac8e61b0a6;hb=553dfa572d77bff616b1ea88d90eef266d202954;hp=284e2e9ffb293986d56026cd45e38f4d5fa37721;hpb=07f8d9645c14da05f318192f502dd826fff19dae;p=sliver-openvswitch.git diff --git a/controller/controller.c b/controller/controller.c index 284e2e9ff..48420c869 100644 --- a/controller/controller.c +++ b/controller/controller.c @@ -31,8 +31,12 @@ * derivatives without specific, written prior permission. */ +#include + #include #include +#include +#include #include #include @@ -42,8 +46,10 @@ #include "daemon.h" #include "fault.h" #include "learning-switch.h" +#include "openflow.h" #include "poll-loop.h" #include "rconn.h" +#include "timeval.h" #include "util.h" #include "vconn-ssl.h" #include "vconn.h" @@ -66,6 +72,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[]); @@ -75,15 +84,17 @@ int main(int argc, char *argv[]) { struct switch_ switches[MAX_SWITCHES]; - struct vconn *listeners[MAX_LISTENERS]; + struct pvconn *listeners[MAX_LISTENERS]; int n_switches, n_listeners; int retval; int i; set_program_name(argv[0]); register_fault_handlers(); + time_init(); vlog_init(); parse_options(argc, argv); + signal(SIGPIPE, SIG_IGN); if (argc - optind < 1) { fatal(0, "at least one vconn argument required; use --help for usage"); @@ -101,27 +112,29 @@ main(int argc, char *argv[]) int retval; retval = vconn_open(name, &vconn); - if (retval) { - VLOG_ERR("%s: connect: %s", name, strerror(retval)); - continue; - } - - if (vconn_is_passive(vconn)) { - if (n_listeners >= MAX_LISTENERS) { - fatal(0, "max %d passive connections", n_listeners); - } - listeners[n_listeners++] = vconn; - } else { + if (!retval) { if (n_switches >= MAX_SWITCHES) { fatal(0, "max %d switch connections", n_switches); } new_switch(&switches[n_switches++], vconn, name); + continue; + } else if (retval == EAFNOSUPPORT) { + struct pvconn *pvconn; + retval = pvconn_open(name, &pvconn); + if (!retval) { + if (n_listeners >= MAX_LISTENERS) { + fatal(0, "max %d passive connections", n_listeners); + } + listeners[n_listeners++] = pvconn; + } } + VLOG_ERR("%s: connect: %s", name, strerror(retval)); } if (n_switches == 0 && n_listeners == 0) { fatal(0, "no active or passive switch connections"); } + die_if_already_running(); daemonize(); while (n_switches > 0 || n_listeners > 0) { @@ -133,14 +146,14 @@ main(int argc, char *argv[]) struct vconn *new_vconn; int retval; - retval = vconn_accept(listeners[i], &new_vconn); + retval = pvconn_accept(listeners[i], &new_vconn); if (!retval || retval == EAGAIN) { if (!retval) { new_switch(&switches[n_switches++], new_vconn, "tcp"); } i++; } else { - vconn_close(listeners[i]); + pvconn_close(listeners[i]); listeners[i] = listeners[--n_listeners]; } } @@ -171,7 +184,7 @@ main(int argc, char *argv[]) /* Wait for something to happen. */ if (n_switches < MAX_SWITCHES) { for (i = 0; i < n_listeners; i++) { - vconn_accept_wait(listeners[i]); + pvconn_wait(listeners[i]); } } for (i = 0; i < n_switches; i++) { @@ -188,8 +201,9 @@ main(int argc, char *argv[]) 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->rconn = rconn_new_from_vconn(name, vconn); + sw->lswitch = lswitch_create(sw->rconn, learn_macs, + setup_flows ? max_idle : -1); } static int @@ -215,11 +229,14 @@ 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'}, + {"force", no_argument, 0, 'f'}, {"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'}, @@ -243,7 +260,11 @@ parse_options(int argc, char *argv[]) break; case 'P': - set_pidfile(optarg ? optarg : "controller.pid"); + set_pidfile(optarg); + break; + + case 'f': + ignore_existing_pidfile(); break; case 'H': @@ -254,6 +275,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(); @@ -288,9 +321,11 @@ usage(void) printf("\nOther options:\n" " -D, --detach run in background as daemon\n" " -P, --pidfile[=FILE] create pidfile (default: %s/controller.pid)\n" + " -f, --force with -P, start even if already running\n" " -H, --hub act as hub instead of learning switch\n" " -n, --noflow pass traffic, but don't add flows\n" - " -v, --verbose=MODULE:FACILITY:LEVEL configure logging levels\n" + " --max-idle=SECS max idle time for new flows\n" + " -v, --verbose=MODULE[:FACILITY[:LEVEL]] set logging levels\n" " -v, --verbose set maximum verbosity level\n" " -h, --help display this help message\n" " -V, --version display version information\n",