Update manpages to mention new --log-file option.
[sliver-openvswitch.git] / controller / controller.c
index 2d79afa..9a33418 100644 (file)
 #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"
@@ -84,7 +84,7 @@ 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;
@@ -97,12 +97,13 @@ main(int argc, char *argv[])
     signal(SIGPIPE, SIG_IGN);
 
     if (argc - optind < 1) {
-        fatal(0, "at least one vconn argument required; use --help for usage");
+        ofp_fatal(0, "at least one vconn argument required; "
+                  "use --help for usage");
     }
 
     retval = vlog_server_listen(NULL, NULL);
     if (retval) {
-        fatal(retval, "Could not listen for vlog connections");
+        ofp_fatal(retval, "Could not listen for vlog connections");
     }
 
     n_switches = n_listeners = 0;
@@ -111,26 +112,29 @@ main(int argc, char *argv[])
         struct vconn *vconn;
         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 {
+        retval = vconn_open(name, OFP_VERSION, &vconn);
+        if (!retval) {
             if (n_switches >= MAX_SWITCHES) {
-                fatal(0, "max %d switch connections", n_switches);
+                ofp_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) {
+                    ofp_fatal(0, "max %d passive connections", n_listeners);
+                }
+                listeners[n_listeners++] = pvconn;
+            }
+        }
+        if (retval) {
+            VLOG_ERR("%s: connect: %s", name, strerror(retval));
         }
     }
     if (n_switches == 0 && n_listeners == 0) {
-        fatal(0, "no active or passive switch connections");
+        ofp_fatal(0, "no active or passive switch connections");
     }
 
     die_if_already_running();
@@ -145,14 +149,14 @@ main(int argc, char *argv[])
             struct vconn *new_vconn;
             int retval;
 
-            retval = vconn_accept(listeners[i], &new_vconn);
+            retval = pvconn_accept(listeners[i], OFP_VERSION, &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];
             }
         }
@@ -170,8 +174,8 @@ main(int argc, char *argv[])
                     }
                     i++;
                 } else {
-                    lswitch_destroy(this->lswitch);
                     rconn_destroy(this->rconn);
+                    lswitch_destroy(this->lswitch);
                     switches[i] = switches[--n_switches];
                 }
             }
@@ -179,17 +183,22 @@ main(int argc, char *argv[])
                 break;
             }
         }
+        for (i = 0; i < n_switches; i++) {
+            struct switch_ *this = &switches[i];
+            lswitch_run(this->lswitch, this->rconn);
+        }
 
         /* 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++) {
             struct switch_ *sw = &switches[i];
             rconn_run_wait(sw->rconn);
             rconn_recv_wait(sw->rconn);
+            lswitch_wait(sw->lswitch);
         }
         poll_block();
     }
@@ -209,14 +218,14 @@ 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);
 
@@ -228,18 +237,22 @@ do_switching(struct switch_ *sw)
 static void
 parse_options(int argc, char *argv[])
 {
-    enum { OPT_MAX_IDLE = UCHAR_MAX + 1 };
+    enum {
+        OPT_MAX_IDLE = UCHAR_MAX + 1,
+        OPT_PEER_CA_CERT,
+        VLOG_OPTION_ENUMS
+    };
     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'},
+        DAEMON_LONG_OPTIONS,
+#ifdef HAVE_OPENSSL
         VCONN_SSL_LONG_OPTIONS
+        {"peer-ca-cert", required_argument, 0, OPT_PEER_CA_CERT},
+#endif
         {0, 0, 0, 0},
     };
     char *short_options = long_options_to_short_options(long_options);
@@ -254,18 +267,6 @@ 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;
@@ -280,8 +281,8 @@ parse_options(int argc, char *argv[])
             } 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'");
+                    ofp_fatal(0, "--max-idle argument must be between 1 and "
+                              "65535 or the word 'permanent'");
                 }
             }
             break;
@@ -293,12 +294,17 @@ parse_options(int argc, char *argv[])
             printf("%s "VERSION" compiled "__DATE__" "__TIME__"\n", argv[0]);
             exit(EXIT_SUCCESS);
 
-        case 'v':
-            vlog_set_verbosity(optarg);
-            break;
+        VLOG_OPTION_HANDLERS
+        DAEMON_OPTION_HANDLERS
 
+#ifdef HAVE_OPENSSL
         VCONN_SSL_OPTION_HANDLERS
 
+        case OPT_PEER_CA_CERT:
+            vconn_ssl_set_peer_ca_cert_file(optarg);
+            break;
+#endif
+
         case '?':
             exit(EXIT_FAILURE);
 
@@ -316,18 +322,14 @@ usage(void)
            "usage: %s [OPTIONS] METHOD\n"
            "where METHOD is any OpenFlow connection method.\n",
            program_name, program_name);
-    vconn_usage(true, true);
+    vconn_usage(true, true, false);
+    daemon_usage();
+    vlog_usage();
     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",
-           RUNDIR);
+           "  -V, --version           display version information\n");
     exit(EXIT_SUCCESS);
 }