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

Reply via email to