Describe dummy test model. Work on OpenFlow intro.
[openvswitch] / lib / cfm.c
index 7503ad5818957e5c57334e5f6304cd11bcb5e9e8..b71c242a54763eb4a182b7df98af1e591f2d328f 100644 (file)
--- a/lib/cfm.c
+++ b/lib/cfm.c
@@ -86,7 +86,9 @@ struct cfm {
     struct hmap_node hmap_node; /* Node in all_cfms list. */
 
     uint64_t mpid;
+    bool check_tnl_key;    /* Verify the tunnel key of inbound packets? */
     bool extended;         /* Extended mode. */
+    bool booted;           /* A full fault interval has occured. */
     enum cfm_fault_reason fault;  /* Connectivity fault status. */
     enum cfm_fault_reason recv_fault;  /* Bit mask of faults occuring on
                                           receive. */
@@ -132,6 +134,7 @@ struct remote_mp {
     uint32_t seq;        /* Most recently received sequence number. */
     uint8_t num_health_ccm; /* Number of received ccm frames every
                                CFM_HEALTH_INTERVAL * 'fault_interval'. */
+    long long int last_rx; /* Last CCM reception time. */
 
 };
 
@@ -159,21 +162,19 @@ cfm_fault_reason_to_str(int reason) {
 }
 
 static void
-ds_put_cfm_fault(struct ds *ds, int old_fault, int new_fault)
+ds_put_cfm_fault(struct ds *ds, int fault)
 {
     int i;
 
     for (i = 0; i < CFM_FAULT_N_REASONS; i++) {
         int reason = 1 << i;
 
-        if ((old_fault | new_fault) & reason) {
-            ds_put_format(ds, " %s%s",
-                          (!(old_fault & reason) ? "+"
-                           : !(new_fault & reason) ? "-"
-                           : ""),
-                          cfm_fault_reason_to_str(reason));
+        if (fault & reason) {
+            ds_put_format(ds, "%s ", cfm_fault_reason_to_str(reason));
         }
     }
+
+    ds_chomp(ds, ' ');
 }
 
 static void
@@ -376,8 +377,9 @@ cfm_run(struct cfm *cfm)
         HMAP_FOR_EACH_SAFE (rmp, rmp_next, node, &cfm->remote_mps) {
 
             if (!rmp->recv) {
-                VLOG_DBG("%s: no CCM from RMP %"PRIu64" in the last %lldms",
-                         cfm->name, rmp->mpid, interval);
+                VLOG_INFO("%s: Received no CCM from RMP %"PRIu64" in the last"
+                          " %lldms", cfm->name, rmp->mpid,
+                          time_msec() - rmp->last_rx);
                 hmap_remove(&cfm->remote_mps, &rmp->node);
                 free(rmp);
             } else {
@@ -398,12 +400,16 @@ cfm_run(struct cfm *cfm)
         if (old_cfm_fault != cfm->fault && !VLOG_DROP_INFO(&rl)) {
             struct ds ds = DS_EMPTY_INITIALIZER;
 
-            ds_put_cfm_fault(&ds, old_cfm_fault, cfm->fault);
-            VLOG_INFO("%s: CFM fault status changed:%s", cfm->name,
-                      ds_cstr_ro(&ds));
+            ds_put_cstr(&ds, "from [");
+            ds_put_cfm_fault(&ds, old_cfm_fault);
+            ds_put_cstr(&ds, "] to [");
+            ds_put_cfm_fault(&ds, cfm->fault);
+            ds_put_char(&ds, ']');
+            VLOG_INFO("%s: CFM faults changed %s.", cfm->name, ds_cstr(&ds));
             ds_destroy(&ds);
         }
 
+        cfm->booted = true;
         timer_set_duration(&cfm->fault_timer, interval);
         VLOG_DBG("%s: new fault interval", cfm->name);
     }
@@ -466,7 +472,7 @@ cfm_compose_ccm(struct cfm *cfm, struct ofpbuf *packet,
         ccm->interval_ms_x = htons(0);
     }
 
-    if (hmap_is_empty(&cfm->remote_mps)) {
+    if (cfm->booted && hmap_is_empty(&cfm->remote_mps)) {
         ccm->flags |= CCM_RDI_MASK;
     }
 
@@ -500,6 +506,7 @@ cfm_configure(struct cfm *cfm, const struct cfm_settings *s)
     }
 
     cfm->mpid = s->mpid;
+    cfm->check_tnl_key = s->check_tnl_key;
     cfm->extended = s->extended;
     cfm->opup = s->opup;
     interval = ms_to_ccm_interval(s->interval);
@@ -528,7 +535,8 @@ bool
 cfm_should_process_flow(const struct cfm *cfm, const struct flow *flow)
 {
     return (ntohs(flow->dl_type) == ETH_TYPE_CFM
-            && eth_addr_equals(flow->dl_dst, cfm_ccm_addr(cfm)));
+            && eth_addr_equals(flow->dl_dst, cfm_ccm_addr(cfm))
+            && (!cfm->check_tnl_key || flow->tunnel.tun_id == htonll(0)));
 }
 
 /* Updates internal statistics relevant to packet 'p'.  Should be called on
@@ -649,6 +657,7 @@ cfm_process_heartbeat(struct cfm *cfm, const struct ofpbuf *p)
             cfm->recv_fault |= cfm_fault;
             rmp->seq = ccm_seq;
             rmp->opup = !ccm_opdown;
+            rmp->last_rx = time_msec();
         }
     }
 }
@@ -678,12 +687,17 @@ cfm_get_health(const struct cfm *cfm)
 
 /* Gets the operational state of 'cfm'.  'cfm' is considered operationally down
  * if it has received a CCM with the operationally down bit set from any of its
- * remote maintenance points. Returns true if 'cfm' is operationally up. False
- * otherwise. */
-bool
+ * remote maintenance points. Returns 1 if 'cfm' is operationally up, 0 if
+ * 'cfm' is operationally down, or -1 if 'cfm' has no operational state
+ * (because it isn't in extended mode). */
+int
 cfm_get_opup(const struct cfm *cfm)
 {
-    return cfm->remote_opup;
+    if (cfm->extended) {
+        return cfm->remote_opup;
+    } else {
+        return -1;
+    }
 }
 
 /* Populates 'rmps' with an array of remote maintenance points reachable by
@@ -723,8 +737,8 @@ cfm_print_details(struct ds *ds, const struct cfm *cfm)
 
     fault = cfm_get_fault(cfm);
     if (fault) {
-        ds_put_cstr(ds, "\tfault:");
-        ds_put_cfm_fault(ds, fault, fault);
+        ds_put_cstr(ds, "\tfault: ");
+        ds_put_cfm_fault(ds, fault);
         ds_put_cstr(ds, "\n");
     }