+static uint64_t
+bfd_rx_packets(const struct bfd *bfd) OVS_REQUIRES(mutex)
+{
+ struct netdev_stats stats;
+
+ if (!netdev_get_stats(bfd->netdev, &stats)) {
+ return stats.rx_packets;
+ } else {
+ return 0;
+ }
+}
+
+/* Decays the bfd->min_rx to bfd->decay_min_rx when 'diff' is less than
+ * the 'expect' value. */
+static void
+bfd_try_decay(struct bfd *bfd) OVS_REQUIRES(mutex)
+{
+ int64_t diff, expect;
+
+ /* The 'diff' is the difference between current interface rx_packets
+ * stats and last-time check. The 'expect' is the recorded number of
+ * bfd control packets received within an approximately decay_min_rx
+ * (2000 ms if decay_min_rx is less than 2000 ms) interval.
+ *
+ * Since the update of rx_packets stats at interface happens
+ * asynchronously to the bfd_rx_packets() function, the 'diff' value
+ * can be jittered. Thusly, we double the decay_rx_ctl to provide
+ * more wiggle room. */
+ diff = bfd_rx_packets(bfd) - bfd->decay_rx_packets;
+ expect = 2 * MAX(bfd->decay_rx_ctl, 1);
+ bfd->in_decay = diff <= expect ? true : false;
+ bfd_decay_update(bfd);
+}
+
+/* Updates the rx_packets, decay_rx_ctl and decay_detect_time. */
+static void
+bfd_decay_update(struct bfd * bfd) OVS_REQUIRES(mutex)
+{
+ bfd->decay_rx_packets = bfd_rx_packets(bfd);
+ bfd->decay_rx_ctl = 0;
+ bfd->decay_detect_time = MAX(bfd->decay_min_rx, 2000) + time_msec();
+}
+
+/* Records the status change and changes the global connectivity seq. */
+static void
+bfd_status_changed(struct bfd *bfd) OVS_REQUIRES(mutex)
+{
+ seq_change(connectivity_seq_get());
+ bfd->status_changed = true;
+}
+
+static void
+bfd_forwarding_if_rx_update(struct bfd *bfd) OVS_REQUIRES(mutex)
+{
+ int64_t incr = bfd_rx_interval(bfd) * bfd->mult;
+ bfd->forwarding_if_rx_detect_time = MAX(incr, 2000) + time_msec();
+}
+