Author: markj
Date: Sat Mar 30 18:00:44 2019
New Revision: 345739
URL: https://svnweb.freebsd.org/changeset/base/345739

Log:
  Do not perform DAD on stf(4) interfaces.
  
  stf(4) interfaces are not multicast-capable so they can't perform DAD.
  They also did not set IFF_DRV_RUNNING when an address was assigned, so
  the logic in nd6_timer() would periodically flag such an address as
  tentative, resulting in interface flapping.
  
  Fix the problem by setting IFF_DRV_RUNNING when an address is assigned,
  and do some related cleanup:
  - In in6if_do_dad(), remove a redundant check for !UP || !RUNNING.
    There is only one caller in the tree, and it only looks at whether
    the return value is non-zero.
  - Have in6if_do_dad() return false if the interface is not
    multicast-capable.
  - Set ND6_IFF_NO_DAD when an address is assigned to an stf(4) interface
    and the interface goes UP as a result. Note that this is not
    sufficient to fix the problem because the new address is marked as
    tentative and DAD is started before in6_ifattach() is called.
    However, setting no_dad is formally correct.
  - Change nd6_timer() to not flag addresses as tentative if no_dad is
    set.
  
  This is based on a patch from Viktor Dukhovni.
  
  Reported by:  Viktor Dukhovni <ietf-d...@dukhovni.org>
  Reviewed by:  ae
  MFC after:    3 weeks
  Sponsored by: The FreeBSD Foundation
  Differential Revision:        https://reviews.freebsd.org/D19751

Modified:
  head/sys/net/if_stf.c
  head/sys/netinet6/in6.c
  head/sys/netinet6/in6_ifattach.c
  head/sys/netinet6/nd6.c

Modified: head/sys/net/if_stf.c
==============================================================================
--- head/sys/net/if_stf.c       Sat Mar 30 17:42:27 2019        (r345738)
+++ head/sys/net/if_stf.c       Sat Mar 30 18:00:44 2019        (r345739)
@@ -724,6 +724,7 @@ stf_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
                }
 
                ifp->if_flags |= IFF_UP;
+               ifp->if_drv_flags |= IFF_DRV_RUNNING;
                break;
 
        case SIOCADDMULTI:

Modified: head/sys/netinet6/in6.c
==============================================================================
--- head/sys/netinet6/in6.c     Sat Mar 30 17:42:27 2019        (r345738)
+++ head/sys/netinet6/in6.c     Sat Mar 30 18:00:44 2019        (r345739)
@@ -1951,26 +1951,14 @@ in6_if_up(struct ifnet *ifp)
 int
 in6if_do_dad(struct ifnet *ifp)
 {
+
        if ((ifp->if_flags & IFF_LOOPBACK) != 0)
                return (0);
-
-       if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) ||
-           (ND_IFINFO(ifp)->flags & ND6_IFF_NO_DAD))
+       if ((ifp->if_flags & IFF_MULTICAST) == 0)
                return (0);
-
-       /*
-        * Our DAD routine requires the interface up and running.
-        * However, some interfaces can be up before the RUNNING
-        * status.  Additionally, users may try to assign addresses
-        * before the interface becomes up (or running).
-        * This function returns EAGAIN in that case.
-        * The caller should mark "tentative" on the address instead of
-        * performing DAD immediately.
-        */
-       if (!((ifp->if_flags & IFF_UP) &&
-           (ifp->if_drv_flags & IFF_DRV_RUNNING)))
-               return (EAGAIN);
-
+       if ((ND_IFINFO(ifp)->flags &
+           (ND6_IFF_IFDISABLED | ND6_IFF_NO_DAD)) != 0)
+               return (0);
        return (1);
 }
 

Modified: head/sys/netinet6/in6_ifattach.c
==============================================================================
--- head/sys/netinet6/in6_ifattach.c    Sat Mar 30 17:42:27 2019        
(r345738)
+++ head/sys/netinet6/in6_ifattach.c    Sat Mar 30 18:00:44 2019        
(r345739)
@@ -692,6 +692,7 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp)
                 * it is rather harmful to have one.
                 */
                ND_IFINFO(ifp)->flags &= ~ND6_IFF_AUTO_LINKLOCAL;
+               ND_IFINFO(ifp)->flags |= ND6_IFF_NO_DAD;
                break;
        default:
                break;

Modified: head/sys/netinet6/nd6.c
==============================================================================
--- head/sys/netinet6/nd6.c     Sat Mar 30 17:42:27 2019        (r345738)
+++ head/sys/netinet6/nd6.c     Sat Mar 30 18:00:44 2019        (r345739)
@@ -900,6 +900,7 @@ nd6_timer(void *arg)
        struct nd_prhead prl;
        struct nd_defrouter *dr, *ndr;
        struct nd_prefix *pr, *npr;
+       struct ifnet *ifp;
        struct in6_ifaddr *ia6, *nia6;
        uint64_t genid;
 
@@ -996,14 +997,15 @@ nd6_timer(void *arg)
                         * Check status of the interface.  If it is down,
                         * mark the address as tentative for future DAD.
                         */
-                       if ((ia6->ia_ifp->if_flags & IFF_UP) == 0 ||
-                           (ia6->ia_ifp->if_drv_flags & IFF_DRV_RUNNING)
-                               == 0 ||
-                           (ND_IFINFO(ia6->ia_ifp)->flags &
-                               ND6_IFF_IFDISABLED) != 0) {
+                       ifp = ia6->ia_ifp;
+                       if ((ND_IFINFO(ifp)->flags & ND6_IFF_NO_DAD) == 0 &&
+                           ((ifp->if_flags & IFF_UP) == 0 ||
+                           (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
+                           (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) != 0)){
                                ia6->ia6_flags &= ~IN6_IFF_DUPLICATED;
                                ia6->ia6_flags |= IN6_IFF_TENTATIVE;
                        }
+
                        /*
                         * A new RA might have made a deprecated address
                         * preferred.
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to