Merge branch 'mainstream'
authorGiuseppe Lettieri <g.lettieri@iet.unipi.it>
Wed, 9 Oct 2013 13:25:33 +0000 (15:25 +0200)
committerGiuseppe Lettieri <g.lettieri@iet.unipi.it>
Wed, 9 Oct 2013 13:25:33 +0000 (15:25 +0200)
22 files changed:
lib/learning-switch.c
lib/ovsdb-idl.c
lib/poll-loop.c
lib/timeval.c
lib/timeval.h
ofproto/automake.mk
ofproto/ofproto-dpif-monitor.c [new file with mode: 0644]
ofproto/ofproto-dpif-monitor.h [new file with mode: 0644]
ofproto/ofproto-dpif-xlate.c
ofproto/ofproto-dpif-xlate.h
ofproto/ofproto-dpif.c
ofproto/ofproto-dpif.h
ovsdb/dot2pic
ovsdb/ovsdb-doc
ovsdb/ovsdb-dot.in
python/ovs/db/idl.py
tests/bfd.at
tests/ofproto-dpif.at
utilities/ovs-lib.in
vswitchd/automake.mk
vswitchd/vswitch.gv
vswitchd/vswitch.pic

index 76ec3e1..b133637 100644 (file)
@@ -477,19 +477,23 @@ lswitch_choose_destination(struct lswitch *sw, const struct flow *flow)
     ofp_port_t out_port;
 
     /* Learn the source MAC. */
