* The mystery of optimistic ipv6 DAD handling
@ 2011-12-27 19:06 David Miller
2011-12-27 19:53 ` David Miller
0 siblings, 1 reply; 9+ messages in thread
From: David Miller @ 2011-12-27 19:06 UTC (permalink / raw)
To: netdev; +Cc: nhorman
This afternoon I audited the neigh attachment logic for ipv6 routes
and found the following gem.
Since the beginning the optimistic DAD support has this code in
ipv6_add_addr():
/*
* part one of RFC 4429, section 3.3
* We should not configure an address as
* optimistic if we do not yet know the link
* layer address of our nexhop router
*/
if (dst_get_neighbour_noref_raw(&rt->dst) == NULL)
ifa->flags &= ~IFA_F_OPTIMISTIC;
(back at inclusion time the test was "rt->rt6i_nexthop == NULL" which
is the same, we're just hiding it behind a function now so we can
change the implementation)
But this is never, ever, true.
addrconf_dst_alloc() will never give you a route with a NULL neighbour.
If the neigh lookup fails, it puts the route and returns a pointer error:
neigh = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, rt->rt6i_dev);
if (IS_ERR(neigh)) {
dst_free(&rt->dst);
return ERR_CAST(neigh);
}
dst_set_neighbour(&rt->dst, neigh);
I verified that back in 2.6.21 when the optimistic DAD code went in,
this same logic was present:
rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
if (rt->rt6i_nexthop == NULL) {
dst_free(&rt->u.dst);
return ERR_PTR(-ENOMEM);
}
But there's a catch, ndisc_get_neigh() has changed over the years, it used to:
static inline struct neighbour * ndisc_get_neigh(struct net_device *dev, struct in6_addr *addr)
{
if (dev)
return __neigh_lookup(&nd_tbl, addr, dev, 1);
return NULL;
}
but then it was changed to say:
--------------------
if (dev)
- return __neigh_lookup(&nd_tbl, addr, dev, 1);
+ return __neigh_lookup_errno(&nd_tbl, addr, dev);
- return NULL;
+ return ERR_PTR(-ENODEV);
--------------------
in order to fix a DoS type scenerio where the neighbour cache could quickly fill up,
this is commit:
--------------------
commit 14deae41566b5cdd992c01d0069518ced5227c83
Author: David S. Miller <davem@davemloft.net>
Date: Sun Jan 4 16:04:39 2009 -0800
ipv6: Fix sporadic sendmsg -EINVAL when sending to multicast groups.
--------------------
Obviously, this could change the optimistic DaD logic. However, two things strike me:
1) even beforehand we'd only get a NULL neigh when the device pointer
is NULL, that can't happen here, rt->rt6i_dev will be non-NULL always
in these circumstances, it's forced to be net->loopback_dev by the
ip6_dst_alloc() call made by addrconf_dst_alloc() (the code back
in 2.6.21 does the same exact thing, just inline)
2) on top of that it's looking up a neighbour using rt->rt6i_gateway
as the key, that's either bogus or pointless. As far as I can tell
it's uninitialized at this point and therefore always all-zeros.
My quick hunch is that the neigh should be looked up based upon 'addr', and
that ipv6_add_addr() should test if the neigh is resolved in order to determine
if the optimistic flag should be cleared. That matches the logic in the comment
"do not yet know the link layer address of our nexthop router."
Neil, any chance you can help me unravel this?
Thanks.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: The mystery of optimistic ipv6 DAD handling
2011-12-27 19:06 The mystery of optimistic ipv6 DAD handling David Miller
@ 2011-12-27 19:53 ` David Miller
2011-12-28 15:19 ` Neil Horman
0 siblings, 1 reply; 9+ messages in thread
From: David Miller @ 2011-12-27 19:53 UTC (permalink / raw)
To: netdev; +Cc: nhorman
From: David Miller <davem@davemloft.net>
Date: Tue, 27 Dec 2011 14:06:52 -0500 (EST)
> However, two things strike me:
>
> 1) even beforehand we'd only get a NULL neigh when the device pointer
> is NULL, that can't happen here, rt->rt6i_dev will be non-NULL always
> in these circumstances, it's forced to be net->loopback_dev by the
> ip6_dst_alloc() call made by addrconf_dst_alloc() (the code back
> in 2.6.21 does the same exact thing, just inline)
>
> 2) on top of that it's looking up a neighbour using rt->rt6i_gateway
> as the key, that's either bogus or pointless. As far as I can tell
> it's uninitialized at this point and therefore always all-zeros.
>
> My quick hunch is that the neigh should be looked up based upon 'addr', and
> that ipv6_add_addr() should test if the neigh is resolved in order to determine
> if the optimistic flag should be cleared. That matches the logic in the comment
> "do not yet know the link layer address of our nexthop router."
>
> Neil, any chance you can help me unravel this?
So the fundamental thing is that these addrconf routes are mainly for
for input and looping back traffic on output.
We create the addrconf route "to us", for input. That's why the lookup
key is the ipv6 address we are configuring on the interface.
For output, the neigh is "don't care". It goes to the loopback device
and for loopback ->hard_header is NULL so
net/ipv6/ndisc.c:ndisc_constructor() directly hooks up
neigh->ops->queue_xmit as the neigh->output method, which is
dev_queue_xmit(). So it doesn't matter that we lookup the neigh in
addrconf_dst_alloc() using the all-zeros rt->rt6i_gateway.
So this route and it's neigh have nothing to do with link layer
address of any nexthop gatway(s) in this interface.
Therefore the test is completely wrong, and all I can determine is
that we should flat out remove it. It never triggers anyways.
Perhaps we should find another appropriate spot to put this kind of
test, but in this spot and against this route object seems totally not
right.
Neil, what say you?
--------------------
ipv6: Remove optimistic DAD flag test in ipv6_add_addr()
The route we have here is for the address being added to the interface,
ie. for input packet processing.
Therefore using that route to determine whether an output nexthop gateway
is known and resolved doesn't make any sense.
So, simply remove this test, it never triggered anyways.
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 59a9d0e..85421cc 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -650,16 +650,6 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
ifa->rt = rt;
- /*
- * part one of RFC 4429, section 3.3
- * We should not configure an address as
- * optimistic if we do not yet know the link
- * layer address of our nexhop router
- */
-
- if (dst_get_neighbour_noref_raw(&rt->dst) == NULL)
- ifa->flags &= ~IFA_F_OPTIMISTIC;
-
ifa->idev = idev;
in6_dev_hold(idev);
/* For caller */
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: The mystery of optimistic ipv6 DAD handling
2011-12-27 19:53 ` David Miller
@ 2011-12-28 15:19 ` Neil Horman
2011-12-28 18:39 ` David Miller
0 siblings, 1 reply; 9+ messages in thread
From: Neil Horman @ 2011-12-28 15:19 UTC (permalink / raw)
To: David Miller; +Cc: netdev
On Tue, Dec 27, 2011 at 02:53:05PM -0500, David Miller wrote:
> From: David Miller <davem@davemloft.net>
> Date: Tue, 27 Dec 2011 14:06:52 -0500 (EST)
>
> > However, two things strike me:
> >
> > 1) even beforehand we'd only get a NULL neigh when the device pointer
> > is NULL, that can't happen here, rt->rt6i_dev will be non-NULL always
> > in these circumstances, it's forced to be net->loopback_dev by the
> > ip6_dst_alloc() call made by addrconf_dst_alloc() (the code back
> > in 2.6.21 does the same exact thing, just inline)
> >
> > 2) on top of that it's looking up a neighbour using rt->rt6i_gateway
> > as the key, that's either bogus or pointless. As far as I can tell
> > it's uninitialized at this point and therefore always all-zeros.
> >
> > My quick hunch is that the neigh should be looked up based upon 'addr', and
> > that ipv6_add_addr() should test if the neigh is resolved in order to determine
> > if the optimistic flag should be cleared. That matches the logic in the comment
> > "do not yet know the link layer address of our nexthop router."
> >
> > Neil, any chance you can help me unravel this?
>
> So the fundamental thing is that these addrconf routes are mainly for
> for input and looping back traffic on output.
>
> We create the addrconf route "to us", for input. That's why the lookup
> key is the ipv6 address we are configuring on the interface.
>
> For output, the neigh is "don't care". It goes to the loopback device
> and for loopback ->hard_header is NULL so
> net/ipv6/ndisc.c:ndisc_constructor() directly hooks up
> neigh->ops->queue_xmit as the neigh->output method, which is
> dev_queue_xmit(). So it doesn't matter that we lookup the neigh in
> addrconf_dst_alloc() using the all-zeros rt->rt6i_gateway.
>
> So this route and it's neigh have nothing to do with link layer
> address of any nexthop gatway(s) in this interface.
>
> Therefore the test is completely wrong, and all I can determine is
> that we should flat out remove it. It never triggers anyways.
>
> Perhaps we should find another appropriate spot to put this kind of
> test, but in this spot and against this route object seems totally not
> right.
>
> Neil, what say you?
Yeah, If the premise that the test never triggers is true (and it seems like
you've confirmed that), then theres no harm in removing it. It still
seems like we might still need the test somewhere (maybe on a manual route add).
I've family in town, so I'm not able to look at this closely today, but I'd say this
is at least a harmless change right now. Lets take this change, and I'll
re-read the RFC and look for appropriate code paths where we may need this
test in a few days. Thanks Dave!
Acked-By: Neil Horman <nhorman@tuxdriver.com>
>
> --------------------
> ipv6: Remove optimistic DAD flag test in ipv6_add_addr()
>
> The route we have here is for the address being added to the interface,
> ie. for input packet processing.
>
> Therefore using that route to determine whether an output nexthop gateway
> is known and resolved doesn't make any sense.
>
> So, simply remove this test, it never triggered anyways.
>
> Signed-off-by: David S. Miller <davem@davemloft.net>
>
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index 59a9d0e..85421cc 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -650,16 +650,6 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
>
> ifa->rt = rt;
>
> - /*
> - * part one of RFC 4429, section 3.3
> - * We should not configure an address as
> - * optimistic if we do not yet know the link
> - * layer address of our nexhop router
> - */
> -
> - if (dst_get_neighbour_noref_raw(&rt->dst) == NULL)
> - ifa->flags &= ~IFA_F_OPTIMISTIC;
> -
> ifa->idev = idev;
> in6_dev_hold(idev);
> /* For caller */
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: The mystery of optimistic ipv6 DAD handling
2011-12-28 15:19 ` Neil Horman
@ 2011-12-28 18:39 ` David Miller
2011-12-28 19:21 ` Neil Horman
0 siblings, 1 reply; 9+ messages in thread
From: David Miller @ 2011-12-28 18:39 UTC (permalink / raw)
To: nhorman; +Cc: netdev
From: Neil Horman <nhorman@tuxdriver.com>
Date: Wed, 28 Dec 2011 10:19:28 -0500
> Yeah, If the premise that the test never triggers is true (and it seems like
> you've confirmed that), then theres no harm in removing it. It still
> seems like we might still need the test somewhere (maybe on a manual route add).
> I've family in town, so I'm not able to look at this closely today, but I'd say this
> is at least a harmless change right now. Lets take this change, and I'll
> re-read the RFC and look for appropriate code paths where we may need this
> test in a few days. Thanks Dave!
>
> Acked-By: Neil Horman <nhorman@tuxdriver.com>
Thanks for reviewing Neil, I've applied this patch to net-next.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: The mystery of optimistic ipv6 DAD handling
2011-12-28 18:39 ` David Miller
@ 2011-12-28 19:21 ` Neil Horman
2011-12-28 19:38 ` David Miller
0 siblings, 1 reply; 9+ messages in thread
From: Neil Horman @ 2011-12-28 19:21 UTC (permalink / raw)
To: David Miller; +Cc: netdev
On Wed, Dec 28, 2011 at 01:39:33PM -0500, David Miller wrote:
> From: Neil Horman <nhorman@tuxdriver.com>
> Date: Wed, 28 Dec 2011 10:19:28 -0500
>
> > Yeah, If the premise that the test never triggers is true (and it seems like
> > you've confirmed that), then theres no harm in removing it. It still
> > seems like we might still need the test somewhere (maybe on a manual route add).
> > I've family in town, so I'm not able to look at this closely today, but I'd say this
> > is at least a harmless change right now. Lets take this change, and I'll
> > re-read the RFC and look for appropriate code paths where we may need this
> > test in a few days. Thanks Dave!
> >
> > Acked-By: Neil Horman <nhorman@tuxdriver.com>
>
> Thanks for reviewing Neil, I've applied this patch to net-next.
No problem, I got some time this afternoon, and I've reread the relevant section
of RFC 4429, and clearly I made a mistake in the above test, but I'm a little
confused over what the test should be. The relevant language from the RFC is:
3.3 Modifications to RFC 2462 Stateless Address Autoconfiguration
* (modifies section 5.5) A host MAY choose to configure a new address
as an Optimistic Address. A host that does not know the SLLAO
of its router SHOULD NOT configure a new address as Optimistic.
A router SHOULD NOT configure an Optimistic Address.
So my read of that is that, when we are adding a new address to the host, we
should not make the address optimistic if:
1) The interface is acting as a router - We catch this with the !forwarding
check in addrconf_prefix_rcv, although we should perhaps move that to a common
code path, as we won't catch that if we manually add an ipv6 address via
inet6_rtm_newaddr
2) If the interface has not recieved a router advertizement, and that
solicitation did not contain a source link layer option in it.
Clearly I misread the RFC the first time through and the test as it existed is
incorrect. I'm wondering though if what we need is a way to lookup if we've
received a RA on the interface, and check to see if it has a source link layer
option attached to it.
Thoughts?
Neil
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: The mystery of optimistic ipv6 DAD handling
2011-12-28 19:21 ` Neil Horman
@ 2011-12-28 19:38 ` David Miller
2011-12-29 0:00 ` Neil Horman
2012-01-03 19:45 ` Neil Horman
0 siblings, 2 replies; 9+ messages in thread
From: David Miller @ 2011-12-28 19:38 UTC (permalink / raw)
To: nhorman; +Cc: netdev
From: Neil Horman <nhorman@tuxdriver.com>
Date: Wed, 28 Dec 2011 14:21:50 -0500
> Clearly I misread the RFC the first time through and the test as it existed is
> incorrect. I'm wondering though if what we need is a way to lookup if we've
> received a RA on the interface, and check to see if it has a source link layer
> option attached to it.
Yes, we could implement this with a new neigh lookup routine, that allows
keying on device pointer and flags.
So in this case we'd pass the device and NTF_ROUTER. If the lookup returns
non-NULL then we've seen an RA with SLLAO specified.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: The mystery of optimistic ipv6 DAD handling
2011-12-28 19:38 ` David Miller
@ 2011-12-29 0:00 ` Neil Horman
2012-01-03 19:45 ` Neil Horman
1 sibling, 0 replies; 9+ messages in thread
From: Neil Horman @ 2011-12-29 0:00 UTC (permalink / raw)
To: David Miller; +Cc: netdev
On Wed, Dec 28, 2011 at 02:38:12PM -0500, David Miller wrote:
> From: Neil Horman <nhorman@tuxdriver.com>
> Date: Wed, 28 Dec 2011 14:21:50 -0500
>
> > Clearly I misread the RFC the first time through and the test as it existed is
> > incorrect. I'm wondering though if what we need is a way to lookup if we've
> > received a RA on the interface, and check to see if it has a source link layer
> > option attached to it.
>
> Yes, we could implement this with a new neigh lookup routine, that allows
> keying on device pointer and flags.
>
> So in this case we'd pass the device and NTF_ROUTER. If the lookup returns
> non-NULL then we've seen an RA with SLLAO specified.
>
Agreed. If its ok with you I'll start working on that in a few days, once we
get through the holidays here.
Happy New Year!
Best
Neil
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: The mystery of optimistic ipv6 DAD handling
2011-12-28 19:38 ` David Miller
2011-12-29 0:00 ` Neil Horman
@ 2012-01-03 19:45 ` Neil Horman
2012-01-03 19:48 ` David Miller
1 sibling, 1 reply; 9+ messages in thread
From: Neil Horman @ 2012-01-03 19:45 UTC (permalink / raw)
To: David Miller; +Cc: netdev
On Wed, Dec 28, 2011 at 02:38:12PM -0500, David Miller wrote:
> From: Neil Horman <nhorman@tuxdriver.com>
> Date: Wed, 28 Dec 2011 14:21:50 -0500
>
> > Clearly I misread the RFC the first time through and the test as it existed is
> > incorrect. I'm wondering though if what we need is a way to lookup if we've
> > received a RA on the interface, and check to see if it has a source link layer
> > option attached to it.
>
> Yes, we could implement this with a new neigh lookup routine, that allows
> keying on device pointer and flags.
>
> So in this case we'd pass the device and NTF_ROUTER. If the lookup returns
> non-NULL then we've seen an RA with SLLAO specified.
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
Dave, I've been looking at this for a bit, and I think the solution is even
easier than we first thought. I'd forgotten two major items:
1) The optimistic flag rules only apply to SLAAC assigned addresses (section 3.1
of RFC 4429 specifically excludes manually address addresses from being flagged
as optimistic)
2) We only add SLAAC addresses to an interface after having received a router
solicitation containing a prefix and (possibly) a SLLAO option.
Because of the above, we can compeltely ignore the manual address add path as
far as the optimistic path is concerned. Since we only call addrconf_prefix_rcv
(where we add the SLAAC address), from ndisc_router_discovery (where we receive
the new router advertisement, and parse its options), I think we can just
augment addrconf_prefix_rcv with an extra parameter (a bool flag), which is set
or cleared based on the value of the ND_OPT_SOURCE_LL_ADDR option in the ndopts
array. addrconf_prefix_rcv can use that flag to set or clear the optimistic
flag.
Thoughts?
Neil
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: The mystery of optimistic ipv6 DAD handling
2012-01-03 19:45 ` Neil Horman
@ 2012-01-03 19:48 ` David Miller
0 siblings, 0 replies; 9+ messages in thread
From: David Miller @ 2012-01-03 19:48 UTC (permalink / raw)
To: nhorman; +Cc: netdev
From: Neil Horman <nhorman@tuxdriver.com>
Date: Tue, 3 Jan 2012 14:45:59 -0500
> Because of the above, we can compeltely ignore the manual address add path as
> far as the optimistic path is concerned. Since we only call addrconf_prefix_rcv
> (where we add the SLAAC address), from ndisc_router_discovery (where we receive
> the new router advertisement, and parse its options), I think we can just
> augment addrconf_prefix_rcv with an extra parameter (a bool flag), which is set
> or cleared based on the value of the ND_OPT_SOURCE_LL_ADDR option in the ndopts
> array. addrconf_prefix_rcv can use that flag to set or clear the optimistic
> flag.
>
> Thoughts?
Sounds perfect, thanks Neil.
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2012-01-03 19:49 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-12-27 19:06 The mystery of optimistic ipv6 DAD handling David Miller
2011-12-27 19:53 ` David Miller
2011-12-28 15:19 ` Neil Horman
2011-12-28 18:39 ` David Miller
2011-12-28 19:21 ` Neil Horman
2011-12-28 19:38 ` David Miller
2011-12-29 0:00 ` Neil Horman
2012-01-03 19:45 ` Neil Horman
2012-01-03 19:48 ` David Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).