[ovs-dev] [PATCH V2 2/4] bfd: Implements forwarding_if_rx

Alex Wang alexw at nicira.com
Tue Aug 6 19:12:13 UTC 2013


This commit adds a new boolean option "forwarding_if_rx" to bfd.

When forwarding_if_rx is true, the forwarding field in "ovs-appctl
bfd/show" output will still be true as long as there are incoming
packets received. This is for indicating the link liveness when
the link is congested and consecutive BFD control packets are lost.
Or when BFD is enabled only on one side of the tunnel.

Signed-off-by: Alex Wang <alexw at nicira.com>

---

v1 -> v2:
- use rx_detect_time to record the next time instant
  for checking rx_packets.
- include unit test to this patch.

---
 lib/bfd.c            |   49 +++++++++++++++--
 tests/bfd.at         |  143 ++++++++++++++++++++++++++++++++++++++++++++++++++
 vswitchd/vswitch.xml |    7 +++
 3 files changed, 194 insertions(+), 5 deletions(-)

diff --git a/lib/bfd.c b/lib/bfd.c
index 8a0f5e1..5a7f3b1 100644
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -189,6 +189,13 @@ struct bfd {
     atomic_bool check_tnl_key;    /* Verify tunnel key of inbound packets? */
     atomic_int ref_cnt;
 
+    /* When forward_if_rx is true, the bfd_forwarding() will
+     * return true as long as there are incoming packets received.
+     * Note, forwarding_override still has higher priority. */
+    bool forwarding_if_rx;
+    bool has_rx;
+    long long int rx_detect_time;
+
     /* BFD decay related variables. */
     bool in_decay;
     int decay_min_rx;
@@ -217,6 +224,8 @@ static void bfd_put_details(struct ds *, const struct bfd *)
     OVS_REQ_WRLOCK(&mutex);
 static uint64_t bfd_rx_packets(const struct bfd *) OVS_REQ_WRLOCK(&mutex);
 static void bfd_try_decay(struct bfd *) OVS_REQ_WRLOCK(&mutex);
+static void bfd_check_rx(struct bfd *) OVS_REQ_WRLOCK(&mutex);
+
 static void bfd_unixctl_show(struct unixctl_conn *, int argc,
                              const char *argv[], void *aux OVS_UNUSED);
 static void bfd_unixctl_set_forwarding_override(struct unixctl_conn *,
@@ -272,7 +281,7 @@ bfd_configure(struct bfd *bfd, const char *name, const struct smap *cfg,
 
     int decay_min_rx;
     long long int min_tx, min_rx;
-    bool cpath_down;
+    bool cpath_down, forwarding_if_rx;
     const char *hwaddr;
     uint8_t ea[ETH_ADDR_LEN];
 
@@ -306,6 +315,8 @@ bfd_configure(struct bfd *bfd, const char *name, const struct smap *cfg,
         bfd->rx_packets = bfd_rx_packets(bfd);
         bfd->in_decay = false;
         bfd->decay_detect_time = 0;
+        bfd->has_rx = false;
+        bfd->rx_detect_time = 0;
 
         /* RFC 5881 section 4
          * The source port MUST be in the range 49152 through 65535.  The same
@@ -380,6 +391,13 @@ bfd_configure(struct bfd *bfd, const char *name, const struct smap *cfg,
         bfd->eth_dst_set = false;
     }
 
+    forwarding_if_rx = smap_get_bool(cfg, "forwarding_if_rx", false);
+    if (bfd->forwarding_if_rx != forwarding_if_rx) {
+        bfd->forwarding_if_rx = forwarding_if_rx;
+        if (bfd->forwarding_if_rx) {
+            bfd_check_rx(bfd);
+        }
+    }
     ovs_mutex_unlock(&mutex);
     return bfd;
 }
@@ -444,6 +462,10 @@ bfd_run(struct bfd *bfd) OVS_EXCLUDED(mutex)
         bfd_set_state(bfd, STATE_DOWN, DIAG_EXPIRED);
     }
 
+    if (bfd->forwarding_if_rx && now >= bfd->rx_detect_time) {
+        bfd_check_rx(bfd);
+    }
+
     if (bfd->state == STATE_UP && bfd->decay_min_rx > 0
         && now >= bfd->decay_detect_time) {
         bfd_try_decay(bfd);
@@ -738,6 +760,7 @@ bfd_set_netdev(struct bfd *bfd, const struct netdev *netdev)
     if (bfd->netdev != netdev) {
         netdev_close(bfd->netdev);
         bfd->netdev = netdev_ref(netdev);
+        bfd->rx_packets = bfd_rx_packets(bfd);
     }
     ovs_mutex_unlock(&mutex);
 }
@@ -750,10 +773,10 @@ bfd_forwarding__(const struct bfd *bfd) OVS_REQ_WRLOCK(mutex)
         return bfd->forwarding_override == 1;
     }
 
-    return bfd->state == STATE_UP
-        && bfd->rmt_diag != DIAG_PATH_DOWN
-        && bfd->rmt_diag != DIAG_CPATH_DOWN
-        && bfd->rmt_diag != DIAG_RCPATH_DOWN;
+    return (bfd->forwarding_if_rx ? bfd->has_rx : bfd->state == STATE_UP)
+           && bfd->rmt_diag != DIAG_PATH_DOWN
+           && bfd->rmt_diag != DIAG_CPATH_DOWN
+           && bfd->rmt_diag != DIAG_RCPATH_DOWN;
 }
 
 /* Helpers. */
@@ -973,6 +996,22 @@ bfd_try_decay(struct bfd *bfd) OVS_REQ_WRLOCK(mutex)
     bfd->in_decay = diff <= measure ? true : false;
 }
 
+static void
+bfd_check_rx(struct bfd *bfd) OVS_REQ_WRLOCK(mutex)
+{
+    uint64_t rx_packets = bfd_rx_packets(bfd);
+    int64_t diff, incr;
+
+    diff = rx_packets - bfd->rx_packets;
+    if (diff < 0) {
+        VLOG_WARN("rx_packets count is smaller than last time.");
+    }
+    bfd->rx_packets = rx_packets;
+    bfd->has_rx = (diff > 0);
+    incr = bfd_rx_interval(bfd) * bfd->mult;
+    bfd->rx_detect_time = (incr > 2000 ? incr : 2000) + time_msec();
+}
+
 static uint32_t
 generate_discriminator(void)
 {
diff --git a/tests/bfd.at b/tests/bfd.at
index 0484e87..9ed37a6 100644
--- a/tests/bfd.at
+++ b/tests/bfd.at
@@ -406,3 +406,146 @@ done
 AT_CHECK([ovs-vsctl del-br br1], [0], [ignore])
 AT_CLEANUP
 
+# Tests below are for bfd forwarding_if_rx feature.
+# 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])
+
+# 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 5`
+do
+    ovs-appctl time/warp 500
+    BFD_CHECK([p0], [false], [false], [none], [down], [No Diagnostic], [none], [down], [No Diagnostic])
+done
+
+# receive packet at 1/100ms rate for 3000ms.
+for i in `seq 0 29`
+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])
+
+# stop sending packets for 3000ms.
+for i in `seq 0 29`; 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 3000ms.
+for i in `seq 0 29`
+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
+
+# 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])
+
+# 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 3000ms.
+for i in `seq 0 5`
+do
+    for i in `seq 0 5`
+    do
+        AT_CHECK([ovs-ofctl packet-out br1 3 2  "90e2ba01475000101856b2e80806000108000604000100101856b2e80202020300000000000002020202"],
+                 [0], [stdout], [])
+    done
+    ovs-appctl time/warp 500
+    # 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
\ No newline at end of file
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index b73a612..4a1b7ef 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -1889,6 +1889,13 @@
           reconfigured.
       </column>
 
+      <column name="bfd" key="forwarding_if_rx" type='{"type": "boolean"}'>
+          When <code>forwarding_if_rx</code> is true the <code>forwarding
+          </code> field in <code>"ovs-appctl bfd/show"</code> output will
+          still be true as long as there are incoming packets received.
+          This option is for indicating the tunnel liveness when the tunnel
+          becomes congested and consecutive BFD control packets are lost.
+      </column>
 
       <column name="bfd" key="cpath_down" type='{"type": "boolean"}'>
           Concatenated path down may be used when the local system should not
-- 
1.7.9.5




More information about the dev mailing list