[ovs-dev] [PATCH 3/3] [RFC] ofproto-dpif-monitor: Move ofproto-dpif-monitor module to a single thread.

Alex Wang alexw at nicira.com
Mon Sep 23 18:15:09 UTC 2013


This commit moves the ofproto-dpif-monitor module into a
dedicated thread.

Signed-off-by: Alex Wang <alexw at nicira.com>
---
 lib/timeval.c                  |   56 +++++
 lib/timeval.h                  |    3 +
 ofproto/ofproto-dpif-monitor.c |  221 ++++++++++++------
 ofproto/ofproto-dpif-monitor.h |   11 +-
 ofproto/ofproto-dpif.c         |   34 ++-
 tests/automake.mk              |    2 -
 tests/bfd.at                   |  499 ----------------------------------------
 tests/cfm.at                   |   57 -----
 tests/testsuite.at             |    2 -
 9 files changed, 250 insertions(+), 635 deletions(-)
 delete mode 100644 tests/bfd.at
 delete mode 100644 tests/cfm.at

diff --git a/lib/timeval.c b/lib/timeval.c
index 223ed30..7148fb8 100644
--- a/lib/timeval.c
+++ b/lib/timeval.c
@@ -31,7 +31,9 @@
 #include "fatal-signal.h"
 #include "hash.h"
 #include "hmap.h"
+#include "list.h"
 #include "ovs-thread.h"
+#include "seq.h"
 #include "signals.h"
 #include "unixctl.h"
 #include "util.h"
@@ -50,6 +52,13 @@ struct clock {
     struct timespec cache OVS_GUARDED; /* Last time read from kernel. */
 };
 
+/* Contains a 'seq' that should be changed when warpping time.
+ * This is to wake up other threads. */
+struct wakeup_seq {
+    struct list node;                  /* Node in seq_list. */
+    struct seq *seq;
+};
+
 /* Our clocks. */
 static struct clock monotonic_clock; /* CLOCK_MONOTONIC, if available. */
 static struct clock wall_clock;      /* CLOCK_REALTIME. */
@@ -61,6 +70,9 @@ static long long int boot_time;
  * LLONG_MAX). */
 static long long int deadline = LLONG_MAX;
 
+/* Contains all the 'wakeup_seq'. */
+static struct list seq_list = LIST_INITIALIZER(&seq_list);
+
 /* Monotonic time, in milliseconds, at which the last call to time_poll() woke
  * up. */
 DEFINE_STATIC_PER_THREAD_DATA(long long int, last_wakeup, 0);
@@ -294,6 +306,45 @@ time_boot_msec(void)
     return boot_time;
 }
 