-    ovs_rwlock_wrlock(&sw->ml->rwlock);
-    if (mac_learning_may_learn(sw->ml, flow->dl_src, 0)) {
-        struct mac_entry *mac = mac_learning_insert(sw->ml, flow->dl_src, 0);
-        if (mac->port.ofp_port != flow->in_port.ofp_port) {
-            VLOG_DBG_RL(&rl, "%016llx: learned that "ETH_ADDR_FMT" is on "
-                        "port %"PRIu16, sw->datapath_id,
-                        ETH_ADDR_ARGS(flow->dl_src), flow->in_port.ofp_port);
-
-            mac->port.ofp_port = flow->in_port.ofp_port;
-            mac_learning_changed(sw->ml);
+    if (sw->ml) {
+        ovs_rwlock_wrlock(&sw->ml->rwlock);
+        if (mac_learning_may_learn(sw->ml, flow->dl_src, 0)) {
+            struct mac_entry *mac = mac_learning_insert(sw->ml, flow->dl_src,
+                                                        0);
+            if (mac->port.ofp_port != flow->in_port.ofp_port) {
+                VLOG_DBG_RL(&rl, "%016llx: learned that "ETH_ADDR_FMT" is on "
+                            "port %"PRIu16, sw->datapath_id,
+                            ETH_ADDR_ARGS(flow->dl_src),
+                            flow->in_port.ofp_port);
+
+                mac->port.ofp_port = flow->in_port.ofp_port;
+                mac_learning_changed(sw->ml);
+            }
         }
+        ovs_rwlock_unlock(&sw->ml->rwlock);
     }
-    ovs_rwlock_unlock(&sw->ml->rwlock);
 
     /* Drop frames for reserved multicast addresses. */
     if (eth_addr_is_reserved(flow->dl_dst)) {
index 116aa86..4631291 100644 (file)
@@ -91,7 +91,6 @@ struct ovsdb_idl_txn {
     char *error;
     bool dry_run;
     struct ds comment;
-    unsigned int commit_seqno;
 
     /* Increments. */
     const char *inc_table;
@@ -1242,7 +1241,6 @@ ovsdb_idl_txn_create(struct ovsdb_idl *idl)
     txn->error = NULL;
     txn->dry_run = false;
     ds_init(&txn->comment);
-    txn->commit_seqno = txn->idl->change_seqno;
 
     txn->inc_table = NULL;
     txn->inc_column = NULL;
index 4eb1187..5e3618b 100644 (file)
@@ -226,6 +226,7 @@ poll_block(void)
         COVERAGE_INC(poll_zero_timeout);
     }
 
+    timewarp_wait();
     retval = time_poll(loop->pollfds, loop->n_waiters,
                        loop->timeout_when, &elapsed);
     if (retval < 0) {
index 64ae845..dbfcdf5 100644 (file)
@@ -33,6 +33,7 @@
 #include "hmap.h"
 #include "ovs-thread.h"
 #include "signals.h"
+#include "seq.h"
 #include "unixctl.h"
 #include "util.h"
 #include "vlog.h"
@@ -57,6 +58,14 @@ static struct clock wall_clock;      /* CLOCK_REALTIME. */
 /* The monotonic time at which the time module was initialized. */
 static long long int boot_time;
 
+/* True only when timeval_dummy_register() is called. */
+static bool timewarp_enabled;
+/* Reference to the seq struct.  Threads other than main thread can
+ * wait on timewarp_seq and be waken up when time is warped. */
+static struct seq *timewarp_seq;
+/* Last value of 'timewarp_seq'. */
+DEFINE_STATIC_PER_THREAD_DATA(uint64_t, last_seq, 0);
+
 /* Monotonic time in milliseconds at which to die with SIGALRM (if not
  * LLONG_MAX). */
 static long long int deadline = LLONG_MAX;
@@ -79,6 +88,7 @@ init_clock(struct clock *c, clockid_t id)
     ovs_mutex_init(&c->mutex);
     atomic_init(&c->slow_path, false);
     xclock_gettime(c->id, &c->cache);
+    timewarp_seq = seq_create();
 }
 
 static void
@@ -313,6 +323,19 @@ xclock_gettime(clock_t id, struct timespec *ts)
     }
 }
 
+/* Makes threads wait on timewarp_seq and be waken up when time is warped.
+ * This function will be no-op unless timeval_dummy_register() is called. */
+void
+timewarp_wait(void)
+{
+    if (timewarp_enabled) {
+        uint64_t *last_seq = last_seq_get();
+
+        *last_seq = seq_read(timewarp_seq);
+        seq_wait(timewarp_seq, *last_seq);
+    }
+}
+
 static long long int
 timeval_diff_msec(const struct timeval *a, const struct timeval *b)
 {
@@ -511,13 +534,14 @@ timeval_warp_cb(struct unixctl_conn *conn,
     atomic_store(&monotonic_clock.slow_path, true);
     timespec_add(&monotonic_clock.warp, &monotonic_clock.warp, &ts);
     ovs_mutex_unlock(&monotonic_clock.mutex);
-
+    seq_change(timewarp_seq);
     unixctl_command_reply(conn, "warped");
 }
 
 void
 timeval_dummy_register(void)
 {
+    timewarp_enabled = true;
     unixctl_command_register("time/stop", "", 0, 0, timeval_stop_cb, NULL);
     unixctl_command_register("time/warp", "MSECS", 1, 1,
                              timeval_warp_cb, NULL);
index 99b3af0..1bbfd5c 100644 (file)
@@ -69,6 +69,8 @@ int get_cpu_usage(void);
 
 long long int time_boot_msec(void);
 
+void timewarp_wait(void);
+
 #ifdef  __cplusplus
 }
 #endif
index 47ca1b8..432f083 100644 (file)
@@ -28,6 +28,8 @@ ofproto_libofproto_a_SOURCES = \
        ofproto/ofproto-dpif-ipfix.h \
        ofproto/ofproto-dpif-mirror.c \
        ofproto/ofproto-dpif-mirror.h \
+       ofproto/ofproto-dpif-monitor.c \
+       ofproto/ofproto-dpif-monitor.h \
        ofproto/ofproto-dpif-sflow.c \
        ofproto/ofproto-dpif-sflow.h \
        ofproto/ofproto-dpif-upcall.c \
diff --git a/ofproto/ofproto-dpif-monitor.c b/ofproto/ofproto-dpif-monitor.c
new file mode 100644 (file)
index 0000000..a0c3843
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+#include "ofproto-dpif-monitor.h"
+
+#include <string.h>
+
+#include "bfd.h"
+#include "cfm.h"
+#include "hash.h"
+#include "hmap.h"
+#include "ofpbuf.h"
+#include "ofproto-dpif.h"
+#include "util.h"
+#include "vlog.h"
+
+/* Monitored port.  It owns references to ofport, bfd, cfm structs. */
+struct mport {
+    struct hmap_node hmap_node;       /* In monitor_hmap. */
+    const struct ofport_dpif *ofport; /* The corresponding ofport. */
+
+    struct cfm *cfm;                  /* Reference to cfm. */
+    struct bfd *bfd;                  /* Reference to bfd. */
+    uint8_t hw_addr[OFP_ETH_ALEN];    /* Hardware address. */
+};
+
+/* hmap that contains "struct mport"s. */
+static struct hmap monitor_hmap = HMAP_INITIALIZER(&monitor_hmap);
+
+static struct ovs_rwlock monitor_rwlock = OVS_RWLOCK_INITIALIZER;
+
+static void mport_register(const struct ofport_dpif *, struct bfd *,
+                           struct cfm *, uint8_t[ETH_ADDR_LEN])
+    OVS_REQ_WRLOCK(monitor_rwlock);
+static void mport_unregister(const struct ofport_dpif *)
+    OVS_REQ_WRLOCK(monitor_rwlock);
+static void mport_update(struct mport *, struct bfd *, struct cfm *,
+                         uint8_t[ETH_ADDR_LEN]) OVS_REQ_WRLOCK(monitor_rwlock);
+static struct mport *mport_find(const struct ofport_dpif *)
+    OVS_REQ_WRLOCK(monitor_rwlock);
+
+/* Tries finding and returning the 'mport' from the monitor_hmap.
+ * If there is no such 'mport', returns NULL. */
+static struct mport *
+mport_find(const struct ofport_dpif *ofport) OVS_REQ_WRLOCK(monitor_rwlock)
+{
+    struct mport *node;
+
+    HMAP_FOR_EACH_WITH_HASH (node, hmap_node, hash_pointer(ofport, 0),
+                             &monitor_hmap) {
+        if (node->ofport == ofport) {
+            return node;
+        }
+    }
+    return NULL;
+}
+
+/* Creates a new mport and inserts it into monitor_hmap, if it doesn't exist.
+ * Otherwise, just updates its fields. */
+static void
+mport_register(const struct ofport_dpif *ofport, struct bfd *bfd,
+               struct cfm *cfm, uint8_t *hw_addr)
+    OVS_REQ_WRLOCK(monitor_rwlock)
+{
+    struct mport *mport = mport_find(ofport);
+
+    if (!mport) {
+        mport = xzalloc(sizeof *mport);
+        mport->ofport = ofport;
+        hmap_insert(&monitor_hmap, &mport->hmap_node, hash_pointer(ofport, 0));
+    }
+    mport_update(mport, bfd, cfm, hw_addr);
+}
+
+/* Removes mport from monitor_hmap and frees it. */
+static void
+mport_unregister(const struct ofport_dpif *ofport)
+    OVS_REQ_WRLOCK(monitor_rwlock)
+{
+    struct mport *mport = mport_find(ofport);
+
+    if (mport) {
+        mport_update(mport, NULL, NULL, NULL);
+        hmap_remove(&monitor_hmap, &mport->hmap_node);
+        free(mport);
+    }
+}
+
+/* Updates the fields of an existing mport struct. */
+static void
+mport_update(struct mport *mport, struct bfd *bfd, struct cfm *cfm,
+             uint8_t hw_addr[ETH_ADDR_LEN]) OVS_REQ_WRLOCK(monitor_rwlock)
+{
+    ovs_assert(mport);
+
+    if (mport->cfm != cfm) {
+        cfm_unref(mport->cfm);
+        mport->cfm = cfm_ref(cfm);
+    }
+    if (mport->bfd != bfd) {
+        bfd_unref(mport->bfd);
+        mport->bfd = bfd_ref(bfd);
+    }
+    if (hw_addr && memcmp(mport->hw_addr, hw_addr, ETH_ADDR_LEN)) {
+        memcpy(mport->hw_addr, hw_addr, ETH_ADDR_LEN);
+    }
+}
+\f
+
+/* Creates the mport in monitor module if either bfd or cfm
+ * is configured.  Otherwise, deletes the mport. */
+void
+ofproto_dpif_monitor_port_update(const struct ofport_dpif *ofport,
+                                 struct bfd *bfd, struct cfm *cfm,
+                                 uint8_t hw_addr[ETH_ADDR_LEN])
+{
+    ovs_rwlock_wrlock(&monitor_rwlock);
+    if (!cfm && !bfd) {
+        mport_unregister(ofport);
+    } else {
+        mport_register(ofport, bfd, cfm, hw_addr);
+    }
+    ovs_rwlock_unlock(&monitor_rwlock);
+}
+
+/* Checks the sending of control packets on all mports.  Sends the control
+ * packets if needed. */
+void
+ofproto_dpif_monitor_run_fast(void)
+{
+    struct mport *mport;
+    static uint32_t buf_stub[128 / 4];
+    struct ofpbuf packet;
+
+    ovs_rwlock_rdlock(&monitor_rwlock);
+    HMAP_FOR_EACH (mport, hmap_node, &monitor_hmap) {
+        if (mport->cfm && cfm_should_send_ccm(mport->cfm)) {
+            ofpbuf_use_stub(&packet, buf_stub, sizeof buf_stub);
+            cfm_compose_ccm(mport->cfm, &packet, mport->hw_addr);
+            ofproto_dpif_send_packet(mport->ofport, &packet);
+        }
+        if (mport->bfd && bfd_should_send_packet(mport->bfd)) {
+            ofpbuf_use_stub(&packet, buf_stub, sizeof buf_stub);
+            bfd_put_packet(mport->bfd, &packet, mport->hw_addr);
+            ofproto_dpif_send_packet(mport->ofport, &packet);
+        }
+    }
+    ovs_rwlock_unlock(&monitor_rwlock);
+}
+
+/* Executes bfd_run(), cfm_run() on all mports. */
+void
+ofproto_dpif_monitor_run(void)
+{
+    struct mport *mport;
+
+    ovs_rwlock_rdlock(&monitor_rwlock);
+    HMAP_FOR_EACH (mport, hmap_node, &monitor_hmap) {
+        if (mport->cfm) {
+            cfm_run(mport->cfm);
+        }
+        if (mport->bfd) {
+            bfd_run(mport->bfd);
+        }
+    }
+    ovs_rwlock_unlock(&monitor_rwlock);
+}
+
+/* Executes the bfd_wait() and cfm_wait() functions on all mports. */
+void
+ofproto_dpif_monitor_wait(void)
+{
+    struct mport *mport;
+
+    ovs_rwlock_rdlock(&monitor_rwlock);
+    HMAP_FOR_EACH (mport, hmap_node, &monitor_hmap) {
+        if (mport->cfm) {
+            cfm_wait(mport->cfm);
+        }
+        if (mport->bfd) {
+            bfd_wait(mport->bfd);
+        }
+    }
+    ovs_rwlock_unlock(&monitor_rwlock);
+}
diff --git a/ofproto/ofproto-dpif-monitor.h b/ofproto/ofproto-dpif-monitor.h
new file mode 100644 (file)
index 0000000..8e26814
--- /dev/null
@@ -0,0 +1,34 @@
+/* Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. */
+
+#ifndef OFPROTO_DPIF_MONITOR_H
+#define OFPROTO_DPIF_MONITOR_H 1
+
+#include <stdint.h>
+
+#include "packets.h"
+
+struct bfd;
+struct cfm;
+struct ofport_dpif;
+
+void ofproto_dpif_monitor_run(void);
+void ofproto_dpif_monitor_run_fast(void);
+void ofproto_dpif_monitor_wait(void);
+
+void ofproto_dpif_monitor_port_update(const struct ofport_dpif *,
+                                      struct bfd *, struct cfm *,
+                                      uint8_t[OFP_ETH_ALEN]);
+
+#endif /* ofproto-dpif-monitor.h */
index 930abc3..de65f6c 100644 (file)
@@ -206,6 +206,8 @@ static struct hmap xports = HMAP_INITIALIZER(&xports);
 static bool may_receive(const struct xport *, struct xlate_ctx *);
 static void do_xlate_actions(const struct ofpact *, size_t ofpacts_len,
                              struct xlate_ctx *);
+static void xlate_actions__(struct xlate_in *, struct xlate_out *)
+    OVS_REQ_RDLOCK(xlate_rwlock);
 static void xlate_normal(struct xlate_ctx *);
 static void xlate_report(struct xlate_ctx *, const char *);
 static void xlate_table_action(struct xlate_ctx *, ofp_port_t in_port,
@@ -2639,13 +2641,23 @@ actions_output_to_local_port(const struct xlate_ctx *ctx)
     return false;
 }
 
+/* Thread safe call to xlate_actions__(). */
+void
+xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
+{
+    ovs_rwlock_rdlock(&xlate_rwlock);
+    xlate_actions__(xin, xout);
+    ovs_rwlock_unlock(&xlate_rwlock);
+}
+
 /* Translates the 'ofpacts_len' bytes of "struct ofpacts" starting at 'ofpacts'
  * into datapath actions in 'odp_actions', using 'ctx'.
  *
  * The caller must take responsibility for eventually freeing 'xout', with
  * xlate_out_uninit(). */
-void
-xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
+static void
+xlate_actions__(struct xlate_in *xin, struct xlate_out *xout)
+    OVS_REQ_RDLOCK(xlate_rwlock)
 {
     struct flow_wildcards *wc = &xout->wc;
     struct flow *flow = &xin->flow;
@@ -2661,8 +2673,6 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
 
     COVERAGE_INC(xlate_actions);
 
-    ovs_rwlock_rdlock(&xlate_rwlock);
-
     /* Flow initialization rules:
      * - 'base_flow' must match the kernel's view of the packet at the
      *   time that action processing starts.  'flow' represents any
@@ -2825,7 +2835,59 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
     memset(&wc->masks.regs, 0, sizeof wc->masks.regs);
 
 out:
+    rule_actions_unref(actions);
+}
+
+/* Sends 'packet' out 'ofport'.
+ * May modify 'packet'.
+ * Returns 0 if successful, otherwise a positive errno value. */
+int
+xlate_send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet)
+{
+    uint64_t odp_actions_stub[1024 / 8];
+    struct xport *xport;
+    struct ofpbuf key, odp_actions;
+    struct dpif_flow_stats stats;
+    struct odputil_keybuf keybuf;
+    struct ofpact_output output;
+    struct xlate_out xout;
+    struct xlate_in xin;
+    struct flow flow;
+    union flow_in_port in_port_;
+    int error;
+
+    ofpbuf_use_stub(&odp_actions, odp_actions_stub, sizeof odp_actions_stub);
+    ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
+    ofpact_init(&output.ofpact, OFPACT_OUTPUT, sizeof output);
+    /* Use OFPP_NONE as the in_port to avoid special packet processing. */
+    in_port_.ofp_port = OFPP_NONE;
+    flow_extract(packet, 0, 0, NULL, &in_port_, &flow);
+
+    ovs_rwlock_rdlock(&xlate_rwlock);
+    xport = xport_lookup(ofport);
+    if (!xport) {
+        error = EINVAL;
+        ovs_rwlock_unlock(&xlate_rwlock);
+        goto out;
+    }
+
+    odp_flow_key_from_flow(&key, &flow, ofp_port_to_odp_port(xport->xbridge, OFPP_LOCAL));
+    dpif_flow_stats_extract(&flow, packet, time_msec(), &stats);
+    output.port = xport->ofp_port;
+    output.max_len = 0;
+    xlate_in_init(&xin, xport->xbridge->ofproto, &flow, NULL, 0, packet);
+    xin.ofpacts_len = sizeof output;
+    xin.ofpacts = &output.ofpact;
+    xin.resubmit_stats = &stats;
+    /* Calls xlate_actions__ directly, since the rdlock is acquired. */
+    xlate_actions__(&xin, &xout);
+    error = dpif_execute(xport->xbridge->dpif,
+                         key.data, key.size,
+                         xout.odp_actions.data, xout.odp_actions.size,
+                         packet);
     ovs_rwlock_unlock(&xlate_rwlock);
 
-    rule_actions_unref(actions);
+out:
+    xlate_out_uninit(&xout);
+    return error;
 }
index 6403f50..554d46e 100644 (file)
@@ -160,4 +160,6 @@ struct dpif_sflow *xlate_get_sflow(const struct ofproto_dpif *)
 struct dpif_ipfix *xlate_get_ipfix(const struct ofproto_dpif *)
     OVS_EXCLUDED(xlate_rwlock);
 
+int xlate_send_packet(const struct ofport_dpif *, struct ofpbuf *);
+
 #endif /* ofproto-dpif-xlate.h */
index 80e97e0..7eff326 100644 (file)
@@ -52,6 +52,7 @@
 #include "ofproto-dpif-governor.h"
 #include "ofproto-dpif-ipfix.h"
 #include "ofproto-dpif-mirror.h"
+#include "ofproto-dpif-monitor.h"
 #include "ofproto-dpif-sflow.h"
 #include "ofproto-dpif-upcall.h"
 #include "ofproto-dpif-xlate.h"
@@ -361,8 +362,6 @@ ofport_dpif_cast(const struct ofport *ofport)
 }
 
 static void port_run(struct ofport_dpif *);
-static void port_run_fast(struct ofport_dpif *);
-static void port_wait(struct ofport_dpif *);
 static int set_bfd(struct ofport *, const struct smap *);
 static int set_cfm(struct ofport *, const struct cfm_settings *);
 static void ofport_update_peer(struct ofport_dpif *);
@@ -470,8 +469,9 @@ struct ofproto_dpif {
     struct classifier facets;     /* Contains 'struct facet's. */
     long long int consistency_rl;
 
-    struct netdev_stats stats; /* To account packets generated and consumed in
-                                * userspace. */
+    struct ovs_mutex stats_mutex;
+    struct netdev_stats stats OVS_GUARDED; /* To account packets generated and
+                                            * consumed in userspace. */
 
     /* Spanning tree. */
     struct stp *stp;
@@ -526,9 +526,6 @@ static int expire(struct dpif_backer *);
 /* NetFlow. */
 static void send_netflow_active_timeouts(struct ofproto_dpif *);
 
-/* Utilities. */
-static int send_packet(const struct ofport_dpif *, struct ofpbuf *packet);
-
 /* Global variables. */
 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
 
@@ -1233,6 +1230,7 @@ construct(struct ofproto *ofproto_)
     ofproto->ml = mac_learning_create(MAC_ENTRY_DEFAULT_IDLE_TIME);
     ofproto->mbridge = mbridge_create();
     ofproto->has_bonded_bundles = false;
+    ovs_mutex_init(&ofproto->stats_mutex);
     ovs_mutex_init(&ofproto->vsp_mutex);
 
     classifier_init(&ofproto->facets);
@@ -1420,6 +1418,7 @@ destruct(struct ofproto *ofproto_)
     sset_destroy(&ofproto->ghost_ports);
     sset_destroy(&ofproto->port_poll_set);
 
+    ovs_mutex_destroy(&ofproto->stats_mutex);
     ovs_mutex_destroy(&ofproto->vsp_mutex);
 
     close_dpif_backer(ofproto->backer);
@@ -1430,7 +1429,6 @@ run_fast(struct ofproto *ofproto_)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
     struct ofputil_packet_in *pin, *next_pin;
-    struct ofport_dpif *ofport;
     struct list pins;
 
     /* Do not perform any periodic activity required by 'ofproto' while
@@ -1447,10 +1445,7 @@ run_fast(struct ofproto *ofproto_)
         free(pin);
     }
 
-    HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
-        port_run_fast(ofport);
-    }
-
+    ofproto_dpif_monitor_run_fast();
     return 0;
 }
 
@@ -1492,6 +1487,9 @@ run(struct ofproto *ofproto_)
         dpif_ipfix_run(ofproto->ipfix);
     }
 
+    ofproto_dpif_monitor_run_fast();
+    ofproto_dpif_monitor_run();
+
     HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
         port_run(ofport);
     }
@@ -1536,7 +1534,6 @@ static void
 wait(struct ofproto *ofproto_)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
-    struct ofport_dpif *ofport;
     struct ofbundle *bundle;
 
     if (ofproto_get_flow_restore_wait()) {
@@ -1549,9 +1546,7 @@ wait(struct ofproto *ofproto_)
     if (ofproto->ipfix) {
         dpif_ipfix_wait(ofproto->ipfix);
     }
-    HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
-        port_wait(ofport);
-    }
+    ofproto_dpif_monitor_wait();
     HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) {
         bundle_wait(bundle);
     }
@@ -1814,6 +1809,9 @@ port_modified(struct ofport *port_)
         bfd_set_netdev(port->bfd, port->up.netdev);
     }
 
+    ofproto_dpif_monitor_port_update(port, port->bfd, port->cfm,
+                                     port->up.pp.hw_addr);
+
     if (port->is_tunnel && tnl_port_reconfigure(port, port->up.netdev,
                                                 port->odp_port)) {
         ofproto_dpif_cast(port->up.ofproto)->backer->need_revalidate =
@@ -1904,11 +1902,9 @@ static int
 set_cfm(struct ofport *ofport_, const struct cfm_settings *s)
 {
     struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
-    int error;
+    int error = 0;
 
-    if (!s) {
-        error = 0;
-    } else {
+    if (s) {
         if (!ofport->cfm) {
             struct ofproto_dpif *ofproto;
 
@@ -1918,13 +1914,17 @@ set_cfm(struct ofport *ofport_, const struct cfm_settings *s)
         }
 
         if (cfm_configure(ofport->cfm, s)) {
-            return 0;
+            error = 0;
+            goto out;
         }
 
         error = EINVAL;
     }
     cfm_unref(ofport->cfm);
     ofport->cfm = NULL;
+out:
+    ofproto_dpif_monitor_port_update(ofport, ofport->bfd, ofport->cfm,
+                                     ofport->up.pp.hw_addr);
     return error;
 }
 
@@ -1958,7 +1958,8 @@ set_bfd(struct ofport *ofport_, const struct smap *cfg)
     if (ofport->bfd != old) {
         ofproto->backer->need_revalidate = REV_RECONFIGURE;
     }
-
+    ofproto_dpif_monitor_port_update(ofport, ofport->bfd, ofport->cfm,
+                                     ofport->up.pp.hw_addr);
     return 0;
 }
 
@@ -1996,7 +1997,7 @@ send_bpdu_cb(struct ofpbuf *pkt, int port_num, void *ofproto_)
             VLOG_WARN_RL(&rl, "%s: cannot send BPDU on port %d "
                          "with unknown MAC", ofproto->up.name, port_num);
         } else {
-            send_packet(ofport, pkt);
+            ofproto_dpif_send_packet(ofport, pkt);
         }
     }
     ofpbuf_delete(pkt);
@@ -2592,7 +2593,7 @@ send_pdu_cb(void *port_, const void *pdu, size_t pdu_size)
                                  pdu_size);
         memcpy(packet_pdu, pdu, pdu_size);
 
-        send_packet(port, &packet);
+        ofproto_dpif_send_packet(port, &packet);
         ofpbuf_uninit(&packet);
     } else {
         VLOG_ERR_RL(&rl, "port %s: cannot obtain Ethernet address of iface "
@@ -2629,7 +2630,7 @@ bundle_send_learning_packets(struct ofbundle *bundle)
     LIST_FOR_EACH (learning_packet, list_node, &packets) {
         int ret;
 
-        ret = send_packet(learning_packet->private_p, learning_packet);
+        ret = ofproto_dpif_send_packet(learning_packet->private_p, learning_packet);
         if (ret) {
             error = ret;
             n_errors++;
@@ -2843,28 +2844,6 @@ ofport_update_peer(struct ofport_dpif *ofport)
     free(peer_name);
 }
 
-static void
-port_run_fast(struct ofport_dpif *ofport)
-{
-    if (ofport->cfm && cfm_should_send_ccm(ofport->cfm)) {
-        struct ofpbuf packet;
-
-        ofpbuf_init(&packet, 0);
-        cfm_compose_ccm(ofport->cfm, &packet, ofport->up.pp.hw_addr);
-        send_packet(ofport, &packet);
-        ofpbuf_uninit(&packet);
-    }
-
-    if (ofport->bfd && bfd_should_send_packet(ofport->bfd)) {
-        struct ofpbuf packet;
-
-        ofpbuf_init(&packet, 0);
-        bfd_put_packet(ofport->bfd, &packet, ofport->up.pp.hw_addr);
-        send_packet(ofport, &packet);
-        ofpbuf_uninit(&packet);
-    }
-}
-
 static void
 port_run(struct ofport_dpif *ofport)
 {
@@ -2876,12 +2855,9 @@ port_run(struct ofport_dpif *ofport)
 
     ofport->carrier_seq = carrier_seq;
 
-    port_run_fast(ofport);
-
     if (ofport->cfm) {
         int cfm_opup = cfm_get_opup(ofport->cfm);
 
-        cfm_run(ofport->cfm);
         cfm_enable = !cfm_get_fault(ofport->cfm);
 
         if (cfm_opup >= 0) {
@@ -2890,7 +2866,6 @@ port_run(struct ofport_dpif *ofport)
     }
 
     if (ofport->bfd) {
-        bfd_run(ofport->bfd);
         bfd_enable = bfd_forwarding(ofport->bfd);
     }
 
@@ -2913,18 +2888,6 @@ port_run(struct ofport_dpif *ofport)
     ofport->may_enable = enable;
 }
 
-static void
-port_wait(struct ofport_dpif *ofport)
-{
-    if (ofport->cfm) {
-        cfm_wait(ofport->cfm);
-    }
-
-    if (ofport->bfd) {
-        bfd_wait(ofport->bfd);
-    }
-}
-
 static int
 port_query_by_name(const struct ofproto *ofproto_, const char *devname,
                    struct ofproto_port *ofproto_port)
@@ -3038,10 +3001,11 @@ port_get_stats(const struct ofport *ofport_, struct netdev_stats *stats)
     if (!error && ofport_->ofp_port == OFPP_LOCAL) {
         struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
 
+        ovs_mutex_lock(&ofproto->stats_mutex);
         /* ofproto->stats.tx_packets represents packets that we created
          * internally and sent to some port (e.g. packets sent with
-         * send_packet()).  Account for them as if they had come from
-         * OFPP_LOCAL and got forwarded. */
+         * ofproto_dpif_send_packet()).  Account for them as if they had
+         * come from OFPP_LOCAL and got forwarded. */
 
         if (stats->rx_packets != UINT64_MAX) {
             stats->rx_packets += ofproto->stats.tx_packets;
@@ -3062,6 +3026,7 @@ port_get_stats(const struct ofport *ofport_, struct netdev_stats *stats)
         if (stats->tx_bytes != UINT64_MAX) {
             stats->tx_bytes += ofproto->stats.rx_bytes;
         }
+        ovs_mutex_unlock(&ofproto->stats_mutex);
     }
 
     return error;
@@ -4825,55 +4790,18 @@ rule_modify_actions(struct rule *rule_, bool reset_counters)
 /* Sends 'packet' out 'ofport'.
  * May modify 'packet'.
  * Returns 0 if successful, otherwise a positive errno value. */
-static int
-send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet)
+int
+ofproto_dpif_send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
-    uint64_t odp_actions_stub[1024 / 8];
-    struct ofpbuf key, odp_actions;
-    struct dpif_flow_stats stats;
-    struct odputil_keybuf keybuf;
-    struct ofpact_output output;
-    struct xlate_out xout;
-    struct xlate_in xin;
-    struct flow flow;
-    union flow_in_port in_port_;
     int error;
 
-    ofpbuf_use_stub(&odp_actions, odp_actions_stub, sizeof odp_actions_stub);
-    ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
-
-    /* Use OFPP_NONE as the in_port to avoid special packet processing. */
-    in_port_.ofp_port = OFPP_NONE;
-    flow_extract(packet, 0, 0, NULL, &in_port_, &flow);
-    odp_flow_key_from_flow(&key, &flow, ofp_port_to_odp_port(ofproto,
-                                                             OFPP_LOCAL));
-    dpif_flow_stats_extract(&flow, packet, time_msec(), &stats);
-
-    ofpact_init(&output.ofpact, OFPACT_OUTPUT, sizeof output);
-    output.port = ofport->up.ofp_port;
-    output.max_len = 0;
-
-    xlate_in_init(&xin, ofproto, &flow, NULL, 0, packet);
-    xin.ofpacts_len = sizeof output;
-    xin.ofpacts = &output.ofpact;
-    xin.resubmit_stats = &stats;
-    xlate_actions(&xin, &xout);
-
-    error = dpif_execute(ofproto->backer->dpif,
-                         key.data, key.size,
-                         xout.odp_actions.data, xout.odp_actions.size,
-                         packet);
-    xlate_out_uninit(&xout);
-
-    if (error) {
-        VLOG_WARN_RL(&rl, "%s: failed to send packet on port %s (%s)",
-                     ofproto->up.name, netdev_get_name(ofport->up.netdev),
-                     ovs_strerror(error));
-    }
+    error = xlate_send_packet(ofport, packet);
 
+    ovs_mutex_lock(&ofproto->stats_mutex);
     ofproto->stats.tx_packets++;
     ofproto->stats.tx_bytes += packet->size;
+    ovs_mutex_unlock(&ofproto->stats_mutex);
     return error;
 }
 
index 14a9669..0863efd 100644 (file)
@@ -95,6 +95,7 @@ bool vsp_adjust_flow(const struct ofproto_dpif *, struct flow *);
 
 void ofproto_dpif_send_packet_in(struct ofproto_dpif *,
                                  struct ofputil_packet_in *pin);
+int ofproto_dpif_send_packet(const struct ofport_dpif *, struct ofpbuf *);
 void ofproto_dpif_flow_mod(struct ofproto_dpif *, struct ofputil_flow_mod *);
 
 struct ofport_dpif *odp_port_to_ofport(const struct dpif_backer *, odp_port_t);
index 7b0ec36..d682be5 100755 (executable)
@@ -1,6 +1,6 @@
 #! /usr/bin/perl
 
-# Copyright (c) 2009, 2010, 2011 Nicira, Inc.
+# Copyright (c) 2009, 2010, 2011, 2013 Nicira, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 use strict;
 use warnings;
 
+use Getopt::Long;
+
+my $font_scale = 0;
+GetOptions("f=i" => \$font_scale) || exit 1;
+
 my ($scale) = 1;
+printf ".ps %+d\n", -$font_scale if $font_scale;
 print ".PS\n";
 print "linethick = 1;\n";
 while (<>) {
@@ -70,4 +76,5 @@ while (<>) {
     }
 
 }
+printf ".ps %+d\n", $font_scale if $font_scale;
 print ".PE\n";
index 662ed97..46f1101 100755 (executable)
@@ -212,6 +212,8 @@ def columnGroupToNroff(table, groupXml):
             else:
                 nameNroff = name
                 typeNroff = typeAndConstraintsToNroff(column)
+            if not column.mutable:
+                typeNroff = "immutable %s" % typeNroff
             body += '.IP "\\fB%s\\fR: %s"\n' % (nameNroff, typeNroff)
             body += blockXmlToNroff(node.childNodes, '.IP') + "\n"
             summary += [('column', nameNroff, typeNroff)]
index 85c126d..8ea8473 100755 (executable)
@@ -41,6 +41,7 @@ def schemaToDot(schemaFile):
     schema = ovs.db.schema.DbSchema.from_json(ovs.json.from_file(schemaFile))
 
     print "digraph %s {" % schema.name
+    print '\trankdir=LR;'
     print '\tsize="6.5,4";'
     print '\tmargin="0";'
     print "\tnode [shape=box];"
index 55fbcba..a01701a 100644 (file)
@@ -733,7 +733,6 @@ class Transaction(object):
         self._status = Transaction.UNCOMMITTED
         self._error = None
         self._comments = []
-        self._commit_seqno = self.idl.change_seqno
 
         self._inc_row = None
         self._inc_column = None
index 0b2b7cc..3154909 100644 (file)
@@ -259,10 +259,25 @@ OVS_VSWITCHD_START([add-br br1 -- set bridge br1 datapath-type=dummy -- \
                     set Interface p1 bfd:enable=true bfd:min_tx=500 bfd:min_rx=500])
 
 ovs-appctl time/stop
-
-# wait for local session state to go from down to up.
 for i in `seq 0 1`; do ovs-appctl time/warp 500; done
-BFD_CHECK([p0], [true], [false], [none], [up], [No Diagnostic], [none], [init], [No Diagnostic])
+
+# figuring out which port initiates the bfd session is important,
+# since this whole unit test is based on exact timing sequence.
+# for example, if p0 starts the bfd session, the p0 should have gone
+# [up] now, and it will decay after 3000ms. if p1 starts the bfd
+# session, we should wait for another 1000ms for p0 to go [up], and
+# then 3000ms for it to decay.
+
+# check which port sends the first bfd control packet.
+if [ ovs-appctl bfd/show p0 | grep "Remote Session State: init" ]
+then
+# if p0 sends first, it should have gone up already.
+    BFD_CHECK([p0], [true], [false], [none], [up], [No Diagnostic], [none], [init], [No Diagnostic])
+else
+# if p1 sends first, wait 1000ms for p0 to go up.
+    BFD_CHECK([p0], [false], [false], [none], [init], [No Diagnostic], [none], [down], [No Diagnostic])
+    for i in `seq 0 1`; do ovs-appctl time/warp 500; done
+fi
 
 
 # Test-1 BFD decay: decay to decay_min_rx
@@ -450,7 +465,7 @@ done
 AT_CHECK([ovs-vsctl set Interface p0 bfd:decay_min_rx=3000 -- set interface p1 bfd:min_tx=5000])
 # there will be poll sequences from both sides. and it is hard to determine the
 # order. so just skip 10000ms and check the RX/TX. at that time, p0 should be in decay already.
