On 2016/10/02 19:37, Martin Pieuchot wrote:
> I'm trying to figure out where the regression in IPv6/NDP is and here's
> what I found so far.
> 
> When the route expiration time got converted from time_second to
> time_uptime we forgot to do the same for values inside RAs.  I'm not
> sure what's the real impact of this, but it is clearly wrong.  Diff
> below should fix that.
> 
> ok?

I haven't been able to trigger the problem again even without the
diff, but looking in ntpd log there have been a few time offsets
recently on that machine so it sounds like a good candidate.

No problems seen with the diff yet, and makes sense and reads well
to me, so OK sthen@.



> Index: netinet6/in6.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/in6.c,v
> retrieving revision 1.192
> diff -u -p -r1.192 in6.c
> --- netinet6/in6.c    4 Sep 2016 10:32:01 -0000       1.192
> +++ netinet6/in6.c    2 Oct 2016 17:18:24 -0000
> @@ -353,7 +353,7 @@ in6_ioctl(u_long cmd, caddr_t data, stru
>       case SIOCGIFALIFETIME_IN6:
>               ifr->ifr_ifru.ifru_lifetime = ia6->ia6_lifetime;
>               if (ia6->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
> -                     time_t maxexpire;
> +                     time_t expire, maxexpire;
>                       struct in6_addrlifetime *retlt =
>                           &ifr->ifr_ifru.ifru_lifetime;
>  
> @@ -365,8 +365,13 @@ in6_ioctl(u_long cmd, caddr_t data, stru
>                           (time_t)~(1ULL << ((sizeof(maxexpire) * 8) - 1));
>                       if (ia6->ia6_lifetime.ia6t_vltime <
>                           maxexpire - ia6->ia6_updatetime) {
> -                             retlt->ia6t_expire = ia6->ia6_updatetime +
> +                             expire = ia6->ia6_updatetime +
>                                   ia6->ia6_lifetime.ia6t_vltime;
> +                             if (expire != 0) {
> +                                     expire -= time_uptime;
> +                                     expire += time_second;
> +                             }
> +                             retlt->ia6t_expire = expire;
>                       } else
>                               retlt->ia6t_expire = maxexpire;
>               }
> @@ -604,7 +609,7 @@ in6_update_ifa(struct ifnet *ifp, struct
>               ia6->ia_ifa.ifa_addr = sin6tosa(&ia6->ia_addr);
>               ia6->ia_addr.sin6_family = AF_INET6;
>               ia6->ia_addr.sin6_len = sizeof(ia6->ia_addr);
> -             ia6->ia6_createtime = ia6->ia6_updatetime = time_second;
> +             ia6->ia6_createtime = ia6->ia6_updatetime = time_uptime;
>               if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) != 0) {
>                       /*
>                        * XXX: some functions expect that ifa_dstaddr is not
> @@ -667,12 +672,12 @@ in6_update_ifa(struct ifnet *ifp, struct
>       ia6->ia6_lifetime = ifra->ifra_lifetime;
>       if (ia6->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
>               ia6->ia6_lifetime.ia6t_expire =
> -                 time_second + ia6->ia6_lifetime.ia6t_vltime;
> +                 time_uptime + ia6->ia6_lifetime.ia6t_vltime;
>       } else
>               ia6->ia6_lifetime.ia6t_expire = 0;
>       if (ia6->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
>               ia6->ia6_lifetime.ia6t_preferred =
> -                 time_second + ia6->ia6_lifetime.ia6t_pltime;
> +                 time_uptime + ia6->ia6_lifetime.ia6t_pltime;
>       } else
>               ia6->ia6_lifetime.ia6t_preferred = 0;
>  
> Index: netinet6/in6.h
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/in6.h,v
> retrieving revision 1.90
> diff -u -p -r1.90 in6.h
> --- netinet6/in6.h    27 Jun 2016 16:33:48 -0000      1.90
> +++ netinet6/in6.h    2 Oct 2016 17:18:24 -0000
> @@ -280,11 +280,11 @@ struct route_in6 {
>  
>  #define IFA6_IS_DEPRECATED(a) \
>       ((a)->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME && \
> -      (u_int32_t)((time_second - (a)->ia6_updatetime)) > \
> +      (u_int32_t)((time_uptime - (a)->ia6_updatetime)) > \
>        (a)->ia6_lifetime.ia6t_pltime)
>  #define IFA6_IS_INVALID(a) \
>       ((a)->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME && \
> -      (u_int32_t)((time_second - (a)->ia6_updatetime)) > \
> +      (u_int32_t)((time_uptime - (a)->ia6_updatetime)) > \
>        (a)->ia6_lifetime.ia6t_vltime)
>  
>  #endif /* _KERNEL */
> Index: netinet6/ip6_forward.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/ip6_forward.c,v
> retrieving revision 1.92
> diff -u -p -r1.92 ip6_forward.c
> --- netinet6/ip6_forward.c    24 Aug 2016 09:41:12 -0000      1.92
> +++ netinet6/ip6_forward.c    2 Oct 2016 17:18:24 -0000
> @@ -104,8 +104,8 @@ ip6_forward(struct mbuf *m, struct rtent
>           IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
>           IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
>               ip6stat.ip6s_cantforward++;
> -             if (ip6_log_time + ip6_log_interval < time_second) {
> -                     ip6_log_time = time_second;
> +             if (ip6_log_time + ip6_log_interval < time_uptime) {
> +                     ip6_log_time = time_uptime;
>                       inet_ntop(AF_INET6, &ip6->ip6_src, src6, sizeof(src6));
>                       inet_ntop(AF_INET6, &ip6->ip6_dst, dst6, sizeof(dst6));
>                       log(LOG_DEBUG,
> @@ -193,8 +193,8 @@ reroute:
>               ip6stat.ip6s_cantforward++;
>               ip6stat.ip6s_badscope++;
>  
> -             if (ip6_log_time + ip6_log_interval < time_second) {
> -                     ip6_log_time = time_second;
> +             if (ip6_log_time + ip6_log_interval < time_uptime) {
> +                     ip6_log_time = time_uptime;
>                       inet_ntop(AF_INET6, &ip6->ip6_src, src6, sizeof(src6));
>                       inet_ntop(AF_INET6, &ip6->ip6_dst, dst6, sizeof(dst6));
>                       log(LOG_DEBUG,
> Index: netinet6/ip6_id.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/ip6_id.c,v
> retrieving revision 1.11
> diff -u -p -r1.11 ip6_id.c
> --- netinet6/ip6_id.c 4 Dec 2015 12:10:26 -0000       1.11
> +++ netinet6/ip6_id.c 2 Oct 2016 17:18:24 -0000
> @@ -197,7 +197,7 @@ ip6id_initid(struct randomtab *p)
>       p->ru_g = ip6id_pmod(p->ru_gen, j, p->ru_n);
>       p->ru_counter = 0;
>  
> -     p->ru_reseed = time_second + p->ru_out;
> +     p->ru_reseed = time_uptime + p->ru_out;
>       p->ru_msb = p->ru_msb ? 0 : (1U << (p->ru_bits - 1));
>  }
>  
> @@ -206,7 +206,7 @@ ip6id_randomid(struct randomtab *p)
>  {
>       int i, n;
>  
> -     if (p->ru_counter >= p->ru_max || time_second > p->ru_reseed)
> +     if (p->ru_counter >= p->ru_max || time_uptime > p->ru_reseed)
>               ip6id_initid(p);
>  
>       /* Skip a random number of ids */
> Index: netinet6/ip6_mroute.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/ip6_mroute.c,v
> retrieving revision 1.104
> diff -u -p -r1.104 ip6_mroute.c
> --- netinet6/ip6_mroute.c     23 Aug 2016 11:01:16 -0000      1.104
> +++ netinet6/ip6_mroute.c     2 Oct 2016 17:18:24 -0000
> @@ -980,10 +980,10 @@ ip6_mforward(struct ip6_hdr *ip6, struct
>        */
>       if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
>               ip6stat.ip6s_cantforward++;
> -             if (ip6_log_time + ip6_log_interval < time_second) {
> +             if (ip6_log_time + ip6_log_interval < time_uptime) {
>                       char src[INET6_ADDRSTRLEN], dst[INET6_ADDRSTRLEN];
>  
> -                     ip6_log_time = time_second;
> +                     ip6_log_time = time_uptime;
>  
>                       inet_ntop(AF_INET6, &ip6->ip6_src, src, sizeof(src));
>                       inet_ntop(AF_INET6, &ip6->ip6_dst, dst, sizeof(dst));
> Index: netinet6/nd6.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/nd6.c,v
> retrieving revision 1.192
> diff -u -p -r1.192 nd6.c
> --- netinet6/nd6.c    15 Sep 2016 02:00:18 -0000      1.192
> +++ netinet6/nd6.c    2 Oct 2016 17:18:24 -0000
> @@ -447,7 +447,7 @@ nd6_timer_work(void *null)
>  
>       /* expire default router list */
>       TAILQ_FOREACH_SAFE(dr, &nd_defrouter, dr_entry, ndr)
> -             if (dr->expire && dr->expire < time_second)
> +             if (dr->expire && dr->expire < time_uptime)
>                       defrtrlist_del(dr);
>  
>       /*
> @@ -479,7 +479,7 @@ nd6_timer_work(void *null)
>                * prefix is not necessary.
>                */
>               if (pr->ndpr_vltime != ND6_INFINITE_LIFETIME &&
> -                 time_second - pr->ndpr_lastupdate > pr->ndpr_vltime) {
> +                 time_uptime - pr->ndpr_lastupdate > pr->ndpr_vltime) {
>                       /*
>                        * address expiration and prefix expiration are
>                        * separate.  NEVER perform in6_purgeaddr here.
> @@ -764,9 +764,9 @@ nd6_free(struct rtentry *rt, int gc)
>                        * XXX: the check for ln_state would be redundant,
>                        *      but we intentionally keep it just in case.
>                        */
> -                     if (dr->expire > time_second) {
> +                     if (dr->expire > time_uptime) {
>                               nd6_llinfo_settimer(ln,
> -                                 dr->expire - time_second);
> +                                 dr->expire - time_uptime);
>                       } else
>                               nd6_llinfo_settimer(ln, nd6_gctimer);
>                       splx(s);
> @@ -1686,6 +1686,7 @@ fill_drlist(void *oldp, size_t *oldlenp,
>       int error = 0, s;
>       struct in6_defrouter *d = NULL, *de = NULL;
>       struct nd_defrouter *dr;
> +     time_t expire;
>       size_t l;
>  
>       s = splsoftnet();
> @@ -1704,7 +1705,12 @@ fill_drlist(void *oldp, size_t *oldlenp,
>                       in6_recoverscope(&d->rtaddr, &dr->rtaddr);
>                       d->flags = dr->flags;
>                       d->rtlifetime = dr->rtlifetime;
> -                     d->expire = dr->expire;
> +                     expire = dr->expire;
> +                     if (expire != 0) {
> +                             expire -= time_uptime;
> +                             expire += time_second;
> +                     }
> +                     d->expire = expire;
>                       d->if_index = dr->ifp->if_index;
>               }
>  
> Index: netinet6/nd6_rtr.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/nd6_rtr.c,v
> retrieving revision 1.147
> diff -u -p -r1.147 nd6_rtr.c
> --- netinet6/nd6_rtr.c        30 Sep 2016 06:27:21 -0000      1.147
> +++ netinet6/nd6_rtr.c        2 Oct 2016 17:18:24 -0000
> @@ -428,7 +428,7 @@ nd6_ra_input(struct mbuf *m, int off, in
>       dr0.rtaddr = saddr6;
>       dr0.flags  = nd_ra->nd_ra_flags_reserved;
>       dr0.rtlifetime = ntohs(nd_ra->nd_ra_router_lifetime);
> -     dr0.expire = time_second + dr0.rtlifetime;
> +     dr0.expire = time_uptime + dr0.rtlifetime;
>       dr0.ifp = ifp;
>       /* unspecified or not? (RFC 2461 6.3.4) */
>       if (advreachable) {
> @@ -518,7 +518,7 @@ nd6_ra_input(struct mbuf *m, int off, in
>                       pr.ndpr_plen = pi->nd_opt_pi_prefix_len;
>                       pr.ndpr_vltime = ntohl(pi->nd_opt_pi_valid_time);
>                       pr.ndpr_pltime = ntohl(pi->nd_opt_pi_preferred_time);
> -                     pr.ndpr_lastupdate = time_second;
> +                     pr.ndpr_lastupdate = time_uptime;
>  
>                       if (in6_init_prefix_ltimes(&pr))
>                               continue; /* prefix lifetime init failed */
> @@ -1350,7 +1350,7 @@ prelist_update(struct nd_prefix *new, st
>  
>               if (lt6_tmp.ia6t_vltime == ND6_INFINITE_LIFETIME)
>                       storedlifetime = ND6_INFINITE_LIFETIME;
> -             else if (time_second - ia6->ia6_updatetime >
> +             else if (time_uptime - ia6->ia6_updatetime >
>                        lt6_tmp.ia6t_vltime) {
>                       /*
>                        * The case of "invalid" address.  We should usually
> @@ -1359,7 +1359,7 @@ prelist_update(struct nd_prefix *new, st
>                       storedlifetime = 0;
>               } else
>                       storedlifetime = lt6_tmp.ia6t_vltime -
> -                             (time_second - ia6->ia6_updatetime);
> +                             (time_uptime - ia6->ia6_updatetime);
>               if (TWOHOUR < new->ndpr_vltime ||
>                   storedlifetime < new->ndpr_vltime) {
>                       lt6_tmp.ia6t_vltime = new->ndpr_vltime;
> @@ -1390,7 +1390,7 @@ prelist_update(struct nd_prefix *new, st
>               in6_init_address_ltimes(pr, &lt6_tmp);
>  
>               ia6->ia6_lifetime = lt6_tmp;
> -             ia6->ia6_updatetime = time_second;
> +             ia6->ia6_updatetime = time_uptime;
>       }
>  
>       if ((!autoconf || ((ifp->if_xflags & IFXF_INET6_NOPRIVACY) == 0 &&
> @@ -1978,11 +1978,11 @@ in6_init_prefix_ltimes(struct nd_prefix 
>       if (ndpr->ndpr_pltime == ND6_INFINITE_LIFETIME)
>               ndpr->ndpr_preferred = 0;
>       else
> -             ndpr->ndpr_preferred = time_second + ndpr->ndpr_pltime;
> +             ndpr->ndpr_preferred = time_uptime + ndpr->ndpr_pltime;
>       if (ndpr->ndpr_vltime == ND6_INFINITE_LIFETIME)
>               ndpr->ndpr_expire = 0;
>       else
> -             ndpr->ndpr_expire = time_second + ndpr->ndpr_vltime;
> +             ndpr->ndpr_expire = time_uptime + ndpr->ndpr_vltime;
>  
>       return 0;
>  }
> @@ -1996,7 +1996,7 @@ in6_init_address_ltimes(struct nd_prefix
>       if (lt6->ia6t_vltime == ND6_INFINITE_LIFETIME)
>               lt6->ia6t_expire = 0;
>       else {
> -             lt6->ia6t_expire = time_second;
> +             lt6->ia6t_expire = time_uptime;
>               lt6->ia6t_expire += lt6->ia6t_vltime;
>       }
>  
> @@ -2004,7 +2004,7 @@ in6_init_address_ltimes(struct nd_prefix
>       if (lt6->ia6t_pltime == ND6_INFINITE_LIFETIME)
>               lt6->ia6t_preferred = 0;
>       else {
> -             lt6->ia6t_preferred = time_second;
> +             lt6->ia6t_preferred = time_uptime;
>               lt6->ia6t_preferred += lt6->ia6t_pltime;
>       }
>  }
> 

Reply via email to