+ if (timer_expired(&cfm->fault_timer)) {
+ long long int interval = cfm_fault_interval(cfm);
+ struct remote_mp *rmp, *rmp_next;
+ bool old_cfm_fault = cfm->fault;
+
+ cfm->fault = cfm->recv_fault;
+ cfm->recv_fault = 0;
+
+ cfm->rmps_array_len = 0;
+ free(cfm->rmps_array);
+ cfm->rmps_array = xmalloc(hmap_count(&cfm->remote_mps) *
+ sizeof *cfm->rmps_array);
+
+ cfm->remote_opup = true;
+ if (cfm->health_interval == CFM_HEALTH_INTERVAL) {
+ /* Calculate the cfm health of the interface. If the number of
+ * remote_mpids of a cfm interface is > 1, the cfm health is
+ * undefined. If the number of remote_mpids is 1, the cfm health is
+ * the percentage of the ccm frames received in the
+ * (CFM_HEALTH_INTERVAL * 3.5)ms, else it is 0. */
+ if (hmap_count(&cfm->remote_mps) > 1) {
+ cfm->health = -1;
+ } else if (hmap_is_empty(&cfm->remote_mps)) {
+ cfm->health = 0;
+ } else {
+ int exp_ccm_recvd;
+
+ rmp = CONTAINER_OF(hmap_first(&cfm->remote_mps),
+ struct remote_mp, node);
+ exp_ccm_recvd = (CFM_HEALTH_INTERVAL * 7) / 2;
+ /* Calculate the percentage of healthy ccm frames received.
+ * Since the 'fault_interval' is (3.5 * cfm_interval), and
+ * 1 CCM packet must be received every cfm_interval,
+ * the 'remote_mpid' health reports the percentage of
+ * healthy CCM frames received every
+ * 'CFM_HEALTH_INTERVAL'th 'fault_interval'. */
+ cfm->health = (rmp->num_health_ccm * 100) / exp_ccm_recvd;
+ cfm->health = MIN(cfm->health, 100);
+ rmp->num_health_ccm = 0;
+ assert(cfm->health >= 0 && cfm->health <= 100);
+ }
+ cfm->health_interval = 0;
+ }
+ cfm->health_interval++;