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
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);
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;
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,
struct flow_wildcards *);
void cfm_process_heartbeat(struct cfm *, const struct ofpbuf *packet);
int cfm_get_fault(const struct cfm *);
+uint64_t cfm_get_flap_count(const struct cfm *);
int cfm_get_health(const struct cfm *);
int cfm_get_opup(const struct cfm *);
void cfm_get_remote_mpids(const struct cfm *, uint64_t **rmps, size_t *n_rmps);
if (ofport->cfm) {
status->faults = cfm_get_fault(ofport->cfm);
+ status->flap_count = cfm_get_flap_count(ofport->cfm);
status->remote_opstate = cfm_get_opup(ofport->cfm);
status->health = cfm_get_health(ofport->cfm);
cfm_get_remote_mpids(ofport->cfm, &status->rmps, &status->n_rmps);
* mode. */
int remote_opstate;
+ uint64_t flap_count;
+
/* Ordinarily a "health status" in the range 0...100 inclusive, with 0
* being worst and 100 being best, or -1 if the health status is not
* well-defined. */
])
])
+m4_define([CFM_VSCTL_LIST_IFACE], [
+AT_CHECK([ovs-vsctl list interface $1 | sed -n '/$2/p'],[0],
+[dnl
+$3
+])
+])
+
# test cfm under demand mode.
AT_SETUP([cfm - demand mode])
-#Create 2 bridges connected by patch ports and enable BFD
+#Create 2 bridges connected by patch ports and enable cfm
OVS_VSWITCHD_START([add-br br1 -- \
set bridge br1 datapath-type=dummy \
other-config:hwaddr=aa:55:aa:56:00:00 -- \
OVS_VSWITCHD_STOP
AT_CLEANUP
+
+# test cfm_flap_count.
+AT_SETUP([cfm - flap_count])
+#Create 2 bridges connected by patch ports and enable cfm
+OVS_VSWITCHD_START([add-br br1 -- \
+ set bridge br1 datapath-type=dummy \
+ other-config:hwaddr=aa:55:aa:56:00:00 -- \
+ add-port br1 p1 -- set Interface p1 type=patch \
+ options:peer=p0 -- \
+ add-port br0 p0 -- set Interface p0 type=patch \
+ options:peer=p1 -- \
+ set Interface p0 cfm_mpid=1 other_config:cfm_interval=100 other_config:cfm_extended=true -- \
+ set Interface p1 cfm_mpid=2 other_config:cfm_interval=100 other_config:cfm_extended=true])
+
+ovs-appctl time/stop
+
+# wait for a while to stablize cfm.
+for i in `seq 0 100`; do ovs-appctl time/warp 100; done
+CFM_CHECK_EXTENDED([p0], [1], [100], [up], [up], [100ms], [2], [up])
+CFM_CHECK_EXTENDED([p1], [2], [100], [up], [up], [100ms], [1], [up])
+
+# turn cfm on p1 off, should increment the cfm_flap_count on p1.
+AT_CHECK([ovs-vsctl remove interface p1 cfm_mpid 2])
+for i in `seq 0 10`; do ovs-appctl time/warp 100; done
+CFM_VSCTL_LIST_IFACE([p0], [cfm_flap_count], [cfm_flap_count : 1])
+CFM_VSCTL_LIST_IFACE([p1], [cfm_flap_count], [cfm_flap_count : [[]]])
+
+# turn cfm on p1 on again, should increment the cfm_flap_count on p1.
+AT_CHECK([ovs-vsctl set interface p1 cfm_mpid=2])
+for i in `seq 0 10`; do ovs-appctl time/warp 100; done
+CFM_VSCTL_LIST_IFACE([p0], [cfm_flap_count], [cfm_flap_count : 2])
+CFM_VSCTL_LIST_IFACE([p1], [cfm_flap_count], [cfm_flap_count : 0])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
\ No newline at end of file
ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_fault);
ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_fault_status);
ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_remote_mpids);
+ ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_flap_count);
ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_health);
ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_remote_opstate);
ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_bfd_status);
ovsrec_interface_set_cfm_fault(cfg, NULL, 0);
ovsrec_interface_set_cfm_fault_status(cfg, NULL, 0);
ovsrec_interface_set_cfm_remote_opstate(cfg, NULL);
+ ovsrec_interface_set_cfm_flap_count(cfg, NULL, 0);
ovsrec_interface_set_cfm_health(cfg, NULL, 0);
ovsrec_interface_set_cfm_remote_mpids(cfg, NULL, 0);
} else {
const char *reasons[CFM_FAULT_N_REASONS];
int64_t cfm_health = status.health;
+ int64_t cfm_flap_count = status.flap_count;
bool faulted = status.faults != 0;
size_t i, j;
}
ovsrec_interface_set_cfm_fault_status(cfg, (char **) reasons, j);
+ ovsrec_interface_set_cfm_flap_count(cfg, &cfm_flap_count, 1);
+
if (status.remote_opstate >= 0) {
const char *remote_opstate = status.remote_opstate ? "up" : "down";
ovsrec_interface_set_cfm_remote_opstate(cfg, remote_opstate);
{"name": "Open_vSwitch",
"version": "7.3.0",
- "cksum": "2483452374 20182",
+ "cksum": "2811681289 20311",
"tables": {
"Open_vSwitch": {
"columns": {
"min": 0,
"max": "unlimited"},
"ephemeral": true},
+ "cfm_flap_count": {
+ "type": {
+ "key": {"type": "integer"},
+ "min": 0,
+ "max": 1}},
"cfm_fault": {
"type": {
"key": { "type": "boolean"},
CFM on this <ref table="Interface"/>.
</column>
+ <column name="cfm_flap_count">
+ Counts the number of cfm fault flapps since boot. A flap is
+ considered to be a change of the <ref column="cfm_fault"/> value.
+ </column>
+
<column name="cfm_fault">
<p>
Indicates a connectivity fault triggered by an inability to receive