Index | Thread | Search

From:
Ryan Vogt <rvogt.ca@gmail.com>
Subject:
Re: rad(8): track vltime / pltime for "auto prefix"es
To:
tech@openbsd.org
Date:
Sat, 25 May 2024 11:40:04 -0700

Download raw body.

Thread
On Fri, May 24, 2024 at 11:16:36AM +0200, Florian Obser wrote:
> On 2024-05-23 13:20 -07, Ryan Vogt wrote:
> > On Mon, May 20, 2024 at 12:16:33PM +0000, Florian Obser wrote:
> >> Prefixes delegated via DHCPv6 have a lifetime, honour it.
> >> 
> >> The "auto prefix" feature derives the prefix to announce from a
> >> configured IPv6 address. If that address has a vltime / pltime use
> >> that value in router advertisements instead of statically configured
> >> values.
> >> 
> >> We also need to count down the vltime / pltime as time progresses.
> >> 
> >> This is on top of "rad(8): reduce calls to getifaddrs(3)" and also needs
> >> "send RTM_CHGADDRATTR for vltime / pltime changes" to work correctly.
> >
> > Hi, I have a question about the intended behaviour of this patch in a
> > few cases, which I've outlined below.

[snip]

> > To set up our situation, I have rad(8) running on igc1. On igc1, I
> > have a static prefix, and a prefix delegated from DHCPv6 (dhcpcd
> > running on igc0):
> >
> > 	$ ifconfig igc1
> > 	[...]
> > 	inet6 fe80::bbbb:bbbb:bbbb:bbbb%igc1 prefixlen 64 scopeid 0x2
> > 	inet6 fdaa:aaaa:aaaa:1::1 prefixlen 64
> > 	inet6 2001:db80:eeee:eeee::1 prefixlen 64 pltime 103481 \
> > 	    vltime 103481
> >
> > The fdaa:... prefix is static, and the 2001:... prefix is delegated by
> > my ISP.

[snip]

> > 4) The fourth case is an extension of the third case, with a more-
> > explicit rad.conf. Here's an rad.conf that someone with an
> > essentially-static delegation from their ISP could use (I'm not so
> > lucky):
> >
> > 	interface igc1 {
> > 		prefix fdaa:aaaa:aaaa:1:: {
> > 			preferred lifetime 2000
> > 			valid lifetime 3000
> > 		}
> > 		prefix 2001:db80:eeee:eeee:: {
> > 			preferred lifetime 4000
> > 			valid lifetime 5000
> > 		}
> > 	}
> >
> > The behaviour with the new patch is that clients receive the following
> > prefix info options from rad:
> >
> > 	- fdaa:aaaa:aaaa:1::/64 with valid time 3000, pref. time 2000
> > 	- 2001:db80:eeee:eeee::/64 with valid time 103481,
> > 	    pref. time 103481
> >
> 
> I don't think this actually happens, if you are not configuring an auto
> prefix rad(8) does not look at prefixes, does it?
> 
>                 if (ra_iface_conf->autoprefix)
>                         get_interface_prefixes(ra_iface,
>                             ra_iface_conf->autoprefix, ifap);
> 
> I think you should get this:
>  	- fdaa:aaaa:aaaa:1::/64 with valid time 3000, pref. time 2000
>  	- 2001:db80:eeee:eeee::/64 with valid time 5000, pref. time 4000

Sorry that I took a while to get back to you -- I wanted to double-
check my testing and investigate a little more.

I'm not sure how much it matters if you're planning on changing the
the rad(8) patch anyway, but I've confirmed that the patch behaves as
I reported in my previous message.

To shed a little light on the situation, here are two slightly
different rad.conf(5) files. The first produces the behaviour I
reported. The second produces the behaviour you expected.

4.a) For this rad.conf:

	interface igc1 {
		prefix fdaa:aaaa:aaaa:1:: {
			preferred lifetime 2000
			valid lifetime 3000
		}
		prefix 2001:db80:eeee:eeee:: {
			preferred lifetime 4000
			valid lifetime 5000
		}
	}

we get RA messages from rad(8) containing these two prefix info options
(the ones I originally reported):

	- fdaa:aaaa:aaaa:1::/64 with valid time 3000, pref. time 2000
	- 2001:db80:eeee:eeee::/64 with valid time 103481,
	    pref. time 103481

4.b) For this rad.conf:

	interface igc1 {
		no auto prefix   # Difference from 4.a is this line 
		prefix fdaa:aaaa:aaaa:1:: {
			preferred lifetime 2000
			valid lifetime 3000
		}
		prefix 2001:db80:eeee:eeee:: {
			preferred lifetime 4000
			valid lifetime 5000
		}
	}

we see the behaviour you expected:

	- fdaa:aaaa:aaaa:1::/64 with valid time 3000, pref. time 2000
	- 2001:db80:eeee:eeee::/64 with valid time 5000,
	    pref. time 4000

Some investigation --

In your previous message, you highlighted a few lines of code in
merge_ra_interfaces():

	if (ra_iface_conf->autoprefix)
		get_interface_prefixes(ra_iface,
		    ra_iface_conf->autoprefix, ifap);

Just before the highlighted code, merge_ra_interfaces() deals with
adding the static prefixes (there's an "add static prefixes for %s"
debug message). For both versions of rad.conf (4.a and 4.b): both
fdaa:aaaa:aaaa:1::/64 and 2001:db80:eeee:eeee::/64 get added as static
prefixes here -- each with a call to add_new_prefix_to_ra_iface().

After the static prefixes are dealt with in merge_ra_interfaces(), we
reach the highlighted lines of code. Here's where the behaviour
becomes different without the "no auto prefix" line in rad.conf.
Without the "no auto prefix" line, we call
add_new_prefix_to_ra_iface() again for both prefixes.

The first prefix, fdaa:aaaa:aaaa:1::/64, gets ignored during its
second call to add_new_prefix_to_ra_iface(), producing an
"ignoring duplicate %s/%d prefix" debug message.

The second prefix, 2001:db80:eeee:eeee::/64, however, takes a
different path through add_new_prefix_to_ra_iface() during its second
call:

	- The call to find_ra_prefix_conf(), right at the top of
	    add_new_prefix_to_ra_iface(), returns non-NULL
	- decaying_vltime != ND6_INFINITE_LIFETIME and
	    decaying_pltime != ND6_INFINITE_LIFETIME, so we go through
	    that branch of the following ifs and else-ifs.

I believe what's happening is that add_new_prefix_to_ra_iface() isn't
recognizing 2001:db80:eeee:eeee::/64 as a duplicate prefix because of
the check for decaying preferred/valid lifetimes.