Author: melifaro
Date: Mon Nov 10 16:01:39 2014
New Revision: 274347
URL: https://svnweb.freebsd.org/changeset/base/274347

Log:
  * Make nd6_dad_duplicated() constant.
  * Simplify refcounting by using nd6_dad_add() / nd6_dad_del().
  
  Reviewed by:  ae
  MFC after:    2 weeks
  Sponsored by: Yandex LLC

Modified:
  head/sys/netinet6/nd6.h
  head/sys/netinet6/nd6_nbr.c

Modified: head/sys/netinet6/nd6.h
==============================================================================
--- head/sys/netinet6/nd6.h     Mon Nov 10 16:01:31 2014        (r274346)
+++ head/sys/netinet6/nd6.h     Mon Nov 10 16:01:39 2014        (r274347)
@@ -430,7 +430,6 @@ void nd6_ns_output(struct ifnet *, const
 caddr_t nd6_ifptomac(struct ifnet *);
 void nd6_dad_start(struct ifaddr *, int);
 void nd6_dad_stop(struct ifaddr *);
-void nd6_dad_duplicated(struct ifaddr *);
 
 /* nd6_rtr.c */
 void nd6_rs_input(struct mbuf *, int, int);

Modified: head/sys/netinet6/nd6_nbr.c
==============================================================================
--- head/sys/netinet6/nd6_nbr.c Mon Nov 10 16:01:31 2014        (r274346)
+++ head/sys/netinet6/nd6_nbr.c Mon Nov 10 16:01:39 2014        (r274347)
@@ -79,9 +79,12 @@ __FBSDID("$FreeBSD$");
 
 struct dadq;
 static struct dadq *nd6_dad_find(struct ifaddr *);
+static void nd6_dad_add(struct dadq *dp);
+static void nd6_dad_del(struct dadq *dp);
 static void nd6_dad_starttimer(struct dadq *, int);
 static void nd6_dad_stoptimer(struct dadq *);
 static void nd6_dad_timer(struct dadq *);
+static void nd6_dad_duplicated(struct ifaddr *, struct dadq *);
 static void nd6_dad_ns_output(struct dadq *, struct ifaddr *);
 static void nd6_dad_ns_input(struct ifaddr *);
 static void nd6_dad_na_input(struct ifaddr *);
@@ -1179,6 +1182,26 @@ static VNET_DEFINE(struct rwlock, dad_rw
 #define        DADQ_WLOCK()            rw_wlock(&V_dad_rwlock) 
 #define        DADQ_WUNLOCK()          rw_wunlock(&V_dad_rwlock)       
 
+static void
+nd6_dad_add(struct dadq *dp)
+{
+
+       ifa_ref(dp->dad_ifa);   /* just for safety */
+       DADQ_WLOCK();
+       TAILQ_INSERT_TAIL(&V_dadq, (struct dadq *)dp, dad_list);
+       DADQ_WUNLOCK();
+}
+
+static void
+nd6_dad_del(struct dadq *dp)
+{
+
+       ifa_free(dp->dad_ifa);
+       DADQ_WLOCK();
+       TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list);
+       DADQ_WUNLOCK();
+}
+
 static struct dadq *
 nd6_dad_find(struct ifaddr *ifa)
 {
@@ -1270,10 +1293,6 @@ nd6_dad_start(struct ifaddr *ifa, int de
 #ifdef VIMAGE
        dp->dad_vnet = curvnet;
 #endif
-       DADQ_WLOCK();
-       TAILQ_INSERT_TAIL(&V_dadq, (struct dadq *)dp, dad_list);
-       DADQ_WUNLOCK();
-
        nd6log((LOG_DEBUG, "%s: starting DAD for %s\n", if_name(ifa->ifa_ifp),
            ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)));
 
@@ -1284,10 +1303,10 @@ nd6_dad_start(struct ifaddr *ifa, int de
         * (re)initialization.
         */
        dp->dad_ifa = ifa;
-       ifa_ref(ifa);   /* just for safety */
        dp->dad_count = V_ip6_dad_count;
        dp->dad_ns_icount = dp->dad_na_icount = 0;
        dp->dad_ns_ocount = dp->dad_ns_tcount = 0;
+       nd6_dad_add(dp);
        if (delay == 0) {
                nd6_dad_ns_output(dp, ifa);
                nd6_dad_starttimer(dp,
@@ -1315,12 +1334,8 @@ nd6_dad_stop(struct ifaddr *ifa)
 
        nd6_dad_stoptimer(dp);
 
-       DADQ_WLOCK();
-       TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list);
-       DADQ_WUNLOCK();
+       nd6_dad_del(dp);
        free(dp, M_IP6NDP);
-       dp = NULL;
-       ifa_free(ifa);
 }
 
 static void
@@ -1367,12 +1382,9 @@ nd6_dad_timer(struct dadq *dp)
                nd6log((LOG_INFO, "%s: could not run DAD, driver problem?\n",
                    if_name(ifa->ifa_ifp)));
 
-               DADQ_WLOCK();
-               TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list);
-               DADQ_WUNLOCK();
+               nd6_dad_del(dp);
                free(dp, M_IP6NDP);
                dp = NULL;
-               ifa_free(ifa);
                goto done;
        }
 
@@ -1408,8 +1420,8 @@ nd6_dad_timer(struct dadq *dp)
 
                if (duplicate) {
                        /* (*dp) will be freed in nd6_dad_duplicated() */
+                       nd6_dad_duplicated(ifa, dp);
                        dp = NULL;
-                       nd6_dad_duplicated(ifa);
                } else {
                        /*
                         * We are done with DAD.  No NA came, no NS came.
@@ -1425,12 +1437,9 @@ nd6_dad_timer(struct dadq *dp)
                            if_name(ifa->ifa_ifp),
                            ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)));
 
-                       DADQ_WLOCK();
-                       TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list);
-                       DADQ_WUNLOCK();
+                       nd6_dad_del(dp);
                        free(dp, M_IP6NDP);
                        dp = NULL;
-                       ifa_free(ifa);
                }
        }
 
@@ -1439,19 +1448,12 @@ done:
 }
 
 void
-nd6_dad_duplicated(struct ifaddr *ifa)
+nd6_dad_duplicated(struct ifaddr *ifa, struct dadq *dp)
 {
        struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
        struct ifnet *ifp;
-       struct dadq *dp;
        char ip6buf[INET6_ADDRSTRLEN];
 
-       dp = nd6_dad_find(ifa);
-       if (dp == NULL) {
-               log(LOG_ERR, "nd6_dad_duplicated: DAD structure not found\n");
-               return;
-       }
-
        log(LOG_ERR, "%s: DAD detected duplicate IPv6 address %s: "
            "NS in/out=%d/%d, NA in=%d\n",
            if_name(ifa->ifa_ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
@@ -1504,12 +1506,8 @@ nd6_dad_duplicated(struct ifaddr *ifa)
                }
        }
 
-       DADQ_WLOCK();
-       TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list);
-       DADQ_WUNLOCK();
+       nd6_dad_del(dp);
        free(dp, M_IP6NDP);
-       dp = NULL;
-       ifa_free(ifa);
 }
 
 static void
@@ -1568,8 +1566,8 @@ nd6_dad_ns_input(struct ifaddr *ifa)
        /* XXX more checks for loopback situation - see nd6_dad_timer too */
 
        if (duplicate) {
+               nd6_dad_duplicated(ifa, dp);
                dp = NULL;      /* will be freed in nd6_dad_duplicated() */
-               nd6_dad_duplicated(ifa);
        } else {
                /*
                 * not sure if I got a duplicate.
@@ -1593,5 +1591,5 @@ nd6_dad_na_input(struct ifaddr *ifa)
                dp->dad_na_icount++;
 
        /* remove the address. */
-       nd6_dad_duplicated(ifa);
+       nd6_dad_duplicated(ifa, dp);
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to