Acked-by: Ethan Jackson <et...@nicira.com>
On Tue, Apr 29, 2014 at 4:15 PM, Alex Wang <al...@nicira.com> wrote: > 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 <al...@nicira.com> > > --- > PATCH -> V2: > - hard code the demand_rx_ccm interval to be 100 * cfm_interval. > --- > lib/cfm.c | 12 +++++++- > tests/cfm.at | 75 > ++++++++++++++++++++++++++++++++++++++++++++++++++ > vswitchd/vswitch.xml | 7 +++-- > 3 files changed, 90 insertions(+), 4 deletions(-) > > diff --git a/lib/cfm.c b/lib/cfm.c > index 6a173a7..1b32625 100644 > --- a/lib/cfm.c > +++ b/lib/cfm.c > @@ -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; > diff --git a/tests/cfm.at b/tests/cfm.at > index a3c44a1..fdca4ac 100644 > --- a/tests/cfm.at > +++ b/tests/cfm.at > @@ -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 > diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml > index 78594e7..91dfdf9 100644 > --- a/vswitchd/vswitch.xml > +++ b/vswitchd/vswitch.xml > @@ -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> > -- > 1.7.9.5 > _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev