X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=lib%2Fcfm.c;h=9c65b3489ddae24897b49aa23369fa73b224ef4e;hb=fb668e3a13eaa07bbb8bc50cbee1d201051b779c;hp=0bd41bf966ed4af7325508abde8239d56b85e4a6;hpb=016953ae96bebb3d3c421757d1f98b9966433bd1;p=cascardo%2Fovs.git diff --git a/lib/cfm.c b/lib/cfm.c index 0bd41bf96..9c65b3489 100644 --- a/lib/cfm.c +++ b/lib/cfm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, 2012 Nicira, Inc. + * Copyright (c) 2010, 2011, 2012, 2013 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -129,6 +129,8 @@ struct cfm { atomic_bool check_tnl_key; /* Verify the tunnel key of inbound packets? */ atomic_bool extended; /* Extended mode. */ atomic_int ref_cnt; + + uint64_t flap_count; /* Count the flaps since boot. */ }; /* Remote MPs represent foreign network entities that are configured to have @@ -156,7 +158,7 @@ static unixctl_cb_func cfm_unixctl_show; static unixctl_cb_func cfm_unixctl_set_fault; static uint64_t -cfm_rx_packets(const struct cfm *cfm) OVS_REQ_WRLOCK(mutex) +cfm_rx_packets(const struct cfm *cfm) OVS_REQUIRES(mutex) { struct netdev_stats stats; @@ -168,7 +170,7 @@ cfm_rx_packets(const struct cfm *cfm) OVS_REQ_WRLOCK(mutex) } static const uint8_t * -cfm_ccm_addr(const struct cfm *cfm) +cfm_ccm_addr(struct cfm *cfm) { bool extended; atomic_read(&cfm->extended, &extended); @@ -204,7 +206,7 @@ ds_put_cfm_fault(struct ds *ds, int fault) } static void -cfm_generate_maid(struct cfm *cfm) OVS_REQ_WRLOCK(mutex) +cfm_generate_maid(struct cfm *cfm) OVS_REQUIRES(mutex) { const char *ovs_md_name = "ovs"; const char *ovs_ma_name = "ovs"; @@ -247,7 +249,7 @@ ccm_interval_to_ms(uint8_t interval) } static long long int -cfm_fault_interval(struct cfm *cfm) OVS_REQ_WRLOCK(mutex) +cfm_fault_interval(struct cfm *cfm) OVS_REQUIRES(mutex) { /* According to the 802.1ag specification we should assume every other MP * with the same MAID has the same transmission interval that we have. If @@ -255,9 +257,13 @@ cfm_fault_interval(struct cfm *cfm) OVS_REQ_WRLOCK(mutex) * as a fault (likely due to a configuration error). Thus we can check all * MPs at once making this quite a bit simpler. * - * According to the specification we should check when (ccm_interval_ms * - * 3.5)ms have passed. */ - return (cfm->ccm_interval_ms * 7) / 2; + * When cfm is not in demand mode, we check when (ccm_interval_ms * 3.5) ms + * have passed. When cfm is in demand mode, we check when + * (MAX(ccm_interval_ms, 500) * 3.5) ms have passed. This ensures that + * ovs-vswitchd has enough time to pull statistics from the datapath. */ + + return (MAX(cfm->ccm_interval_ms, cfm->demand ? 500 : cfm->ccm_interval_ms) + * 7) / 2; } static uint8_t @@ -289,7 +295,7 @@ cfm_is_valid_mpid(bool extended, uint64_t mpid) } static struct remote_mp * -lookup_remote_mp(const struct cfm *cfm, uint64_t mpid) OVS_REQ_WRLOCK(mutex) +lookup_remote_mp(const struct cfm *cfm, uint64_t mpid) OVS_REQUIRES(mutex) { struct remote_mp *rmp; @@ -326,6 +332,7 @@ cfm_create(const struct netdev *netdev) OVS_EXCLUDED(mutex) cfm->fault_override = -1; cfm->health = -1; cfm->last_tx = 0; + cfm->flap_count = 0; atomic_init(&cfm->extended, false); atomic_init(&cfm->check_tnl_key, false); atomic_init(&cfm->ref_cnt, 1); @@ -473,16 +480,23 @@ cfm_run(struct cfm *cfm) OVS_EXCLUDED(mutex) cfm->fault |= CFM_FAULT_RECV; } - if (old_cfm_fault != cfm->fault && !VLOG_DROP_INFO(&rl)) { - struct ds ds = DS_EMPTY_INITIALIZER; + if (old_cfm_fault != cfm->fault) { + if (!VLOG_DROP_INFO(&rl)) { + struct ds ds = DS_EMPTY_INITIALIZER; + + 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); + } - 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); + /* If there is a flap, increments the counter. */ + if (old_cfm_fault == false || cfm->fault == false) { + cfm->flap_count++; + } } cfm->booted = true; @@ -576,12 +590,27 @@ cfm_compose_ccm(struct cfm *cfm, struct ofpbuf *packet, void cfm_wait(struct cfm *cfm) OVS_EXCLUDED(mutex) { + poll_timer_wait_until(cfm_wake_time(cfm)); +} + + +/* Returns the next cfm wakeup time. */ +long long int +cfm_wake_time(struct cfm *cfm) OVS_EXCLUDED(mutex) +{ + long long int retval; + + if (!cfm) { + return LLONG_MAX; + } + ovs_mutex_lock(&mutex); - timer_wait(&cfm->tx_timer); - timer_wait(&cfm->fault_timer); + retval = MIN(cfm->tx_timer.t, cfm->fault_timer.t); ovs_mutex_unlock(&mutex); + return retval; } + /* Configures 'cfm' with settings from 's'. */ bool cfm_configure(struct cfm *cfm, const struct cfm_settings *s) @@ -611,7 +640,6 @@ cfm_configure(struct cfm *cfm, const struct cfm_settings *s) } if (s->extended && s->demand) { - interval_ms = MAX(interval_ms, 500); if (!cfm->demand) { cfm->demand = true; cfm->rx_packets = cfm_rx_packets(cfm); @@ -648,9 +676,10 @@ cfm_set_netdev(struct cfm *cfm, const struct netdev *netdev) /* Returns true if 'cfm' should process packets from 'flow'. Sets * fields in 'wc' that were used to make the determination. */ bool -cfm_should_process_flow(const struct cfm *cfm, const struct flow *flow, +cfm_should_process_flow(const struct cfm *cfm_, const struct flow *flow, struct flow_wildcards *wc) { + struct cfm *cfm = CONST_CAST(struct cfm *, cfm_); bool check_tnl_key; atomic_read(&cfm->check_tnl_key, &check_tnl_key); @@ -726,7 +755,6 @@ cfm_process_heartbeat(struct cfm *cfm, const struct ofpbuf *p) ccm_seq = ntohl(ccm->seq); if (ccm_interval != cfm->ccm_interval) { - cfm_fault |= CFM_FAULT_INTERVAL; VLOG_WARN_RL(&rl, "%s: received a CCM with an unexpected interval" " (%"PRIu8") from RMP %"PRIu64, cfm->name, ccm_interval, ccm_mpid); @@ -734,7 +762,6 @@ cfm_process_heartbeat(struct cfm *cfm, const struct ofpbuf *p) if (extended && ccm_interval == 0 && ccm_interval_ms_x != cfm->ccm_interval_ms) { - cfm_fault |= CFM_FAULT_INTERVAL; VLOG_WARN_RL(&rl, "%s: received a CCM with an unexpected extended" " interval (%"PRIu16"ms) from RMP %"PRIu64, cfm->name, ccm_interval_ms_x, ccm_mpid); @@ -795,7 +822,7 @@ out: } static int -cfm_get_fault__(const struct cfm *cfm) OVS_REQ_WRLOCK(mutex) +cfm_get_fault__(const struct cfm *cfm) OVS_REQUIRES(mutex) { if (cfm->fault_override >= 0) { return cfm->fault_override ? CFM_FAULT_OVERRIDE : 0; @@ -817,6 +844,17 @@ cfm_get_fault(const struct cfm *cfm) OVS_EXCLUDED(mutex) return fault; } +/* Gets the number of cfm fault flapping since start. */ +uint64_t +cfm_get_flap_count(const struct cfm *cfm) OVS_EXCLUDED(mutex) +{ + uint64_t flap_count; + ovs_mutex_lock(&mutex); + flap_count = cfm->flap_count; + ovs_mutex_unlock(&mutex); + return flap_count; +} + /* Gets the health of 'cfm'. Returns an integer between 0 and 100 indicating * the health of the link as a percentage of ccm frames received in * CFM_HEALTH_INTERVAL * 'fault_interval' if there is only 1 remote_mpid, @@ -839,8 +877,9 @@ cfm_get_health(const struct cfm *cfm) OVS_EXCLUDED(mutex) * '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) OVS_EXCLUDED(mutex) +cfm_get_opup(const struct cfm *cfm_) OVS_EXCLUDED(mutex) { + struct cfm *cfm = CONST_CAST(struct cfm *, cfm_); bool extended; int opup; @@ -860,13 +899,13 @@ cfm_get_remote_mpids(const struct cfm *cfm, uint64_t **rmps, size_t *n_rmps) OVS_EXCLUDED(mutex) { ovs_mutex_lock(&mutex); - *rmps = xmemdup(cfm->rmps_array, cfm->rmps_array_len); + *rmps = xmemdup(cfm->rmps_array, cfm->rmps_array_len * sizeof **rmps); *n_rmps = cfm->rmps_array_len; ovs_mutex_unlock(&mutex); } static struct cfm * -cfm_find(const char *name) OVS_REQ_WRLOCK(&mutex) +cfm_find(const char *name) OVS_REQUIRES(mutex) { struct cfm *cfm; @@ -879,7 +918,7 @@ cfm_find(const char *name) OVS_REQ_WRLOCK(&mutex) } static void -cfm_print_details(struct ds *ds, const struct cfm *cfm) OVS_REQ_WRLOCK(&mutex) +cfm_print_details(struct ds *ds, struct cfm *cfm) OVS_REQUIRES(mutex) { struct remote_mp *rmp; bool extended; @@ -926,7 +965,7 @@ cfm_unixctl_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux OVS_UNUSED) OVS_EXCLUDED(mutex) { struct ds ds = DS_EMPTY_INITIALIZER; - const struct cfm *cfm; + struct cfm *cfm; ovs_mutex_lock(&mutex); if (argc > 1) {