2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-01 06:45:17 +00:00

cfm: Require ccm received in demand mode.

This commit adds a new requirement that cfm session must receive
at least one ccm every 100 * cfm_interval amount of time in demand
mode.  Otherwise, even if the data packets are received on the
monitored interface, the cfm session still reports "[recv]" fault.

Since the datapath flow is not purged when the userspace Open Vswitch
crashes, data packet can still be forwarded through the tunnel and
fool the remote CFM session in demand mode.  Thus, this commit can
prevent the remote CFM session from falsely declaring tunnel liveness
in this situation.

Signed-off-by: Alex Wang <alexw@nicira.com>
Acked-by: Ethan Jackson <ethan@nicira.com>
This commit is contained in:
Alex Wang
2014-04-09 10:58:54 -07:00
parent 6e9231f70f
commit 5767a79a40
3 changed files with 90 additions and 4 deletions

View File

@@ -137,6 +137,11 @@ struct cfm {
/* 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
@@ -459,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;
}
@@ -836,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;

View File

@@ -14,6 +14,19 @@ Remote MPID $7
])
])
m4_define([CFM_CHECK_EXTENDED_FAULT], [
AT_CHECK([ovs-appctl cfm/show $1 | sed -e '/next CCM tx:/d' | sed -e '/next fault check:/d' | sed -e '/recv since check:/d'],[0],
[dnl
---- $1 ----
MPID $2: extended
fault: $3
average health: $4
opstate: $5
remote_opstate: $6
interval: $7
])
])
m4_define([CFM_VSCTL_LIST_IFACE], [
AT_CHECK([ovs-vsctl list interface $1 | sed -n '/$2/p'],[0],
[dnl
@@ -101,6 +114,68 @@ done
OVS_VSWITCHD_STOP
AT_CLEANUP
# test demand_rx_ccm under demand mode.
AT_SETUP([cfm - demand_rx_ccm])
#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 ofport_request=2 -- \
add-port br0 p0 -- set Interface p0 type=patch \
options:peer=p1 ofport_request=1 -- \
set Interface p0 cfm_mpid=1 other_config:cfm_interval=300 other_config:cfm_extended=true other_config:cfm_demand=true -- \
set Interface p1 cfm_mpid=2 other_config:cfm_interval=300 other_config:cfm_extended=true other_config:cfm_demand=true])
ovs-appctl time/stop
# wait for a while to stablize cfm. (need a longer time, since in demand mode
# the fault interval is (MAX(ccm_interval_ms, 500) * 3.5) ms)
for i in `seq 0 200`; do ovs-appctl time/warp 100; done
CFM_CHECK_EXTENDED([p0], [1], [100], [up], [up], [300ms], [2], [up])
CFM_CHECK_EXTENDED([p1], [2], [100], [up], [up], [300ms], [1], [up])
# turn off the cfm on p1.
AT_CHECK([ovs-vsctl clear Interface p1 cfm_mpid])
# cfm should never go down while receiving data packets.
for i in `seq 0 200`
do
ovs-appctl time/warp 100
AT_CHECK([ovs-ofctl packet-out br1 3 2 "90e2ba01475000101856b2e80806000108000604000100101856b2e80202020300000000000002020202"],
[0], [stdout], [])
done
CFM_CHECK_EXTENDED([p0], [1], [0], [up], [up], [300ms], [2], [up])
# wait longer, since the demand_rx_ccm interval is 100 * 300 ms.
# since there is no ccm received, the [recv] fault should be raised.
for i in `seq 0 200`
do
ovs-appctl time/warp 100
AT_CHECK([ovs-ofctl packet-out br1 3 2 "90e2ba01475000101856b2e80806000108000604000100101856b2e80202020300000000000002020202"],
[0], [stdout], [])
done
CFM_CHECK_EXTENDED_FAULT([p0], [1], [recv], [0], [up], [up], [300ms])
# now turn on the cfm on p1 again,
AT_CHECK([ovs-vsctl set Interface p1 cfm_mpid=2])
# cfm should be up for both p0 and p1
for i in `seq 0 200`; do ovs-appctl time/warp 100; done
CFM_CHECK_EXTENDED([p0], [1], [100], [up], [up], [300ms], [2], [up])
CFM_CHECK_EXTENDED([p1], [2], [100], [up], [up], [300ms], [1], [up])
# now turn off the cfm on p1 again
AT_CHECK([ovs-vsctl clear Interface p1 cfm_mpid])
# since there is no ccm received, the [recv] fault should be raised.
for i in `seq 0 400`
do
ovs-appctl time/warp 100
AT_CHECK([ovs-ofctl packet-out br1 3 2 "90e2ba01475000101856b2e80806000108000604000100101856b2e80202020300000000000002020202"],
[0], [stdout], [])
done
CFM_CHECK_EXTENDED_FAULT([p0], [1], [recv], [0], [up], [up], [300ms])
OVS_VSWITCHD_STOP
AT_CLEANUP
# test cfm_flap_count.
AT_SETUP([cfm - flap_count])
#Create 2 bridges connected by patch ports and enable cfm

View File

@@ -2231,9 +2231,10 @@
<ref column="other_config" key="cfm_extended"/> is true, the CFM
module operates in demand mode. When in demand mode, traffic
received on the <ref table="Interface"/> is used to indicate
liveness. CCMs are still transmitted and received, but if the
<ref table="Interface"/> is receiving traffic, their absence does not
cause a connectivity fault.
liveness. CCMs are still transmitted and received. At least one
CCM must be received every 100 * <ref column="other_config"
key="cfm_interval"/> amount of time. Otherwise, even if traffic
are received, the CFM module will raise the connectivity fault.
</p>
<p>