Add "Manager" and "manager_options" to allow options for OVSDB connections.
authorBen Pfaff <blp@nicira.com>
Fri, 5 Nov 2010 17:22:18 +0000 (10:22 -0700)
committerBen Pfaff <blp@nicira.com>
Fri, 5 Nov 2010 17:22:18 +0000 (10:22 -0700)
I'm retaining the "managers" column in the Open_vSwitch table for now, but
I hope that applications transition to using "manager_options" eventually
so that we could drop it.

CC: Andrew Lambeth <wal@nicira.com>
CC: Jeremy Stribling <strib@nicira.com>
12 files changed:
lib/jsonrpc.c
lib/jsonrpc.h
ovsdb/jsonrpc-server.c
ovsdb/jsonrpc-server.h
ovsdb/ovsdb-server.1.in
ovsdb/ovsdb-server.c
utilities/ovs-vsctl.8.in
utilities/ovs-vsctl.c
vswitchd/bridge.c
vswitchd/vswitch.ovsschema
vswitchd/vswitch.pic
vswitchd/vswitch.xml

index 52e9772..a83dde9 100644 (file)
@@ -946,3 +946,16 @@ jsonrpc_session_force_reconnect(struct jsonrpc_session *s)
 {
     reconnect_force_reconnect(s->reconnect, time_msec());
 }
+
+void
+jsonrpc_session_set_max_backoff(struct jsonrpc_session *s, int max_backoff)
+{
+    reconnect_set_backoff(s->reconnect, 0, max_backoff);
+}
+
+void
+jsonrpc_session_set_probe_interval(struct jsonrpc_session *s,
+                                   int probe_interval)
+{
+    reconnect_set_probe_interval(s->reconnect, probe_interval);
+}
index 154c459..d95148c 100644 (file)
@@ -115,4 +115,9 @@ bool jsonrpc_session_is_connected(const struct jsonrpc_session *);
 unsigned int jsonrpc_session_get_seqno(const struct jsonrpc_session *);
 void jsonrpc_session_force_reconnect(struct jsonrpc_session *);
 
+void jsonrpc_session_set_max_backoff(struct jsonrpc_session *,
+                                     int max_backofF);
+void jsonrpc_session_set_probe_interval(struct jsonrpc_session *,
+                                        int probe_interval);
+
 #endif /* jsonrpc.h */
index 3c439ee..a59a590 100644 (file)
@@ -51,6 +51,8 @@ static void ovsdb_jsonrpc_session_run_all(struct ovsdb_jsonrpc_remote *);
 static void ovsdb_jsonrpc_session_wait_all(struct ovsdb_jsonrpc_remote *);
 static void ovsdb_jsonrpc_session_close_all(struct ovsdb_jsonrpc_remote *);
 static void ovsdb_jsonrpc_session_reconnect_all(struct ovsdb_jsonrpc_remote *);
+static void ovsdb_jsonrpc_session_set_all_options(
+    struct ovsdb_jsonrpc_remote *, const struct ovsdb_jsonrpc_options *);
 
 /* Triggers. */
 static void ovsdb_jsonrpc_trigger_create(struct ovsdb_jsonrpc_session *,
@@ -88,8 +90,8 @@ struct ovsdb_jsonrpc_remote {
     struct list sessions;       /* List of "struct ovsdb_jsonrpc_session"s. */
 };
 
-static void ovsdb_jsonrpc_server_add_remote(struct ovsdb_jsonrpc_server *,
-                                            const char *name);
+static struct ovsdb_jsonrpc_remote *ovsdb_jsonrpc_server_add_remote(
+    struct ovsdb_jsonrpc_server *, const char *name);
 static void ovsdb_jsonrpc_server_del_remote(struct shash_node *);
 
 struct ovsdb_jsonrpc_server *
@@ -114,8 +116,17 @@ ovsdb_jsonrpc_server_destroy(struct ovsdb_jsonrpc_server *svr)
     free(svr);
 }
 
-/* Sets 'svr''s current set of remotes to the names in 'new_remotes'.  The data
- * values in 'new_remotes' are ignored.
+struct ovsdb_jsonrpc_options *
+ovsdb_jsonrpc_default_options(void)
+{
+    struct ovsdb_jsonrpc_options *options = xzalloc(sizeof *options);
+    options->probe_interval = RECONNECT_DEFAULT_PROBE_INTERVAL;
+    options->max_backoff = RECONNECT_DEFAULT_MAX_BACKOFF;
+    return options;
+}
+
+/* Sets 'svr''s current set of remotes to the names in 'new_remotes', with
+ * options in the struct ovsdb_jsonrpc_options supplied as the data values.
  *
  * A remote is an active or passive stream connection method, e.g. "pssl:" or
  * "tcp:1.2.3.4". */
@@ -131,13 +142,22 @@ ovsdb_jsonrpc_server_set_remotes(struct ovsdb_jsonrpc_server *svr,
         }
     }
     SHASH_FOR_EACH (node, new_remotes) {
-        if (!shash_find(&svr->remotes, node->name)) {
-            ovsdb_jsonrpc_server_add_remote(svr, node->name);
+        const struct ovsdb_jsonrpc_options *options = node->data;
+        struct ovsdb_jsonrpc_remote *remote;
+
+        remote = shash_find_data(&svr->remotes, node->name);
+        if (!remote) {
+            remote = ovsdb_jsonrpc_server_add_remote(svr, node->name);
+            if (!remote) {
+                continue;
+            }
         }
+
+        ovsdb_jsonrpc_session_set_all_options(remote, options);
     }
 }
 
-static void
+static struct ovsdb_jsonrpc_remote *
 ovsdb_jsonrpc_server_add_remote(struct ovsdb_jsonrpc_server *svr,
                                 const char *name)
 {
@@ -148,7 +168,7 @@ ovsdb_jsonrpc_server_add_remote(struct ovsdb_jsonrpc_server *svr,
     error = jsonrpc_pstream_open(name, &listener);
     if (error && error != EAFNOSUPPORT) {
         VLOG_ERR_RL(&rl, "%s: listen failed: %s", name, strerror(error));
-        return;
+        return NULL;
     }
 
     remote = xmalloc(sizeof *remote);
@@ -160,6 +180,7 @@ ovsdb_jsonrpc_server_add_remote(struct ovsdb_jsonrpc_server *svr,
     if (!listener) {
         ovsdb_jsonrpc_session_create(remote, jsonrpc_session_open(name));
     }
+    return remote;
 }
 
 static void
@@ -252,6 +273,8 @@ struct ovsdb_jsonrpc_session {
 static void ovsdb_jsonrpc_session_close(struct ovsdb_jsonrpc_session *);
 static int ovsdb_jsonrpc_session_run(struct ovsdb_jsonrpc_session *);
 static void ovsdb_jsonrpc_session_wait(struct ovsdb_jsonrpc_session *);
+static void ovsdb_jsonrpc_session_set_options(
+    struct ovsdb_jsonrpc_session *, const struct ovsdb_jsonrpc_options *);
 static void ovsdb_jsonrpc_session_got_request(struct ovsdb_jsonrpc_session *,
                                              struct jsonrpc_msg *);
 static void ovsdb_jsonrpc_session_got_notify(struct ovsdb_jsonrpc_session *,
@@ -318,6 +341,14 @@ ovsdb_jsonrpc_session_run(struct ovsdb_jsonrpc_session *s)
     return jsonrpc_session_is_alive(s->js) ? 0 : ETIMEDOUT;
 }
 
+static void
+ovsdb_jsonrpc_session_set_options(struct ovsdb_jsonrpc_session *session,
+                                  const struct ovsdb_jsonrpc_options *options)
+{
+    jsonrpc_session_set_max_backoff(session->js, options->max_backoff);
+    jsonrpc_session_set_probe_interval(session->js, options->probe_interval);
+}
+
 static void
 ovsdb_jsonrpc_session_run_all(struct ovsdb_jsonrpc_remote *remote)
 {
@@ -375,6 +406,20 @@ ovsdb_jsonrpc_session_reconnect_all(struct ovsdb_jsonrpc_remote *remote)
     }
 }
 
+/* Sets the options for all of the JSON-RPC sessions managed by 'remote' to
+ * 'options'. */
+static void
+ovsdb_jsonrpc_session_set_all_options(
+    struct ovsdb_jsonrpc_remote *remote,
+    const struct ovsdb_jsonrpc_options *options)
+{
+    struct ovsdb_jsonrpc_session *s;
+
+    LIST_FOR_EACH (s, node, &remote->sessions) {
+        ovsdb_jsonrpc_session_set_options(s, options);
+    }
+}
+
 static const char *
 get_db_name(const struct ovsdb_jsonrpc_session *s)
 {
index 66dfa97..9906e81 100644 (file)
@@ -22,6 +22,13 @@ struct shash;
 struct ovsdb_jsonrpc_server *ovsdb_jsonrpc_server_create(struct ovsdb *);
 void ovsdb_jsonrpc_server_destroy(struct ovsdb_jsonrpc_server *);
 
+/* Options for a remote. */
+struct ovsdb_jsonrpc_options {
+    int max_backoff;            /* Maximum reconnection backoff, in msec. */
+    int probe_interval;         /* Max idle time before probing, in msec. */
+};
+struct ovsdb_jsonrpc_options *ovsdb_jsonrpc_default_options(void);
+
 void ovsdb_jsonrpc_server_set_remotes(struct ovsdb_jsonrpc_server *,
                                       const struct shash *);
 
index d7beba7..79a39c6 100644 (file)
@@ -41,11 +41,31 @@ Adds \fIremote\fR as a connection method used by \fBovsdb\-server\fR.
 .
 .IP "\fBdb:\fItable\fB,\fIcolumn\fR"
 Reads additional connection methods from \fIcolumn\fR in all of the
-rows in \fItable\fR within the \fBovsdb\-server\fR database.  The
-\fIcolumn\fR must have type string or set of strings.  The connection
-methods in the column must have one of the forms described above.  As
-the contents of \fIcolumn\fR changes, \fBovsdb\-server\fR also adds
-and drops connection methods accordingly.
+rows in \fItable\fR.  As the contents of \fIcolumn\fR changes,
+\fBovsdb\-server\fR also adds and drops connection methods
+accordingly.
+.IP
+If \fIcolumn\fR's type is string or set of strings, then the
+connection methods are taken directly from the column.  The connection
+methods in the column must have one of the forms described above.
+.IP
+If \fIcolumn\fR's type is UUID or set of UUIDs and references a table,
+then each UUID is looked up in the referenced table to obtain a row.
+The following columns in the row, if present and of the correct type,
+configure a connection method.  Any additional columns are ignored.
+.RS
+.IP "\fBtarget\fR (string)"
+Connection method, in one of the forms described above.  This column
+is mandatory: if it is missing or empty then no connection method can
+be configured.
+.IP "\fBmax_backoff\fR (integer)"
+Maximum number of milliseconds to wait between connection attempts.
+.IP "\fBinactivity_probe\fR (integer)
+Maximum number of milliseconds of idle time on connection to
+client before sending an inactivity probe message.
+.RE
+.IP
+It is an error for \fIcolumn\fR to have another type.
 .RE
 .
 .IP "\fB\-\-run=\fIcommand\fR]"
index 45d7a77..872cc9f 100644 (file)
@@ -168,10 +168,10 @@ main(int argc, char *argv[])
 }
 
 static void
-parse_db_string_column(const struct ovsdb *db,
-                       const char *name_,
-                       const struct ovsdb_table **tablep,
-                       const struct ovsdb_column **columnp)
+parse_db_column(const struct ovsdb *db,
+                const char *name_,
+                const struct ovsdb_table **tablep,
+                const struct ovsdb_column **columnp)
 {
     char *name, *table_name, *column_name;
     const struct ovsdb_column *column;
@@ -198,11 +198,26 @@ parse_db_string_column(const struct ovsdb *db,
     }
     free(name);
 
+    *columnp = column;
+    *tablep = table;
+}
+
+static void
+parse_db_string_column(const struct ovsdb *db,
+                       const char *name,
+                       const struct ovsdb_table **tablep,
+                       const struct ovsdb_column **columnp)
+{
+    const struct ovsdb_column *column;
+    const struct ovsdb_table *table;
+
+    parse_db_column(db, name, &table, &column);
+
     if (column->type.key.type != OVSDB_TYPE_STRING
         || column->type.value.type != OVSDB_TYPE_VOID) {
         ovs_fatal(0, "\"%s\": table \"%s\" column \"%s\" is "
                   "not string or set of strings",
-                  name_, table->schema->name, column->name);
+                  name, table->schema->name, column->name);
     }
 
     *columnp = column;
@@ -238,6 +253,99 @@ query_db_string(const struct ovsdb *db, const char *name)
 }
 #endif /* HAVE_OPENSSL */
 
+static struct ovsdb_jsonrpc_options *
+add_remote(struct shash *remotes, const char *target)
+{
+    struct ovsdb_jsonrpc_options *options;
+
+    options = shash_find_data(remotes, target);
+    if (!options) {
+        options = ovsdb_jsonrpc_default_options();
+        shash_add(remotes, target, options);
+    }
+
+    return options;
+}
+
+static const union ovsdb_atom *
+read_column(const struct ovsdb_row *row, const char *column_name,
+            enum ovsdb_atomic_type type)
+{
+    static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+    const struct ovsdb_table_schema *schema = row->table->schema;
+    const struct ovsdb_column *column;
+    const struct ovsdb_datum *datum;
+
+    column = ovsdb_table_schema_get_column(schema, column_name);
+    if (!column) {
+        VLOG_DBG_RL(&rl, "Table `%s' has no `%s' column",
+                    schema->name, column_name);
+        return false;
+    }
+
+    if (column->type.key.type != type
+        || column->type.value.type != OVSDB_TYPE_VOID
+        || column->type.n_max != 1) {
+        if (!VLOG_DROP_DBG(&rl)) {
+            char *type_name = ovsdb_type_to_english(&column->type);
+            VLOG_DBG("Table `%s' column `%s' has type %s, not expected "
+                     "type %s.", schema->name, column_name, type_name,
+                     ovsdb_atomic_type_to_string(type));
+        }
+        return false;
+    }
+
+    datum = &row->fields[column->index];
+    return datum->n ? datum->keys : NULL;
+}
+
+static bool
+read_integer_column(const struct ovsdb_row *row, const char *column_name,
+                    long long int *integerp)
+{
+    const union ovsdb_atom *atom;
+
+    atom = read_column(row, column_name, OVSDB_TYPE_INTEGER);
+    *integerp = atom ? atom->integer : 0;
+    return atom != NULL;
+}
+
+static bool
+read_string_column(const struct ovsdb_row *row, const char *column_name,
+                   const char **stringp)
+{
+    const union ovsdb_atom *atom;
+
+    atom = read_column(row, column_name, OVSDB_TYPE_STRING);
+    *stringp = atom ? atom->string : 0;
+    return atom != NULL;
+}
+
+/* Adds a remote and options to 'remotes', based on the Manager table row in
+ * 'row'. */
+static void
+add_manager_options(struct shash *remotes, const struct ovsdb_row *row)
+{
+    static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+    struct ovsdb_jsonrpc_options *options;
+    long long int max_backoff, probe_interval;
+    const char *target;
+
+    if (!read_string_column(row, "target", &target) || !target) {
+        VLOG_INFO_RL(&rl, "Table `%s' has missing or invalid `target' column",
+                     row->table->schema->name);
+        return;
+    }
+
+    options = add_remote(remotes, target);
+    if (read_integer_column(row, "max_backoff", &max_backoff)) {
+        options->max_backoff = max_backoff;
+    }
+    if (read_integer_column(row, "probe_interval", &probe_interval)) {
+        options->probe_interval = probe_interval;
+    }
+}
+
 static void
 query_db_remotes(const char *name, const struct ovsdb *db,
                  struct shash *remotes)
@@ -246,15 +354,36 @@ query_db_remotes(const char *name, const struct ovsdb *db,
     const struct ovsdb_table *table;
     const struct ovsdb_row *row;
 
-    parse_db_string_column(db, name, &table, &column);
+    parse_db_column(db, name, &table, &column);
 
-    HMAP_FOR_EACH (row, hmap_node, &table->rows) {
-        const struct ovsdb_datum *datum;
-        size_t i;
+    if (column->type.key.type == OVSDB_TYPE_STRING
+        && column->type.value.type == OVSDB_TYPE_VOID) {
+        HMAP_FOR_EACH (row, hmap_node, &table->rows) {
+            const struct ovsdb_datum *datum;
+            size_t i;
+
+            datum = &row->fields[column->index];
+            for (i = 0; i < datum->n; i++) {
+                add_remote(remotes, datum->keys[i].string);
+            }
+        }
+    } else if (column->type.key.type == OVSDB_TYPE_UUID
+               && column->type.key.u.uuid.refTable
+               && column->type.value.type == OVSDB_TYPE_VOID) {
+        const struct ovsdb_table *ref_table = column->type.key.u.uuid.refTable;
+        HMAP_FOR_EACH (row, hmap_node, &table->rows) {
+            const struct ovsdb_datum *datum;
+            size_t i;
+
+            datum = &row->fields[column->index];
+            for (i = 0; i < datum->n; i++) {
+                const struct ovsdb_row *ref_row;
 
-        datum = &row->fields[column->index];
-        for (i = 0; i < datum->n; i++) {
-            shash_add_once(remotes, datum->keys[i].string, NULL);
+                ref_row = ovsdb_table_get_row(ref_table, &datum->keys[i].uuid);
+                if (ref_row) {
+                    add_manager_options(remotes, ref_row);
+                }
+            }
         }
     }
 }
@@ -275,7 +404,7 @@ reconfigure_from_db(struct ovsdb_jsonrpc_server *jsonrpc,
         if (!strncmp(name, "db:", 3)) {
             query_db_remotes(name, db, &resolved_remotes);
         } else {
-            shash_add_once(&resolved_remotes, name, NULL);
+            add_remote(&resolved_remotes, name);
         }
     }
     ovsdb_jsonrpc_server_set_remotes(jsonrpc, &resolved_remotes);
index 281756c..d478824 100644 (file)
@@ -450,6 +450,9 @@ identified by mirror name.
 .IP "\fBController\fR"
 Configuration for an OpenFlow controller.  A controller attached to a
 particular bridge may be identified by the bridge's name.
+.IP "\fBManager\fR"
+Configuration for an OVSDB connection.  Records may be identified
+by target (e.g. \fBtcp:1.2.3.4\fR).
 .IP "\fBNetFlow\fR"
 A NetFlow configuration attached to a bridge.  Records may be
 identified by bridge name.
index 4f346f1..b8e6470 100644 (file)
@@ -1852,6 +1852,10 @@ static const struct vsctl_table_class tables[] = {
      {{&ovsrec_table_mirror, &ovsrec_mirror_col_name, NULL},
       {NULL, NULL, NULL}}},
 
+    {&ovsrec_table_manager,
+     {{&ovsrec_table_manager, &ovsrec_manager_col_target, NULL},
+      {NULL, NULL, NULL}}},
+
     {&ovsrec_table_netflow,
      {{&ovsrec_table_bridge,
        &ovsrec_bridge_col_name,
index 53a24e3..5085703 100644 (file)
@@ -533,30 +533,52 @@ iterate_and_prune_ifaces(struct bridge *br,
  * should not be and in fact is not directly involved in that.  But
  * ovs-vswitchd needs to make sure that ovsdb-server can reach the managers, so
  * it has to tell in-band control where the managers are to enable that.
+ * (Thus, only managers connected in-band are collected.)
  */
 static void
-collect_managers(const struct ovsrec_open_vswitch *ovs_cfg,
-                 struct sockaddr_in **managersp, size_t *n_managersp)
+collect_in_band_managers(const struct ovsrec_open_vswitch *ovs_cfg,
+                         struct sockaddr_in **managersp, size_t *n_managersp)
 {
     struct sockaddr_in *managers = NULL;
     size_t n_managers = 0;
+    struct shash targets;
+    size_t i;
 
-    if (ovs_cfg->n_managers > 0) {
-        size_t i;
+    /* Collect all of the potential targets, as the union of the "managers"
+     * column and the "targets" columns of the rows pointed to by
+     * "manager_options", excluding any that are out-of-band. */
+    shash_init(&targets);
+    for (i = 0; i < ovs_cfg->n_managers; i++) {
+        shash_add_once(&targets, ovs_cfg->managers[i], NULL);
+    }
+    for (i = 0; i < ovs_cfg->n_manager_options; i++) {
+        struct ovsrec_manager *m = ovs_cfg->manager_options[i];
+
+        if (m->connection_mode && !strcmp(m->connection_mode, "out-of-band")) {
+            shash_find_and_delete(&targets, m->target);
+        } else {
+            shash_add_once(&targets, m->target, NULL);
+        }
+    }
+
+    /* Now extract the targets' IP addresses. */
+    if (!shash_is_empty(&targets)) {
+        struct shash_node *node;
 
-        managers = xmalloc(ovs_cfg->n_managers * sizeof *managers);
-        for (i = 0; i < ovs_cfg->n_managers; i++) {
-            const char *name = ovs_cfg->managers[i];
-            struct sockaddr_in *sin = &managers[i];
+        managers = xmalloc(shash_count(&targets) * sizeof *managers);
+        SHASH_FOR_EACH (node, &targets) {
+            const char *target = node->name;
+            struct sockaddr_in *sin = &managers[n_managers];
 
-            if ((!strncmp(name, "tcp:", 4)
-                 && inet_parse_active(name + 4, JSONRPC_TCP_PORT, sin)) ||
-                (!strncmp(name, "ssl:", 4)
-                 && inet_parse_active(name + 4, JSONRPC_SSL_PORT, sin))) {
+            if ((!strncmp(target, "tcp:", 4)
+                 && inet_parse_active(target + 4, JSONRPC_TCP_PORT, sin)) ||
+                (!strncmp(target, "ssl:", 4)
+                 && inet_parse_active(target + 4, JSONRPC_SSL_PORT, sin))) {
                 n_managers++;
             }
         }
     }
+    shash_destroy(&targets);
 
     *managersp = managers;
     *n_managersp = n_managers;
@@ -575,7 +597,7 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
 
     COVERAGE_INC(bridge_reconfigure);
 
-    collect_managers(ovs_cfg, &managers, &n_managers);
+    collect_in_band_managers(ovs_cfg, &managers, &n_managers);
 
     /* Collect old and new bridges. */
     shash_init(&old_br);
index 0be1b17..05a2e05 100644 (file)
@@ -8,6 +8,10 @@
                   "min": 0, "max": "unlimited"}},
        "managers": {
          "type": {"key": "string", "min": 0, "max": "unlimited"}},
+       "manager_options": {
+         "type": {"key": {"type": "uuid",
+                          "refTable": "Manager"},
+                  "min": 0, "max": "unlimited"}},
        "ssl": {
          "type": {"key": {"type": "uuid",
                           "refTable": "SSL"},
        "external_ids": {
          "type": {"key": "string", "value": "string",
                   "min": 0, "max": "unlimited"}}}},
+   "Manager": {
+     "columns": {
+       "target": {
+         "type": "string"},
+       "max_backoff": {
+         "type": {"key": {"type": "integer",
+                          "minInteger": 1000},
+                  "min": 0, "max": 1}},
+       "inactivity_probe": {
+         "type": {"key": "integer", "min": 0, "max": 1}},
+       "connection_mode": {
+         "type": {"key": {"type": "string",
+                  "enum": ["set", ["in-band", "out-of-band"]]},
+                  "min": 0, "max": 1}},
+       "external_ids": {
+         "type": {"key": "string", "value": "string",
+                  "min": 0, "max": "unlimited"}}}},
    "SSL": {
      "columns": {
        "private_key": {
index 67c3338..871f3e4 100644 (file)
-.\"  Creator: Graphviz version 2.20.2 (Sun Oct 12 22:28:10 UTC 2008)
-.\"  For: (blp) Ben Pfaff,,,
-.\"  Title: Open_vSwitch
-.\"  save point size and font
-.nr .S \n(.s
-.nr DF \n(.f
-.PS 6.50000 3.59722
-# to change drawing size, multiply the width and height on the .PS line above and the number on the two lines below (rounded to the nearest integer) by a scale factor
-.nr SF 6500
-scalethickness = 6500
-# don't change anything below this line in this drawing
-# non-fatal run-time pic version determination, version 2
-boxrad=2.0 # will be reset to 0.0 by gpic only
-scale=1.0 # required for comparisons
-# boxrad is now 0.0 in gpic, else it remains 2.0
-# dashwid is 0.1 in 10th Edition, 0.05 in DWB 2 and in gpic
-# fillval is 0.3 in 10th Edition (fill 0 means black), 0.5 in gpic (fill 0 means white), undefined in DWB 2
-# fill has no meaning in DWB 2, gpic can use fill or filled, 10th Edition uses fill only
-# DWB 2 doesn't use fill and doesn't define fillval
-# reset works in gpic and 10th edition, but isn't defined in DWB 2
-# DWB 2 compatibility definitions
-if boxrad > 1.0 && dashwid < 0.075 then X
-       fillval = 1;
-       define fill Y Y;
-       define solid Y Y;
-       define reset Y scale=1.0 Y;
-X
-reset # set to known state
-# GNU pic vs. 10th Edition d\(e'tente
-if fillval > 0.4 then X
-       define setfillval Y fillval = 1 - Y;
-       define bold Y thickness 2 Y;
-       # if you use gpic and it barfs on encountering "solid",
-       #       install a more recent version of gpic or switch to DWB or 10th Edition pic;
-       #       sorry, the groff folks changed gpic; send any complaint to them;
-X else Z
-       define setfillval Y fillval = Y;
-       define bold Y Y;
-       define filled Y fill Y;
-Z
-# arrowhead has no meaning in DWB 2, arrowhead = 7 makes filled arrowheads in gpic and in 10th Edition
-# arrowhead is undefined in DWB 2, initially 1 in gpic, 2 in 10th Edition
-arrowhead = 7 # not used by graphviz
-# GNU pic supports a boxrad variable to draw boxes with rounded corners; DWB and 10th Ed. do not
-boxrad = 0 # no rounded corners in graphviz
-# GNU pic supports a linethick variable to set line thickness; DWB and 10th Ed. do not
-linethick = 1; oldlinethick = linethick
-# .PS w/o args causes GNU pic to scale drawing to fit 8.5x11 paper; DWB does not
-# maxpsht and maxpswid have no meaning in DWB 2.0, set page boundaries in gpic and in 10th Edition
-# maxpsht and maxpswid are predefined to 11.0 and 8.5 in gpic
-maxpsht = 3.597222
-maxpswid = 6.500000
-Dot: [
-define attrs0 % %; define unfilled % %; define rounded % %; define diagonals % %
-setfillval 0.000000
-setfillval 0.827451
-.ft R 
-.ps 8*\n(SFu/6500u
-setfillval 1.000000
-setfillval 1.000000
-setfillval 1.000000
-{
-define attrs1 % %
-#      Bridge
-setfillval 0.000000
-box attrs1 wid 0.53352 ht 0.32011 at (2.19631,2.56088);
-{
-define attrs2 % %
-setfillval 0.000000
-"Bridge" at (2.19631,2.55791);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      sFlow
-setfillval 0.000000
-box attrs1 wid 0.49795 ht 0.32011 at (0.24897,1.76060);
-{
-define attrs2 % %
-setfillval 0.000000
-"sFlow" at (0.24897,1.75764);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Bridge -> sFlow
-setfillval 0.000000
-setfillval 0.000000
-P0: (1.92955,2.52531)
-P1: (1.84522,2.51062)
-P2: (1.75320,2.49315)
-P3: (1.65489,2.47281)
-P4: (1.55168,2.44948)
-P5: (1.44494,2.42305)
-P6: (1.33607,2.39342)
-P7: (1.22645,2.36049)
-P8: (1.11747,2.32414)
-P9: (1.01051,2.28427)
-P10: (0.90698,2.24077)
-P11: (0.86432,2.21866)
-P12: (0.82183,2.19517)
-P13: (0.77965,2.17050)
-P14: (0.73796,2.14488)
-P15: (0.69690,2.11850)
-P16: (0.65665,2.09160)
-P17: (0.61736,2.06437)
-P18: (0.57918,2.03703)
-P19: (0.54229,2.00981)
-P20: (0.50684,1.98290)
-move to P0; line attrs1 to P1 then to P2
-move to P2; line attrs1 to P3 then to P4
-move to P4; line attrs1 to P5 then to P6
-move to P6; line attrs1 to P7 then to P8
-move to P8; line attrs1 to P9 then to P10
-move to P10; line attrs1 to P11 then to P12
-move to P12; line attrs1 to P13 then to P14
-move to P14; line attrs1 to P15 then to P16
-move to P16; line attrs1 to P17 then to P18
-move to P18; line attrs1 to P19 then to P20
-{
-define attrs2 % %
-define attrs2 % solid %
-oldlinethick = linethick;linethick = 1 * scalethickness / 10153
-P0: (0.52462,1.95622)
-P1: (0.43570,1.92066)
-P2: (0.48016,2.00068)
-move to P0; line attrs2 to P1
-move to P1; line attrs2 to P2
-move to P2; line attrs2 to P0
-}
-linethick = oldlinethick
-{
-define attrs2 % %
-setfillval 0.000000
-"sflow" at (1.12483,2.15777);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Mirror
-setfillval 0.000000
-box attrs1 wid 0.51573 ht 0.32011 at (1.73393,1.76060);
-{
-define attrs2 % %
-setfillval 0.000000
-"Mirror" at (1.73393,1.75764);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Bridge -> Mirror
-setfillval 0.000000
-setfillval 0.000000
-P0: (2.09850,2.40082)
-P1: (2.08807,2.38482)
-P2: (2.07808,2.36881)
-P3: (2.06840,2.35280)
-P4: (2.05894,2.33680)
-P5: (2.04959,2.32079)
-P6: (2.04024,2.30479)
-P7: (2.03077,2.28878)
-P8: (2.02110,2.27278)
-P9: (2.01111,2.25677)
-P10: (2.00068,2.24077)
-P11: (1.98735,2.21676)
-P12: (1.97401,2.19275)
-P13: (1.96067,2.16874)
-P14: (1.94733,2.14473)
-P15: (1.93399,2.12073)
-P16: (1.92066,2.09672)
-P17: (1.90732,2.07271)
-P18: (1.89398,2.04870)
-P19: (1.88064,2.02469)
-P20: (1.86731,2.00068)
-move to P0; line attrs1 to P1 then to P2
-move to P2; line attrs1 to P3 then to P4
-move to P4; line attrs1 to P5 then to P6
-move to P6; line attrs1 to P7 then to P8
-move to P8; line attrs1 to P9 then to P10
-move to P10; line attrs1 to P11 then to P12
-move to P12; line attrs1 to P13 then to P14
-move to P14; line attrs1 to P15 then to P16
-move to P16; line attrs1 to P17 then to P18
-move to P18; line attrs1 to P19 then to P20
-{
-define attrs2 % %
-define attrs2 % solid %
-oldlinethick = linethick;linethick = 1 * scalethickness / 10153
-P0: (1.89398,1.98290)
-P1: (1.82285,1.92066)
-P2: (1.84063,2.00958)
-move to P0; line attrs2 to P1
-move to P1; line attrs2 to P2
-move to P2; line attrs2 to P0
-}
-linethick = oldlinethick
-{
-define attrs2 % %
-setfillval 0.000000
-"mirrors" at (2.24966,2.15777);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Port
-setfillval 0.000000
-box attrs1 wid 0.48016 ht 0.32011 at (3.31669,1.76060);
-{
-define attrs2 % %
-setfillval 0.000000
-"Port" at (3.31224,1.75764);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Bridge -> Port
-setfillval 0.000000
-setfillval 0.000000
-P0: (2.37415,2.40082)
-P1: (2.40743,2.37073)
-P2: (2.44300,2.33936)
-P3: (2.48050,2.30703)
-P4: (2.51955,2.27406)
-P5: (2.55976,2.24077)
-P6: (2.60078,2.20747)
-P7: (2.64223,2.17450)
-P8: (2.68373,2.14217)
-P9: (2.72490,2.11080)
-P10: (2.76539,2.08071)
-P11: (2.78699,2.06471)
-P12: (2.80907,2.04877)
-P13: (2.83157,2.03294)
-P14: (2.85445,2.01726)
-P15: (2.87765,2.00180)
-P16: (2.90112,1.98660)
-P17: (2.92480,1.97172)
-P18: (2.94863,1.95722)
-P19: (2.97258,1.94314)
-P20: (2.99658,1.92955)
-move to P0; line attrs1 to P1 then to P2
-move to P2; line attrs1 to P3 then to P4
-move to P4; line attrs1 to P5 then to P6
-move to P6; line attrs1 to P7 then to P8
-move to P8; line attrs1 to P9 then to P10
-move to P10; line attrs1 to P11 then to P12
-move to P12; line attrs1 to P13 then to P14
-move to P14; line attrs1 to P15 then to P16
-move to P16; line attrs1 to P17 then to P18
-move to P18; line attrs1 to P19 then to P20
-{
-define attrs2 % %
-define attrs2 % solid %
-oldlinethick = linethick;linethick = 1 * scalethickness / 10153
-P0: (3.01436,1.95622)
-P1: (3.07661,1.88509)
-P2: (2.98769,1.90287)
-move to P0; line attrs2 to P1
-move to P1; line attrs2 to P2
-move to P2; line attrs2 to P0
-}
-linethick = oldlinethick
-{
-define attrs2 % %
-setfillval 0.000000
-"ports" at (2.92100,2.15777);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Controller
-setfillval 0.000000
-box attrs1 wid 0.74692 ht 0.32011 at (4.09029,1.76060);
-{
-define attrs2 % %
-setfillval 0.000000
-"Controller" at (4.08584,1.75764);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Bridge -> Controller
-setfillval 0.000000
-setfillval 0.000000
-P0: (2.46306,2.48085)
-P1: (2.51818,2.46164)
-P2: (2.57638,2.44137)
-P3: (2.63704,2.42003)
-P4: (2.69952,2.39762)
-P5: (2.76317,2.37415)
-P6: (2.82735,2.34960)
-P7: (2.89142,2.32399)
-P8: (2.95475,2.29732)
-P9: (3.01669,2.26958)
-P10: (3.07661,2.24077)
-P11: (3.11337,2.22284)
-P12: (3.14447,2.20619)
-P13: (3.17120,2.19051)
-P14: (3.19483,2.17546)
-P15: (3.21666,2.16074)
-P16: (3.23794,2.14601)
-P17: (3.25998,2.13097)
-P18: (3.28404,2.11528)
-P19: (3.31141,2.09864)
-P20: (3.34337,2.08071)
-P21: (3.37271,2.06713)
-P22: (3.40205,2.05318)
-P23: (3.43140,2.03902)
-P24: (3.46074,2.02480)
-P25: (3.49008,2.01069)
-P26: (3.51943,1.99684)
-P27: (3.54877,1.98342)
-P28: (3.57811,1.97059)
-P29: (3.60746,1.95851)
-P30: (3.63680,1.94733)
-move to P0; line attrs1 to P1 then to P2
-move to P2; line attrs1 to P3 then to P4
-move to P4; line attrs1 to P5 then to P6
-move to P6; line attrs1 to P7 then to P8
-move to P8; line attrs1 to P9 then to P10
-move to P10; line attrs1 to P11 then to P12
-move to P12; line attrs1 to P13 then to P14
-move to P14; line attrs1 to P15 then to P16
-move to P16; line attrs1 to P17 then to P18
-move to P18; line attrs1 to P19 then to P20
-move to P20; line attrs1 to P21 then to P22
-move to P22; line attrs1 to P23 then to P24
-move to P24; line attrs1 to P25 then to P26
-move to P26; line attrs1 to P27 then to P28
-move to P28; line attrs1 to P29 then to P30
-{
-define attrs2 % %
-define attrs2 % solid %
-oldlinethick = linethick;linethick = 1 * scalethickness / 10153
-P0: (3.64569,1.97401)
-P1: (3.71683,1.91176)
-P2: (3.61902,1.92066)
-move to P0; line attrs2 to P1
-move to P1; line attrs2 to P2
-move to P2; line attrs2 to P0
-}
-linethick = oldlinethick
-{
-define attrs2 % %
-setfillval 0.000000
-"controller" at (3.63680,2.15777);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      NetFlow
-setfillval 0.000000
-box attrs1 wid 0.65800 ht 0.32011 at (0.98700,1.76060);
-{
-define attrs2 % %
-setfillval 0.000000
-"NetFlow" at (0.98700,1.75764);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Bridge -> NetFlow
-setfillval 0.000000
-setfillval 0.000000
-P0: (1.92955,2.48085)
-P1: (1.88055,2.46404)
-P2: (1.82989,2.44564)
-P3: (1.77806,2.42563)
-P4: (1.72553,2.40402)
-P5: (1.67279,2.38081)
-P6: (1.62032,2.35601)
-P7: (1.56860,2.32960)
-P8: (1.51810,2.30159)
-P9: (1.46931,2.27198)
-P10: (1.42271,2.24077)
-P11: (1.39363,2.21891)
-P12: (1.36509,2.19609)
-P13: (1.33708,2.17242)
-P14: (1.30960,2.14801)
-P15: (1.28266,2.12295)
-P16: (1.25625,2.09736)
-P17: (1.23038,2.07134)
-P18: (1.20503,2.04500)
-P19: (1.18023,2.01845)
-P20: (1.15595,1.99179)
-move to P0; line attrs1 to P1 then to P2
-move to P2; line attrs1 to P3 then to P4
-move to P4; line attrs1 to P5 then to P6
-move to P6; line attrs1 to P7 then to P8
-move to P8; line attrs1 to P9 then to P10
-move to P10; line attrs1 to P11 then to P12
-move to P12; line attrs1 to P13 then to P14
-move to P14; line attrs1 to P15 then to P16
-move to P16; line attrs1 to P17 then to P18
-move to P18; line attrs1 to P19 then to P20
-{
-define attrs2 % %
-define attrs2 % solid %
-oldlinethick = linethick;linethick = 1 * scalethickness / 10153
-P0: (1.18263,1.97401)
-P1: (1.10260,1.92066)
-P2: (1.12927,2.00958)
-move to P0; line attrs2 to P1
-move to P1; line attrs2 to P2
-move to P2; line attrs2 to P0
-}
-linethick = oldlinethick
-{
-define attrs2 % %
-setfillval 0.000000
-"netflow" at (1.71170,2.15777);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Mirror -> Port
-setfillval 0.000000
-setfillval 0.000000
-P0: (1.79617,1.60055)
-P1: (1.81565,1.56758)
-P2: (1.83679,1.53318)
-P3: (1.85963,1.49803)
-P4: (1.88424,1.46283)
-P5: (1.91065,1.42827)
-P6: (1.93894,1.39504)
-P7: (1.96914,1.36384)
-P8: (2.00132,1.33535)
-P9: (2.03553,1.31029)
-P10: (2.07182,1.28933)
-P11: (2.17646,1.23651)
-P12: (2.27299,1.19543)
-P13: (2.36344,1.16609)
-P14: (2.44983,1.14848)
-P15: (2.53420,1.14261)
-P16: (2.61857,1.14848)
-P17: (2.70496,1.16609)
-P18: (2.79541,1.19543)
-P19: (2.89194,1.23651)
-P20: (2.99658,1.28933)
-P21: (3.02512,1.30421)
-P22: (3.05207,1.32191)
-P23: (3.07741,1.34207)
-P24: (3.10115,1.36431)
-P25: (3.12329,1.38825)
-P26: (3.14383,1.41353)
-P27: (3.16277,1.43977)
-P28: (3.18011,1.46660)
-P29: (3.19585,1.49364)
-P30: (3.20999,1.52052)
-move to P0; line attrs1 to P1 then to P2
-move to P2; line attrs1 to P3 then to P4
-move to P4; line attrs1 to P5 then to P6
-move to P6; line attrs1 to P7 then to P8
-move to P8; line attrs1 to P9 then to P10
-move to P10; line attrs1 to P11 then to P12
-move to P12; line attrs1 to P13 then to P14
-move to P14; line attrs1 to P15 then to P16
-move to P16; line attrs1 to P17 then to P18
-move to P18; line attrs1 to P19 then to P20
-move to P20; line attrs1 to P21 then to P22
-move to P22; line attrs1 to P23 then to P24
-move to P24; line attrs1 to P25 then to P26
-move to P26; line attrs1 to P27 then to P28
-move to P28; line attrs1 to P29 then to P30
-{
-define attrs2 % %
-define attrs2 % solid %
-oldlinethick = linethick;linethick = 1 * scalethickness / 10153
-P0: (3.18331,1.53830)
-P1: (3.25445,1.60055)
-P2: (3.23666,1.51163)
-move to P0; line attrs2 to P1
-move to P1; line attrs2 to P2
-move to P2; line attrs2 to P0
-}
-linethick = oldlinethick
-{
-define attrs2 % %
-setfillval 0.000000
-"select_src_port" at (2.52975,1.35750);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Mirror -> Port
-setfillval 0.000000
-setfillval 0.000000
-P0: (1.99179,1.76060)
-P1: (2.07850,1.76060)
-P2: (2.17219,1.76060)
-P3: (2.27133,1.76060)
-P4: (2.37436,1.76060)
-P5: (2.47974,1.76060)
-P6: (2.58592,1.76060)
-P7: (2.69135,1.76060)
-P8: (2.79448,1.76060)
-P9: (2.89378,1.76060)
-P10: (2.98769,1.76060)
-move to P0; line attrs1 to P1 then to P2
-move to P2; line attrs1 to P3 then to P4
-move to P4; line attrs1 to P5 then to P6
-move to P6; line attrs1 to P7 then to P8
-move to P8; line attrs1 to P9 then to P10
-{
-define attrs2 % %
-define attrs2 % solid %
-oldlinethick = linethick;linethick = 1 * scalethickness / 10153
-P0: (2.98769,1.79617)
-P1: (3.07661,1.76060)
-P2: (2.98769,1.73393)
-move to P0; line attrs2 to P1
-move to P1; line attrs2 to P2
-move to P2; line attrs2 to P0
-}
-linethick = oldlinethick
-{
-define attrs2 % %
-setfillval 0.000000
-"output_port" at (2.52975,1.82877);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Mirror -> Port
-setfillval 0.000000
-setfillval 0.000000
-P0: (1.99179,1.60055)
-P1: (1.99979,1.59788)
-P2: (2.00780,1.59521)
-P3: (2.01580,1.59254)
-P4: (2.02380,1.58988)
-P5: (2.03181,1.58721)
-P6: (2.03981,1.58454)
-P7: (2.04781,1.58187)
-P8: (2.05581,1.57921)
-P9: (2.06382,1.57654)
-P10: (2.07182,1.57387)
-P11: (2.17501,1.54698)
-P12: (2.26780,1.52521)
-P13: (2.35312,1.50889)
-P14: (2.43390,1.49833)
-P15: (2.51308,1.49384)
-P16: (2.59360,1.49576)
-P17: (2.67838,1.50441)
-P18: (2.77037,1.52009)
-P19: (2.87249,1.54314)
-P20: (2.98769,1.57387)
-move to P0; line attrs1 to P1 then to P2
-move to P2; line attrs1 to P3 then to P4
-move to P4; line attrs1 to P5 then to P6
-move to P6; line attrs1 to P7 then to P8
-move to P8; line attrs1 to P9 then to P10
-move to P10; line attrs1 to P11 then to P12
-move to P12; line attrs1 to P13 then to P14
-move to P14; line attrs1 to P15 then to P16
-move to P16; line attrs1 to P17 then to P18
-move to P18; line attrs1 to P19 then to P20
-{
-define attrs2 % %
-define attrs2 % solid %
-oldlinethick = linethick;linethick = 1 * scalethickness / 10153
-P0: (2.97880,1.60055)
-P1: (3.07661,1.60055)
-P2: (2.99658,1.54720)
-move to P0; line attrs2 to P1
-move to P1; line attrs2 to P2
-move to P2; line attrs2 to P0
-}
-linethick = oldlinethick
-{
-define attrs2 % %
-setfillval 0.000000
-"select_dst_port" at (2.53420,1.64204);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      QoS
-setfillval 0.000000
-box attrs1 wid 0.48016 ht 0.32011 at (2.77428,0.96033);
-{
-define attrs2 % %
-setfillval 0.000000
-"QoS" at (2.76984,0.95736);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Port -> QoS
-setfillval 0.000000
-setfillval 0.000000
-P0: (3.20999,1.60055)
-P1: (3.18522,1.56461)
-P2: (3.15912,1.52642)
-P3: (3.13196,1.48643)
-P4: (3.10399,1.44505)
-P5: (3.07550,1.40270)
-P6: (3.04673,1.35982)
-P7: (3.01797,1.31684)
-P8: (2.98947,1.27418)
-P9: (2.96150,1.23226)
-P10: (2.93434,1.19152)
-move to P0; line attrs1 to P1 then to P2
-move to P2; line attrs1 to P3 then to P4
-move to P4; line attrs1 to P5 then to P6
-move to P6; line attrs1 to P7 then to P8
-move to P8; line attrs1 to P9 then to P10
-{
-define attrs2 % %
-define attrs2 % solid %
-oldlinethick = linethick;linethick = 1 * scalethickness / 10153
-P0: (2.96101,1.17373)
-P1: (2.88098,1.12038)
-P2: (2.90766,1.20930)
-move to P0; line attrs2 to P1
-move to P1; line attrs2 to P2
-move to P2; line attrs2 to P0
-}
-linethick = oldlinethick
-{
-define attrs2 % %
-setfillval 0.000000
-"qos" at (3.20554,1.35750);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Interface
-setfillval 0.000000
-box attrs1 wid 0.69357 ht 0.32011 at (3.52120,0.96033);
-{
-define attrs2 % %
-setfillval 0.000000
-"Interface" at (3.52120,0.95736);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Port -> Interface
-setfillval 0.000000
-setfillval 0.000000
-P0: (3.36115,1.60055)
-P1: (3.36941,1.56486)
-P2: (3.37815,1.52742)
-P3: (3.38732,1.48859)
-P4: (3.39686,1.44874)
-P5: (3.40672,1.40826)
-P6: (3.41685,1.36751)
-P7: (3.42719,1.32686)
-P8: (3.43769,1.28670)
-P9: (3.44830,1.24739)
-P10: (3.45896,1.20930)
-move to P0; line attrs1 to P1 then to P2
-move to P2; line attrs1 to P3 then to P4
-move to P4; line attrs1 to P5 then to P6
-move to P6; line attrs1 to P7 then to P8
-move to P8; line attrs1 to P9 then to P10
-{
-define attrs2 % %
-define attrs2 % solid %
-oldlinethick = linethick;linethick = 1 * scalethickness / 10153
-P0: (3.48564,1.20930)
-P1: (3.47674,1.12038)
-P2: (3.43228,1.20041)
-move to P0; line attrs2 to P1
-move to P1; line attrs2 to P2
-move to P2; line attrs2 to P0
-}
-linethick = oldlinethick
-{
-define attrs2 % %
-setfillval 0.000000
-"interfaces" at (3.75239,1.35750);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Queue
-setfillval 0.000000
-box attrs1 wid 0.55130 ht 0.32011 at (2.77428,0.16005);
-{
-define attrs2 % %
-setfillval 0.000000
-"Queue" at (2.77428,0.15709);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      QoS -> Queue
-setfillval 0.000000
-setfillval 0.000000
-P0: (2.77428,0.80027)
-P1: (2.77428,0.76483)
-P2: (2.77428,0.72800)
-P3: (2.77428,0.69000)
-P4: (2.77428,0.65103)
-P5: (2.77428,0.61132)
-P6: (2.77428,0.57108)
-P7: (2.77428,0.53051)
-P8: (2.77428,0.48984)
-P9: (2.77428,0.44927)
-P10: (2.77428,0.40903)
-move to P0; line attrs1 to P1 then to P2
-move to P2; line attrs1 to P3 then to P4
-move to P4; line attrs1 to P5 then to P6
-move to P6; line attrs1 to P7 then to P8
-move to P8; line attrs1 to P9 then to P10
-{
-define attrs2 % %
-define attrs2 % solid %
-oldlinethick = linethick;linethick = 1 * scalethickness / 10153
-P0: (2.80985,0.40903)
-P1: (2.77428,0.32011)
-P2: (2.74761,0.40903)
-move to P0; line attrs2 to P1
-move to P1; line attrs2 to P2
-move to P2; line attrs2 to P0
-}
-linethick = oldlinethick
-{
-define attrs2 % %
-setfillval 0.000000
-"queues value" at (3.18331,0.55723);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Open_vSwitch
-setfillval 0.000000
-box attrs1 wid 1.03146 ht 0.32011 at (4.49042,3.36115);
-{
-define attrs2 % %
-setfillval 0.000000
-"Open_vSwitch" at (4.49042,3.35819);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Open_vSwitch -> Bridge
-setfillval 0.000000
-setfillval 0.000000
-P0: (3.97469,3.20109)
-P1: (3.92643,3.18509)
-P2: (3.87773,3.16908)
-P3: (3.82872,3.15308)
-P4: (3.77950,3.13707)
-P5: (3.73016,3.12107)
-P6: (3.68083,3.10506)
-P7: (3.63161,3.08906)
-P8: (3.58259,3.07305)
-P9: (3.53390,3.05705)
-P10: (3.48564,3.04104)
-P11: (3.38867,3.00613)
-P12: (3.29037,2.97090)
-P13: (3.19154,2.93556)
-P14: (3.09297,2.90033)
-P15: (2.99547,2.86542)
-P16: (2.89984,2.83105)
-P17: (2.80687,2.79742)
-P18: (2.71737,2.76475)
-P19: (2.63214,2.73325)
-P20: (2.55198,2.70315)
-move to P0; line attrs1 to P1 then to P2
-move to P2; line attrs1 to P3 then to P4
-move to P4; line attrs1 to P5 then to P6
-move to P6; line attrs1 to P7 then to P8
-move to P8; line attrs1 to P9 then to P10
-move to P10; line attrs1 to P11 then to P12
-move to P12; line attrs1 to P13 then to P14
-move to P14; line attrs1 to P15 then to P16
-move to P16; line attrs1 to P17 then to P18
-move to P18; line attrs1 to P19 then to P20
-{
-define attrs2 % %
-define attrs2 % solid %
-oldlinethick = linethick;linethick = 1 * scalethickness / 10153
-P0: (2.56088,2.66758)
-P1: (2.46306,2.66758)
-P2: (2.53420,2.72982)
-move to P0; line attrs2 to P1
-move to P1; line attrs2 to P2
-move to P2; line attrs2 to P0
-}
-linethick = oldlinethick
-{
-define attrs2 % %
-setfillval 0.000000
-"bridges" at (3.76129,2.95805);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Open_vSwitch -> Controller
-setfillval 0.000000
-setfillval 0.000000
-P0: (4.36594,3.20109)
-P1: (4.34122,3.16220)
-P2: (4.31543,3.12043)
-P3: (4.28911,3.07609)
-P4: (4.26279,3.02952)
-P5: (4.23700,2.98102)
-P6: (4.21228,2.93092)
-P7: (4.18917,2.87954)
-P8: (4.16818,2.82721)
-P9: (4.14986,2.77423)
-P10: (4.13475,2.72093)
-P11: (4.11548,2.64795)
-P12: (4.10010,2.57354)
-P13: (4.08825,2.49837)
-P14: (4.07955,2.42316)
-P15: (4.07361,2.34858)
-P16: (4.07008,2.27534)
-P17: (4.06858,2.20412)
-P18: (4.06873,2.13563)
-P19: (4.07016,2.07055)
-P20: (4.07250,2.00958)
-move to P0; line attrs1 to P1 then to P2
-move to P2; line attrs1 to P3 then to P4
-move to P4; line attrs1 to P5 then to P6
-move to P6; line attrs1 to P7 then to P8
-move to P8; line attrs1 to P9 then to P10
-move to P10; line attrs1 to P11 then to P12
-move to P12; line attrs1 to P13 then to P14
-move to P14; line attrs1 to P15 then to P16
-move to P16; line attrs1 to P17 then to P18
-move to P18; line attrs1 to P19 then to P20
-{
-define attrs2 % %
-define attrs2 % solid %
-oldlinethick = linethick;linethick = 1 * scalethickness / 10153
-P0: (4.10807,2.00958)
-P1: (4.07250,1.92066)
-P2: (4.04583,2.00958)
-move to P0; line attrs2 to P1
-move to P1; line attrs2 to P2
-move to P2; line attrs2 to P0
-}
-linethick = oldlinethick
-{
-define attrs2 % %
-setfillval 0.000000
-"controller" at (4.42818,2.55791);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Capability
-setfillval 0.000000
-box attrs1 wid 0.74692 ht 0.32011 at (5.17510,2.56088);
-{
-define attrs2 % %
-setfillval 0.000000
-"Capability" at (5.17510,2.55791);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Open_vSwitch -> Capability
-setfillval 0.000000
-setfillval 0.000000
-P0: (4.63269,3.20109)
-P1: (4.66305,3.16515)
-P2: (4.69522,3.12697)
-P3: (4.72889,3.08698)
-P4: (4.76373,3.04559)
-P5: (4.79942,3.00325)
-P6: (4.83564,2.96037)
-P7: (4.87208,2.91739)
-P8: (4.90842,2.87473)
-P9: (4.94432,2.83281)
-P10: (4.97948,2.79207)
-move to P0; line attrs1 to P1 then to P2
-move to P2; line attrs1 to P3 then to P4
-move to P4; line attrs1 to P5 then to P6
-move to P6; line attrs1 to P7 then to P8
-move to P8; line attrs1 to P9 then to P10
-{
-define attrs2 % %
-define attrs2 % solid %
-oldlinethick = linethick;linethick = 1 * scalethickness / 10153
-P0: (5.00616,2.80985)
-P1: (5.03283,2.72093)
-P2: (4.95280,2.77428)
-move to P0; line attrs2 to P1
-move to P1; line attrs2 to P2
-move to P2; line attrs2 to P0
-}
-linethick = oldlinethick
-{
-define attrs2 % %
-setfillval 0.000000
-"capabilities value" at (5.41518,2.95805);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      SSL
-setfillval 0.000000
-box attrs1 wid 0.48016 ht 0.32011 at (6.18878,2.56088);
-{
-define attrs2 % %
-setfillval 0.000000
-"SSL" at (6.18878,2.55791);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-{
-define attrs1 % %
-#      Open_vSwitch -> SSL
-setfillval 0.000000
-setfillval 0.000000
-P0: (5.00616,3.29891)
-P1: (5.11780,3.28184)
-P2: (5.23244,3.26270)
-P3: (5.34771,3.24153)
-P4: (5.46128,3.21838)
-P5: (5.57079,3.19331)
-P6: (5.67390,3.16638)
-P7: (5.76827,3.13763)
-P8: (5.85153,3.10712)
-P9: (5.92135,3.07491)
-P10: (5.97538,3.04104)
-P11: (5.99617,3.02160)
-P12: (6.01585,3.00078)
-P13: (6.03436,2.97878)
-P14: (6.05163,2.95582)
-P15: (6.06763,2.93211)
-P16: (6.08229,2.90787)
-P17: (6.09557,2.88331)
-P18: (6.10740,2.85865)
-P19: (6.11774,2.83409)
-P20: (6.12654,2.80985)
-move to P0; line attrs1 to P1 then to P2
-move to P2; line attrs1 to P3 then to P4
-move to P4; line attrs1 to P5 then to P6
-move to P6; line attrs1 to P7 then to P8
-move to P8; line attrs1 to P9 then to P10
-move to P10; line attrs1 to P11 then to P12
-move to P12; line attrs1 to P13 then to P14
-move to P14; line attrs1 to P15 then to P16
-move to P16; line attrs1 to P17 then to P18
-move to P18; line attrs1 to P19 then to P20
-{
-define attrs2 % %
-define attrs2 % solid %
-oldlinethick = linethick;linethick = 1 * scalethickness / 10153
-P0: (6.15321,2.81874)
-P1: (6.15321,2.72093)
-P2: (6.09986,2.80096)
-move to P0; line attrs2 to P1
-move to P1; line attrs2 to P2
-move to P2; line attrs2 to P0
-}
-linethick = oldlinethick
-{
-define attrs2 % %
-setfillval 0.000000
-"ssl" at (6.14877,2.95805);
-}
-linethick = oldlinethick
-}
-linethick = oldlinethick
-]
+.PS
+linethick = 1;
+box at 2.735854117,2.79404 wid 0.5917916422 height 0.349255 "Bridge"
+box at 0.2716435539,1.9209025 wid 0.5432871078 height 0.349255 "sFlow"
+box at 0.999288406,1.9209025 wid 0.5723870344 height 0.349255 "Mirror"
+box at 2.735854117,1.9209025 wid 0.5238825 height 0.349255 "Port"
+box at 3.589573039,1.9209025 wid 0.834300344 height 0.349255 "Controller"
+box at 4.540315,1.9209025 wid 0.717928578 height 0.349255 "NetFlow"
+box at 2.153715883,1.047765 wid 0.5238825 height 0.349255 "QoS"
+box at 2.153715883,0.1746275 wid 0.6014939461 height 0.349255 "Queue"
+box at 4.288083039,3.6671775 wid 1.125369461 height 0.349255 "Open_vSwitch"
+box at 3.608991617,2.79404 wid 0.824660906 height 0.349255 "Capability"
+box at 4.97688375,2.79404 wid 0.5238825 height 0.349255 "SSL"
+box at 5.782126078,2.79404 wid 0.746986594 height 0.349255 "Manager"
+box at 2.9686675,1.047765 wid 0.756695883 height 0.349255 "Interface"
+spline -> from 2.442619619,2.741512048 to 2.442619619,2.741512048 to 2.152179161,2.684932738 to 1.697309449,2.583858341 to 1.319415539,2.444785 to 1.046507682,2.344339262 to 0.751526909,2.19262289 to 0.5443278877,2.078276803
+"sflow" at 1.498862758,2.35747125
+spline -> from 2.441222599,2.64595588 to 2.441222599,2.64595588 to 2.117044108,2.482923646 to 1.599797453,2.222868373 to 1.280857787,2.062490477
+"mirrors" at 2.2701575,2.35747125
+spline -> from 2.735854117,2.61731697 to 2.735854117,2.61731697 to 2.735854117,2.465880002 to 2.735854117,2.248713243 to 2.735854117,2.097346126
+"ports" at 2.910481617,2.35747125
+spline -> from 2.941216057,2.616897864 to 2.941216057,2.616897864 to 3.001357768,2.562972892 to 3.066389049,2.502621628 to 3.123876422,2.444785 to 3.233682194,2.334280718 to 3.350123811,2.203310093 to 3.439044134,2.100000464
+"controller" at 3.613811336,2.35747125
+spline -> from 3.030625337,2.650077089 to 3.030625337,2.650077089 to 3.058565737,2.638831078 to 3.08671569,2.628423279 to 3.114167133,2.6194125 to 3.486333261,2.497732058 to 3.629388109,2.623743262 to 3.977595344,2.444785 to 4.142653257,2.359985886 to 4.294369629,2.212809829 to 4.398587321,2.096018957
+"netflow" at 4.482129117,2.35747125
+spline -> from 1.286026761,1.9209025 to 1.286026761,1.9209025 to 1.615513928,1.9209025 to 2.151690204,1.9209025 to 2.471468082,1.9209025
+"select_src_port" at 1.872425906,2.00821625
+spline -> from 1.258645169,1.745436788 to 1.258645169,1.745436788 to 1.291056033,1.729929866 to 1.324654364,1.716658176 to 1.358182844,1.707437844 to 1.798942654,1.58631621 to 1.946607668,1.583661872 to 2.386599117,1.707437844 to 2.419429087,1.716728027 to 2.452189206,1.729999717 to 2.483831709,1.745436788
+"output_port" at 1.872425906,1.794751594
+spline -> from 1.067043876,1.745157384 to 1.067043876,1.745157384 to 1.124391547,1.623197538 to 1.219738162,1.470014295 to 1.358182844,1.39702 to 1.762550283,1.183904599 to 1.983628698,1.181389963 to 2.386599117,1.39702 to 2.523437226,1.470293699 to 2.61591995,1.623407091 to 2.671172091,1.745366937
+"select_dst_port" at 1.872425906,1.48433375
+spline -> from 2.61801548,1.74417947 to 2.61801548,1.74417947 to 2.517010934,1.592742502 to 2.372279662,1.375575743 to 2.271344967,1.224208626
+"qos" at 2.6194125,1.48433375
+spline -> from 2.782933691,1.74417947 to 2.782933691,1.74417947 to 2.82337742,1.592742502 to 2.881214048,1.375575743 to 2.921587926,1.224208626
+"interfaces" at 3.211190172,1.48433375
+spline -> from 2.153715883,0.87104197 to 2.153715883,0.87104197 to 2.153715883,0.719605002 to 2.153715883,0.5024661834 to 2.153715883,0.3510571558
+"queues value" at 2.599993922,0.61119625
+spline -> from 3.724595022,3.601727113 to 3.724595022,3.601727113 to 3.49604255,3.552831413 to 3.240737145,3.467333789 to 3.046271961,3.3179225 to 2.930598705,3.229072028 to 2.849431843,3.083781948 to 2.799139123,2.9686675
+"bridges" at 3.288794633,3.23060875
+spline -> from 3.794446022,3.490733874 to 3.794446022,3.490733874 to 3.724734724,3.444981469 to 3.662148228,3.388122755 to 3.618700906,3.3179225 to 3.554996794,3.215031977 to 3.554857092,3.07763506 to 3.569455951,2.96936601
+"capabilities value" at 4.19106,3.23060875
+spline -> from 4.579291858,3.492410298 to 4.579291858,3.492410298 to 4.646139265,3.442327131 to 4.712427864,3.383372887 to 4.763419094,3.3179225 to 4.843747744,3.214892275 to 4.898231524,3.077495358 to 4.932039408,2.969296159
+"ssl" at 4.957465172,3.23060875
+spline -> from 4.738831542,3.490733874 to 4.738831542,3.490733874 to 4.853876139,3.439952197 to 4.97548673,3.381067804 to 5.083616078,3.3179225 to 5.25768477,3.216219444 to 5.439437072,3.078822527 to 5.573900247,2.970204222
+"manager_options" at 5.922805992,3.23060875
 .PE
-.\"  restore point size and font
-.ps \n(.S
-.ft \n(DF
index 8151807..89bada3 100644 (file)
         Set of bridges managed by the daemon.
       </column>
 
-      <column name="managers">
-        Remote database clients to which the Open vSwitch's database server
-        should connect or to which it should listen.
-      </column>
-
       <column name="ssl">
         SSL used globally by the daemon.
       </column>
         </dl>
       </column>
     </group>
+
+    <group title="Database Configuration">
+      <p>
+        These columns primarily configure the Open vSwitch database
+        (<code>ovsdb-server</code>), not the Open vSwitch switch
+        (<code>ovs-vswitchd</code>).  The OVSDB database also uses the <ref
+        column="ssl"/> settings.
+      </p>
+
+      <p>
+        The Open vSwitch switch does read the database configuration to
+        determine remote IP addresses to which in-band control should apply.
+      </p>
+
+      <column name="manager_options">
+        Database clients to which the Open vSwitch database server should
+        connect or to which it should listen, along with options for how these
+        connection should be configured.  See the <ref table="Manager"/> table
+        for more information.
+      </column>
+
+      <column name="managers">
+        <p>
+          Remote database clients to which the Open vSwitch's database server
+          should connect or to which it should listen.  Adding an OVSDB target
+          to this set is equivalent to adding it to <ref
+          column="manager_options"/> with all of the default options.
+        </p>
+
+        <p>
+          Use of this column is deprecated and may be removed sometime in the
+          future.  New applications should use and set <ref
+          column="manager_options"/> instead.
+        </p>
+      </column>
+    </group>
   </table>
 
   <table name="Bridge">
     </group>
   </table>
 
+  <table name="Manager" title="OVSDB management connection.">
+    <p>
+      Configuration for a database connection to an Open vSwitch database
+      (OVSDB) client.
+    </p>
+
+    <p>
+      This table primarily configures the Open vSwitch database
+      (<code>ovsdb-server</code>), not the Open vSwitch switch
+      (<code>ovs-vswitchd</code>).  The switch does read the table to determine
+      what connections should be treated as in-band.
+    </p>
+
+    <p>
+      The Open vSwitch database server can initiate and maintain active
+      connections to remote clients.  It can also listen for database
+      connections.
+    </p>
+
+    <group title="Core Features">
+      <column name="target">
+        <p>Connection method for managers.</p>
+        <p>
+          The following connection methods are currently supported:
+        </p>
+        <dl>
+          <dt><code>ssl:<var>ip</var></code>[<code>:<var>port</var></code>]</dt>
+          <dd>
+            <p>
+              The specified SSL <var>port</var> (default: 6632) on the host at
+              the given <var>ip</var>, which must be expressed as an IP address
+              (not a DNS name).  The <ref table="Open_vSwitch" column="ssl"/>
+              column in the <ref table="Open_vSwitch"/> table must point to a
+              valid SSL configuration when this form is used.
+            </p>
+            <p>
+              SSL support is an optional feature that is not always built as
+              part of Open vSwitch.
+            </p>
+          </dd>
+
+          <dt><code>tcp:<var>ip</var></code>[<code>:<var>port</var></code>]</dt>
+          <dd>
+            The specified TCP <var>port</var> (default: 6632) on the host at
+            the given <var>ip</var>, which must be expressed as an IP address
+            (not a DNS name).
+          </dd>
+          <dt><code>pssl:</code>[<var>port</var>][<code>:<var>ip</var></code>]</dt>
+          <dd>
+            <p>
+              Listens for SSL connections on the specified TCP <var>port</var>
+              (default: 6632).  If <var>ip</var>, which must be expressed as an
+              IP address (not a DNS name), is specified, then connections are
+              restricted to the specified local IP address.
+            </p>
+            <p>
+              The <ref table="Open_vSwitch" column="ssl"/> column in the <ref
+              table="Open_vSwitch"/> table must point to a valid SSL
+              configuration when this form is used.
+            </p>
+            <p>
+              SSL support is an optional feature that is not always built as
+              part of Open vSwitch.
+            </p>
+          </dd>
+          <dt><code>ptcp:</code>[<var>port</var>][<code>:<var>ip</var></code>]</dt>
+          <dd>
+            Listens for connections on the specified TCP <var>port</var>
+            (default: 6632).  If <var>ip</var>, which must be expressed as an
+            IP address (not a DNS name), is specified, then connections are
+            restricted to the specified local IP address.
+          </dd>
+        </dl>
+        <p>When multiple managers are configured, the <ref column="target"/>
+        values must be unique.  Duplicate <ref column="target"/> values yield
+        unspecified results.</p>
+      </column>
+
+      <column name="connection_mode">
+        <p>
+          If it is specified, this setting must be one of the following strings
+          that describes how Open vSwitch contacts this OVSDB client over the
+          network:
+        </p>
+        
+        <dl>
+          <dt><code>in-band</code></dt>
+          <dd>
+            In this mode, this connection's traffic travels over a bridge
+            managed by Open vSwitch.  With this setting, Open vSwitch allows
+            traffic to and from the client regardless of the contents of the
+            OpenFlow flow table.  (Otherwise, Open vSwitch would never be able
+            to connect to the client, because it did not have a flow to enable
+            it.)  This is the most common connection mode because it is not
+            necessary to maintain two independent networks.
+          </dd>
+          <dt><code>out-of-band</code></dt>
+          <dd>
+            In this mode, the client's traffic uses a control network separate
+            from that managed by Open vSwitch, that is, Open vSwitch does not
+            use any of its own network devices to communicate with the client.
+            The control network must be configured separately, before or after
+            <code>ovs-vswitchd</code> is started.
+          </dd>
+        </dl>
+
+        <p>
+          If not specified, the default is implementation-specific.
+        </p>
+      </column>
+    </group>
+
+    <group title="Client Failure Detection and Handling">
+      <column name="max_backoff">
+        Maximum number of milliseconds to wait between connection attempts.
+        Default is implementation-specific.
+      </column>
+
+      <column name="inactivity_probe">
+        Maximum number of milliseconds of idle time on connection to the client
+        before sending an inactivity probe message.  If Open vSwitch does not
+        communicate with the client for the specified number of seconds, it
+        will send a probe.  If a response is not received for the same
+        additional amount of time, Open vSwitch assumes the connection has been
+        broken and attempts to reconnect.  Default is implementation-specific.
+      </column>
+    </group>
+
+    <group title="Other Features">
+      <column name="external_ids">
+        Key-value pairs for use by external frameworks that integrate with Open
+        vSwitch, rather than by Open vSwitch itself.  System integrators should
+        either use the Open vSwitch development mailing list to coordinate on
+        common key-value definitions, or choose key names that are likely to be
+        unique.  No common key-value pairs are currently defined.
+      </column>
+    </group>
+  </table>
+
   <table name="NetFlow">
     A NetFlow target.  NetFlow is a protocol that exports a number of
     details about terminating IP flows, such as the principals involved