No subject


Fri Jun 29 21:31:54 UTC 2012


think I can
finish the bfd decay tests soon and check if  there is any hidden bugs.

Hope to hear comments from you.

Kind Regards,
Alex Wang,


On Fri, Jul 12, 2013 at 7:03 PM, Alex Wang <alexw at nicira.com> wrote:

> When there is no incoming data traffic at the interface for a period,
> BFD decay allows the bfd session to increase the min_rx. This is
> helpful in that some interfaces usually idle for long time. And cpu
> consumption can be reduced by processing fewer bfd control packets.
>
> Signed-off-by: Alex Wang <alexw at nicira.com>
> ---
>
> v1 -> v2:
> - remove bfd:decay_enable option, only use bfd:decay_min_rx.
> - add bfd_set_netdev() function.
> - reset decay_min_rx when itself or min_rx is reconfigured.
> - use bfd_poll() to update the decay changes.
> - refine the code as suggested by Ethan.
>
> ---
>  lib/bfd.c              |   97
> ++++++++++++++++++++++++++++++++++++++++++++++--
>  lib/bfd.h              |    5 ++-
>  ofproto/ofproto-dpif.c |    7 +++-
>  vswitchd/vswitch.xml   |   10 +++++
>  4 files changed, 113 insertions(+), 6 deletions(-)
>
> diff --git a/lib/bfd.c b/lib/bfd.c
> index aa1a3f7..e5b04ec 100644
> --- a/lib/bfd.c
> +++ b/lib/bfd.c
> @@ -24,6 +24,7 @@
>  #include "hash.h"
>  #include "hmap.h"
>  #include "list.h"
> +#include "netdev.h"
>  #include "netlink.h"
>  #include "odp-util.h"
>  #include "ofpbuf.h"
> @@ -152,6 +153,9 @@ struct bfd {
>      bool cpath_down;              /* Concatenated Path Down. */
>      uint8_t mult;                 /* bfd.DetectMult. */
>
> +    struct netdev *netdev;
> +    uint64_t rx_packets;          /* Packets received by 'netdev'. */
> +
>      enum state state;             /* bfd.SessionState. */
>      enum state rmt_state;         /* bfd.RemoteSessionState. */
>
> @@ -182,6 +186,10 @@ struct bfd {
>
>      int ref_cnt;
>      int forwarding_override;      /* Manual override of 'forwarding'
> status. */
> +
> +    /* BFD decay related variables. */
> +    int decay_min_rx;
> +    long long int decay_detect_time; /* Decay detection time. */
>  };
>
>  static bool bfd_in_poll(const struct bfd *);
> @@ -191,6 +199,8 @@ static const char *bfd_state_str(enum state);
>  static long long int bfd_min_tx(const struct bfd *);
>  static long long int bfd_tx_interval(const struct bfd *);
>  static long long int bfd_rx_interval(const struct bfd *);
> +static uint64_t bfd_rx_packets(const struct bfd *);
> +static void bfd_decay(struct bfd *);
>  static void bfd_set_next_tx(struct bfd *);
>  static void bfd_set_state(struct bfd *, enum state, enum diag);
>  static uint32_t generate_discriminator(void);
> @@ -242,12 +252,13 @@ bfd_get_status(const struct bfd *bfd, struct smap
> *smap)
>   * handle for the session, or NULL if BFD is not enabled according to
> 'cfg'.
>   * Also returns NULL if cfg is NULL. */
>  struct bfd *
> -bfd_configure(struct bfd *bfd, const char *name,
> -              const struct smap *cfg)
> +bfd_configure(struct bfd *bfd, const char *name, const struct smap *cfg,
> +              struct netdev *netdev)
>  {
>      static uint16_t udp_src = 0;
>      static bool init = false;
>
> +    int decay_min_rx;
>      long long int min_tx, min_rx;
>      bool cpath_down;
>
> @@ -276,6 +287,9 @@ bfd_configure(struct bfd *bfd, const char *name,
>          bfd->min_tx = 1000;
>          bfd->mult = 3;
>          bfd->ref_cnt = 1;
> +        bfd->netdev = netdev_ref(netdev);
> +        bfd->decay_detect_time = 0;
> +        bfd->rx_packets = bfd_rx_packets(bfd);
>
>          /* RFC 5881 section 4
>           * The source port MUST be in the range 49152 through 65535.  The
> same
> @@ -295,6 +309,7 @@ bfd_configure(struct bfd *bfd, const char *name,
>              || (!bfd_in_poll(bfd) && bfd->cfg_min_tx < bfd->min_tx)) {
>              bfd->min_tx = bfd->cfg_min_tx;
>          }
> +        bfd->decay_min_rx = 0;
>          bfd_poll(bfd);
>      }
>
> @@ -309,6 +324,19 @@ bfd_configure(struct bfd *bfd, const char *name,
>          bfd_poll(bfd);
>      }
>
> +    decay_min_rx = smap_get_int(cfg, "decay_min_rx", 0);
> +    if (bfd->decay_min_rx != decay_min_rx ) {
> +        if (decay_min_rx > 0 && decay_min_rx < bfd->cfg_min_rx) {
> +            VLOG_WARN("%s: decay_min_rx cannot be less than %lld ms",
> +                      bfd->name, bfd->cfg_min_rx);
> +            bfd->decay_min_rx = 0;
> +        } else {
> +            bfd->decay_min_rx = decay_min_rx;
> +        }
> +        bfd->min_rx = bfd->cfg_min_rx;
> +        bfd_poll(bfd);
> +    }
> +
>      cpath_down = smap_get_bool(cfg, "cpath_down", false);
>      if (bfd->cpath_down != cpath_down) {
>          bfd->cpath_down = cpath_down;
> @@ -340,6 +368,7 @@ bfd_unref(struct bfd *bfd)
>              hmap_remove(&all_bfds, &bfd->node);
>              free(bfd->name);
>              free(bfd);
> +            netdev_close(bfd->netdev);
>          }
>      }
>  }
> @@ -360,11 +389,23 @@ bfd_wait(const struct bfd *bfd)
>  void
>  bfd_run(struct bfd *bfd)
>  {
> -    if (bfd->state > STATE_DOWN && time_msec() >= bfd->detect_time) {
> +    long long int now = time_msec();
> +
> +    if (bfd->state > STATE_DOWN && now >= bfd->detect_time) {
>          bfd_set_state(bfd, STATE_DOWN, DIAG_EXPIRED);
>      }
>
> +    if (bfd->state == STATE_UP && bfd->decay_min_rx > 0
> +        && now >= bfd->decay_detect_time) {
> +        bfd_decay(bfd);
> +    }
> +
>      if (bfd->min_tx != bfd->cfg_min_tx || bfd->min_rx != bfd->cfg_min_rx)
> {
> +        /* Do not poll if already decayed to decay_min_rx. */
> +        if (bfd->state == STATE_UP && bfd->poll_min_rx ==
> bfd->decay_min_rx
> +            && bfd->cfg_min_tx == bfd->min_tx) {
> +            return;
> +        }
>          bfd_poll(bfd);
>      }
>  }
> @@ -616,6 +657,17 @@ bfd_process_packet(struct bfd *bfd, const struct flow
> *flow,
>      }
>      /* XXX: RFC 5880 Section 6.8.6 Demand mode related calculations here.
> */
>  }
> +
> +/* Must be called when the netdev owned by 'bfd' should change. */
> +void
> +bfd_set_netdev(struct bfd *bfd, const struct netdev *netdev)
> +{
> +    if (bfd->netdev != netdev) {
> +        netdev_close(bfd->netdev);
> +        bfd->netdev = netdev_ref(netdev);
> +    }
> +}
> +
>
>  /* Helpers. */
>  static bool
> @@ -630,7 +682,8 @@ bfd_poll(struct bfd *bfd)
>      if (bfd->state > STATE_DOWN && !bfd_in_poll(bfd)
>          && !(bfd->flags & FLAG_FINAL)) {
>          bfd->poll_min_tx = bfd->cfg_min_tx;
> -        bfd->poll_min_rx = bfd->cfg_min_rx;
> +        bfd->poll_min_rx = bfd->min_rx == bfd->decay_min_rx
> +                           ? bfd->decay_min_rx : bfd->cfg_min_rx;
>          bfd->flags |= FLAG_POLL;
>          bfd->next_tx = 0;
>          VLOG_INFO_RL(&rl, "%s: Initiating poll sequence", bfd->name);
> @@ -804,6 +857,42 @@ bfd_set_state(struct bfd *bfd, enum state state, enum
> diag diag)
>      }
>  }
>
> +static uint64_t
> +bfd_rx_packets(const struct bfd *bfd)
> +{
> +    struct netdev_stats stats;
> +
> +    if (!netdev_get_stats(bfd->netdev, &stats)) {
> +        return stats.rx_packets;
> +    } else {
> +        return 0;
> +    }
> +}
> +
> +static void
> +bfd_decay(struct bfd *bfd)
> +{
> +    uint64_t rx_packets = bfd_rx_packets(bfd);
> +    int64_t diff;
> +
> +    diff = rx_packets - bfd->rx_packets;
> +    bfd->rx_packets = rx_packets;
> +    bfd->decay_detect_time = (bfd->decay_min_rx < 2000 ?
> +                              2000 : bfd->decay_min_rx) + time_msec();
> +
> +    if (diff <= (bfd->decay_min_rx / bfd->min_rx + 5)) {
> +        /* Decay when there is no obvious data traffic. */
> +        if (bfd->min_rx != bfd->decay_min_rx) {
> +            bfd->min_rx = bfd->decay_min_rx;
> +        }
> +    } else {
> +        /* Restore the min_rx. */
> +        if (bfd->min_rx != bfd->cfg_min_rx) {
> +            bfd->min_rx = bfd->cfg_min_rx;
> +        }
> +    }
> +}
> +
>  static uint32_t
>  generate_discriminator(void)
>  {
> diff --git a/lib/bfd.h b/lib/bfd.h
> index ab854d8..db652e1 100644
> --- a/lib/bfd.h
> +++ b/lib/bfd.h
> @@ -24,6 +24,7 @@
>  struct bfd;
>  struct flow;
>  struct flow_wildcards;
> +struct netdev;
>  struct ofpbuf;
>  struct smap;
>
> @@ -39,11 +40,13 @@ void bfd_process_packet(struct bfd *, const struct
> flow *,
>                          const struct ofpbuf *);
>
>  struct bfd *bfd_configure(struct bfd *, const char *name,
> -                          const struct smap *smap);
> +                          const struct smap *smap,
> +                          struct netdev *netdev);
>  struct bfd *bfd_ref(const struct bfd *);
>  void bfd_unref(struct bfd *);
>
>  bool bfd_forwarding(const struct bfd *);
>  void bfd_get_status(const struct bfd *, struct smap *);
> +void bfd_set_netdev(struct bfd *, const struct netdev *);
>
>  #endif /* bfd.h */
> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> index 67e6c7a..63e4299 100644
> --- a/ofproto/ofproto-dpif.c
> +++ b/ofproto/ofproto-dpif.c
> @@ -1748,6 +1748,10 @@ port_modified(struct ofport *port_)
>          cfm_set_netdev(port->cfm, port->up.netdev);
>      }
>
> +    if (port->bfd) {
> +        bfd_set_netdev(port->bfd, port->up.netdev);
> +    }
> +
>      if (port->is_tunnel && tnl_port_reconfigure(port, port->up.netdev,
>                                                  port->odp_port)) {
>          ofproto_dpif_cast(port->up.ofproto)->backer->need_revalidate =
> @@ -1882,7 +1886,8 @@ set_bfd(struct ofport *ofport_, const struct smap
> *cfg)
>      struct bfd *old;
>
>      old = ofport->bfd;
> -    ofport->bfd = bfd_configure(old, netdev_get_name(ofport->up.netdev),
> cfg);
> +    ofport->bfd = bfd_configure(old, netdev_get_name(ofport->up.netdev),
> +                                cfg, ofport->up.netdev);
>      if (ofport->bfd != old) {
>          ofproto->backer->need_revalidate = REV_RECONFIGURE;
>      }
> diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
> index 3385912..7d2d601 100644
> --- a/vswitchd/vswitch.xml
> +++ b/vswitchd/vswitch.xml
> @@ -1880,6 +1880,16 @@
>            specified.  Defaults to <code>100</code>.
>        </column>
>
> +      <column name="bfd" key="decay_min_rx" type='{"type": "integer"}'>
> +          <code>decay_min_rx</code> is used to set the
> <code>min_rx</code>,
> +          when there is no obvious incoming data traffic at the interface.
> +          It cannot be less than the <code>min_rx</code>. The decay
> feature
> +          is disable by setting the <code>decay_min_rx</code> to 0. And
> the
> +          feature is reset everytime the itself or <code>min_rx</code> is
> +          reconfigured.
> +      </column>
> +
> +
>        <column name="bfd" key="cpath_down" type='{"type": "boolean"}'>
>            Concatenated path down may be used when the local system should
> not
>            have traffic forwarded to it for some reason other than a
> connectivty
> --
> 1.7.9.5
>
>

--047d7b3a8756ee3c6604e15af156
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Hey Ethan,<div><br></div><div style>Sorry, I didn&#39;t ad=
d the version number. Should be [PATCH 1/2 V2]</div><div style><br></div><d=
iv>One clarification:</div><div>&quot;&quot;&quot;</div><div><span style=3D=
"font-family:arial,sans-serif;font-size:13.333333969116211px">+ =A0 =A0bfd-=
&gt;decay_detect_time =3D (bfd-&gt;decay_min_rx &lt; 2000 ?</span><br style=
=3D"font-family:arial,sans-serif;font-size:13.333333969116211px">

<span style=3D"font-family:arial,sans-serif;font-size:13.333333969116211px"=
>+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A02000 : bfd-&g=
t;decay_min_rx) + time_msec();</span><br></div><div>&quot;&quot;&quot;</div=
>
<div>The decay_detect_time should be greater than 2000, since &quot;facet_p=
ush_stats()&quot;</div><div>is called every 2 seconds. If the &quot;decay_d=
etect_time&quot; is less than 2 sec, there can</div><div>be flips between d=
ecay and non-decay.</div>

<div><br></div><div>From what I experimented on ejja and ejjb, this patch w=
orks fine. Also I think I can</div><div>finish the bfd decay tests soon and=
 check if =A0there is any hidden bugs.=A0</div>
<div><br></div><div>Hope to hear comments from you.</div><div><br></div><di=
v>Kind Regards,</div><div>Alex Wang,</div><div class=3D"gmail_extra"><br><b=
r><div class=3D"gmail_quote">On Fri, Jul 12, 2013 at 7:03 PM, Alex Wang <sp=
an dir=3D"ltr">&lt;<a href=3D"mailto:alexw at nicira.com" target=3D"_blank">al=
exw at nicira.com</a>&gt;</span> wrote:<br>

<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex">When there is no incoming data traffic at the interface fo=
r a period,<br>

BFD decay allows the bfd session to increase the min_rx. This is<br>
helpful in that some interfaces usually idle for long time. And cpu<br>
consumption can be reduced by processing fewer bfd control packets.<br>
<br>
Signed-off-by: Alex Wang &lt;<a href=3D"mailto:alexw at nicira.com" target=3D"=
_blank">alexw at nicira.com</a>&gt;<br>
---<br>
<br>
v1 -&gt; v2:<br>
- remove bfd:decay_enable option, only use bfd:decay_min_rx.<br>
- add bfd_set_netdev() function.<br>
- reset decay_min_rx when itself or min_rx is reconfigured.<br>
- use bfd_poll() to update the decay changes.<br>
- refine the code as suggested by Ethan.<br>
<br>
---<br>
=A0lib/bfd.c =A0 =A0 =A0 =A0 =A0 =A0 =A0| =A0 97 ++++++++++++++++++++++++++=
++++++++++++++++++++--<br>
=A0lib/bfd.h =A0 =A0 =A0 =A0 =A0 =A0 =A0| =A0 =A05 ++-<br>
=A0ofproto/ofproto-dpif.c | =A0 =A07 +++-<br>
=A0vswitchd/vswitch.xml =A0 | =A0 10 +++++<br>
=A04 files changed, 113 insertions(+), 6 deletions(-)<br>
<br>
diff --git a/lib/bfd.c b/lib/bfd.c<br>
index aa1a3f7..e5b04ec 100644<br>
--- a/lib/bfd.c<br>
+++ b/lib/bfd.c<br>
@@ -24,6 +24,7 @@<br>
=A0#include &quot;hash.h&quot;<br>
=A0#include &quot;hmap.h&quot;<br>
=A0#include &quot;list.h&quot;<br>
+#include &quot;netdev.h&quot;<br>
=A0#include &quot;netlink.h&quot;<br>
=A0#include &quot;odp-util.h&quot;<br>
=A0#include &quot;ofpbuf.h&quot;<br>
@@ -152,6 +153,9 @@ struct bfd {<br>
=A0 =A0 =A0bool cpath_down; =A0 =A0 =A0 =A0 =A0 =A0 =A0/* Concatenated Path=
 Down. */<br>
=A0 =A0 =A0uint8_t mult; =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* bfd.DetectMult.=
 */<br>
<br>
+ =A0 =A0struct netdev *netdev;<br>
+ =A0 =A0uint64_t rx_packets; =A0 =A0 =A0 =A0 =A0/* Packets received by &#3=
9;netdev&#39;. */<br>
+<br>
=A0 =A0 =A0enum state state; =A0 =A0 =A0 =A0 =A0 =A0 /* bfd.SessionState. *=
/<br>
=A0 =A0 =A0enum state rmt_state; =A0 =A0 =A0 =A0 /* bfd.RemoteSessionState.=
 */<br>
<br>
@@ -182,6 +186,10 @@ struct bfd {<br>
<br>
=A0 =A0 =A0int ref_cnt;<br>
=A0 =A0 =A0int forwarding_override; =A0 =A0 =A0/* Manual override of &#39;f=
orwarding&#39; status. */<br>
+<br>
+ =A0 =A0/* BFD decay related variables. */<br>
+ =A0 =A0int decay_min_rx;<br>
+ =A0 =A0long long int decay_detect_time; /* Decay detection time. */<br>
=A0};<br>
<br>
=A0static bool bfd_in_poll(const struct bfd *);<br>
@@ -191,6 +199,8 @@ static const char *bfd_state_str(enum state);<br>
=A0static long long int bfd_min_tx(const struct bfd *);<br>
=A0static long long int bfd_tx_interval(const struct bfd *);<br>
=A0static long long int bfd_rx_interval(const struct bfd *);<br>
+static uint64_t bfd_rx_packets(const struct bfd *);<br>
+static void bfd_decay(struct bfd *);<br>
=A0static void bfd_set_next_tx(struct bfd *);<br>
=A0static void bfd_set_state(struct bfd *, enum state, enum diag);<br>
=A0static uint32_t generate_discriminator(void);<br>
@@ -242,12 +252,13 @@ bfd_get_status(const struct bfd *bfd, struct smap *sm=
ap)<br>
=A0 * handle for the session, or NULL if BFD is not enabled according to &#=
39;cfg&#39;.<br>
=A0 * Also returns NULL if cfg is NULL. */<br>
=A0struct bfd *<br>
-bfd_configure(struct bfd *bfd, const char *name,<br>
- =A0 =A0 =A0 =A0 =A0 =A0 =A0const struct smap *cfg)<br>
+bfd_configure(struct bfd *bfd, const char *name, const struct smap *cfg,<b=
r>
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0struct netdev *netdev)<br>
=A0{<br>
=A0 =A0 =A0static uint16_t udp_src =3D 0;<br>
=A0 =A0 =A0static bool init =3D false;<br>
<br>
+ =A0 =A0int decay_min_rx;<br>
=A0 =A0 =A0long long int min_tx, min_rx;<br>
=A0 =A0 =A0bool cpath_down;<br>
<br>
@@ -276,6 +287,9 @@ bfd_configure(struct bfd *bfd, const char *name,<br>
=A0 =A0 =A0 =A0 =A0bfd-&gt;min_tx =3D 1000;<br>
=A0 =A0 =A0 =A0 =A0bfd-&gt;mult =3D 3;<br>
=A0 =A0 =A0 =A0 =A0bfd-&gt;ref_cnt =3D 1;<br>
+ =A0 =A0 =A0 =A0bfd-&gt;netdev =3D netdev_ref(netdev);<br>
+ =A0 =A0 =A0 =A0bfd-&gt;decay_detect_time =3D 0;<br>
+ =A0 =A0 =A0 =A0bfd-&gt;rx_packets =3D bfd_rx_packets(bfd);<br>
<br>
=A0 =A0 =A0 =A0 =A0/* RFC 5881 section 4<br>
=A0 =A0 =A0 =A0 =A0 * The source port MUST be in the range 49152 through 65=
535. =A0The same<br>
@@ -295,6 +309,7 @@ bfd_configure(struct bfd *bfd, const char *name,<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0|| (!bfd_in_poll(bfd) &amp;&amp; bfd-&gt;cfg_min=
_tx &lt; bfd-&gt;min_tx)) {<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0bfd-&gt;min_tx =3D bfd-&gt;cfg_min_tx;<br>
=A0 =A0 =A0 =A0 =A0}<br>
+ =A0 =A0 =A0 =A0bfd-&gt;decay_min_rx =3D 0;<br>
=A0 =A0 =A0 =A0 =A0bfd_poll(bfd);<br>
=A0 =A0 =A0}<br>
<br>
@@ -309,6 +324,19 @@ bfd_configure(struct bfd *bfd, const char *name,<br>
=A0 =A0 =A0 =A0 =A0bfd_poll(bfd);<br>
=A0 =A0 =A0}<br>
<br>
+ =A0 =A0decay_min_rx =3D smap_get_int(cfg, &quot;decay_min_rx&quot;, 0);<b=
r>
+ =A0 =A0if (bfd-&gt;decay_min_rx !=3D decay_min_rx ) {<br>
+ =A0 =A0 =A0 =A0if (decay_min_rx &gt; 0 &amp;&amp; decay_min_rx &lt; bfd-&=
gt;cfg_min_rx) {<br>
+ =A0 =A0 =A0 =A0 =A0 =A0VLOG_WARN(&quot;%s: decay_min_rx cannot be less th=
an %lld ms&quot;,<br>
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bfd-&gt;name, bfd-&gt;cfg_min_=
rx);<br>
+ =A0 =A0 =A0 =A0 =A0 =A0bfd-&gt;decay_min_rx =3D 0;<br>
+ =A0 =A0 =A0 =A0} else {<br>
+ =A0 =A0 =A0 =A0 =A0 =A0bfd-&gt;decay_min_rx =3D decay_min_rx;<br>
+ =A0 =A0 =A0 =A0}<br>
+ =A0 =A0 =A0 =A0bfd-&gt;min_rx =3D bfd-&gt;cfg_min_rx;<br>
+ =A0 =A0 =A0 =A0bfd_poll(bfd);<br>
+ =A0 =A0}<br>
+<br>
=A0 =A0 =A0cpath_down =3D smap_get_bool(cfg, &quot;cpath_down&quot;, false)=
;<br>
=A0 =A0 =A0if (bfd-&gt;cpath_down !=3D cpath_down) {<br>
=A0 =A0 =A0 =A0 =A0bfd-&gt;cpath_down =3D cpath_down;<br>
@@ -340,6 +368,7 @@ bfd_unref(struct bfd *bfd)<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0hmap_remove(&amp;all_bfds, &amp;bfd-&gt;node);<b=
r>
=A0 =A0 =A0 =A0 =A0 =A0 =A0free(bfd-&gt;name);<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0free(bfd);<br>
+ =A0 =A0 =A0 =A0 =A0 =A0netdev_close(bfd-&gt;netdev);<br>
=A0 =A0 =A0 =A0 =A0}<br>
=A0 =A0 =A0}<br>
=A0}<br>
@@ -360,11 +389,23 @@ bfd_wait(const struct bfd *bfd)<br>
=A0void<br>
=A0bfd_run(struct bfd *bfd)<br>
=A0{<br>
- =A0 =A0if (bfd-&gt;state &gt; STATE_DOWN &amp;&amp; time_msec() &gt;=3D b=
fd-&gt;detect_time) {<br>
+ =A0 =A0long long int now =3D time_msec();<br>
+<br>
+ =A0 =A0if (bfd-&gt;state &gt; STATE_DOWN &amp;&amp; now &gt;=3D bfd-&gt;d=
etect_time) {<br>
=A0 =A0 =A0 =A0 =A0bfd_set_state(bfd, STATE_DOWN, DIAG_EXPIRED);<br>
=A0 =A0 =A0}<br>
<br>
+ =A0 =A0if (bfd-&gt;state =3D=3D STATE_UP &amp;&amp; bfd-&gt;decay_min_rx =
&gt; 0<br>
+ =A0 =A0 =A0 =A0&amp;&amp; now &gt;=3D bfd-&gt;decay_detect_time) {<br>
+ =A0 =A0 =A0 =A0bfd_decay(bfd);<br>
+ =A0 =A0}<br>
+<br>
=A0 =A0 =A0if (bfd-&gt;min_tx !=3D bfd-&gt;cfg_min_tx || bfd-&gt;min_rx !=
=3D bfd-&gt;cfg_min_rx) {<br>
+ =A0 =A0 =A0 =A0/* Do not poll if already decayed to decay_min_rx. */<br>
+ =A0 =A0 =A0 =A0if (bfd-&gt;state =3D=3D STATE_UP &amp;&amp; bfd-&gt;poll_=
min_rx =3D=3D bfd-&gt;decay_min_rx<br>
+ =A0 =A0 =A0 =A0 =A0 =A0&amp;&amp; bfd-&gt;cfg_min_tx =3D=3D bfd-&gt;min_t=
x) {<br>
+ =A0 =A0 =A0 =A0 =A0 =A0return;<br>
+ =A0 =A0 =A0 =A0}<br>
=A0 =A0 =A0 =A0 =A0bfd_poll(bfd);<br>
=A0 =A0 =A0}<br>
=A0}<br>
@@ -616,6 +657,17 @@ bfd_process_packet(struct bfd *bfd, const struct flow =
*flow,<br>
=A0 =A0 =A0}<br>
=A0 =A0 =A0/* XXX: RFC 5880 Section 6.8.6 Demand mode related calculations =
here. */<br>
=A0}<br>
+<br>
+/* Must be called when the netdev owned by &#39;bfd&#39; should change. */=
<br>
+void<br>
+bfd_set_netdev(struct bfd *bfd, const struct netdev *netdev)<br>
+{<br>
+ =A0 =A0if (bfd-&gt;netdev !=3D netdev) {<br>
+ =A0 =A0 =A0 =A0netdev_close(bfd-&gt;netdev);<br>
+ =A0 =A0 =A0 =A0bfd-&gt;netdev =3D netdev_ref(netdev);<br>
+ =A0 =A0}<br>
+}<br>
+<br>
<br>
=A0/* Helpers. */<br>
=A0static bool<br>
@@ -630,7 +682,8 @@ bfd_poll(struct bfd *bfd)<br>
=A0 =A0 =A0if (bfd-&gt;state &gt; STATE_DOWN &amp;&amp; !bfd_in_poll(bfd)<b=
r>
=A0 =A0 =A0 =A0 =A0&amp;&amp; !(bfd-&gt;flags &amp; FLAG_FINAL)) {<br>
=A0 =A0 =A0 =A0 =A0bfd-&gt;poll_min_tx =3D bfd-&gt;cfg_min_tx;<br>
- =A0 =A0 =A0 =A0bfd-&gt;poll_min_rx =3D bfd-&gt;cfg_min_rx;<br>
+ =A0 =A0 =A0 =A0bfd-&gt;poll_min_rx =3D bfd-&gt;min_rx =3D=3D bfd-&gt;deca=
y_min_rx<br>
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ? bfd-&gt;decay_min_r=
x : bfd-&gt;cfg_min_rx;<br>
=A0 =A0 =A0 =A0 =A0bfd-&gt;flags |=3D FLAG_POLL;<br>
=A0 =A0 =A0 =A0 =A0bfd-&gt;next_tx =3D 0;<br>
=A0 =A0 =A0 =A0 =A0VLOG_INFO_RL(&amp;rl, &quot;%s: Initiating poll sequence=
&quot;, bfd-&gt;name);<br>
@@ -804,6 +857,42 @@ bfd_set_state(struct bfd *bfd, enum state state, enum =
diag diag)<br>
=A0 =A0 =A0}<br>
=A0}<br>
<br>
+static uint64_t<br>
+bfd_rx_packets(const struct bfd *bfd)<br>
+{<br>
+ =A0 =A0struct netdev_stats stats;<br>
+<br>
+ =A0 =A0if (!netdev_get_stats(bfd-&gt;netdev, &amp;stats)) {<br>
+ =A0 =A0 =A0 =A0return stats.rx_packets;<br>
+ =A0 =A0} else {<br>
+ =A0 =A0 =A0 =A0return 0;<br>
+ =A0 =A0}<br>
+}<br>
+<br>
+static void<br>
+bfd_decay(struct bfd *bfd)<br>
+{<br>
+ =A0 =A0uint64_t rx_packets =3D bfd_rx_packets(bfd);<br>
+ =A0 =A0int64_t diff;<br>
+<br>
+ =A0 =A0diff =3D rx_packets - bfd-&gt;rx_packets;<br>
+ =A0 =A0bfd-&gt;rx_packets =3D rx_packets;<br>
+ =A0 =A0bfd-&gt;decay_detect_time =3D (bfd-&gt;decay_min_rx &lt; 2000 ?<br=
>
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A02000 : bfd-&gt=
;decay_min_rx) + time_msec();<br>
+<br>
+ =A0 =A0if (diff &lt;=3D (bfd-&gt;decay_min_rx / bfd-&gt;min_rx + 5)) {<br=
>
+ =A0 =A0 =A0 =A0/* Decay when there is no obvious data traffic. */<br>
+ =A0 =A0 =A0 =A0if (bfd-&gt;min_rx !=3D bfd-&gt;decay_min_rx) {<br>
+ =A0 =A0 =A0 =A0 =A0 =A0bfd-&gt;min_rx =3D bfd-&gt;decay_min_rx;<br>
+ =A0 =A0 =A0 =A0}<br>
+ =A0 =A0} else {<br>
+ =A0 =A0 =A0 =A0/* Restore the min_rx. */<br>
+ =A0 =A0 =A0 =A0if (bfd-&gt;min_rx !=3D bfd-&gt;cfg_min_rx) {<br>
+ =A0 =A0 =A0 =A0 =A0 =A0bfd-&gt;min_rx =3D bfd-&gt;cfg_min_rx;<br>
+ =A0 =A0 =A0 =A0}<br>
+ =A0 =A0}<br>
+}<br>
+<br>
=A0static uint32_t<br>
=A0generate_discriminator(void)<br>
=A0{<br>
diff --git a/lib/bfd.h b/lib/bfd.h<br>
index ab854d8..db652e1 100644<br>
--- a/lib/bfd.h<br>
+++ b/lib/bfd.h<br>
@@ -24,6 +24,7 @@<br>
=A0struct bfd;<br>
=A0struct flow;<br>
=A0struct flow_wildcards;<br>
+struct netdev;<br>
=A0struct ofpbuf;<br>
=A0struct smap;<br>
<br>
@@ -39,11 +40,13 @@ void bfd_process_packet(struct bfd *, const struct flow=
 *,<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0const struct ofpbuf *);<=
br>
<br>
=A0struct bfd *bfd_configure(struct bfd *, const char *name,<br>
- =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0const struct smap *sma=
p);<br>
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0const struct smap *sma=
p,<br>
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct netdev *netdev)=
;<br>
=A0struct bfd *bfd_ref(const struct bfd *);<br>
=A0void bfd_unref(struct bfd *);<br>
<br>
=A0bool bfd_forwarding(const struct bfd *);<br>
=A0void bfd_get_status(const struct bfd *, struct smap *);<br>
+void bfd_set_netdev(struct bfd *, const struct netdev *);<br>
<br>
=A0#endif /* bfd.h */<br>
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c<br>
index 67e6c7a..63e4299 100644<br>
--- a/ofproto/ofproto-dpif.c<br>
+++ b/ofproto/ofproto-dpif.c<br>
@@ -1748,6 +1748,10 @@ port_modified(struct ofport *port_)<br>
=A0 =A0 =A0 =A0 =A0cfm_set_netdev(port-&gt;cfm, port-&gt;up.netdev);<br>
=A0 =A0 =A0}<br>
<br>
+ =A0 =A0if (port-&gt;bfd) {<br>
+ =A0 =A0 =A0 =A0bfd_set_netdev(port-&gt;bfd, port-&gt;up.netdev);<br>
+ =A0 =A0}<br>
+<br>
=A0 =A0 =A0if (port-&gt;is_tunnel &amp;&amp; tnl_port_reconfigure(port, por=
t-&gt;up.netdev,<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0port-&gt;odp_port)) {<br>
=A0 =A0 =A0 =A0 =A0ofproto_dpif_cast(port-&gt;up.ofproto)-&gt;backer-&gt;ne=
ed_revalidate =3D<br>
@@ -1882,7 +1886,8 @@ set_bfd(struct ofport *ofport_, const struct smap *cf=
g)<br>
=A0 =A0 =A0struct bfd *old;<br>
<br>
=A0 =A0 =A0old =3D ofport-&gt;bfd;<br>
- =A0 =A0ofport-&gt;bfd =3D bfd_configure(old, netdev_get_name(ofport-&gt;u=
p.netdev), cfg);<br>
+ =A0 =A0ofport-&gt;bfd =3D bfd_configure(old, netdev_get_name(ofport-&gt;u=
p.netdev),<br>
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0cfg, ofpor=
t-&gt;up.netdev);<br>
=A0 =A0 =A0if (ofport-&gt;bfd !=3D old) {<br>
=A0 =A0 =A0 =A0 =A0ofproto-&gt;backer-&gt;need_revalidate =3D REV_RECONFIGU=
RE;<br>
=A0 =A0 =A0}<br>
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml<br>
index 3385912..7d2d601 100644<br>
--- a/vswitchd/vswitch.xml<br>
+++ b/vswitchd/vswitch.xml<br>
@@ -1880,6 +1880,16 @@<br>
=A0 =A0 =A0 =A0 =A0 =A0specified. =A0Defaults to &lt;code&gt;100&lt;/code&g=
t;.<br>
=A0 =A0 =A0 =A0&lt;/column&gt;<br>
<br>
+ =A0 =A0 =A0&lt;column name=3D&quot;bfd&quot; key=3D&quot;decay_min_rx&quo=
t; type=3D&#39;{&quot;type&quot;: &quot;integer&quot;}&#39;&gt;<br>
+ =A0 =A0 =A0 =A0 =A0&lt;code&gt;decay_min_rx&lt;/code&gt; is used to set t=
he &lt;code&gt;min_rx&lt;/code&gt;,<br>
+ =A0 =A0 =A0 =A0 =A0when there is no obvious incoming data traffic at the =
interface.<br>
+ =A0 =A0 =A0 =A0 =A0It cannot be less than the &lt;code&gt;min_rx&lt;/code=
&gt;. The decay feature<br>
+ =A0 =A0 =A0 =A0 =A0is disable by setting the &lt;code&gt;decay_min_rx&lt;=
/code&gt; to 0. And the<br>
+ =A0 =A0 =A0 =A0 =A0feature is reset everytime the itself or &lt;code&gt;m=
in_rx&lt;/code&gt; is<br>
+ =A0 =A0 =A0 =A0 =A0reconfigured.<br>
+ =A0 =A0 =A0&lt;/column&gt;<br>
+<br>
+<br>
=A0 =A0 =A0 =A0&lt;column name=3D&quot;bfd&quot; key=3D&quot;cpath_down&quo=
t; type=3D&#39;{&quot;type&quot;: &quot;boolean&quot;}&#39;&gt;<br>
=A0 =A0 =A0 =A0 =A0 =A0Concatenated path down may be used when the local sy=
stem should not<br>
=A0 =A0 =A0 =A0 =A0 =A0have traffic forwarded to it for some reason other t=
han a connectivty<br>
<span><font color=3D"#888888">--<br>
1.7.9.5<br>
<br>
</font></span></blockquote></div><br></div></div>

--047d7b3a8756ee3c6604e15af156--


More information about the dev mailing list