[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20130927081604.GB28287@order.stressinduktion.org>
Date: Fri, 27 Sep 2013 10:16:04 +0200
From: Hannes Frederic Sowa <hannes@...essinduktion.org>
To: Paul Marks <pmarks@...gle.com>
Cc: netdev@...r.kernel.org, davem@...emloft.net,
yoshfuji@...ux-ipv6.org, lorenzo@...gle.com
Subject: Re: [PATCH] ipv6: Fix preferred_lft not updating in some cases
On Wed, Sep 25, 2013 at 03:12:55PM -0700, Paul Marks wrote:
> Consider the scenario where an IPv6 router is advertising a fixed
> preferred_lft of 1800 seconds, while the valid_lft begins at 3600
> seconds and counts down in realtime.
>
> A client should reset its preferred_lft to 1800 every time the RA is
> received, but a bug is causing Linux to ignore the update.
>
> The core problem is here:
> if (prefered_lft != ifp->prefered_lft) {
>
> Note that ifp->prefered_lft is an offset, so it doesn't decrease over
> time. Thus, the comparison is always (1800 != 1800), which fails to
> trigger an update.
>
> The most direct solution would be to compute a "stored_prefered_lft",
> and use that value in the comparison. But I think that trying to filter
> out unnecessary updates here is a premature optimization. In order for
> the filter to apply, both of these would need to hold:
>
> - The advertised valid_lft and preferred_lft are both declining in
> real time.
> - No clock skew exists between the router & client.
>
> So in this patch, I've set "update_lft = 1" unconditionally, which
> allows the surrounding code to be greatly simplified.
I actually find this much harder to follow when verifying against the RFC.
> Signed-off-by: Paul Marks <pmarks@...gle.com>
> ---
> net/ipv6/addrconf.c | 52 +++++++++++++++-------------------------------------
> 1 file changed, 15 insertions(+), 37 deletions(-)
>
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index d6ff126..9a5052c 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -2193,43 +2193,21 @@ ok:
> else
> stored_lft = 0;
> if (!update_lft && !create && stored_lft) {
> - if (valid_lft > MIN_VALID_LIFETIME ||
> - valid_lft > stored_lft)
> - update_lft = 1;
> - else if (stored_lft <= MIN_VALID_LIFETIME) {
> - /* valid_lft <= stored_lft is always true */
> - /*
> - * RFC 4862 Section 5.5.3e:
> - * "Note that the preferred lifetime of
> - * the corresponding address is always
> - * reset to the Preferred Lifetime in
> - * the received Prefix Information
> - * option, regardless of whether the
> - * valid lifetime is also reset or
> - * ignored."
> - *
> - * So if the preferred lifetime in
> - * this advertisement is different
> - * than what we have stored, but the
> - * valid lifetime is invalid, just
> - * reset prefered_lft.
> - *
> - * We must set the valid lifetime
> - * to the stored lifetime since we'll
> - * be updating the timestamp below,
> - * else we'll set it back to the
> - * minimum.
> - */
> - if (prefered_lft != ifp->prefered_lft) {
Wouldn't the easiest solution be to just drop this if and execute the two
lines below unconditionally?
> - valid_lft = stored_lft;
> - update_lft = 1;
> - }
> - } else {
> - valid_lft = MIN_VALID_LIFETIME;
> - if (valid_lft < prefered_lft)
> - prefered_lft = valid_lft;
> - update_lft = 1;
> - }
> + const u32 minimum_lft = min(
> + stored_lft, (u32)MIN_VALID_LIFETIME);
> + valid_lft = max(valid_lft, minimum_lft);
Quick question: Don't we need a prefered_lft = min(preferred_lft, valid_lft)
here?
> +
> + /* RFC4862 Section 5.5.3e:
> + * "Note that the preferred lifetime of the
> + * corresponding address is always reset to
> + * the Preferred Lifetime in the received
> + * Prefix Information option, regardless of
> + * whether the valid lifetime is also reset or
> + * ignored."
> + *
> + * So we should always update prefered_lft here.
> + */
> + update_lft = 1;
> }
>
> if (update_lft) {
Thanks,
Hannes
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists