The work done in this timer should be considerably reduced when we'll
move autoconf out of the kernel.  However we'll always need to check
for IPv6 address life time expiration.   This use case doesn't justify
a specific global data structure. 

So let's iterate over the global list of interfaces instead.  This also
prepare the work to split the NET_LOCK().  Since the ioctl(2) are
per-ifp it makes sense to serialize write operations on a per interface
basis.

ok?

Index: netinet6/nd6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/nd6.c,v
retrieving revision 1.203
diff -u -p -r1.203 nd6.c
--- netinet6/nd6.c      9 Feb 2017 15:23:35 -0000       1.203
+++ netinet6/nd6.c      1 Mar 2017 11:30:52 -0000
@@ -435,7 +435,7 @@ nd6_timer_work(void *null)
 {
        struct nd_defrouter *dr, *ndr;
        struct nd_prefix *pr, *npr;
-       struct in6_ifaddr *ia6, *nia6;
+       struct ifnet *ifp;
        int s;
 
        NET_LOCK(s);
@@ -453,18 +453,26 @@ nd6_timer_work(void *null)
         * However, from a stricter spec-conformance standpoint, we should
         * rather separate address lifetimes and prefix lifetimes.
         */
-       TAILQ_FOREACH_SAFE(ia6, &in6_ifaddr, ia_list, nia6) {
-               /* check address lifetime */
-               if (IFA6_IS_INVALID(ia6)) {
-                       in6_purgeaddr(&ia6->ia_ifa);
-               } else if (IFA6_IS_DEPRECATED(ia6)) {
-                       ia6->ia6_flags |= IN6_IFF_DEPRECATED;
-               } else {
-                       /*
-                        * A new RA might have made a deprecated address
-                        * preferred.
-                        */
-                       ia6->ia6_flags &= ~IN6_IFF_DEPRECATED;
+       TAILQ_FOREACH(ifp, &ifnet, if_list) {
+               struct ifaddr *ifa, *nifa;
+               struct in6_ifaddr *ia6;
+
+               TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrlist, ifa_list, nifa) {
+                       if (ifa->ifa_addr->sa_family != AF_INET6)
+                               continue;
+                       ia6 = ifatoia6(ifa);
+                       /* check address lifetime */
+                       if (IFA6_IS_INVALID(ia6)) {
+                               in6_purgeaddr(&ia6->ia_ifa);
+                       } else if (IFA6_IS_DEPRECATED(ia6)) {
+                               ia6->ia6_flags |= IN6_IFF_DEPRECATED;
+                       } else {
+                               /*
+                                * A new RA might have made a deprecated address
+                                * preferred.
+                                */
+                               ia6->ia6_flags &= ~IN6_IFF_DEPRECATED;
+                       }
                }
        }
 

Reply via email to