secchan: Make secchan into a library.
authorBen Pfaff <blp@nicira.com>
Mon, 2 Mar 2009 22:27:10 +0000 (14:27 -0800)
committerBen Pfaff <blp@nicira.com>
Mon, 2 Mar 2009 22:34:44 +0000 (14:34 -0800)
12 files changed:
secchan/automake.mk
secchan/discovery.c
secchan/executer.c
secchan/main.c [new file with mode: 0644]
secchan/netflow.c
secchan/ofproto.c
secchan/ofproto.h
secchan/pinsched.c
secchan/secchan.c [deleted file]
secchan/secchan.h [deleted file]
secchan/status.c
secchan/status.h

index 76a279dd440ee0c92cd46a51025959926920ccda..d3e4e819b146f0259072c9d496c1c3cbd806af98 100644 (file)
@@ -1,11 +1,15 @@
 bin_PROGRAMS += secchan/secchan
 man_MANS += secchan/secchan.8
 
-#      secchan/stp-secchan.c \
-#      secchan/stp-secchan.h
-#
+secchan_secchan_SOURCES = secchan/main.c
+secchan_secchan_LDADD = \
+       secchan/libsecchan.a \
+       lib/libopenflow.a \
+       $(FAULT_LIBS) \
+       $(SSL_LIBS)
 
-secchan_secchan_SOURCES = \
+noinst_LIBRARIES += secchan/libsecchan.a
+secchan_libsecchan_a_SOURCES = \
        secchan/discovery.c \
        secchan/discovery.h \
        secchan/executer.c \
@@ -22,16 +26,8 @@ secchan_secchan_SOURCES = \
        secchan/pktbuf.h \
        secchan/pinsched.c \
        secchan/pinsched.h \
-       secchan/secchan.c \
-       secchan/secchan.h \
        secchan/status.c \
        secchan/status.h
-#if SUPPORT_SNAT
-#secchan_secchan_SOURCES += \
-#      secchan/snat.c \
-#      secchan/snat.h
-#endif
-secchan_secchan_LDADD = lib/libopenflow.a $(FAULT_LIBS) $(SSL_LIBS)
 
 EXTRA_DIST += secchan/secchan.8.in
 DISTCLEANFILES += secchan/secchan.8
index 105614ff28c9a748a4737f843c20a4892d77f0df..42f40f143f8c15848814b03592327a407423dfd3 100644 (file)
@@ -43,7 +43,6 @@
 #include "netdev.h"
 #include "openflow/openflow.h"
 #include "packets.h"
-#include "secchan.h"
 #include "status.h"
 
 #define THIS_MODULE VLM_discovery
index b235862b91243d6cc2e205d136da8ecc83328b8b..5f59832c4c621f1892abac6f5944b8f5dd20725c 100644 (file)
@@ -50,7 +50,6 @@
 #include "openflow/openflow.h"
 #include "poll-loop.h"
 #include "rconn.h"
-#include "secchan.h"
 #include "socket-util.h"
 #include "util.h"
 #include "vconn.h"
diff --git a/secchan/main.c b/secchan/main.c
new file mode 100644 (file)
index 0000000..18a591f
--- /dev/null
@@ -0,0 +1,488 @@
+/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford
+ * Junior University
+ *
+ * We are making the OpenFlow specification and associated documentation
+ * (Software) available for public use and benefit with the expectation
+ * that others will use, modify and enhance the Software and contribute
+ * those enhancements back to the community. However, since we would
+ * like to make the Software available for broadest use, with as few
+ * restrictions as possible permission is hereby granted, free of
+ * charge, to any person obtaining a copy of this Software to deal in
+ * the Software under the copyrights without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The name and trademarks of copyright holder(s) may NOT be used in
+ * advertising or publicity pertaining to the Software or any
+ * derivatives without specific, written prior permission.
+ */
+
+#include <config.h>
+#include <assert.h>
+#include <errno.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+
+#include "cfg.h"
+#include "command-line.h"
+#include "compiler.h"
+#include "daemon.h"
+#include "dirs.h"
+#include "discovery.h"
+#include "dpif.h"
+#include "fail-open.h"
+#include "fault.h"
+#include "in-band.h"
+#include "leak-checker.h"
+#include "list.h"
+#include "netdev.h"
+#include "ofpbuf.h"
+#include "ofproto.h"
+#include "openflow/openflow.h"
+#include "packets.h"
+#include "poll-loop.h"
+#include "rconn.h"
+#include "signals.h"
+#include "status.h"
+#include "timeval.h"
+#include "util.h"
+#include "vconn-ssl.h"
+#include "vconn.h"
+#include "vlog-socket.h"
+
+#include "vlog.h"
+#define THIS_MODULE VLM_secchan
+
+static void reconfigure(struct ofproto *);
+static void parse_options(int argc, char *argv[], struct ofsettings *);
+static void usage(void) NO_RETURN;
+
+int
+main(int argc, char *argv[])
+{
+    struct signal *sighup;
+    struct ofproto *ofproto;
+    struct ofsettings s;
+    int retval;
+
+    set_program_name(argv[0]);
+    register_fault_handlers();
+    time_init();
+    vlog_init();
+    parse_options(argc, argv, &s);
+    signal(SIGPIPE, SIG_IGN);
+    sighup = signal_register(SIGHUP);
+
+    die_if_already_running();
+    daemonize();
+
+    /* Start listening for vlogconf requests. */
+    retval = vlog_server_listen(NULL, NULL);
+    if (retval) {
+        ofp_fatal(retval, "Could not listen for vlog connections");
+    }
+
+    VLOG_INFO("OpenFlow reference implementation version %s", VERSION BUILDNR);
+    VLOG_INFO("OpenFlow protocol version 0x%02x", OFP_VERSION);
+
+    /* Start OpenFlow processing. */
+    ofproto = ofproto_create(&s);
+
+    reconfigure(ofproto);
+    while (ofproto_is_alive(ofproto)) {
+        if (signal_poll(sighup)) {
+            reconfigure(ofproto);
+        }
+
+        /* Do work. */
+        ofproto_run(ofproto);
+
+        /* Wait for something to happen. */
+        ofproto_wait(ofproto);
+        signal_wait(sighup);
+        poll_block();
+    }
+
+    return 0;
+}
+
+static void
+reconfigure(struct ofproto *ofproto)
+{
+    cfg_read();
+    ofproto_reconfigure(ofproto);
+}
+\f
+/* User interface. */
+
+static void
+parse_options(int argc, char *argv[], struct ofsettings *s)
+{
+    enum {
+        OPT_DATAPATH_ID = UCHAR_MAX + 1,
+        OPT_MANUFACTURER,
+        OPT_HARDWARE,
+        OPT_SOFTWARE,
+        OPT_SERIAL,
+        OPT_ACCEPT_VCONN,
+        OPT_NO_RESOLV_CONF,
+        OPT_BR_NAME,
+        OPT_FAIL_MODE,
+        OPT_INACTIVITY_PROBE,
+        OPT_MAX_IDLE,
+        OPT_MAX_BACKOFF,
+        OPT_RATE_LIMIT,
+        OPT_BURST_LIMIT,
+        OPT_BOOTSTRAP_CA_CERT,
+        OPT_STP,
+        OPT_NO_STP,
+        OPT_OUT_OF_BAND,
+        OPT_IN_BAND,
+        OPT_COMMAND_ACL,
+        OPT_COMMAND_DIR,
+        VLOG_OPTION_ENUMS,
+        LEAK_CHECKER_OPTION_ENUMS
+    };
+    static struct option long_options[] = {
+        {"datapath-id", required_argument, 0, OPT_DATAPATH_ID},
+        {"manufacturer", required_argument, 0, OPT_MANUFACTURER},
+        {"hardware", required_argument, 0, OPT_HARDWARE},
+        {"software", required_argument, 0, OPT_SOFTWARE},
+        {"serial", required_argument, 0, OPT_SERIAL},
+        {"accept-vconn", required_argument, 0, OPT_ACCEPT_VCONN},
+        {"no-resolv-conf", no_argument, 0, OPT_NO_RESOLV_CONF},
+        {"config",      required_argument, 0, 'F'},
+        {"br-name",     required_argument, 0, OPT_BR_NAME},
+        {"fail",        required_argument, 0, OPT_FAIL_MODE},
+        {"inactivity-probe", required_argument, 0, OPT_INACTIVITY_PROBE},
+        {"max-idle",    required_argument, 0, OPT_MAX_IDLE},
+        {"max-backoff", required_argument, 0, OPT_MAX_BACKOFF},
+        {"listen",      required_argument, 0, 'l'},
+        {"rate-limit",  optional_argument, 0, OPT_RATE_LIMIT},
+        {"burst-limit", required_argument, 0, OPT_BURST_LIMIT},
+        {"stp",         no_argument, 0, OPT_STP},
+        {"no-stp",      no_argument, 0, OPT_NO_STP},
+        {"out-of-band", no_argument, 0, OPT_OUT_OF_BAND},
+        {"in-band",     no_argument, 0, OPT_IN_BAND},
+        {"command-acl", required_argument, 0, OPT_COMMAND_ACL},
+        {"command-dir", required_argument, 0, OPT_COMMAND_DIR},
+        {"verbose",     optional_argument, 0, 'v'},
+        {"help",        no_argument, 0, 'h'},
+        {"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},
+#endif
+        {0, 0, 0, 0},
+    };
+    char *short_options = long_options_to_short_options(long_options);
+
+    /* Set defaults that we can figure out before parsing options. */
+    s->datapath_id = 0;
+    s->mfr_desc = "Nicira Networks, Inc.";
+    s->hw_desc = "Reference Implementation";
+    s->sw_desc = VERSION BUILDNR;
+    s->serial_desc = "None";
+    s->n_listeners = 0;
+    s->fail_mode = FAIL_OPEN;
+    s->max_idle = 15;
+    s->probe_interval = 15;
+    s->max_backoff = 15;
+    s->update_resolv_conf = true;
+    s->rate_limit = 0;
+    s->burst_limit = 0;
+    s->accept_controller_re = NULL;
+    s->enable_stp = false;
+    s->in_band = true;
+    s->command_acl = "";
+    s->command_dir = xasprintf("%s/commands", ofp_pkgdatadir);
+    for (;;) {
+        int error;
+        int c;
+
+        c = getopt_long(argc, argv, short_options, long_options, NULL);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+        case OPT_DATAPATH_ID:
+            if (strlen(optarg) != 12
+                || strspn(optarg, "0123456789abcdefABCDEF") != 12) {
+                ofp_fatal(0, "argument to --datapath-id must be "
+                          "exactly 12 hex digits");
+            }
+            s->datapath_id = strtoll(optarg, NULL, 16);
+            if (!s->datapath_id) {
+                ofp_fatal(0, "argument to --datapath-id must be nonzero");
+            }
+            break;
+
+        case OPT_MANUFACTURER:
+            s->mfr_desc = optarg;
+            break;
+
+        case OPT_HARDWARE:
+            s->hw_desc = optarg;
+            break;
+
+        case OPT_SOFTWARE:
+            s->sw_desc = optarg;
+            break;
+
+        case OPT_SERIAL:
+            s->serial_desc = optarg;
+            break;
+
+        case OPT_ACCEPT_VCONN:
+            s->accept_controller_re = (optarg[0] == '^' ? optarg
+                                       : xasprintf("^%s", optarg));
+            break;
+
+        case OPT_BR_NAME:
+            s->br_name = optarg;
+            break;
+
+        case OPT_NO_RESOLV_CONF:
+            s->update_resolv_conf = false;
+            break;
+
+        case OPT_FAIL_MODE:
+            if (!strcmp(optarg, "open")) {
+                s->fail_mode = FAIL_OPEN;
+            } else if (!strcmp(optarg, "closed")) {
+                s->fail_mode = FAIL_CLOSED;
+            } else {
+                ofp_fatal(0, "-f or --fail argument must be \"open\" "
+                          "or \"closed\"");
+            }
+            break;
+
+        case OPT_INACTIVITY_PROBE:
+            s->probe_interval = atoi(optarg);
+            if (s->probe_interval < 5) {
+                ofp_fatal(0, "--inactivity-probe argument must be at least 5");
+            }
+            break;
+
+        case OPT_MAX_IDLE:
+            if (!strcmp(optarg, "permanent")) {
+                s->max_idle = OFP_FLOW_PERMANENT;
+            } else {
+                s->max_idle = atoi(optarg);
+                if (s->max_idle < 1 || s->max_idle > 65535) {
+                    ofp_fatal(0, "--max-idle argument must be between 1 and "
+                              "65535 or the word 'permanent'");
+                }
+            }
+            break;
+
+        case OPT_MAX_BACKOFF:
+            s->max_backoff = atoi(optarg);
+            if (s->max_backoff < 1) {
+                ofp_fatal(0, "--max-backoff argument must be at least 1");
+            } else if (s->max_backoff > 3600) {
+                s->max_backoff = 3600;
+            }
+            break;
+
+        case OPT_RATE_LIMIT:
+            if (optarg) {
+                s->rate_limit = atoi(optarg);
+                if (s->rate_limit < 1) {
+                    ofp_fatal(0, "--rate-limit argument must be at least 1");
+                }
+            } else {
+                s->rate_limit = 1000;
+            }
+            break;
+
+        case OPT_BURST_LIMIT:
+            s->burst_limit = atoi(optarg);
+            if (s->burst_limit < 1) {
+                ofp_fatal(0, "--burst-limit argument must be at least 1");
+            }
+            break;
+
+        case OPT_STP:
+            s->enable_stp = true;
+            break;
+
+        case OPT_NO_STP:
+            s->enable_stp = false;
+            break;
+
+        case OPT_OUT_OF_BAND:
+            s->in_band = false;
+            break;
+
+        case OPT_IN_BAND:
+            s->in_band = true;
+            break;
+
+        case OPT_COMMAND_ACL:
+            s->command_acl = (s->command_acl[0]
+                              ? xasprintf("%s,%s", s->command_acl, optarg)
+                              : optarg);
+            break;
+
+        case OPT_COMMAND_DIR:
+            s->command_dir = optarg;
+            break;
+
+        case 'F':
+            error = cfg_add_file(optarg);
+            if (error) {
+                ofp_fatal(error, "failed to add configuration file or "
+                        "directory \"%s\"", optarg);
+            }
+            break;
+
+        case 'l':
+            if (s->n_listeners >= MAX_MGMT) {
+                ofp_fatal(0,
+                          "-l or --listen may be specified at most %d times",
+                          MAX_MGMT);
+            }
+            s->listener_names[s->n_listeners++] = optarg;
+            break;
+
+        case 'h':
+            usage();
+
+        case 'V':
+            printf("%s %s compiled "__DATE__" "__TIME__"\n",
+                   program_name, VERSION BUILDNR);
+            exit(EXIT_SUCCESS);
+
+        DAEMON_OPTION_HANDLERS
+
+        VLOG_OPTION_HANDLERS
+
+        LEAK_CHECKER_OPTION_HANDLERS
+
+#ifdef HAVE_OPENSSL
+        VCONN_SSL_OPTION_HANDLERS
+
+        case OPT_BOOTSTRAP_CA_CERT:
+            vconn_ssl_set_ca_cert_file(optarg, true);
+            break;
+#endif
+
+        case '?':
+            exit(EXIT_FAILURE);
+
+        default:
+            abort();
+        }
+    }
+    free(short_options);
+
+    argc -= optind;
+    argv += optind;
+    if (argc < 1 || argc > 2) {
+        ofp_fatal(0, "need one or two non-option arguments; "
+                  "use --help for usage");
+    }
+
+    /* Local and remote vconns. */
+    s->dp_name = argv[0];
+    s->controller_name = argc > 1 ? xstrdup(argv[1]) : NULL;
+
+    /* Set accept_controller_regex. */
+    if (!s->accept_controller_re) {
+        s->accept_controller_re = vconn_ssl_is_configured() ? "^ssl:.*" : ".*";
+    }
+
+    /* Mode of operation. */
+    s->discovery = s->controller_name == NULL;
+    if (s->discovery && !s->in_band) {
+        ofp_fatal(0, "Cannot perform discovery with out-of-band control");
+    }
+
+    /* Rate limiting. */
+    if (s->rate_limit) {
+        if (s->rate_limit < 100) {
+            VLOG_WARN("Rate limit set to unusually low value %d",
+                      s->rate_limit);
+        }
+        if (!s->burst_limit) {
+            s->burst_limit = s->rate_limit / 4;
+        }
+        s->burst_limit = MAX(s->burst_limit, 1);
+        s->burst_limit = MIN(s->burst_limit, INT_MAX / 1000);
+    }
+}
+
+static void
+usage(void)
+{
+    printf("%s: secure channel, a relay for OpenFlow messages.\n"
+           "usage: %s [OPTIONS] DATAPATH [CONTROLLER]\n"
+           "DATAPATH is a local datapath (e.g. \"dp0\").\n"
+           "CONTROLLER is an active OpenFlow connection method; if it is\n"
+           "omitted, then secchan performs controller discovery.\n",
+           program_name, program_name);
+    vconn_usage(true, true, true);
+    printf("\nConfiguration options:\n"
+           "  -F, --config=FILE|DIR   reads configuration from FILE or DIR\n"
+           "  --br-name=NAME          bridge name to use for configuration\n"
+           "\nOpenFlow options:\n"
+           "  -d, --datapath-id=ID    Use ID as the OpenFlow switch ID\n"
+           "                          (ID must consist of 12 hex digits)\n"
+           "  --manufacturer=MFR      Identify manufacturer as MFR\n"
+           "  --hardware=HW           Identify hardware as HW\n"
+           "  --software=SW           Identify software as SW\n"
+           "  --serial=SERIAL         Identify serial number as SERIAL\n"
+           "\nController discovery options:\n"
+           "  --accept-vconn=REGEX    accept matching discovered controllers\n"
+           "  --no-resolv-conf        do not update /etc/resolv.conf\n"
+           "\nNetworking options:\n"
+           "  --fail=open|closed      when controller connection fails:\n"
+           "                            closed: drop all packets\n"
+           "                            open (default): act as learning switch\n"
+           "  --inactivity-probe=SECS time between inactivity probes\n"
+           "  --max-idle=SECS         max idle for flows set up by secchan\n"
+           "  --max-backoff=SECS      max time between controller connection\n"
+           "                          attempts (default: 15 seconds)\n"
+           "  -l, --listen=METHOD     allow management connections on METHOD\n"
+           "                          (a passive OpenFlow connection method)\n"
+           "  --out-of-band           controller connection is out-of-band\n"
+           "  --stp                   enable 802.1D Spanning Tree Protocol\n"
+           "  --no-stp                disable 802.1D Spanning Tree Protocol\n"
+           "\nRate-limiting of \"packet-in\" messages to the controller:\n"
+           "  --rate-limit[=PACKETS]  max rate, in packets/s (default: 1000)\n"
+           "  --burst-limit=BURST     limit on packet credit for idle time\n"
+           "\nRemote command execution options:\n"
+           "  --command-acl=[!]GLOB[,[!]GLOB...] set allowed/denied commands\n"
+           "  --command-dir=DIR       set command dir (default: %s/commands)\n",
+           ofp_pkgdatadir);
+    daemon_usage();
+    vlog_usage();
+    printf("\nOther options:\n"
+           "  -h, --help              display this help message\n"
+           "  -V, --version           display version information\n");
+    leak_checker_usage();
+    exit(EXIT_SUCCESS);
+}
index 193109c4b8da82229178e909110ac2c8b661f807..c08b3d8ce2bae108b98175892cc96f92438212b3 100644 (file)
@@ -41,7 +41,6 @@
 #include "flow.h"
 #include "netflow.h"
 #include "packets.h"
