Re: git: 9e792f7ef729 - main - sys/netinet6: Fix SLAAC for interfaces with no /64 LL address

From: Reid Linnemann <rlinnemann_at_netgate.com>
Date: Sat, 06 Sep 2025 04:03:07 UTC
Hi Bjoern,

See responses inline below:

On Fri, Sep 5, 2025 at 5:17 PM Bjoern A. Zeeb <bz@freebsd.org> wrote:

> On Fri, 5 Sep 2025, Kristof Provost wrote:
>
> Hi,
>
> > The branch main has been updated by kp:
> >
> > URL:
> https://cgit.FreeBSD.org/src/commit/?id=9e792f7ef7298080c058fbc2d36a4e60e596dae9
> >
> > commit 9e792f7ef7298080c058fbc2d36a4e60e596dae9
> > Author:     Reid Linnemann <rlinnemann@netgate.com>
> > AuthorDate: 2025-09-05 19:57:44 +0000
> > Commit:     Kristof Provost <kp@FreeBSD.org>
> > CommitDate: 2025-09-05 21:48:48 +0000
> >
> >    sys/netinet6: Fix SLAAC for interfaces with no /64 LL address
> >
> >    in6_ifadd() asserts that an interface has an existing LL address with
> a /64
> >    prefix from which to extract the ifid for SLAAC address selection
> (even though
> >    the comments suggest that an ifid will be generated if one does not
> exist). This
> >    is adequate for most generic cases, however to support PPP links with
> /128 LL
> >    addresses we must be able to fall back on another source for the ifid
> since we
> >    cannot assume the /128 LL has a unique ifid in the lower 64 bits.
>
> Excuse my ignorance but where do you have a IPv6 LL/128 on a PPP link?
>
> I am totally suprised given this hasn't been a problem in about 25
> years and I wonder what software this is or what got broken where?
>
> Okay, I scrolled through the review.  I see I am the third person asking
> the same question as the intial intuitive reply.
>
> I was intiially tempted to say 'please back this out' but see the end.
>
>
While the impetus for this change was PPPoE, you can effectively ignore it.
The IID selection is equally valid for any other scenario where the LLA
prefix and RA prefix do not match, in which case *in6_ifadd()* originally
would just throw its hands up and return an error.


> For (1) do not start applying IPv4 to IPv6 just because.  It's not just
> a different number, it is also different concepts. People said this 20
> years ago and still do.
>
>
I'm not comparing IPv4 to IPv6, the specific PPP(oE) problem I'm addressing
that prompted this change is at the generic level of the struct ifaddr, in
which any p2p address has a source and destination address.

PPP(oE) implementations simply have to work around some of the behavior in
the v6 implementation right now, primarily that only addresses with a /128
prefix are permitted to have a dstaddr (see *in6_validate_ifra()*), RA
processing previously gave up if it could not get a IID from a /64 LLA, and
an existing LLA prefix cannot be changed from /64 to /128, requiring the
PPP(oE) client software to first remove an existing LLA (for instance if
net.inet6.ip6.auto_linklocal is enabled) once address negotiation is
complete in order to add a proper ifaddr to the address list.

Either /64 dstaddrs needed to be permitted (which is not sensible as a p2p
address is by definition composed solely of two endpoints), or RA
processing should work in the case where the RA prefix doesn't match the
LLA prefix (which I would argue should have been done since the original
KAME implementation).


> (2) Both of you talk about PPPoE in the review which tells me something
> got wrong as that is a totally different protocol and has nothing to do
> with IIDs.
>
> Selecting an appropriate LL for IPV6CP can be done entirely in user
> space for protocol negotiations.  And to my memory we have no IPV6CP
> implementation in the kernel to require anything different.
>
> I don't know what the mentioned if_pppoe.ko is but if this is a convoluted
> implenentation in-kernel incl. protocol negotiations then I am tempted to
> say you are off on your own with that, especially if you want to do things
> differently.  Looking what Linux is doing is not always the best source of
> truth.
>
> Please follow what the IPV6CP RFC (got updated since I last implemented it
> 20-something years ago I have to admit) says and you end up with a /64 LL
> on the interface and your problem is solved.
>
>
I did refer to RFC5072, however I don't see any mention at all of prefix
selection for the negotiated address. Regardless, let's ignore PPPoE for
the purpose of this conversation because IID selection for SLAAC is not
specific to this case.

With regard to address selection for SLAAC, RFC2462 section 5.5.3 states:
  "d) *If the prefix advertised does not match the prefix of an address*
*       already in the list*, and the Valid Lifetime is not 0, form an
       address (and add it to the list) by combining the advertised
       prefix with the link's interface identifier as follows:"

This is perfectly applicable to the situation that prompted the change, as
the LLA prefix does not match the RA prefix. In such a case, rather than
giving up and going home when the LLA prefix doesn't match the advertised
prefix, we should take the bare minimum effort and try to get it from the
horse's mouth before returning an error.

Your negotiated LOCAL_LL (fe80::LOCAL_IID/64) address goes onto the IF:
>
> IF: flags=1008051<UP,POINTOPOINT,RUNNING,MULTICAST,LOWER_UP> metric 0 mtu
> 1492
>          options=80000<LINKSTATE>
>         inet ...
>          inet6 LOCAL_LL%IF prefixlen 64 scopeid 0x<n>
>         inet6 ...
>          nd6 options=122<ACCEPT_RTADV,AUTO_LINKLOCAL,NO_DAD>
>
> You get an entry in the routing table:
>         fe80::%IF/64  link#11                 US  IF
>
> and possibly a
>         default             REMOTE_LL%IF      UGS IF
>
> if you decide to install a default route.
>
> Other routes I would assume are installed on the link but I assume you
> could
> chose the REMOTE_LL%IF as well if you wanted to complicate things.
>
> So I crystal-ball that your real problem could have been stated that you
> may need to get the IID for IPV6CP negotiations in-kernel?  If that is not
> the case, then I am still lost as-to what you are trying to accomplish.
> But then you'd still never need the /128.  So maybe I am just lsot.
>
>
Again, we can forget PPPoE. PPPoE, whether in-kernel or in-userland handles
IID selection itself for IPV6CP negotiation. The issue I'm addressing is
SLAAC on interfaces with LLA prefixes that do not match the prefix in the
RA.

As PPP or PPPoE are both point-to-point links the ifaddr for the link
should consist of a srcaddr and dstaddr, regardless of the specific IP
protocol, and I think it follows that for either protocol the host address
should be fully masked for the same reason.


> ..
>
> >    To do this, the static function get_ifid() in in6_ifattach.c is
> renamed to
> >    non-static in6_get_ifid(), and this is used in lieu of a proper /64
> LL address
> >    to attempt to obtain a valid ifid.
>
> ..
>
> Now we can start arguing if we forget most of the explanation about
> PPP[not oE], if it makes sense to keep this?  But then we should fix
> style, avoid unneeded initializations, etc. which should have been caught
> in proper review in first place.
> I assume the entire thing up there and in review distracted from the actual
> case more than it was good for.
> Sadly the commit message also kept carrying that forward.
>
>
That's a fair criticism, I can submit another diff to correct style. Aside
from the verbose initializations, was there anything else I missed? I hear
what you are saying about the commit message, I intended to change it but I
neglected to do so, that's my fault and I apologize for the confusion.


> So the change is probably right, the description is not?
>
> If I am guessing right, are you going to fix style, etc.?  Might want a
> test
> case for the extra condition added which I have not cross-checked yet
> either
> for all possible cases? ...
>
>
> >    Reviewed by     kp
> >    Sponsored by:   Rubicon Communications, LLC ("Netgate")
> >    Differential Revision:  https://reviews.freebsd.org/D51778
> > ---
> > sys/netinet6/in6_ifattach.c |  7 +++---
> > sys/netinet6/in6_ifattach.h |  1 +
> > sys/netinet6/nd6_rtr.c      | 54
> ++++++++++++++++++++++++++++++++-------------
> > 3 files changed, 43 insertions(+), 19 deletions(-)
>
> --
> Bjoern A. Zeeb                                                     r15:7
>


Thanks,

-Reid

-- 
Reid Linnemann
Senior Software Engineer
rlinnemann@netgate.com
<http://www.netgate.com>