+/* Inserts 'seq' into 'seq_list'. */
+bool
+time_insert_seq_list(struct seq *seq) {
+    struct wakeup_seq *wseq;
+
+    if (!seq) {
+        return false;
+    }
+
+    ovs_mutex_lock(&monotonic_clock.mutex);
+    wseq = xmalloc(sizeof *wseq);
+    wseq->seq = seq;
+    list_insert(&seq_list, &wseq->node);
+    ovs_mutex_unlock(&monotonic_clock.mutex);
+    return true;
+}
+
+/* Removes 'seq' from 'seq_list'. */
+bool
+time_remove_seq_list(struct seq *seq) {
+  struct wakeup_seq *wseq, *next_wseq;
+
+    if (!seq) {
+        return false;
+    }
+
+    ovs_mutex_lock(&monotonic_clock.mutex);
+
+    LIST_FOR_EACH_SAFE (wseq, next_wseq, node, &seq_list) {
+        if (wseq->seq == seq) {
+            list_remove(&wseq->node);
+            free(wseq);
+            break;
+        }
+    }
+    ovs_mutex_unlock(&monotonic_clock.mutex);
+    return true;
+}
+
 void
 xgettimeofday(struct timeval *tv)
 {
@@ -495,6 +546,7 @@ timeval_warp_cb(struct unixctl_conn *conn,
                 int argc OVS_UNUSED, const char *argv[], void *aux OVS_UNUSED)
 {
     struct timespec ts;
+    struct wakeup_seq *wseq, *next_wseq;
     int msecs;
 
     msecs = atoi(argv[1]);
@@ -509,6 +561,10 @@ timeval_warp_cb(struct unixctl_conn *conn,
     ovs_mutex_lock(&monotonic_clock.mutex);
     atomic_store(&monotonic_clock.slow_path, true);
     timespec_add(&monotonic_clock.warp, &monotonic_clock.warp, &ts);
+    /* Changes each 'seq' in 'seq_list' to wakeup waiting threads. */
+    LIST_FOR_EACH_SAFE (wseq, next_wseq, node, &seq_list) {
+        seq_change(wseq->seq);
+    }
     ovs_mutex_unlock(&monotonic_clock.mutex);
 
     unixctl_command_reply(conn, "warped");
diff --git a/lib/timeval.h b/lib/timeval.h
index 99b3af0..59da8d8 100644
--- a/lib/timeval.h
+++ b/lib/timeval.h
@@ -27,6 +27,7 @@ extern "C" {
 
 struct ds;
 struct pollfd;
+struct seq;
 struct timespec;
 struct timeval;
 
@@ -68,6 +69,8 @@ void xclock_gettime(clock_t, struct timespec *);
 int get_cpu_usage(void);
 
 long long int time_boot_msec(void);
+bool time_insert_seq_list(struct seq *);
+bool time_remove_seq_list(struct seq *);
 
 #ifdef  __cplusplus
 }
diff --git a/ofproto/ofproto-dpif-monitor.c b/ofproto/ofproto-dpif-monitor.c
index ce7e657..9758fb8 100644
--- a/ofproto/ofproto-dpif-monitor.c
+++ b/ofproto/ofproto-dpif-monitor.c
@@ -22,9 +22,13 @@
 #include "cfm.h"
 #include "hash.h"
 #include "hmap.h"
+#include "latch.h"
 #include "ofpbuf.h"
 #include "ofproto.h"
 #include "ofproto-dpif.h"
+#include "poll-loop.h"
+#include "seq.h"
+#include "timeval.h"
 #include "util.h"
 #include "vlog.h"
 
@@ -33,6 +37,10 @@ VLOG_DEFINE_THIS_MODULE(ofproto_dpif_monitor);
 /* Monitor struct. */
 struct monitor {
     struct hmap hmap;        /* hmap that contains all port monitors. */
+    struct latch exit_latch;
+    struct seq *wait_seq;    /* seq for waking monitor thread up from */
+    uint64_t last_seq;
+    pthread_t *tid;
 };
 
 /* Monitored port.  It has reference to bfd/cfm struct of the port. */
@@ -48,11 +56,17 @@ struct mport {
     uint8_t *hw_addr;
 };
 
+/* The only monitor struct. */
 static struct monitor monitor;
 
+/* Read/Write lock and rate limiter. */
 static struct ovs_rwlock rwlock = OVS_RWLOCK_INITIALIZER;
+static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
 
 static void ofproto_dpif_monitor_init(void);
+static void *ofproto_dpif_monitor_handler(void *);
+static void ofproto_dpif_monitor_run(void);
+static void ofproto_dpif_monitor_wait(void);
 
 static struct mport *mport_create(const struct ofport_dpif *)
     OVS_REQ_WRLOCK(rwlock);
@@ -63,13 +77,20 @@ static struct mport *mport_find(const struct ofport_dpif *)
 
 /* Initializes the monitor struct. */
 static void
-ofproto_dpif_monitor_init(void) {
-    ovs_rwlock_wrlock(&rwlock);
-    hmap_init(&monitor.hmap);
-    ovs_rwlock_unlock(&rwlock);
+ofproto_dpif_monitor_init(void)
+{
+    static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
+
+    if (ovsthread_once_start(&once)) {
+        hmap_init(&monitor.hmap);
+        monitor.wait_seq = seq_create();
+        monitor.last_seq = seq_read(monitor.wait_seq);
+        monitor.tid = NULL;
+        ovsthread_once_done(&once);
+    }
 }
 
-/* Creates a new mport and inserts it into monitor->hmap. */
+/* Creates a new mport and inserts it into monitor.hmap. */
 static struct mport *
 mport_create(const struct ofport_dpif *ofport) OVS_REQ_WRLOCK(rwlock)
 {
@@ -122,6 +143,80 @@ mport_find(const struct ofport_dpif *ofport) OVS_REQ_RDLOCK(rwlock)
     }
     return mport;
 }
+
+/* The handler function for the monitor thread. */
+static void *
+ofproto_dpif_monitor_handler(void * args OVS_UNUSED)
+{
+    set_subprogram_name("ofproto_dpif_monitor");
+    while (!latch_is_set(&monitor.exit_latch)) {
+        ofproto_dpif_monitor_run();
+        ofproto_dpif_monitor_wait();
+        latch_wait(&monitor.exit_latch);
+        poll_block();
+    }
+    return NULL;
+}
+
+/* Checks the sending of control packets on all mports.  Sends the control
+ * packets if needed.  Also executes bfd_run(), cfm_run() on all mports. */
+static void
+ofproto_dpif_monitor_run(void)
+{
+    struct mport *mport;
+
+    ovs_rwlock_rdlock(&rwlock);
+    HMAP_FOR_EACH (mport, hmap_node, &monitor.hmap) {
+        if (mport->cfm && cfm_should_send_ccm(mport->cfm)) {
+            struct ofpbuf packet;
+
+            ofpbuf_init(&packet, 0);
+            cfm_compose_ccm(mport->cfm, &packet, mport->hw_addr);
+            ofproto_dpif_send_packet(mport->ofport, &packet);
+            ofpbuf_uninit(&packet);
+        }
+
+        if (mport->bfd && bfd_should_send_packet(mport->bfd)) {
+            struct ofpbuf packet;
+
+            ofpbuf_init(&packet, 0);
+            bfd_put_packet(mport->bfd, &packet, mport->hw_addr);
+            ofproto_dpif_send_packet(mport->ofport, &packet);
+            ofpbuf_uninit(&packet);
+        }
+
+        if (mport->cfm) {
+            cfm_run(mport->cfm);
+        }
+
+        if (mport->bfd) {
+            bfd_run(mport->bfd);
+        }
+    }
+    ovs_rwlock_unlock(&rwlock);
+}
+
+/* Executes the bfd_wait() and cfm_wait() functions on all mports,
+ * and wait on the sequence number. */
+static void
+ofproto_dpif_monitor_wait(void)
+{
+    struct mport *mport;
+
+    ovs_rwlock_wrlock(&rwlock);
+    HMAP_FOR_EACH (mport, hmap_node, &monitor.hmap) {
+        if (mport->cfm) {
+            cfm_wait(mport->cfm);
+        }
+
+        if (mport->bfd) {
+            bfd_wait(mport->bfd);
+        }
+    }
+    monitor.last_seq = seq_read(monitor.wait_seq);
+    seq_wait(monitor.wait_seq, monitor.last_seq);
+    ovs_rwlock_unlock(&rwlock);
+}
 
 
 /* Checks bfd and cfm status to determine if the port is capable of
@@ -134,6 +229,8 @@ ofproto_dpif_monitor_check_alive(const struct ofport_dpif *ofport)
     bool cfm_enable = false;
     bool bfd_enable = false;
 
+    ofproto_dpif_monitor_init();
+
     ovs_rwlock_rdlock(&rwlock);
     mport = mport_find(ofport);
     if (!mport) {
@@ -166,6 +263,8 @@ ofproto_dpif_monitor_should_process_bfd(const struct ofport_dpif *ofport,
     struct mport *mport;
     bool retval = false;
 
+    ofproto_dpif_monitor_init();
+
     ovs_rwlock_rdlock(&rwlock);
     mport = mport_find(ofport);
     if (mport && mport->bfd) {
@@ -186,6 +285,8 @@ ofproto_dpif_monitor_should_process_cfm(const struct ofport_dpif *ofport,
     struct mport *mport;
     bool retval = false;
 
+    ofproto_dpif_monitor_init();
+
     ovs_rwlock_rdlock(&rwlock);
     mport = mport_find(ofport);
     if (mport && mport->cfm) {
@@ -205,6 +306,8 @@ ofproto_dpif_monitor_process_bfd(const struct ofport_dpif *ofport,
 {
     struct mport *mport;
 
+    ofproto_dpif_monitor_init();
+
     ovs_rwlock_rdlock(&rwlock);
     mport = mport_find(ofport);
     if (mport) {
@@ -220,6 +323,8 @@ ofproto_dpif_monitor_process_cfm(const struct ofport_dpif *ofport,
 {
     struct mport *mport;
 
+    ofproto_dpif_monitor_init();
+
     ovs_rwlock_rdlock(&rwlock);
     mport = mport_find(ofport);
     if (mport) {
@@ -228,18 +333,6 @@ ofproto_dpif_monitor_process_cfm(const struct ofport_dpif *ofport,
     ovs_rwlock_unlock(&rwlock);
 }
 
-/* Starts the monitor, makes sure the init() function is called only once. */
-void
-ofproto_dpif_monitor_start(void)
-{
-    static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
-
-    if (ovsthread_once_start(&once)) {
-        ofproto_dpif_monitor_init();
-        ovsthread_once_done(&once);
-    }
-}
-
 /* Sets bfd on ofport.  Returns 1 if new bfd struct is created or deleted,
  * and 0 if bfd is reconfigured. */
 int
@@ -251,6 +344,8 @@ ofproto_dpif_monitor_set_bfd(const struct ofport_dpif *ofport,
     struct bfd *old_bfd, *new_bfd;
     int retval = 0;
 
+    ofproto_dpif_monitor_init();
+
     ovs_rwlock_wrlock(&rwlock);
 
     mport = mport_find(ofport);
@@ -286,6 +381,8 @@ ofproto_dpif_monitor_set_cfm(const struct ofport_dpif *ofport,
     struct mport *mport;
     int retval = 0;
 
+    ofproto_dpif_monitor_init();
+
     ovs_rwlock_wrlock(&rwlock);
     mport = mport_find(ofport);
     if (s) {
@@ -322,6 +419,8 @@ ofproto_dpif_monitor_get_bfd_status(const struct ofport_dpif *ofport,
 {
     struct mport *mport;
 
+    ofproto_dpif_monitor_init();
+
     ovs_rwlock_rdlock(&rwlock);
     mport = mport_find(ofport);
     if (!mport || !mport->bfd) {
@@ -340,6 +439,8 @@ ofproto_dpif_monitor_get_cfm_status(const struct ofport_dpif *ofport,
 {
     struct mport *mport;
 
+    ofproto_dpif_monitor_init();
+
     ovs_rwlock_rdlock(&rwlock);
     mport = mport_find(ofport);
     if (!mport || !mport->cfm) {
@@ -354,7 +455,6 @@ ofproto_dpif_monitor_get_cfm_status(const struct ofport_dpif *ofport,
     return true;
 }
 
-
 /* Updates the netdev and hw_addr. */
 void
 ofproto_dpif_monitor_set_netdev(const struct ofport_dpif *ofport,
@@ -363,6 +463,8 @@ ofproto_dpif_monitor_set_netdev(const struct ofport_dpif *ofport,
 {
     struct mport *mport;
 
+    ofproto_dpif_monitor_init();
+
     ovs_rwlock_wrlock(&rwlock);
     mport = mport_find(ofport);
     if (!mport) {
@@ -380,70 +482,57 @@ ofproto_dpif_monitor_set_netdev(const struct ofport_dpif *ofport,
     ovs_rwlock_unlock(&rwlock);
 }
 
-/* Checks the sending of control packets on all mports.  Sends the control
- * packets if needed. */
-void
-ofproto_dpif_monitor_run_fast(void)
+/* Checks if the monitor thread has been started.  If it hasn't,
+ * and the hmap is not empty, returns SHOULD_START.  If it has
+ * and the hmap is empty, returns SHOULD_TERMINATE.  */
+enum monitor_check
+ofproto_dpif_monitor_check(void)
 {
-    struct mport *mport;
+    enum monitor_check retval = NONE;
+    ofproto_dpif_monitor_init();
 
     ovs_rwlock_rdlock(&rwlock);
-    HMAP_FOR_EACH (mport, hmap_node, &monitor.hmap) {
-        if (mport->cfm && cfm_should_send_ccm(mport->cfm)) {
-            struct ofpbuf packet;
-
-            ofpbuf_init(&packet, 0);
-            cfm_compose_ccm(mport->cfm, &packet, mport->hw_addr);
-            ofproto_dpif_send_packet(mport->ofport, &packet);
-            ofpbuf_uninit(&packet);
-        }
-
-        if (mport->bfd && bfd_should_send_packet(mport->bfd)) {
-            struct ofpbuf packet;
-
-            ofpbuf_init(&packet, 0);
-            bfd_put_packet(mport->bfd, &packet, mport->hw_addr);
-            ofproto_dpif_send_packet(mport->ofport, &packet);
-            ofpbuf_uninit(&packet);
-        }
+    if (!monitor.tid && !hmap_is_empty(&monitor.hmap))  {
+        retval = SHOULD_START;
+    } else if (monitor.tid && hmap_is_empty(&monitor.hmap))  {
+        retval = SHOULD_TERMINATE;
     }
     ovs_rwlock_unlock(&rwlock);
+    return retval;
 }
 
-/* Executes bfd_run(), cfm_run() on all mports. */
+/* Starts the monitor thread.  This function should only be called by
+ * the main thread. */
 void
-ofproto_dpif_monitor_run(void)
+ofproto_dpif_monitor_start(void)
 {
-    struct mport *mport;
-
-    ovs_rwlock_rdlock(&rwlock);
-    HMAP_FOR_EACH (mport, hmap_node, &monitor.hmap) {
-        if (mport->cfm) {
-            cfm_run(mport->cfm);
-        }
+    ovs_assert(!monitor.tid);
 
-        if (mport->bfd) {
-            bfd_run(mport->bfd);
-        }
-    }
+    /* Malloc tid. */
+    ovs_rwlock_wrlock(&rwlock);
+    monitor.tid = xmalloc(sizeof *monitor.tid);
+    latch_init(&monitor.exit_latch);
     ovs_rwlock_unlock(&rwlock);
+
+    xpthread_create(monitor.tid, NULL, ofproto_dpif_monitor_handler, NULL);
+    time_insert_seq_list(monitor.wait_seq);
 }
 
-/* Executes the bfd_wait() and cfm_wait() functions on all mports. */
+/* Terminates the monitor thread.  This function should only be called by
+ * the main thread. */
 void
-ofproto_dpif_monitor_wait(void)
+ofproto_dpif_monitor_terminate(void)
 {
-    struct mport *mport;
+    ovs_assert(monitor.tid);
 
-    ovs_rwlock_rdlock(&rwlock);
-    HMAP_FOR_EACH (mport, hmap_node, &monitor.hmap) {
-        if (mport->cfm) {
-            cfm_wait(mport->cfm);
-        }
+    time_remove_seq_list(monitor.wait_seq);
+    latch_set(&monitor.exit_latch);
+    xpthread_join(*monitor.tid, NULL);
 
-        if (mport->bfd) {
-            bfd_wait(mport->bfd);
-        }
-    }
+    /* Frees the tid. */
+    ovs_rwlock_wrlock(&rwlock);
+    latch_destroy(&monitor.exit_latch);
+    free(monitor.tid);
+    monitor.tid = NULL;
     ovs_rwlock_unlock(&rwlock);
 }
diff --git a/ofproto/ofproto-dpif-monitor.h b/ofproto/ofproto-dpif-monitor.h
index 169973e..fd61197 100644
--- a/ofproto/ofproto-dpif-monitor.h
+++ b/ofproto/ofproto-dpif-monitor.h
@@ -25,10 +25,15 @@ struct ofpbuf;
 struct ofproto_cfm_status;
 struct ofport_dpif;
 
+enum monitor_check {
+    SHOULD_START,     /* should start the monitor thread. */
+    SHOULD_TERMINATE, /* should terminate the monitor thread. */
+    NONE              /* do nothing */
+};
+
+enum monitor_check ofproto_dpif_monitor_check(void);
 void ofproto_dpif_monitor_start(void);
-void ofproto_dpif_monitor_run(void);
-void ofproto_dpif_monitor_run_fast(void);
-void ofproto_dpif_monitor_wait(void);
+void ofproto_dpif_monitor_terminate(void);
 
 bool ofproto_dpif_monitor_check_alive(const struct ofport_dpif *ofport);
 
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 2ebcdf9..e42cc12 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -363,6 +363,8 @@ static void ofport_update_peer(struct ofport_dpif *);
 static void run_fast_rl(void);
 static int run_fast(struct ofproto *);
 
+static void check_monitor(void);
+
 struct dpif_completion {
     struct list list_node;
     struct ofoperation *op;
@@ -1235,8 +1237,6 @@ construct(struct ofproto *ofproto_)
         return error;
     }
 
-    ofproto_dpif_monitor_start();
-
     max_ports = dpif_get_max_ports(ofproto->backer->dpif);
     ofproto_init_max_ports(ofproto_, MIN(max_ports, ofp_to_u16(OFPP_MAX)));
 
@@ -1460,7 +1460,6 @@ run_fast(struct ofproto *ofproto_)
         free(CONST_CAST(void *, pin->packet));
         free(pin);
     }
-    ofproto_dpif_monitor_run_fast();
 
     return 0;
 }
@@ -1503,8 +1502,6 @@ 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);
     }
@@ -1562,7 +1559,6 @@ wait(struct ofproto *ofproto_)
         dpif_ipfix_wait(ofproto->ipfix);
     }
 
-    ofproto_dpif_monitor_wait();
     HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) {
         bundle_wait(bundle);
     }
@@ -1903,6 +1899,29 @@ set_ipfix(
     return 0;
 }
 
+/* Checks the monitor state and decides if to start
+ * the monitor thread, terminate the thread or do
+ * nothing. */
+static void
+check_monitor(void)
+{
+    switch (ofproto_dpif_monitor_check()) {
+    case SHOULD_START:
+        ofproto_dpif_monitor_start();
+        break;
+
+    case SHOULD_TERMINATE:
+        ofproto_dpif_monitor_terminate();
+        break;
+
+    case NONE:
+        break;
+
+    default:
+        NOT_REACHED();
+    }
+}
+
 static int
 set_cfm(struct ofport *ofport_, const struct cfm_settings *s)
 {
@@ -1912,12 +1931,14 @@ set_cfm(struct ofport *ofport_, const struct cfm_settings *s)
 
     error = ofproto_dpif_monitor_set_cfm(ofport, s, ofport->up.netdev,
                                          ofport->up.pp.hw_addr);
+    check_monitor();
     if (error > 0) {
         error = 0;
         ofproto->backer->need_revalidate = REV_RECONFIGURE;
     } else if (error < 0) {
         error = -error;
     }
+
     return error;
 }
 
@@ -1939,6 +1960,7 @@ set_bfd(struct ofport *ofport_, const struct smap *cfg)
 
     error = ofproto_dpif_monitor_set_bfd(ofport, cfg, ofport->up.netdev,
                                          ofport->up.pp.hw_addr);
+    check_monitor();
     if (error > 0) {
         error = 0;
         ofproto->backer->need_revalidate = REV_RECONFIGURE;
diff --git a/tests/automake.mk b/tests/automake.mk
index 8f51a65..6f6814e 100644
--- a/tests/automake.mk
+++ b/tests/automake.mk
@@ -21,8 +21,6 @@ TESTSUITE_AT = \
 	tests/ovs-ofctl.at \
 	tests/odp.at \
 	tests/multipath.at \
-	tests/bfd.at \
-	tests/cfm.at \
 	tests/lacp.at \
 	tests/learn.at \
 	tests/vconn.at \
diff --git a/tests/bfd.at b/tests/bfd.at
deleted file mode 100644
index db6c6f5..0000000
--- a/tests/bfd.at
+++ /dev/null
@@ -1,499 +0,0 @@
-AT_BANNER([bfd])
-
-m4_define([BFD_CHECK], [
-AT_CHECK([ovs-appctl bfd/show $1 | sed -e '/Time:/d' | sed -e '/Discriminator/d' | sed -e '/Interval:/d'],[0],
-[dnl
-	Forwarding: $2
-	Detect Multiplier: 3
-	Concatenated Path Down: $3
-
-	Local Flags: $4
-	Local Session State: $5
-	Local Diagnostic: $6
-
-	Remote Flags: $7
-	Remote Session State: $8
-	Remote Diagnostic: $9
-])
-])
-
-m4_define([BFD_CHECK_TX], [
-AT_CHECK([ovs-appctl bfd/show $1 | sed -n '/TX Interval/p'],[0],
-[dnl
-	TX Interval: Approx $2
-	Local Minimum TX Interval: $3
-	Remote Minimum TX Interval: $4
-])
-])
-
-m4_define([BFD_CHECK_RX], [
-AT_CHECK([ovs-appctl bfd/show $1 | sed -n '/RX Interval/p'],[0],
-[dnl
-	RX Interval: Approx $2
-	Local Minimum RX Interval: $3
-	Remote Minimum RX Interval: $4
-])
-])
-AT_SETUP([bfd - basic config on different bridges])
-#Create 2 bridges connected by patch ports and enable BFD
-OVS_VSWITCHD_START(
-   [add-br br1 -- \
-       set bridge br1 datapath-type=dummy \
-       other-config:hwaddr=aa:55:aa:56:00:00 -- \
-    add-port br1 p1 -- set Interface p1 type=patch \
-       options:peer=p0 -- \
-    add-port br0 p0 -- set Interface p0 type=patch \
-       options:peer=p1 -- \
-    set Interface p0 bfd:enable=true -- \
-    set Interface p1 bfd:enable=true ])
-ovs-appctl time/stop
-for i in `seq 0 40`; do ovs-appctl time/warp 100; done
-
-#Verify that BFD has been enabled on both interfaces.
-BFD_CHECK([p1], [true], [false], [none], [up], [No Diagnostic], [none], [up], [No Diagnostic])
-BFD_CHECK([p0], [true], [false], [none], [up], [No Diagnostic], [none], [up], [No Diagnostic])
-
-AT_CHECK([ ovs-vsctl set interface p0 bfd:enable=false])
-for i in `seq 0 40`; do ovs-appctl time/warp 100; done
-BFD_CHECK([p1], [false], [false], [none], [down], [Control Detection Time Expired], [none], [down], [No Diagnostic])
-
-AT_CHECK([ ovs-vsctl set interface p0 bfd:enable=true])
-for i in `seq 0 40`; do ovs-appctl time/warp 100; done
-BFD_CHECK([p1], [true], [false], [none], [up], [Control Detection Time Expired], [none], [up], [No Diagnostic])
-BFD_CHECK([p0], [true], [false], [none], [up], [No Diagnostic], [none], [up], [Control Detection Time Expired])
-
-ovs-vsctl del-br br0
-AT_CHECK([ovs-appctl bfd/show p0], [2],[ignore], [no such bfd object
-ovs-appctl: ovs-vswitchd: server returned an error
-])
-ovs-vsctl del-br br1
-#Check that the entries are gone.
-AT_CHECK([ovs-appctl bfd/show p1], [2],[ignore], [no such bfd object
-ovs-appctl: ovs-vswitchd: server returned an error
-])
-
-OVS_VSWITCHD_STOP
-AT_CLEANUP
-
-
-AT_SETUP([bfd - Verify tunnel down detection])
-#Create 3 bridges - br-bfd0, br-bfd1 and br-sw which is midway between the two. br2 is
-#connected to br-bfd0 and br-bfd1 through patch ports p0-2 and p1-2. Enable BFD on
-#interfaces in br-bfd0 and br-bfd1. When br-sw is dropping all packets, BFD should detect
-# that the tunnel is down, and come back up when br-sw is working fine.
-
-OVS_VSWITCHD_START(
-   [add-br br-bfd0 -- \
-       set bridge br-bfd0 datapath-type=dummy \
-       other-config:hwaddr=aa:55:aa:56:00:00 -- \
-    add-br br-bfd1 -- \
-       set bridge br-bfd1 datapath-type=dummy \
-       other-config:hwaddr=aa:55:aa:57:00:00 -- \
-    add-br br-sw -- \
-       set bridge br-sw datapath-type=dummy \
-       other-config:hwaddr=aa:55:aa:58:00:00 -- \
-    add-port br-sw p1-sw -- set Interface p1-sw type=patch \
-       options:peer=p1 -- \
-    add-port br-sw p0-sw -- set Interface p0-sw type=patch \
-       options:peer=p0 -- \
-    add-port br-bfd1 p1 -- set Interface p1 type=patch \
-       options:peer=p1-sw bfd:enable=true -- \
-    add-port br-bfd0 p0 -- set Interface p0 type=patch \
-       options:peer=p0-sw bfd:enable=true --])
-
-ovs-appctl time/stop
-
-#Create 2 bridges connected by patch ports and enable BFD
-
-AT_CHECK([ovs-ofctl add-flow br-sw 'priority=0,actions=NORMAL'])
-#Verify that BFD is enabled.
-for i in `seq 0 40`; do ovs-appctl time/warp 100; done
-BFD_CHECK([p1], [true], [false], [none], [up], [No Diagnostic], [none], [up], [No Diagnostic])
-BFD_CHECK([p0], [true], [false], [none], [up], [No Diagnostic], [none], [up], [No Diagnostic])
-
-#Drop all packets in the br-sw bridge so that the tunnel is down.
-AT_CHECK([ ovs-ofctl add-flow br-sw 'priority=5,actions=drop' ])
-for i in `seq 0 40`; do ovs-appctl time/warp 100; done
-BFD_CHECK([p1], [false], [false], [none], [down], [Control Detection Time Expired], [none], [down], [No Diagnostic])
-BFD_CHECK([p0], [false], [false], [none], [down], [Control Detection Time Expired], [none], [down], [No Diagnostic])
-
-#Delete the added flow
-AT_CHECK([ovs-ofctl del-flows br-sw], [0])
-AT_CHECK([ovs-ofctl add-flow br-sw 'priority=0,actions=NORMAL'])
-#Verify that BFD is back up again.
-for i in `seq 0 40`; do ovs-appctl time/warp 100; done
-
-BFD_CHECK([p1], [true], [false], [none], [up], [Control Detection Time Expired], [none], [up], [Control Detection Time Expired])
-BFD_CHECK([p0], [true], [false], [none], [up], [Control Detection Time Expired], [none], [up], [Control Detection Time Expired])
-
-#Now, Verify one-side tunnel down detection
-#When br-sw is dropping packets from one end, BFD should detect
-# that the tunnel is down, and come back up when br-sw is working fine.
-
-#Bring down the br-bfd1 - br-sw link. So BFD packets will be sent from p0,
-# but not received by p1. p0 will receive all BFD packets from p1.
-
-AT_CHECK([ ovs-ofctl add-flow br-sw 'in_port=1,priority=5,actions=drop'])
-for i in `seq 0 40`; do ovs-appctl time/warp 100; done
-# Make sure p1 BFD state is down since it received no BFD packets.
-BFD_CHECK([p1], [false], [false], [none], [down], [Control Detection Time Expired], [none], [down], [No Diagnostic])
-for i in `seq 0 40`; do ovs-appctl time/warp 100; done
-# p0 will be in init state once it receives "down" BFD message from p1.
-BFD_CHECK([p0], [false], [false], [none], [init], [Neighbor Signaled Session Down], [none], [down], [Control Detection Time Expired])
-
-AT_CHECK([ovs-ofctl del-flows br-sw])
-AT_CHECK([ovs-ofctl add-flow br-sw 'priority=0,actions=NORMAL'])
-#Ensure that BFD is back up again.
-
-for i in `seq 0 10`; do ovs-appctl time/warp 100; done
-#Bring down the br-bfd0 - br-sw link
-AT_CHECK([ ovs-ofctl add-flow br-sw 'in_port=2,priority=5,actions=drop'])
-for i in `seq 0 40`; do ovs-appctl time/warp 100; done
-BFD_CHECK([p0], [false], [false], [none], [down], [Control Detection Time Expired], [none], [down], [No Diagnostic])
-for i in `seq 0 40`; do ovs-appctl time/warp 100; done
-BFD_CHECK([p1], [false], [false], [none], [init], [Neighbor Signaled Session Down], [none], [down], [Control Detection Time Expired])
-OVS_VSWITCHD_STOP
-AT_CLEANUP
-
-
-AT_SETUP([bfd - concatenated path down])
-#Create 2 bridges connected by patch ports and enable BFD
-OVS_VSWITCHD_START()
-ovs-appctl time/stop
-AT_CHECK([ ovs-vsctl -- add-br br1 -- \
-           set bridge br1 datapath-type=dummy \
-           other-config:hwaddr=aa:55:aa:56:00:00 ])
-AT_CHECK([ ovs-vsctl -- add-port br1 p1 -- set Interface p1 type=patch \
-           options:peer=p0 ])
-AT_CHECK([ ovs-vsctl -- add-port br0 p0 -- set Interface p0 type=patch \
-           options:peer=p1 ])
-AT_CHECK([ ovs-vsctl -- set interface p0 bfd:enable=true ])
-AT_CHECK([ ovs-vsctl -- set interface p1 bfd:enable=true ])
-for i in `seq 0 40`; do ovs-appctl time/warp 100; done
-
-#Verify that BFD has been enabled on both interfaces.
-BFD_CHECK([p1], [true], [false], [none], [up], [No Diagnostic], [none], [up], [No Diagnostic])
-BFD_CHECK([p0], [true], [false], [none], [up], [No Diagnostic], [none], [up], [No Diagnostic])
-
-#Set cpath_down to true on one interface, make sure the remote interface updates its values.
-AT_CHECK([ovs-vsctl set interface p0 bfd:cpath_down=true])
-for i in `seq 0 40`; do ovs-appctl time/warp 100; done
-BFD_CHECK([p1], [false], [false], [none], [up], [No Diagnostic], [none], [up], [Concatenated Path Down])
-OVS_VSWITCHD_STOP
-AT_CLEANUP
-
-
-AT_SETUP([bfd - Edit the Min Tx/Rx values])
-#Create 2 bridges connected by patch ports and enable BFD
-OVS_VSWITCHD_START()
-ovs-appctl time/stop
-AT_CHECK([ ovs-vsctl -- add-br br1 -- \
-           set bridge br1 datapath-type=dummy ])
-AT_CHECK([ ovs-vsctl -- add-port br1 p1 -- set Interface p1 type=patch \
-           options:peer=p0 ])
-AT_CHECK([ ovs-vsctl -- add-port br0 p0 -- set Interface p0 type=patch \
-           options:peer=p1 ])
-AT_CHECK([ ovs-vsctl -- set interface p0 bfd:enable=true ])
-AT_CHECK([ ovs-vsctl -- set interface p1 bfd:enable=true ])
-for i in `seq 0 30`; do ovs-appctl time/warp 100; done
-#Verify that BFD has been enabled on both interfaces.
-BFD_CHECK([p1], [true], [false], [none], [up], [No Diagnostic], [none], [up], [No Diagnostic])
-BFD_CHECK([p0], [true], [false], [none], [up], [No Diagnostic], [none], [up], [No Diagnostic])
-#Edit the min Tx value.
-AT_CHECK([ovs-vsctl set interface p0 bfd:min_tx=200])
-for i in `seq 0 20`; do ovs-appctl time/warp 100; done
-BFD_CHECK_TX([p0], [1000ms], [200ms], [100ms])
-BFD_CHECK_TX([p1], [1000ms], [100ms], [200ms])
-
-#Edit the min Rx value.
-AT_CHECK([ovs-vsctl set interface p1 bfd:min_rx=300])
-for i in `seq 0 20`; do ovs-appctl time/warp 100; done
-BFD_CHECK_RX([p1], [300ms], [300ms], [1000ms])
-BFD_CHECK_RX([p0], [1000ms], [1000ms], [300ms])
-
-OVS_VSWITCHD_STOP
-AT_CLEANUP
-
-AT_SETUP([bfd - check_tnl_key])
-OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=gre \
-                    options:remote_ip=2.2.2.2 options:key=1 ofport_request=1 -- \
-                    set interface p1 bfd:enable=true -- \
-                    set bridge br0 fail-mode=standalone])
-
-# by default check_tnl_key is false. so we should process a bfd packet with tun_id=1.
-AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x1,src=2.2.2.2,dst=2.2.2.1,tos=0x0,ttl=64,flags(key)),in_port(1),skb_mark(0/0),eth(src=00:11:22:33:44:55,dst=00:23:20:00:00:01),eth_type(0x0800),ipv4(src=169.254.1.0/0.0.0.0,dst=169.254.1.1/0.0.0.0,proto=17/0xff,tos=0/0,ttl=255/0,frag=no/0xff),udp(src=49152/0,dst=3784/0xffff)' -generate], [0], [stdout])
-# check that the packet should be handled as BFD packet.
-AT_CHECK([tail -2 stdout], [0], [dnl
-This flow is handled by the userspace slow path because it:
-	- Consists of BFD packets.
-], [])
-
-# turn on the check_tnl_key.
-AT_CHECK([ovs-vsctl set interface p1 bfd:check_tnl_key=true])
-AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x1,src=2.2.2.2,dst=2.2.2.1,tos=0x0,ttl=64,flags(key)),in_port(1),skb_mark(0/0),eth(src=00:11:22:33:44:55,dst=00:23:20:00:00:01),eth_type(0x0800),ipv4(src=169.254.1.0/0.0.0.0,dst=169.254.1.1/0.0.0.0,proto=17/0xff,tos=0/0,ttl=255/0,frag=no/0xff),udp(src=49152/0,dst=3784/0xffff)' -generate], [0], [stdout])
-# check that the packet should be handled as normal packet.
-AT_CHECK([tail -1 stdout], [0],[dnl
-Datapath actions: 100
-], [])
-
-# set the tunnel key to 0.
-AT_CHECK([ovs-vsctl set interface p1 options:key=0])
-AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=2.2.2.2,dst=2.2.2.1,tos=0x0,ttl=64,flags(key)),in_port(1),skb_mark(0/0),eth(src=00:11:22:33:44:55,dst=00:23:20:00:00:01),eth_type(0x0800),ipv4(src=169.254.1.0/0.0.0.0,dst=169.254.1.1/0.0.0.0,proto=17/0xff,tos=0/0,ttl=255/0,frag=no/0xff),udp(src=49152/0,dst=3784/0xffff)' -generate], [0], [stdout])
-# check that the packet should be handled as BFD packet.
-AT_CHECK([tail -2 stdout], [0], [dnl
-This flow is handled by the userspace slow path because it:
-	- Consists of BFD packets.
-], [])
-
-OVS_VSWITCHD_STOP
-AT_CLEANUP
-
-# Tests below are for bfd forwarding_if_rx feature.
-# forwarding_if_rx Test1: bfd is enabled on one end of link.
-AT_SETUP([bfd - bfd forwarding_if_rx 1])
-OVS_VSWITCHD_START([add-br br1 -- set bridge br1 datapath-type=dummy -- \
-                    add-port br1 p1 -- set Interface p1 type=patch \
-                    options:peer=p0 ofport_request=2 -- \
-                    add-port br0 p0 -- set Interface p0 type=patch \
-                    options:peer=p1 ofport_request=1 -- \
-                    set Interface p0 bfd:enable=true bfd:min_tx=500 bfd:min_rx=500 -- \
-                    add-port br1 p2 -- set Interface p2 type=internal ofport_request=3])
-
-ovs-appctl time/stop
-# check the inital status.
-BFD_CHECK([p0], [false], [false], [none], [down], [No Diagnostic], [none], [down], [No Diagnostic])
-BFD_CHECK_TX([p0], [1000ms], [1000ms], [0ms])
-BFD_CHECK_RX([p0], [500ms], [500ms], [1ms])
-
-# enable forwarding_if_rx.
-AT_CHECK([ovs-vsctl set Interface p0 bfd:forwarding_if_rx=true], [0])
-
-# there should be no change of forwarding flag, since
-# there is no traffic.
-for i in `seq 0 3`
-do
-    ovs-appctl time/warp 500
-    BFD_CHECK([p0], [false], [false], [none], [down], [No Diagnostic], [none], [down], [No Diagnostic])
-done
-
-# receive one packet.
-AT_CHECK([ovs-ofctl packet-out br1 3 2  "90e2ba01475000101856b2e80806000108000604000100101856b2e80202020300000000000002020202"],
-             [0], [stdout], [])
-for i in `seq 0 14`
-do
-    ovs-appctl time/warp 100
-    # the forwarding flag should be true, since there is data received.
-    BFD_CHECK([p0], [true], [false], [none], [down], [No Diagnostic], [none], [down], [No Diagnostic])
-    BFD_CHECK_TX([p0], [1000ms], [1000ms], [0ms])
-    BFD_CHECK_RX([p0], [500ms], [500ms], [1ms])
-done
-
-# Stop sending packets for 1000ms.
-for i in `seq 0 9`; do ovs-appctl time/warp 100; done
-BFD_CHECK([p0], [false], [false], [none], [down], [No Diagnostic], [none], [down], [No Diagnostic])
-BFD_CHECK_TX([p0], [1000ms], [1000ms], [0ms])
-BFD_CHECK_RX([p0], [500ms], [500ms], [1ms])
-
-# receive packet at 1/100ms rate for 1000ms.
-for i in `seq 0 9`
-do
-    ovs-appctl time/warp 100
-    AT_CHECK([ovs-ofctl packet-out br1 3 2  "90e2ba01475000101856b2e80806000108000604000100101856b2e80202020300000000000002020202"],
-             [0], [stdout], [])
-done
-# the forwarding flag should be true, since there is data received.
-BFD_CHECK([p0], [true], [false], [none], [down], [No Diagnostic], [none], [down], [No Diagnostic])
-BFD_CHECK_TX([p0], [1000ms], [1000ms], [0ms])
-BFD_CHECK_RX([p0], [500ms], [500ms], [1ms])
-
-# reset bfd forwarding_if_rx.
-AT_CHECK([ovs-vsctl set Interface p0 bfd:forwarding_if_rx=false], [0])
-# forwarding flag should turn to false since the STATE is DOWN.
-BFD_CHECK([p0], [false], [false], [none], [down], [No Diagnostic], [none], [down], [No Diagnostic])
-BFD_CHECK_TX([p0], [1000ms], [1000ms], [0ms])
-BFD_CHECK_RX([p0], [500ms], [500ms], [1ms])
-
-AT_CHECK([ovs-vsctl del-br br1], [0], [ignore])
-AT_CLEANUP
-
-# forwarding_if_rx Test2: bfd is enabled on both ends of link.
-AT_SETUP([bfd - bfd forwarding_if_rx 2])
-OVS_VSWITCHD_START([add-br br1 -- set bridge br1 datapath-type=dummy -- \
-                    add-port br1 p1 -- set Interface p1 type=patch \
-                    options:peer=p0 ofport_request=2 -- \
-                    add-port br0 p0 -- set Interface p0 type=patch \
-                    options:peer=p1 ofport_request=1 -- \
-                    set Interface p0 bfd:enable=true bfd:min_tx=500 bfd:min_rx=500 -- \
-                    set Interface p1 bfd:enable=true bfd:min_tx=300 bfd:min_rx=300 -- \
-                    add-port br1 p2 -- set Interface p2 type=internal ofport_request=3])
-
-ovs-appctl time/stop
-# advance the clock, to stablize the states.
-for i in `seq 0 9`; do ovs-appctl time/warp 500; done
-
-# enable forwarding_if_rx.
-AT_CHECK([ovs-vsctl set Interface p0 bfd:forwarding_if_rx=true], [0])
-
-# there should be no change of the forwarding flag, since
-# the bfd on both ends is already up.
-for i in `seq 0 5`
-do
-    ovs-appctl time/warp 500
-    BFD_CHECK([p0], [true], [false], [none], [up], [No Diagnostic], [none], [up], [No Diagnostic])
-done
-
-# stop the bfd on one side.
-AT_CHECK([ovs-vsctl set Interface p1 bfd:enable=false], [0])
-# for within 1500ms, the detection timer is not out.
-# there is no change to status.
-for i in `seq 0 1`
-do
-    ovs-appctl time/warp 500
-    BFD_CHECK([p0], [true], [false], [none], [up], [No Diagnostic], [none], [up], [No Diagnostic])
-    for i in `seq 0 5`
-    do
-        AT_CHECK([ovs-ofctl packet-out br1 3 2  "90e2ba01475000101856b2e80806000108000604000100101856b2e80202020300000000000002020202"],
-                 [0], [stdout], [])
-    done
-done
-
-# at 1500ms, the STATE should go DOWN, due to Control Detection Time Expired.
-# but forwarding flag should be still true.
-ovs-appctl time/warp 500
-BFD_CHECK([p0], [true], [false], [none], [down], [Control Detection Time Expired], [none], [down], [No Diagnostic])
-
-# receive packet at 1/100ms rate for 1000ms.
-for i in `seq 0 9`
-do
-    AT_CHECK([ovs-ofctl packet-out br1 3 2  "90e2ba01475000101856b2e80806000108000604000100101856b2e80202020300000000000002020202"],
-             [0], [stdout], [])
-    ovs-appctl time/warp 100
-    # the forwarding flag should always be true during this time.
-    BFD_CHECK([p0], [true], [false], [none], [down], [Control Detection Time Expired], [none], [down], [No Diagnostic])
-done
-
-# reset bfd forwarding_if_rx.
-AT_CHECK([ovs-vsctl set Interface p0 bfd:forwarding_if_rx=false], [0])
-# forwarding flag should turn to false since the STATE is DOWN.
-BFD_CHECK([p0], [false], [false], [none], [down], [Control Detection Time Expired], [none], [down], [No Diagnostic])
-BFD_CHECK_TX([p0], [1000ms], [1000ms], [0ms])
-BFD_CHECK_RX([p0], [500ms], [500ms], [1ms])
-
-# re-enable bfd on the other end. the states should be up.
-AT_CHECK([ovs-vsctl set Interface p1 bfd:enable=true bfd:min_tx=300 bfd:min_rx=300])
-# advance the clock, to stablize the states.
-for i in `seq 0 9`; do ovs-appctl time/warp 500; done
-BFD_CHECK([p0], [true], [false], [none], [up], [Control Detection Time Expired], [none], [up], [No Diagnostic])
-BFD_CHECK([p1], [true], [false], [none], [up], [No Diagnostic], [none], [up], [Control Detection Time Expired])
-BFD_CHECK_TX([p0], [500ms], [500ms], [300ms])
-BFD_CHECK_RX([p0], [500ms], [500ms], [300ms])
-
-AT_CHECK([ovs-vsctl del-br br1], [0], [ignore])
-AT_CLEANUP
-
-# forwarding_if_rx Test3: bfd is enabled on both ends of link and decay is enabled.
-AT_SETUP([bfd - bfd forwarding_if_rx 3])
-OVS_VSWITCHD_START([add-br br1 -- set bridge br1 datapath-type=dummy -- \
-                    add-port br1 p1 -- set Interface p1 type=patch \
-                    options:peer=p0 ofport_request=2 -- \
-                    add-port br0 p0 -- set Interface p0 type=patch \
-                    options:peer=p1 ofport_request=1 -- \
-                    set Interface p0 bfd:enable=true bfd:min_tx=300 bfd:min_rx=300 bfd:decay_min_rx=3000 -- \
-                    set Interface p1 bfd:enable=true bfd:min_tx=500 bfd:min_rx=500])
-
-ovs-appctl time/stop
-# advance the clock, to stablize the states.
-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], [500ms])
-BFD_CHECK_RX([p0], [3000ms], [3000ms], [500ms])
-
-# enable forwarding_if_rx.
-AT_CHECK([ovs-vsctl set Interface p0 bfd:forwarding_if_rx=true], [0])
-
-# there should be no change of the forwarding flag, since
-# the bfd on both ends is already up.
-for i in `seq 0 9`
-do
-    ovs-appctl time/warp 500
-    BFD_CHECK([p0], [true], [false], [none], [up], [No Diagnostic], [none], [up], [No Diagnostic])
-done
-
-# reconfigure the decay_min_rx to 1000ms. check the poll sequence.
-AT_CHECK([ovs-vsctl set interface p0 bfd:decay_min_rx=1000])
-BFD_CHECK([p0], [true], [false], [none], [up], [No Diagnostic], [final], [up], [No Diagnostic])
-BFD_CHECK([p1], [true], [false], [none], [up], [No Diagnostic], [poll], [up], [No Diagnostic])
-BFD_CHECK_TX([p0], [500ms], [300ms], [500ms])
-BFD_CHECK_RX([p0], [500ms], [300ms], [500ms])
-
-# wait for 2000ms to decay.
-for i in `seq 0 3`; do ovs-appctl time/warp 500; done
-BFD_CHECK([p0], [true], [false], [none], [up], [No Diagnostic], [final], [up], [No Diagnostic])
-BFD_CHECK([p1], [true], [false], [none], [up], [No Diagnostic], [poll], [up], [No Diagnostic])
-BFD_CHECK_TX([p0], [500ms], [300ms], [500ms])
-BFD_CHECK_RX([p0], [1000ms], [1000ms], [500ms])
-
-# wait for 1000ms, so that the flags will go back to none.
-for i in `seq 0 1`; 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], [500ms])
-BFD_CHECK_RX([p0], [1000ms], [1000ms], [500ms])
-
-# stop the bfd on one side.
-AT_CHECK([ovs-vsctl set Interface p1 bfd:enable=false], [0])
-# for within 2500ms, the detection timer is not out.
-# there is no change to status.
-for i in `seq 0 4`
-do
-    ovs-appctl time/warp 500
-    BFD_CHECK([p0], [true], [false], [none], [up], [No Diagnostic], [none], [up], [No Diagnostic])
-    AT_CHECK([ovs-ofctl packet-out br1 3 2  "90e2ba01475000101856b2e80806000108000604000100101856b2e80202020300000000000002020202"],
-             [0], [stdout], [])
-done
-
-# at 3000ms, the STATE should go DOWN, due to Control Detection Time Expired.
-# but forwarding flag should be still true.
-ovs-appctl time/warp 500
-BFD_CHECK([p0], [true], [false], [none], [down], [Control Detection Time Expired], [none], [down], [No Diagnostic])
-
-# receive packet at 1/100ms rate for 1000ms.
-for i in `seq 0 9`
-do
-    AT_CHECK([ovs-ofctl packet-out br1 3 2  "90e2ba01475000101856b2e80806000108000604000100101856b2e80202020300000000000002020202"],
-             [0], [stdout], [])
-    ovs-appctl time/warp 100
-    # the forwarding flag should always be true during this time.
-    BFD_CHECK([p0], [true], [false], [none], [down], [Control Detection Time Expired], [none], [down], [No Diagnostic])
-done
-
-# stop receiving for 2000ms.
-for i in `seq 0 19`; do ovs-appctl time/warp 100; done
-BFD_CHECK([p0], [false], [false], [none], [down], [Control Detection Time Expired], [none], [down], [No Diagnostic])
-
-# reset bfd forwarding_if_rx.
-AT_CHECK([ovs-vsctl set Interface p0 bfd:forwarding_if_rx=false])
-# forwarding flag should turn to false since the STATE is DOWN.
-BFD_CHECK([p0], [false], [false], [none], [down], [Control Detection Time Expired], [none], [down], [No Diagnostic])
-BFD_CHECK_TX([p0], [1000ms], [1000ms], [0ms])
-BFD_CHECK_RX([p0], [300ms], [300ms], [1ms])
-
-# re-enable bfd forwarding_if_rx.
-AT_CHECK([ovs-vsctl set Interface p0 bfd:forwarding_if_rx=true])
-# there should be no change.
-BFD_CHECK([p0], [false], [false], [none], [down], [Control Detection Time Expired], [none], [down], [No Diagnostic])
-BFD_CHECK_TX([p0], [1000ms], [1000ms], [0ms])
-BFD_CHECK_RX([p0], [300ms], [300ms], [1ms])
-
-# re-enable bfd on the other end. the states should be up.
-AT_CHECK([ovs-vsctl set Interface p1 bfd:enable=true bfd:min_tx=300 bfd:min_rx=300])
-# advance the clock, to stablize the states.
-for i in `seq 0 9`; do ovs-appctl time/warp 500; done
-BFD_CHECK([p0], [true], [false], [none], [up], [Control Detection Time Expired], [none], [up], [No Diagnostic])
-BFD_CHECK([p1], [true], [false], [none], [up], [No Diagnostic], [none], [up], [Control Detection Time Expired])
-BFD_CHECK_TX([p0], [300ms], [300ms], [300ms])
-BFD_CHECK_RX([p0], [1000ms], [1000ms], [300ms])
-
-AT_CHECK([ovs-vsctl del-br br1], [0], [ignore])
-AT_CLEANUP
\ No newline at end of file
diff --git a/tests/cfm.at b/tests/cfm.at
deleted file mode 100644
index 638e03f..0000000
--- a/tests/cfm.at
+++ /dev/null
@@ -1,57 +0,0 @@
-AT_BANNER([cfm])
-
-m4_define([CFM_CHECK_EXTENDED], [
-AT_CHECK([ovs-appctl cfm/show $1 | sed -e '/next CCM tx:/d' | sed -e '/next fault check:/d' | sed -e  '/recv since check:/d'],[0],
-[dnl
----- $1 ----
-MPID $2: extended
-	average health: $3
-	opstate: $4
-	remote_opstate: $5
-	interval: $6
-Remote MPID $7
-	opstate: $8
-])
-])
-
-# test cfm under demand mode.
-AT_SETUP([cfm - demand mode])
-#Create 2 bridges connected by patch ports and enable BFD
-OVS_VSWITCHD_START([add-br br1 -- \
-                    set bridge br1 datapath-type=dummy \
-                    other-config:hwaddr=aa:55:aa:56:00:00 -- \
-                    add-port br1 p1 -- set Interface p1 type=patch \
-                    options:peer=p0 -- \
-                    add-port br0 p0 -- set Interface p0 type=patch \
-                    options:peer=p1 -- \
-                    set Interface p0 cfm_mpid=1 other_config:cfm_interval=300 other_config:cfm_extended=true -- \
-                    set Interface p1 cfm_mpid=2 other_config:cfm_interval=300 other_config:cfm_extended=true ])
-
-ovs-appctl time/stop
-# wait for a while to stablize cfm.
-for i in `seq 0 100`; do ovs-appctl time/warp 100; done
-CFM_CHECK_EXTENDED([p0], [1], [100], [up], [up], [300ms], [2], [up])
-CFM_CHECK_EXTENDED([p1], [2], [100], [up], [up], [300ms], [1], [up])
-
-# turn on demand mode on one end.
-AT_CHECK([ovs-vsctl set interface p0 other_config:cfm_demand=true])
-
-# cfm should never go down.
-for i in `seq 0 100`
-do
-    ovs-appctl time/warp 100
-    CFM_CHECK_EXTENDED([p0], [1], [100], [up], [up], [300ms], [2], [up])
-    CFM_CHECK_EXTENDED([p1], [2], [100], [up], [up], [300ms], [1], [up])
-done
-
-# turn on demand mode on the other end.
-AT_CHECK([ovs-vsctl set interface p1 other_config:cfm_demand=true])
-for i in `seq 0 100`
-do
-    ovs-appctl time/warp 100
-    CFM_CHECK_EXTENDED([p0], [1], [100], [up], [up], [300ms], [2], [up])
-    CFM_CHECK_EXTENDED([p1], [2], [100], [up], [up], [300ms], [1], [up])
-done
-
-OVS_VSWITCHD_STOP
-AT_CLEANUP
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 9e16f94..199e17e 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -67,8 +67,6 @@ EOF
 m4_include([tests/ovsdb-macros.at])
 m4_include([tests/ofproto-macros.at])
 
-m4_include([tests/bfd.at])
-m4_include([tests/cfm.at])
 m4_include([tests/lacp.at])
 m4_include([tests/library.at])
 m4_include([tests/heap.at])
-- 
1.7.9.5




More information about the dev mailing list