Rename struct buffer to struct ofpbuf.
[sliver-openvswitch.git] / controller / controller.c
index 0cc4258..775e905 100644 (file)
  * derivatives without specific, written prior permission.
  */
 
+#include <config.h>
+
 #include <errno.h>
 #include <getopt.h>
+#include <limits.h>
+#include <signal.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "buffer.h"
 #include "command-line.h"
 #include "compiler.h"
+#include "daemon.h"
 #include "fault.h"
 #include "learning-switch.h"
+#include "ofpbuf.h"
+#include "openflow.h"
 #include "poll-loop.h"
 #include "rconn.h"
+#include "timeval.h"
 #include "util.h"
 #include "vconn-ssl.h"
 #include "vconn.h"
@@ -65,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[]);
@@ -81,8 +91,10 @@ main(int argc, char *argv[])
 
     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");
@@ -121,6 +133,9 @@ main(int argc, char *argv[])
         fatal(0, "no active or passive switch connections");
     }
 
+    die_if_already_running();
+    daemonize();
+
     while (n_switches > 0 || n_listeners > 0) {
         int iteration;
         int i;
@@ -185,22 +200,23 @@ 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
 do_switching(struct switch_ *sw)
 {
     unsigned int packets_sent;
-    struct buffer *msg;
+    struct ofpbuf *msg;
 
     packets_sent = rconn_packets_sent(sw->rconn);
 
     msg = rconn_recv(sw->rconn);
     if (msg) {
         lswitch_process_packet(sw->lswitch, sw->rconn, msg);
-        buffer_delete(msg);
+        ofpbuf_delete(msg);
     }
     rconn_run(sw->rconn);
 
@@ -212,9 +228,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'},
@@ -233,6 +254,18 @@ parse_options(int argc, char *argv[])
         }
 
         switch (c) {
+        case 'D':
+            set_detach();
+            break;
+
+        case 'P':
+            set_pidfile(optarg);
+            break;
+
+        case 'f':
+            ignore_existing_pidfile();
+            break;
+
         case 'H':
             learn_macs = false;
             break;
@@ -241,6 +274,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();
 
@@ -273,10 +318,16 @@ usage(void)
            program_name, program_name);
     vconn_usage(true, true);
     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"
+           "  --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");
+           "  -V, --version           display version information\n",
+           RUNDIR);
     exit(EXIT_SUCCESS);
 }