-for i in `seq 0 19`; do echo $i; ovs-appctl bfd/show; ovs-appctl time/warp 500; done
+for i in `seq 0 19`; do ovs-appctl time/warp 500; done
 BFD_CHECK([p0], [true], [false], [none], [up], [No Diagnostic], [none], [up], [No Diagnostic])
 BFD_CHECK([p1], [true], [false], [none], [up], [No Diagnostic], [none], [up], [No Diagnostic])
 BFD_CHECK_TX([p0], [500ms], [300ms], [5000ms])
@@ -493,15 +508,12 @@ BFD_CHECK_RX([p0], [300ms], [300ms], [1ms])
 
 # resume the bfd on p1. the bfd should not go to decay mode direclty.
 AT_CHECK([ovs-vsctl set Interface p1 bfd:enable=true])
-for i in `seq 0 1`; do ovs-appctl time/warp 500; done
-BFD_CHECK([p0], [true], [false], [none], [up], [Control Detection Time Expired], [none], [up], [No Diagnostic])
+for i in `seq 0 3`; do ovs-appctl time/warp 500; done
 BFD_CHECK_TX([p0], [500ms], [300ms], [500ms])
 BFD_CHECK_RX([p0], [500ms], [300ms], [500ms])
 
-# since the decay_min_rx is still 3000ms, so after 3000ms, there should be the decay and poll sequence.
+# since the decay_min_rx is still 3000ms, so after 3000ms, there should be the decay.
 for i in `seq 0 5`; do ovs-appctl time/warp 500; done
-BFD_CHECK([p0], [true], [false], [none], [up], [Control Detection Time Expired], [final], [up], [No Diagnostic])
-BFD_CHECK([p1], [true], [false], [none], [up], [No Diagnostic], [poll], [up], [Control Detection Time Expired])
 BFD_CHECK_TX([p0], [500ms], [300ms], [500ms])
 BFD_CHECK_RX([p0], [3000ms], [3000ms], [500ms])
 # End of Test-8 ################################################################
index b706373..87e3d0e 100644 (file)
@@ -2839,40 +2839,6 @@ AT_CHECK([ovs-appctl bond/show | sed -n '/^.*may_enable:.*/p'], [0], [dnl
        may_enable: true
 ])
 
-OVS_VSWITCHD_STOP
-AT_CLEANUP
-
-# Unit test for appctl coverage/show command
-AT_SETUP([ofproto-dpif - coverage/show])
-OVS_VSWITCHD_START
-
-ovs-appctl time/stop
-# before the first 5 seconds, nothing can be calculated but the total count.
-# there should be two unixctl commands received, but the count of the "appctl
-# coverage/show" command is not updated to the total. so there show only 1.
-AT_CHECK([ovs-appctl coverage/show | sed -n '/^unixctl_received.*/p'], [], [dnl
-unixctl_received           0.0/sec     0.000/sec        0.0000/sec   total: 1
-])
-
-ovs-appctl time/warp 5000
-# at first 5 second time instant, should have stats.
-AT_CHECK([ovs-appctl coverage/show | sed -n '/^unixctl_received.*/p'], [], [dnl
-unixctl_received           0.6/sec     0.050/sec        0.0008/sec   total: 3
-])
-
-for i in `seq 0 10`; do ovs-appctl time/warp 5000; done
-# advance to first 1 minute time instant.
-AT_CHECK([ovs-appctl coverage/show | sed -n '/^unixctl_received.*/p'], [], [dnl
-unixctl_received           0.2/sec     0.250/sec        0.0042/sec   total: 15
-])
-
-ovs-appctl time/warp 60000
-# advance to next 1 minute time instant directly, should observe the per-minute
-# rate drop.
-AT_CHECK([ovs-appctl coverage/show | sed -n '/^unixctl_received.*/p'], [], [dnl
-unixctl_received           0.4/sec     0.033/sec        0.0047/sec   total: 17
-])
-
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 \f
index 1684ddc..029ed3b 100644 (file)
@@ -49,6 +49,14 @@ ovs_ctl () {
             # pipe). So, do not log the o/p to ovs-ctl.log.
             "${datadir}/scripts/ovs-ctl" "$@"
         ;;
+        "status")
+            # In case of the command 'status', we should return the exit status
+            # of ovs-ctl. It is also useful to document the o/p in ovs-ctl.log.
+            display=`"${datadir}/scripts/ovs-ctl" "$@" 2>&1`
+            rc=$?
+            echo "${display}" | tee -a "${logdir}/ovs-ctl.log"
+            return ${rc}
+        ;;
         *)
             echo "`date -u`:$@" >> "${logdir}/ovs-ctl.log"
             "${datadir}/scripts/ovs-ctl" "$@" 2>&1 | tee -a "${logdir}/ovs-ctl.log"
index 3a271c6..6260a72 100644 (file)
@@ -48,7 +48,7 @@ if HAVE_DOT
          echo "regenerating vswitch.pic";                              \
          (echo ".\\\" Generated from vswitch.gv with cksum \"$$sum\""; \
           dot -T plain < $(srcdir)/vswitchd/vswitch.gv                 \
-           | $(srcdir)/ovsdb/dot2pic) > $@;                            \
+           | $(srcdir)/ovsdb/dot2pic -f 3) > $@;                       \
        fi
 else
        touch $@