-#include "secchan.h"
 #include "socket-util.h"
 #include "svec.h"
 #include "timeval.h"
index 1485e4539be424df7912dd06209aca19fd059dc8..f61a35f14f063101a96f770cf8b9184bd4eb72b1 100644 (file)
@@ -57,7 +57,6 @@
 #include "poll-loop.h"
 #include "port-array.h"
 #include "rconn.h"
-#include "secchan.h"
 #include "shash.h"
 #include "status.h"
 #include "svec.h"
@@ -194,7 +193,7 @@ static uint16_t odp_port_to_ofp_port(uint16_t odp_port);
 static uint16_t ofp_port_to_odp_port(uint16_t ofp_port);
 
 struct ofproto *
-ofproto_create(const struct settings *settings)
+ofproto_create(const struct ofsettings *settings)
 {
     struct dpifmon *dpifmon;
     struct rconn *controller;
index df0acd8bb1d10b9fcc12229f8993bf495f5fce45..a9351c92975b1e043b1f47854bd1a884d631af84 100644 (file)
 #ifndef OFPROTO_H
 #define OFPROTO_H 1
 
+#include <stdbool.h>
+#include <stddef.h>
 #include "flow.h"
 
-struct dpif;
-struct ofproto;
-struct settings;
-struct switch_status;
+/* Behavior when the connection to the controller fails. */
+enum fail_mode {
+    FAIL_OPEN,                  /* Act as learning switch. */
+    FAIL_CLOSED                 /* Drop all packets. */
+};
 
-struct ofproto *ofproto_create(const struct settings *);
+/* Maximum number of management connection listeners. */
+#define MAX_MGMT 8
+
+/* Settings that may be configured by the user. */
+struct ofsettings {
+    /* Configuration. */
+    const char *br_name;      /* Bridge name to use for configuration lookup */
+
+    /* Overall mode of operation. */
+    bool discovery;           /* Discover the controller automatically? */
+    bool in_band;             /* Connect to controller in-band? */
+
+    /* Datapath. */
+    uint64_t datapath_id;       /* Datapath ID. */
+    const char *dp_name;        /* Name of local datapath. */
+
+    /* Description strings. */
+    const char *mfr_desc;       /* Manufacturer. */
+    const char *hw_desc;        /* Hardware. */
+    const char *sw_desc;        /* Software version. */
+    const char *serial_desc;    /* Serial number. */
+
+    /* Related vconns and network devices. */
+    const char *controller_name; /* Controller (if not discovery mode). */
+    const char *listener_names[MAX_MGMT]; /* Listen for mgmt connections. */
+    size_t n_listeners;          /* Number of mgmt connection listeners. */
+
+    /* Failure behavior. */
+    enum fail_mode fail_mode; /* Act as learning switch if no controller? */
+    int max_idle;             /* Idle time for flows in fail-open mode. */
+    int probe_interval;       /* # seconds idle before sending echo request. */
+    int max_backoff;          /* Max # seconds between connection attempts. */
+
+    /* Packet-in rate-limiting. */
+    int rate_limit;           /* Tokens added to bucket per second. */
+    int burst_limit;          /* Maximum number token bucket size. */
+
+    /* Discovery behavior. */
+    const char *accept_controller_re; /* Controller vconns to accept. */
+    bool update_resolv_conf;          /* Update /etc/resolv.conf? */
+
+    /* Spanning tree protocol. */
+    bool enable_stp;
+
+    /* Remote command execution. */
+    char *command_acl;          /* Command white/blacklist, as shell globs. */
+    char *command_dir;          /* Directory that contains commands. */
+};
+
+struct ofproto *ofproto_create(const struct ofsettings *);
 void ofproto_reconfigure(struct ofproto *);
 void ofproto_run(struct ofproto *);
 void ofproto_wait(struct ofproto *);
index fd877e43c217de26d52f6f33e794ccdcade423ea..31254fb9b3e0e343d5055f33adc899911ab846fa 100644 (file)
@@ -42,7 +42,6 @@
 #include "queue.h"
 #include "random.h"
 #include "rconn.h"
-#include "secchan.h"
 #include "status.h"
 #include "timeval.h"
 #include "vconn.h"
diff --git a/secchan/secchan.c b/secchan/secchan.c
deleted file mode 100644 (file)
index 3411e4e..0000000
+++ /dev/null
@@ -1,489 +0,0 @@
-/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford
- * Junior University
- *
- * We are making the OpenFlow specification and associated documentation
- * (Software) available for public use and benefit with the expectation
- * that others will use, modify and enhance the Software and contribute
- * those enhancements back to the community. However, since we would
- * like to make the Software available for broadest use, with as few
- * restrictions as possible permission is hereby granted, free of
- * charge, to any person obtaining a copy of this Software to deal in
- * the Software under the copyrights without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * The name and trademarks of copyright holder(s) may NOT be used in
- * advertising or publicity pertaining to the Software or any
- * derivatives without specific, written prior permission.
- */
-
-#include <config.h>
-#include "secchan.h"
-#include <assert.h>
-#include <errno.h>
-#include <getopt.h>
-#include <inttypes.h>
-#include <netinet/in.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <string.h>
-
-#include "cfg.h"
-#include "command-line.h"
-#include "compiler.h"
-#include "daemon.h"
-#include "dirs.h"
-#include "discovery.h"
-#include "dpif.h"
-#include "fail-open.h"
-#include "fault.h"
-#include "in-band.h"
-#include "leak-checker.h"
-#include "list.h"
-#include "netdev.h"
-#include "ofpbuf.h"
-#include "ofproto.h"
-#include "openflow/openflow.h"
-#include "packets.h"
-#include "poll-loop.h"
-#include "rconn.h"
-#include "signals.h"
-#include "status.h"
-#include "timeval.h"
-#include "util.h"
-#include "vconn-ssl.h"
-#include "vconn.h"
-#include "vlog-socket.h"
-
-#include "vlog.h"
-#define THIS_MODULE VLM_secchan
-
-static void reconfigure(struct ofproto *);
-static void parse_options(int argc, char *argv[], struct settings *);
-static void usage(void) NO_RETURN;
-
-int
-main(int argc, char *argv[])
-{
-    struct signal *sighup;
-    struct ofproto *ofproto;
-    struct settings s;
-    int retval;
-
-    set_program_name(argv[0]);
-    register_fault_handlers();
-    time_init();
-    vlog_init();
-    parse_options(argc, argv, &s);
-    signal(SIGPIPE, SIG_IGN);
-    sighup = signal_register(SIGHUP);
-
-    die_if_already_running();
-    daemonize();
-
-    /* Start listening for vlogconf requests. */
-    retval = vlog_server_listen(NULL, NULL);
-    if (retval) {
-        ofp_fatal(retval, "Could not listen for vlog connections");
-    }
-
-    VLOG_INFO("OpenFlow reference implementation version %s", VERSION BUILDNR);
-    VLOG_INFO("OpenFlow protocol version 0x%02x", OFP_VERSION);
-
-    /* Start OpenFlow processing. */
-    ofproto = ofproto_create(&s);
-
-    reconfigure(ofproto);
-    while (ofproto_is_alive(ofproto)) {
-        if (signal_poll(sighup)) {
-            reconfigure(ofproto);
-        }
-
-        /* Do work. */
-        ofproto_run(ofproto);
-
-        /* Wait for something to happen. */
-        ofproto_wait(ofproto);
-        signal_wait(sighup);
-        poll_block();
-    }
-
-    return 0;
-}
-
-static void
-reconfigure(struct ofproto *ofproto)
-{
-    cfg_read();
-    ofproto_reconfigure(ofproto);
-}
-\f
-/* User interface. */
-
-static void
-parse_options(int argc, char *argv[], struct settings *s)
-{
-    enum {
-        OPT_DATAPATH_ID = UCHAR_MAX + 1,
-        OPT_MANUFACTURER,
-        OPT_HARDWARE,
-        OPT_SOFTWARE,
-        OPT_SERIAL,
-        OPT_ACCEPT_VCONN,
-        OPT_NO_RESOLV_CONF,
-        OPT_BR_NAME,
-        OPT_FAIL_MODE,
-        OPT_INACTIVITY_PROBE,
-        OPT_MAX_IDLE,
-        OPT_MAX_BACKOFF,
-        OPT_RATE_LIMIT,
-        OPT_BURST_LIMIT,
-        OPT_BOOTSTRAP_CA_CERT,
-        OPT_STP,
-        OPT_NO_STP,
-        OPT_OUT_OF_BAND,
-        OPT_IN_BAND,
-        OPT_COMMAND_ACL,
-        OPT_COMMAND_DIR,
-        VLOG_OPTION_ENUMS,
-        LEAK_CHECKER_OPTION_ENUMS
-    };
-    static struct option long_options[] = {
-        {"datapath-id", required_argument, 0, OPT_DATAPATH_ID},
-        {"manufacturer", required_argument, 0, OPT_MANUFACTURER},
-        {"hardware", required_argument, 0, OPT_HARDWARE},
-        {"software", required_argument, 0, OPT_SOFTWARE},
-        {"serial", required_argument, 0, OPT_SERIAL},
-        {"accept-vconn", required_argument, 0, OPT_ACCEPT_VCONN},
-        {"no-resolv-conf", no_argument, 0, OPT_NO_RESOLV_CONF},
-        {"config",      required_argument, 0, 'F'},
-        {"br-name",     required_argument, 0, OPT_BR_NAME},
-        {"fail",        required_argument, 0, OPT_FAIL_MODE},
-        {"inactivity-probe", required_argument, 0, OPT_INACTIVITY_PROBE},
-        {"max-idle",    required_argument, 0, OPT_MAX_IDLE},
-        {"max-backoff", required_argument, 0, OPT_MAX_BACKOFF},
-        {"listen",      required_argument, 0, 'l'},
-        {"rate-limit",  optional_argument, 0, OPT_RATE_LIMIT},
-        {"burst-limit", required_argument, 0, OPT_BURST_LIMIT},
-        {"stp",         no_argument, 0, OPT_STP},
-        {"no-stp",      no_argument, 0, OPT_NO_STP},
-        {"out-of-band", no_argument, 0, OPT_OUT_OF_BAND},
-        {"in-band",     no_argument, 0, OPT_IN_BAND},
-        {"command-acl", required_argument, 0, OPT_COMMAND_ACL},
-        {"command-dir", required_argument, 0, OPT_COMMAND_DIR},
-        {"verbose",     optional_argument, 0, 'v'},
-        {"help",        no_argument, 0, 'h'},
-        {"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},
-#endif
-        {0, 0, 0, 0},
-    };
-    char *short_options = long_options_to_short_options(long_options);
-
-    /* Set defaults that we can figure out before parsing options. */
-    s->datapath_id = 0;
-    s->mfr_desc = "Nicira Networks, Inc.";
-    s->hw_desc = "Reference Implementation";
-    s->sw_desc = VERSION BUILDNR;
-    s->serial_desc = "None";
-    s->n_listeners = 0;
-    s->fail_mode = FAIL_OPEN;
-    s->max_idle = 15;
-    s->probe_interval = 15;
-    s->max_backoff = 15;
-    s->update_resolv_conf = true;
-    s->rate_limit = 0;
-    s->burst_limit = 0;
-    s->accept_controller_re = NULL;
-    s->enable_stp = false;
-    s->in_band = true;
-    s->command_acl = "";
-    s->command_dir = xasprintf("%s/commands", ofp_pkgdatadir);
-    for (;;) {
-        int error;
-        int c;
-
-        c = getopt_long(argc, argv, short_options, long_options, NULL);
-        if (c == -1) {
-            break;
-        }
-
-        switch (c) {
-        case OPT_DATAPATH_ID:
-            if (strlen(optarg) != 12
-                || strspn(optarg, "0123456789abcdefABCDEF") != 12) {
-                ofp_fatal(0, "argument to --datapath-id must be "
-                          "exactly 12 hex digits");
-            }
-            s->datapath_id = strtoll(optarg, NULL, 16);
-            if (!s->datapath_id) {
-                ofp_fatal(0, "argument to --datapath-id must be nonzero");
-            }
-            break;
-
-        case OPT_MANUFACTURER:
-            s->mfr_desc = optarg;
-            break;
-
-        case OPT_HARDWARE:
-            s->hw_desc = optarg;
-            break;
-
-        case OPT_SOFTWARE:
-            s->sw_desc = optarg;
-            break;
-
-        case OPT_SERIAL:
-            s->serial_desc = optarg;
-            break;
-
-        case OPT_ACCEPT_VCONN:
-            s->accept_controller_re = (optarg[0] == '^' ? optarg
-                                       : xasprintf("^%s", optarg));
-            break;
-
-        case OPT_BR_NAME:
-            s->br_name = optarg;
-            break;
-
-        case OPT_NO_RESOLV_CONF:
-            s->update_resolv_conf = false;
-            break;
-
-        case OPT_FAIL_MODE:
-            if (!strcmp(optarg, "open")) {
-                s->fail_mode = FAIL_OPEN;
-            } else if (!strcmp(optarg, "closed")) {
-                s->fail_mode = FAIL_CLOSED;
-            } else {
-                ofp_fatal(0, "-f or --fail argument must be \"open\" "
-                          "or \"closed\"");
-            }
-            break;
-
-        case OPT_INACTIVITY_PROBE:
-            s->probe_interval = atoi(optarg);
-            if (s->probe_interval < 5) {
-                ofp_fatal(0, "--inactivity-probe argument must be at least 5");
-            }
-            break;
-
-        case OPT_MAX_IDLE:
-            if (!strcmp(optarg, "permanent")) {
-                s->max_idle = OFP_FLOW_PERMANENT;
-            } else {
-                s->max_idle = atoi(optarg);
-                if (s->max_idle < 1 || s->max_idle > 65535) {
-                    ofp_fatal(0, "--max-idle argument must be between 1 and "
-                              "65535 or the word 'permanent'");
-                }
-            }
-            break;
-
-        case OPT_MAX_BACKOFF:
-            s->max_backoff = atoi(optarg);
-            if (s->max_backoff < 1) {
-                ofp_fatal(0, "--max-backoff argument must be at least 1");
-            } else if (s->max_backoff > 3600) {
-                s->max_backoff = 3600;
-            }
-            break;
-
-        case OPT_RATE_LIMIT:
-            if (optarg) {
-                s->rate_limit = atoi(optarg);
-                if (s->rate_limit < 1) {
-                    ofp_fatal(0, "--rate-limit argument must be at least 1");
-                }
-            } else {
-                s->rate_limit = 1000;
-            }
-            break;
-
-        case OPT_BURST_LIMIT:
-            s->burst_limit = atoi(optarg);
-            if (s->burst_limit < 1) {
-                ofp_fatal(0, "--burst-limit argument must be at least 1");
-            }
-            break;
-
-        case OPT_STP:
-            s->enable_stp = true;
-            break;
-
-        case OPT_NO_STP:
-            s->enable_stp = false;
-            break;
-
-        case OPT_OUT_OF_BAND:
-            s->in_band = false;
-            break;
-
-        case OPT_IN_BAND:
-            s->in_band = true;
-            break;
-
-        case OPT_COMMAND_ACL:
-            s->command_acl = (s->command_acl[0]
-                              ? xasprintf("%s,%s", s->command_acl, optarg)
-                              : optarg);
-            break;
-
-        case OPT_COMMAND_DIR:
-            s->command_dir = optarg;
-            break;
-
-        case 'F':
-            error = cfg_add_file(optarg);
-            if (error) {
-                ofp_fatal(error, "failed to add configuration file or "
-                        "directory \"%s\"", optarg);
-            }
-            break;
-
-        case 'l':
-            if (s->n_listeners >= MAX_MGMT) {
-                ofp_fatal(0,
-                          "-l or --listen may be specified at most %d times",
-                          MAX_MGMT);
-            }
-            s->listener_names[s->n_listeners++] = optarg;
-            break;
-
-        case 'h':
-            usage();
-
-        case 'V':
-            printf("%s %s compiled "__DATE__" "__TIME__"\n",
-                   program_name, VERSION BUILDNR);
-            exit(EXIT_SUCCESS);
-
-        DAEMON_OPTION_HANDLERS
-
-        VLOG_OPTION_HANDLERS
-
-        LEAK_CHECKER_OPTION_HANDLERS
-
-#ifdef HAVE_OPENSSL
-        VCONN_SSL_OPTION_HANDLERS
-
-        case OPT_BOOTSTRAP_CA_CERT:
-            vconn_ssl_set_ca_cert_file(optarg, true);
-            break;
-#endif
-
-        case '?':
-            exit(EXIT_FAILURE);
-
-        default:
-            abort();
-        }
-    }
-    free(short_options);
-
-    argc -= optind;
-    argv += optind;
-    if (argc < 1 || argc > 2) {
-        ofp_fatal(0, "need one or two non-option arguments; "
-                  "use --help for usage");
-    }
-
-    /* Local and remote vconns. */
-    s->dp_name = argv[0];
-    s->controller_name = argc > 1 ? xstrdup(argv[1]) : NULL;
-
-    /* Set accept_controller_regex. */
-    if (!s->accept_controller_re) {
-        s->accept_controller_re = vconn_ssl_is_configured() ? "^ssl:.*" : ".*";
-    }
-
-    /* Mode of operation. */
-    s->discovery = s->controller_name == NULL;
-    if (s->discovery && !s->in_band) {
-        ofp_fatal(0, "Cannot perform discovery with out-of-band control");
-    }
-
-    /* Rate limiting. */
-    if (s->rate_limit) {
-        if (s->rate_limit < 100) {
-            VLOG_WARN("Rate limit set to unusually low value %d",
-                      s->rate_limit);
-        }
-        if (!s->burst_limit) {
-            s->burst_limit = s->rate_limit / 4;
-        }
-        s->burst_limit = MAX(s->burst_limit, 1);
-        s->burst_limit = MIN(s->burst_limit, INT_MAX / 1000);
-    }
-}
-
-static void
-usage(void)
-{
-    printf("%s: secure channel, a relay for OpenFlow messages.\n"
-           "usage: %s [OPTIONS] DATAPATH [CONTROLLER]\n"
-           "DATAPATH is a local datapath (e.g. \"dp0\").\n"
-           "CONTROLLER is an active OpenFlow connection method; if it is\n"
-           "omitted, then secchan performs controller discovery.\n",
-           program_name, program_name);
-    vconn_usage(true, true, true);
-    printf("\nConfiguration options:\n"
-           "  -F, --config=FILE|DIR   reads configuration from FILE or DIR\n"
-           "  --br-name=NAME          bridge name to use for configuration\n"
-           "\nOpenFlow options:\n"
-           "  -d, --datapath-id=ID    Use ID as the OpenFlow switch ID\n"
-           "                          (ID must consist of 12 hex digits)\n"
-           "  --manufacturer=MFR      Identify manufacturer as MFR\n"
-           "  --hardware=HW           Identify hardware as HW\n"
-           "  --software=SW           Identify software as SW\n"
-           "  --serial=SERIAL         Identify serial number as SERIAL\n"
-           "\nController discovery options:\n"
-           "  --accept-vconn=REGEX    accept matching discovered controllers\n"
-           "  --no-resolv-conf        do not update /etc/resolv.conf\n"
-           "\nNetworking options:\n"
-           "  --fail=open|closed      when controller connection fails:\n"
-           "                            closed: drop all packets\n"
-           "                            open (default): act as learning switch\n"
-           "  --inactivity-probe=SECS time between inactivity probes\n"
-           "  --max-idle=SECS         max idle for flows set up by secchan\n"
-           "  --max-backoff=SECS      max time between controller connection\n"
-           "                          attempts (default: 15 seconds)\n"
-           "  -l, --listen=METHOD     allow management connections on METHOD\n"
-           "                          (a passive OpenFlow connection method)\n"
-           "  --out-of-band           controller connection is out-of-band\n"
-           "  --stp                   enable 802.1D Spanning Tree Protocol\n"
-           "  --no-stp                disable 802.1D Spanning Tree Protocol\n"
-           "\nRate-limiting of \"packet-in\" messages to the controller:\n"
-           "  --rate-limit[=PACKETS]  max rate, in packets/s (default: 1000)\n"
-           "  --burst-limit=BURST     limit on packet credit for idle time\n"
-           "\nRemote command execution options:\n"
-           "  --command-acl=[!]GLOB[,[!]GLOB...] set allowed/denied commands\n"
-           "  --command-dir=DIR       set command dir (default: %s/commands)\n",
-           ofp_pkgdatadir);
-    daemon_usage();
-    vlog_usage();
-    printf("\nOther options:\n"
-           "  -h, --help              display this help message\n"
-           "  -V, --version           display version information\n");
-    leak_checker_usage();
-    exit(EXIT_SUCCESS);
-}
diff --git a/secchan/secchan.h b/secchan/secchan.h
deleted file mode 100644 (file)
index a8564b8..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford
- * Junior University
- *
- * We are making the OpenFlow specification and associated documentation
- * (Software) available for public use and benefit with the expectation
- * that others will use, modify and enhance the Software and contribute
- * those enhancements back to the community. However, since we would
- * like to make the Software available for broadest use, with as few
- * restrictions as possible permission is hereby granted, free of
- * charge, to any person obtaining a copy of this Software to deal in
- * the Software under the copyrights without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * The name and trademarks of copyright holder(s) may NOT be used in
- * advertising or publicity pertaining to the Software or any
- * derivatives without specific, written prior permission.
- */
-
-#ifndef SECCHAN_H
-#define SECCHAN_H 1
-
-#include <stdbool.h>
-#include <stddef.h>
-#include "list.h"
-
-/* Behavior when the connection to the controller fails. */
-enum fail_mode {
-    FAIL_OPEN,                  /* Act as learning switch. */
-    FAIL_CLOSED                 /* Drop all packets. */
-};
-
-/* Maximum number of management connection listeners. */
-#define MAX_MGMT 8
-
-/* Settings that may be configured by the user. */
-struct settings {
-    /* Configuration. */
-    const char *br_name;      /* Bridge name to use for configuration lookup */
-
-    /* Overall mode of operation. */
-    bool discovery;           /* Discover the controller automatically? */
-    bool in_band;             /* Connect to controller in-band? */
-
-    /* Datapath. */
-    uint64_t datapath_id;       /* Datapath ID. */
-    const char *dp_name;        /* Name of local datapath. */
-
-    /* Description strings. */
-    const char *mfr_desc;       /* Manufacturer. */
-    const char *hw_desc;        /* Hardware. */
-    const char *sw_desc;        /* Software version. */
-    const char *serial_desc;    /* Serial number. */
-
-    /* Related vconns and network devices. */
-    const char *controller_name; /* Controller (if not discovery mode). */
-    const char *listener_names[MAX_MGMT]; /* Listen for mgmt connections. */
-    size_t n_listeners;          /* Number of mgmt connection listeners. */
-
-    /* Failure behavior. */
-    enum fail_mode fail_mode; /* Act as learning switch if no controller? */
-    int max_idle;             /* Idle time for flows in fail-open mode. */
-    int probe_interval;       /* # seconds idle before sending echo request. */
-    int max_backoff;          /* Max # seconds between connection attempts. */
-
-    /* Packet-in rate-limiting. */
-    int rate_limit;           /* Tokens added to bucket per second. */
-    int burst_limit;          /* Maximum number token bucket size. */
-
-    /* Discovery behavior. */
-    const char *accept_controller_re; /* Controller vconns to accept. */
-    bool update_resolv_conf;          /* Update /etc/resolv.conf? */
-
-    /* Spanning tree protocol. */
-    bool enable_stp;
-
-    /* Remote command execution. */
-    char *command_acl;          /* Command white/blacklist, as shell globs. */
-    char *command_dir;          /* Directory that contains commands. */
-};
-
-#endif /* secchan.h */
index fd57e514bdc956cd2533c49ecf573b5123b2e0a0..3f9b0f4bb1908ad66b9dfc5f36fce3d706957f76 100644 (file)
@@ -39,9 +39,9 @@
 #include <unistd.h>
 #include "dynamic-string.h"
 #include "ofpbuf.h"
+#include "ofproto.h"
 #include "openflow/nicira-ext.h"
 #include "rconn.h"
-#include "secchan.h"
 #include "timeval.h"
 #include "vconn.h"
 
@@ -126,7 +126,7 @@ rconn_status_cb(struct status_reply *sr, void *rconn_)
 static void
 config_status_cb(struct status_reply *sr, void *s_)
 {
-    const struct settings *s = s_;
+    const struct ofsettings *s = s_;
     size_t i;
 
     for (i = 0; i < s->n_listeners; i++) {
@@ -152,7 +152,7 @@ switch_status_cb(struct status_reply *sr, void *ss_)
 }
 
 struct switch_status *
-switch_status_create(const struct settings *settings)
+switch_status_create(const struct ofsettings *settings)
 {
     struct switch_status *ss = xcalloc(1, sizeof *ss);
     ss->booted = time_now();
index dbb0300a6dee80b33435cae871c8eddaacf921a3..f87662066940a4df007bf2f91239b8fe0dba17cc 100644 (file)
 struct nicira_header;
 struct rconn;
 struct secchan;
-struct settings;
+struct ofsettings;
 struct status_reply;
 
-struct switch_status *switch_status_create(const struct settings *);
+struct switch_status *switch_status_create(const struct ofsettings *);
 
 int switch_status_handle_request(struct switch_status *, struct rconn *,
                                  struct nicira_header *);