cfm: Fix broken fault logic.
authorEthan Jackson <ethan@nicira.com>
Thu, 7 Apr 2011 00:23:40 +0000 (17:23 -0700)
committerEthan Jackson <ethan@nicira.com>
Thu, 7 Apr 2011 16:30:04 +0000 (09:30 -0700)
If the last receive time for a remote MP was before the last fault
check, the CFM code would not declare a fault.  This is, of course,
exactly the wrong response.

Bug #5303.

lib/cfm.c
lib/timer.c
lib/timer.h

index 5a547d0d885018e2ae298ab5b16e60a69d9e884e..a504714cf5540e89f69db34e113634504960e0d4 100644 (file)
--- a/lib/cfm.c
+++ b/lib/cfm.c
@@ -174,11 +174,14 @@ cfm_run(struct cfm *cfm)
     if (timer_expired(&cfmi->fault_timer)) {
         bool fault;
         struct remote_mp *rmp;
+        long long int interval;
 
-        fault = now < cfmi->x_recv_time + cfm_fault_interval(cfmi);
+        interval = cfm_fault_interval(cfmi);
+        fault = now < cfmi->x_recv_time + interval;
 
         HMAP_FOR_EACH (rmp, node, &cfm->remote_mps) {
-            if (timer_expired_at(&cfmi->fault_timer, rmp->recv_time)) {
+            if (rmp->recv_time < timer_enabled_at(&cfmi->fault_timer, interval)
+                || timer_expired_at(&cfmi->fault_timer, rmp->recv_time)) {
                 rmp->fault = true;
             }
 
@@ -188,7 +191,7 @@ cfm_run(struct cfm *cfm)
         }
 
         cfm->fault = fault;
-        timer_set_duration(&cfmi->fault_timer, cfm_fault_interval(cfmi));
+        timer_set_duration(&cfmi->fault_timer, interval);
     }
 }
 
index b640a7be89f0bb2ca1dbf4cf5cd3d2dff4f3ade0..1c3c0f488a5b660e1a24f1e4e50892106e706492 100644 (file)
@@ -40,3 +40,16 @@ timer_wait(const struct timer *timer)
         poll_timer_wait_until(timer->t);
     }
 }
+
+/* Returns the time at which 'timer' was set with 'duration'.  Infinite timers
+ * were enabled at time LLONG_MAX.  Manually expired timers were enabled at
+ * LLONG_MIN. */
+long long int
+timer_enabled_at(const struct timer *timer, long long int duration)
+{
+    switch (timer->t) {
+    case LLONG_MAX: return LLONG_MAX;
+    case LLONG_MIN: return LLONG_MIN;
+    default: return timer->t - duration;
+    }
+}
index d2bfd86b08c45b3ed7758c300b25788c0184fdd3..73020556659ef21ac7a5289cfdc64c2edffda953 100644 (file)
@@ -26,6 +26,7 @@ struct timer {
 };
 
 long long int timer_msecs_until_expired(const struct timer *);
+long long int timer_enabled_at(const struct timer *, long long int duration);
 void timer_wait(const struct timer *);
 
 /* Causes 'timer' to expire when 'duration' milliseconds have passed.