index 56d666c..51fdae1 100644 (file)
@@ -1,4 +1,5 @@
 digraph Open_vSwitch {
+       rankdir=LR;
        size="6.5,4";
        margin="0";
        node [shape=box];
index 81339d2..3bd4e12 100644 (file)
@@ -1,92 +1,94 @@
-.\" Generated from vswitch.gv with cksum "2412173910 1224"
+.\" Generated from vswitch.gv with cksum "813191710 1237"
+.ps -3
 .PS
 linethick = 1;
 linethick = 1;
-box at 1.639964024,1.91216 wid 0.4050050488 height 0.23902 "Bridge"
+box at 2.421242138,1.420752459 wid 0.3611105806 height 0.213115 "Bridge"
 linethick = 1;
-box at 5.72978744,1.31461 wid 0.3718099512 height 0.23902 "sFlow"
+box at 3.907122541,0.970866694 wid 0.3315131694 height 0.213115 "sFlow"
 linethick = 1;
-box at 6.22790512,1.31461 wid 0.3917250976 height 0.23902 "Mirror"
+box at 3.907122541,0.651194194 wid 0.3492699112 height 0.213115 "Mirror"
 linethick = 1;
-box at 0.2589399268,1.31461 wid 0.35853 height 0.23902 "IPFIX"
+box at 3.907122541,1.929884194 wid 0.3196725 height 0.213115 "IPFIX"
 linethick = 1;
-box at 0.736994268,1.31461 wid 0.35853 height 0.23902 "Port"
+box at 3.907122541,0.2249556694 wid 0.3196725 height 0.213115 "Port"
 linethick = 1;
-box at 1.321254756,1.31461 wid 0.570970976 height 0.23902 "Controller"
+box at 3.907122541,1.610211694 wid 0.509089112 height 0.213115 "Controller"
 linethick = 1;
-box at 2.03167,1.31461 wid 0.610839512 height 0.23902 "Flow_Table"
+box at 3.907122541,1.290539194 wid 0.544636694 height 0.213115 "Flow_Table"
 linethick = 1;
-box at 5.17191476,1.31461 wid 0.491329512 height 0.23902 "NetFlow"
+box at 3.907122541,2.249556694 wid 0.438079194 height 0.213115 "NetFlow"
 linethick = 0.5;
-box at 0.35853,0.71706 wid 0.35853 height 0.23902 "QoS"
-box at 0.35853,0.71706 wid 0.302974444444444 height 0.183464444444444
+box at 5.09685834,0.42623 wid 0.3196725 height 0.213115 "QoS"
+box at 5.09685834,0.42623 wid 0.264116944444444 height 0.157559444444444
 linethick = 0.5;
-box at 0.35853,0.11951 wid 0.4116450244 height 0.23902 "Queue"
-box at 0.35853,0.11951 wid 0.356089468844444 height 0.183464444444444
+box at 6.31630237,0.42623 wid 0.3670309153 height 0.213115 "Queue"
+box at 6.31630237,0.42623 wid 0.311475359744445 height 0.157559444444444
 linethick = 0.5;
-box at 0.683884024,2.50971 wid 1.367720244 height 0.23902 "Flow_Sample_Collector_Set"
-box at 0.683884024,2.50971 wid 1.31216468844444 height 0.183464444444444
+box at 0.609764638,2.113376209 wid 1.219486653 height 0.213115 "Flow_Sample_Collector_Set"
+box at 0.609764638,2.113376209 wid 1.16393109744444 height 0.157559444444444
 linethick = 0.5;
-box at 2.177759024,2.50971 wid 0.770170244 height 0.23902 "Open_vSwitch"
-box at 2.177759024,2.50971 wid 0.714614688444444 height 0.183464444444444
+box at 0.609764638,1.101079959 wid 0.686699153 height 0.213115 "Open_vSwitch"
+box at 0.609764638,1.101079959 wid 0.631143597444444 height 0.157559444444444
 linethick = 1;
-box at 2.177759024,1.91216 wid 0.35853 height 0.23902 "SSL"
+box at 2.421242138,0.781407459 wid 0.3196725 height 0.213115 "SSL"
 linethick = 1;
-box at 2.728795732,1.91216 wid 0.511215976 height 0.23902 "Manager"
+box at 2.421242138,1.101079959 wid 0.455810362 height 0.213115 "Manager"
 linethick = 1;
-box at 0.916259268,0.71706 wid 0.517860732 height 0.23902 "Interface"
+box at 5.09685834,0.1065575 wid 0.461734959 height 0.213115 "Interface"
 linethick = 1;
-spline -> from 1.83949792,1.821380204 to 1.83949792,1.821380204 to 1.872052444,1.809763832 to 1.905897676,1.799533776 to 1.938739024,1.79265 to 2.331687904,1.7101881 to 5.21254816,1.889883336 to 5.55052244,1.67314 to 5.63322336,1.620173168 to 5.6791152,1.516773116 to 5.70397328,1.43459804
-"sflow?" at 5.80627384,1.613385
+spline -> from 2.585425934,1.312575285 to 2.585425934,1.312575285 to 2.608314485,1.295909692 to 2.63111779,1.278434262 to 2.652088306,1.260916209 to 2.703534267,1.217994848 to 2.699016229,1.184834154 to 2.758645806,1.154358709 to 3.077892076,0.991453603 to 3.506551587,0.966220787 to 3.739401036,0.966092918
+"sflow?" at 3.14344625,1.207637459
 linethick = 1;
-spline -> from 1.839450116,1.821284596 to 1.839450116,1.821284596 to 1.872052444,1.809668224 to 1.905897676,1.799485972 to 1.938739024,1.79265 to 2.378774844,1.701153144 to 5.58780956,1.888544824 to 5.98219256,1.67314 to 6.07541036,1.622133132 to 6.1404238,1.518541864 to 6.18010112,1.43579314
-"mirrors*" at 6.30725976,1.613385
+spline -> from 2.602048904,1.315686764 to 2.602048904,1.315686764 to 2.620845647,1.299234286 to 2.638150585,1.280949019 to 2.652088306,1.260916209 to 2.760819579,1.104916029 to 2.618714497,0.975299486 to 2.758645806,0.846535403 to 3.02580677,0.600728562 to 3.482938445,0.603584303 to 3.732325618,0.627240068
+"mirrors*" at 3.14344625,0.899814153
 linethick = 1;
-spline -> from 1.44033452,1.898966096 to 1.44033452,1.898966096 to 1.223830204,1.877406492 to 0.873952728,1.820806556 to 0.610839512,1.67314 to 0.505861928,1.614245472 to 0.4118171188,1.51466974 to 0.3474107896,1.435362904
-"ipfix?" at 0.733647988,1.613385
+spline -> from 2.530911117,1.527523074 to 2.530911117,1.527523074 to 2.592927582,1.581867399 to 2.674721119,1.644139602 to 2.758645806,1.681221612 to 3.076357648,1.821664397 to 3.190203681,1.737569218 to 3.528246694,1.817402097 to 3.60036481,1.834408674 to 3.679046868,1.85708411 to 3.745964978,1.877628396
+"ipfix?" at 3.14344625,1.870680847
 linethick = 1;
-spline -> from 1.439569656,1.871861228 to 1.439569656,1.871861228 to 1.302372176,1.836725288 to 1.12195988,1.775010324 to 0.989255976,1.67314 to 0.907176508,1.610086524 to 0.84111138,1.512853188 to 0.797179504,1.43555412
-"ports*" at 1.132046524,1.613385
+spline -> from 2.602091527,1.31918185 to 2.602091527,1.31918185 to 2.621399746,1.301919535 to 2.638832553,1.28252607 to 2.652088306,1.260916209 to 2.832980318,0.966817509 to 2.525753734,0.746286107 to 2.758645806,0.491357944 to 3.012678886,0.2132940166 to 3.494830262,0.1973231785 to 3.745964978,0.2103359804
+"ports*" at 3.14344625,0.544636694
 linethick = 1;
-spline -> from 1.43842236,1.800203032 to 1.43842236,1.800203032 to 1.39420366,1.765545132 to 1.353140024,1.72309518 to 1.327899512,1.67314 to 1.291090432,1.600334508 to 1.29022996,1.508168396 to 1.298165424,1.435506316
-"controller*" at 1.573564268,1.613385
+spline -> from 2.60341284,1.443981994 to 2.60341284,1.443981994 to 2.866141012,1.477483672 to 3.352469442,1.539500137 to 3.651128803,1.577562476
+"controller*" at 3.14344625,1.616136291
 linethick = 1;
-spline -> from 1.733755472,1.79241098 to 1.733755472,1.79241098 to 1.76205544,1.754837036 to 1.792697804,1.71281732 to 1.819229024,1.67314 to 1.870666128,1.596127756 to 1.923776372,1.506495256 to 1.96402734,1.436127768
-"flow_tables value*" at 2.327146524,1.613385
+spline -> from 2.601835789,1.365385182 to 2.601835789,1.365385182 to 2.652130929,1.352086806 to 2.707114599,1.339598267 to 2.758645806,1.33196875 to 3.055685493,1.28806706 to 3.400420317,1.281460495 to 3.634079603,1.283463776
+"flow_tables value*" at 3.14344625,1.3852475
 linethick = 1;
-spline -> from 1.83949792,1.821523616 to 1.83949792,1.821523616 to 1.872100248,1.809907244 to 1.90594548,1.799629384 to 1.938739024,1.79265 to 2.27451432,1.721230824 to 4.744929432,1.870188088 to 5.02611256,1.67314 to 5.103077,1.61912148 to 5.13940804,1.516964332 to 5.15661748,1.435458512
-"netflow?" at 5.32154128,1.613385
+spline -> from 2.465612681,1.527650943 to 2.465612681,1.527650943 to 2.518635693,1.642392059 to 2.618245644,1.821962758 to 2.758645806,1.923959597 to 3.037826456,2.126717208 to 3.4396761,2.203481231 to 3.686505893,2.232337002
+"netflow?" at 3.14344625,2.267287862
 linethick = 0.5;
-spline -> from 6.03429892,1.412082356 to 6.03429892,1.412082356 to 6.01469928,1.420209036 to 5.9946216,1.427714264 to 5.9755,1.43412 to 5.56247344,1.571030656 to 5.44869992,1.583650912 to 5.01607372,1.626674512 to 4.690146048,1.65903782 to 4.606536852,1.636187508 to 4.279127256,1.626674512 to 2.80920206,1.583842128 to 2.396749148,1.813492544 to 0.976014268,1.43412 to 0.956271216,1.42886156 to 0.936289144,1.421882176 to 0.916689504,1.413898908
-"select_src_port*" at 4.647600488,1.613385
+spline -> from 3.907122541,0.3339597296 to 3.907122541,0.3339597296 to 3.907122541,0.3983332465 to 3.907122541,0.47950875 to 3.907122541,0.543613742
+"select_src_port*" at 4.235660625,0.438079194
 linethick = 0.5;
-spline -> from 6.03429892,1.412082356 to 6.03429892,1.412082356 to 6.01469928,1.420209036 to 5.9946216,1.427714264 to 5.9755,1.43412 to 5.56247344,1.571030656 to 5.44869992,1.583650912 to 5.01607372,1.626674512 to 4.690146048,1.65903782 to 4.606536852,1.636187508 to 4.279127256,1.626674512 to 2.80920206,1.583842128 to 2.396749148,1.813492544 to 0.976014268,1.43412 to 0.956271216,1.42886156 to 0.936289144,1.421882176 to 0.916689504,1.413898908
-"output_port?" at 4.647600488,1.613385
+spline -> from 3.74485678,0.2306373153 to 3.74485678,0.2306373153 to 3.380984229,0.2450481516 to 2.525029143,0.2888859071 to 2.438973306,0.3847919194 to 2.40734704,0.4200454027 to 2.40734704,0.456108723 to 2.438973306,0.491357944 to 2.524176683,0.586279365 to 3.364062898,0.630223678 to 3.733817423,0.645056482
+"output_port?" at 2.708350666,0.438079194
 linethick = 0.5;
-spline -> from 6.03429892,1.412082356 to 6.03429892,1.412082356 to 6.01469928,1.420209036 to 5.9946216,1.427714264 to 5.9755,1.43412 to 5.56247344,1.571030656 to 5.44869992,1.583650912 to 5.01607372,1.626674512 to 4.690146048,1.65903782 to 4.606536852,1.636187508 to 4.279127256,1.626674512 to 2.80920206,1.583842128 to 2.396749148,1.813492544 to 0.976014268,1.43412 to 0.956271216,1.42886156 to 0.936289144,1.421882176 to 0.916689504,1.413898908
-"select_dst_port*" at 4.647600488,1.613385
+spline -> from 3.746007601,0.232167481 to 3.746007601,0.232167481 to 3.499731907,0.2491570088 to 3.072905185,0.3055728116 to 3.220423388,0.491357944 to 3.283377559,0.570679347 to 3.551945082,0.614240053 to 3.733945292,0.635125323
+"select_dst_port*" at 3.551902459,0.438079194
 linethick = 1;
-spline -> from 0.659121552,1.193092232 to 0.659121552,1.193092232 to 0.63507614,1.155470484 to 0.60854492,1.1138332 to 0.584260488,1.07559 to 0.533827268,0.996091948 to 0.4774089872,0.906459448 to 0.43358228,0.836713412
-"qos?" at 0.6871825,1.015835
+spline -> from 4.067598136,0.2520979958 to 4.067598136,0.2520979958 to 4.29469348,0.2905141057 to 4.70728412,0.3603433666 to 4.93531717,0.3988702963
+"qos?" at 4.52272653,0.4203096653
 linethick = 1;
-spline -> from 0.773277504,1.19366588 to 0.773277504,1.19366588 to 0.804350104,1.090026808 to 0.848951236,0.941404172 to 0.880023836,0.837812904
-"interfaces+" at 1.108765976,1.015835
+spline -> from 4.068450596,0.186646117 to 4.068450596,0.186646117 to 4.135411329,0.1722054446 to 4.214050764,0.1570870665 to 4.28616888,0.1479955806 to 4.48052976,0.1234234211 to 4.70259559,0.1133175078 to 4.86541545,0.1092129129
+"interfaces+" at 4.52272653,0.2012743306
 linethick = 1;
-spline -> from 0.35853,0.59611588 to 0.35853,0.59611588 to 0.35853,0.492476808 to 0.35853,0.3438732936 to 0.35853,0.2402533432
-"queues value*" at 0.690480976,0.418285
+spline -> from 5.25882574,0.42623 to 5.25882574,0.42623 to 5.48515387,0.42623 to 5.89433467,0.42623 to 6.13174478,0.42623
+"queues value*" at 5.73023612,0.47950875
 linethick = 1;
-spline -> from 0.877346812,2.38876588 to 0.877346812,2.38876588 to 1.043226692,2.285126808 to 1.280955984,2.136504172 to 1.446740256,2.032912904
-"bridge" at 1.390952988,2.210935
+spline -> from 0.888817419,2.00669084 to 0.888817419,2.00669084 to 1.263985065,1.863264445 to 1.920421888,1.612257598 to 2.238346845,1.490696802
+"bridge" at 1.70492,1.882530041
 linethick = 1;
-spline -> from 0.640764816,2.38852686 to 0.640764816,2.38852686 to 0.559115584,2.158876444 to 0.3827570672,1.66286214 to 0.3015046084,1.434311216
-"ipfix?" at 0.640717012,1.91216
+spline -> from 1.117404568,2.220359939 to 1.117404568,2.220359939 to 1.711441319,2.323507599 to 2.716960512,2.428999524 to 3.528246694,2.166654959 to 3.583827086,2.148710676 to 3.58587299,2.121645071 to 3.634804194,2.089720444 to 3.670607514,2.06636304 to 3.709863297,2.042366291 to 3.747158422,2.0203302
+"ipfix?" at 2.421242138,2.385694556
 linethick = 1;
-spline -> from 1.906375716,2.389148312 to 1.906375716,2.389148312 to 1.85455618,2.356545984 to 1.804553196,2.317155488 to 1.766070976,2.27069 to 1.70971006,2.2025693 to 1.677776988,2.107534948 to 1.660185116,2.032434864
-"bridges*" at 1.958625488,2.210935
+spline -> from 0.953945363,1.164289868 to 0.953945363,1.164289868 to 1.071883204,1.18577186 to 1.204696472,1.209811232 to 1.326044153,1.231335847 to 1.647123212,1.288280175 to 2.021566267,1.352598282 to 2.23898619,1.389722915
+"bridges*" at 1.70492,1.420752459
 linethick = 1;
-spline -> from 2.177759024,2.38876588 to 2.177759024,2.38876588 to 2.177759024,2.285126808 to 2.177759024,2.136504172 to 2.177759024,2.032912904
-"ssl?" at 2.260746768,2.210935
+spline -> from 0.953945363,1.037912673 to 0.953945363,1.037912673 to 1.071883204,1.016388058 to 1.204696472,0.992391309 to 1.326044153,0.970866694 to 1.657565847,0.912046954 to 2.045989246,0.845384582 to 2.259700968,0.808899294
+"ssl?" at 1.70492,1.024145444
 linethick = 1;
-spline -> from 2.289237952,2.38876588 to 2.289237952,2.38876588 to 2.384845952,2.285126808 to 2.52190002,2.136504172 to 2.617460216,2.032912904
-"manager_options*" at 2.924696524,2.210935
+spline -> from 0.9547552,1.101079959 to 0.9547552,1.101079959 to 1.318116275,1.101079959 to 1.880057907,1.101079959 to 2.192271382,1.101079959
+"manager_options*" at 1.70492,1.154358709
+.ps +3
 .PE