On 2016/09/02 10:37, Florian Obser wrote:
> Our kernel based rtsol code is like this little child. We bring up
> the interface, send our first solicitation and get an advertisment
> back with a pltime of a week or so.
>
> We lean back, quite happy that we can do v6 now, but after 60 seconds
> we wake up, oh shit, better check if that prefix is still valid. and
> so on and on.
>
> This is particularly annoying if you try to debug ICMPv6 with tcpdump
> in a network with a lot of openbsd machines.
>
> To stop naddy from pestering me about this at every hackathon (rightly
> so!), let's base the timeout on the prefixes pltime. ;)
There's a problem with this: we lose the exponential backoff for the
quick timer. Say you have v6 at home and enable autoconf on your laptop
then move to a network without v6 - this results in you spamming the
network with a multicast frame every second, which does not make you
a good network citizen especially if that's on a wireless lan.
310 void
311 nd6_rs_output_timo(void *ignored_arg)
312 {
313 struct ifnet *ifp;
314 struct in6_ifaddr *ia6;
315 u_int32_t pltime_expire = ND6_INFINITE_LIFETIME, t;
316 int timeout = ND6_RS_OUTPUT_INTERVAL;
318 if (nd6_rs_timeout_count == 0)
319 return;
320
321 if (nd6_rs_output_timeout < ND6_RS_OUTPUT_INTERVAL)
322 /* exponential backoff if running quick timeouts */
323 timeout = nd6_rs_output_timeout * 2;
I've tried a few things along the lines of these here instead
if (nd6_rs_output_timeout < ND6_RS_OUTPUT_INTERVAL) {
nd6_rs_output_timeout *= 2;
timeout = nd6_rs_output_timeout;
}
but haven't hit on a working combination yet.
I think the current state is quite a lot worse than the previous one
(even though it's better on networks that *do* have v6), so I'm wondering
if it might be better to revert if it's complicated to fix here (there
was a different plan for sending RS in the future anyway wasn't there?)
324
325 TAILQ_FOREACH(ifp, &ifnet, if_list) {
326 if (ISSET(ifp->if_flags, IFF_RUNNING) &&
327 ISSET(ifp->if_xflags, IFXF_AUTOCONF6)) {
328 t = nd6_rs_next_pltime_timo(ifp);
329 if (t == ND6_INFINITE_LIFETIME || t <
330 ND6_RS_OUTPUT_INTERVAL) {
331 timeout = ND6_RS_OUTPUT_QUICK_INTERVAL;
332 ia6 = in6ifa_ifpforlinklocal(ifp,
333 IN6_IFF_TENTATIVE);
334 if (ia6 != NULL)
335 nd6_rs_output(ifp, ia6);
336 }
337
338 pltime_expire = MIN(pltime_expire, t);
339 }
340 }
341 if (pltime_expire != ND6_INFINITE_LIFETIME)
342 timeout = MAX(timeout, pltime_expire / 2);
343
344 nd6_rs_output_set_timo(timeout);
345 }