X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fcfm.c;h=1b326252902c21b98f644fc247f317ec9b9d23db;hb=5767a79a40599e5e6e70662833b27ffdbdab7e37;hp=325931d49bd6e65c2b421f800302e03af621d57b;hpb=18dcfc56cb66d4a318034e80cc628674c12bf16e;p=sliver-openvswitch.git diff --git a/lib/cfm.c b/lib/cfm.c index 325931d49..1b3262529 100644 --- a/lib/cfm.c +++ b/lib/cfm.c @@ -133,6 +133,15 @@ struct cfm { struct ovs_refcount ref_cnt; uint64_t flap_count; /* Count the flaps since boot. */ + + /* True when the variables returned by cfm_get_*() are changed + * since last check. */ + bool status_changed; + + /* When 'cfm->demand' is set, at least one ccm is required to be received + * every 100 * cfm_interval. If ccm is not received within this interval, + * even if data packets are received, the cfm fault will be set. */ + struct timer demand_rx_ccm_t; }; /* Remote MPs represent foreign network entities that are configured to have @@ -285,7 +294,7 @@ ms_to_ccm_interval(int interval_ms) static uint32_t hash_mpid(uint64_t mpid) { - return hash_bytes(&mpid, sizeof mpid, 0); + return hash_uint64(mpid); } static bool @@ -343,6 +352,7 @@ cfm_create(const struct netdev *netdev) OVS_EXCLUDED(mutex) cfm_generate_maid(cfm); hmap_insert(all_cfms, &cfm->hmap_node, hash_string(cfm->name, 0)); ovs_mutex_unlock(&mutex); + return cfm; } @@ -385,6 +395,14 @@ cfm_ref(const struct cfm *cfm_) return cfm; } +/* Records the status change and changes the global connectivity seq. */ +static void +cfm_status_changed(struct cfm *cfm) OVS_REQUIRES(mutex) +{ + seq_change(connectivity_seq_get()); + cfm->status_changed = true; +} + /* Should be run periodically to update fault statistics messages. */ void cfm_run(struct cfm *cfm) OVS_EXCLUDED(mutex) @@ -393,11 +411,11 @@ cfm_run(struct cfm *cfm) OVS_EXCLUDED(mutex) if (timer_expired(&cfm->fault_timer)) { long long int interval = cfm_fault_interval(cfm); struct remote_mp *rmp, *rmp_next; + enum cfm_fault_reason old_cfm_fault = cfm->fault; uint64_t old_flap_count = cfm->flap_count; int old_health = cfm->health; size_t old_rmps_array_len = cfm->rmps_array_len; bool old_rmps_deleted = false; - bool old_cfm_fault = cfm->fault; bool old_rmp_opup = cfm->remote_opup; bool demand_override; bool rmp_set_opup = false; @@ -446,7 +464,8 @@ cfm_run(struct cfm *cfm) OVS_EXCLUDED(mutex) if (cfm->demand) { uint64_t rx_packets = cfm_rx_packets(cfm); demand_override = hmap_count(&cfm->remote_mps) == 1 - && rx_packets > cfm->rx_packets; + && rx_packets > cfm->rx_packets + && !timer_expired(&cfm->demand_rx_ccm_t); cfm->rx_packets = rx_packets; } @@ -498,7 +517,7 @@ cfm_run(struct cfm *cfm) OVS_EXCLUDED(mutex) } /* If there is a flap, increments the counter. */ - if (old_cfm_fault == false || cfm->fault == false) { + if (old_cfm_fault == 0 || cfm->fault == 0) { cfm->flap_count++; } } @@ -510,7 +529,7 @@ cfm_run(struct cfm *cfm) OVS_EXCLUDED(mutex) || (old_rmps_array_len != cfm->rmps_array_len || old_rmps_deleted) || old_cfm_fault != cfm->fault || old_flap_count != cfm->flap_count) { - seq_change(connectivity_seq_get()); + cfm_status_changed(cfm); } cfm->booted = true; @@ -557,7 +576,7 @@ cfm_compose_ccm(struct cfm *cfm, struct ofpbuf *packet, eth_push_vlan(packet, htons(ETH_TYPE_VLAN), htons(tci)); } - ccm = packet->l3; + ccm = ofpbuf_l3(packet); ccm->mdlevel_version = 0; ccm->opcode = CCM_OPCODE; ccm->tlv_offset = 70; @@ -718,8 +737,9 @@ cfm_process_heartbeat(struct cfm *cfm, const struct ofpbuf *p) ovs_mutex_lock(&mutex); - eth = p->l2; - ccm = ofpbuf_at(p, (uint8_t *)p->l3 - (uint8_t *)p->data, CCM_ACCEPT_LEN); + eth = ofpbuf_l2(p); + ccm = ofpbuf_at(p, (uint8_t *)ofpbuf_l3(p) - (uint8_t *)ofpbuf_data(p), + CCM_ACCEPT_LEN); if (!ccm) { VLOG_INFO_RL(&rl, "%s: Received an unparseable 802.1ag CCM heartbeat.", @@ -822,6 +842,10 @@ cfm_process_heartbeat(struct cfm *cfm, const struct ofpbuf *p) rmp->mpid = ccm_mpid; if (!cfm_fault) { rmp->num_health_ccm++; + if (cfm->demand) { + timer_set_duration(&cfm->demand_rx_ccm_t, + 100 * cfm->ccm_interval_ms); + } } rmp->recv = true; cfm->recv_fault |= cfm_fault; @@ -835,6 +859,20 @@ out: ovs_mutex_unlock(&mutex); } +/* Returns and resets the 'cfm->status_changed'. */ +bool +cfm_check_status_change(struct cfm *cfm) OVS_EXCLUDED(mutex) +{ + bool ret; + + ovs_mutex_lock(&mutex); + ret = cfm->status_changed; + cfm->status_changed = false; + ovs_mutex_unlock(&mutex); + + return ret; +} + static int cfm_get_fault__(const struct cfm *cfm) OVS_REQUIRES(mutex) { @@ -1028,13 +1066,14 @@ cfm_unixctl_set_fault(struct unixctl_conn *conn, int argc, const char *argv[], goto out; } cfm->fault_override = fault_override; + cfm_status_changed(cfm); } else { HMAP_FOR_EACH (cfm, hmap_node, all_cfms) { cfm->fault_override = fault_override; + cfm_status_changed(cfm); } } - seq_change(connectivity_seq_get()); unixctl_command_reply(conn, "OK"); out: