Module Name:    src
Committed By:   roy
Date:           Thu Jun 20 13:56:29 UTC 2013

Modified Files:
        src/sys/dev/mii: mii_physubr.c
        src/sys/net: if.c
        src/sys/netinet6: in6.c in6.h nd6_rtr.c

Log Message:
Move the detaching and making tentative addresses out if in6_if_up
and into in6_if_link_up.

This fixes a possible panic where link is up but not the interface.
Note that a better solution would be to listen to the routing socket
in the kernel, but I don't know how to do that.

Reachable Router tests for IFF_UP as well.


To generate a diff of this commit:
cvs rdiff -u -r1.79 -r1.80 src/sys/dev/mii/mii_physubr.c
cvs rdiff -u -r1.263 -r1.264 src/sys/net/if.c
cvs rdiff -u -r1.164 -r1.165 src/sys/netinet6/in6.c
cvs rdiff -u -r1.72 -r1.73 src/sys/netinet6/in6.h
cvs rdiff -u -r1.88 -r1.89 src/sys/netinet6/nd6_rtr.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/mii/mii_physubr.c
diff -u src/sys/dev/mii/mii_physubr.c:1.79 src/sys/dev/mii/mii_physubr.c:1.80
--- src/sys/dev/mii/mii_physubr.c:1.79	Sun Jun 16 06:29:08 2013
+++ src/sys/dev/mii/mii_physubr.c	Thu Jun 20 13:56:29 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: mii_physubr.c,v 1.79 2013/06/16 06:29:08 msaitoh Exp $	*/
+/*	$NetBSD: mii_physubr.c,v 1.80 2013/06/20 13:56:29 roy Exp $	*/
 
 /*-
  * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mii_physubr.c,v 1.79 2013/06/16 06:29:08 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mii_physubr.c,v 1.80 2013/06/20 13:56:29 roy Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -436,9 +436,7 @@ mii_phy_statusmsg(struct mii_softc *sc)
 {
 	struct mii_data *mii = sc->mii_pdata;
 	struct ifnet *ifp = mii->mii_ifp;
-	int s;
 
-	s = splnet();
 	if (mii->mii_media_status & IFM_AVALID) {
 		if (mii->mii_media_status & IFM_ACTIVE)
 			if_link_state_change(ifp, LINK_STATE_UP);
@@ -446,7 +444,6 @@ mii_phy_statusmsg(struct mii_softc *sc)
 			if_link_state_change(ifp, LINK_STATE_DOWN);
 	} else
 		if_link_state_change(ifp, LINK_STATE_UNKNOWN);
-	splx(s);
 
 	ifp->if_baudrate = ifmedia_baudrate(mii->mii_media_active);
 }

Index: src/sys/net/if.c
diff -u src/sys/net/if.c:1.263 src/sys/net/if.c:1.264
--- src/sys/net/if.c:1.263	Tue Jun 11 12:08:29 2013
+++ src/sys/net/if.c	Thu Jun 20 13:56:29 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: if.c,v 1.263 2013/06/11 12:08:29 roy Exp $	*/
+/*	$NetBSD: if.c,v 1.264 2013/06/20 13:56:29 roy Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.263 2013/06/11 12:08:29 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.264 2013/06/20 13:56:29 roy Exp $");
 
 #include "opt_inet.h"
 
@@ -1333,14 +1333,19 @@ link_rtrequest(int cmd, struct rtentry *
 
 /*
  * Handle a change in the interface link state.
+ * XXX: We should listen to the routing socket in-kernel rather
+ * than calling in6_if_link_* functions directly from here.
  */
 void
 if_link_state_change(struct ifnet *ifp, int link_state)
 {
-	int old_link_state;
+	int old_link_state, s;
 
-	if (ifp->if_link_state == link_state)
+	s = splnet();
+	if (ifp->if_link_state == link_state) {
+		splx(s);
 		return;
+	}
 
 	old_link_state = ifp->if_link_state;
 	ifp->if_link_state = link_state;
@@ -1349,7 +1354,7 @@ if_link_state_change(struct ifnet *ifp, 
 		link_state == LINK_STATE_UP ? "UP" :
 		link_state == LINK_STATE_DOWN ? "DOWN" :
 		"UNKNOWN",
-		old_link_state == LINK_STATE_UP ? "UP" :
+		 old_link_state == LINK_STATE_UP ? "UP" :
 		old_link_state == LINK_STATE_DOWN ? "DOWN" :
 		"UNKNOWN");
 #endif
@@ -1366,7 +1371,7 @@ if_link_state_change(struct ifnet *ifp, 
 	 */
 	if (link_state == LINK_STATE_UP &&
 	    old_link_state == LINK_STATE_UNKNOWN)
-		in6_if_down(ifp);
+		in6_if_link_down(ifp);
 #endif
 
 	/* Notify that the link state has changed. */
@@ -1379,10 +1384,12 @@ if_link_state_change(struct ifnet *ifp, 
 
 #ifdef INET6
 	if (link_state == LINK_STATE_DOWN)
-		in6_if_down(ifp);
+		in6_if_link_down(ifp);
 	else if (link_state == LINK_STATE_UP)
-		in6_if_up(ifp);
+		in6_if_link_up(ifp);
 #endif
+
+	splx(s);
 }
 
 /*

Index: src/sys/netinet6/in6.c
diff -u src/sys/netinet6/in6.c:1.164 src/sys/netinet6/in6.c:1.165
--- src/sys/netinet6/in6.c:1.164	Tue Jun 11 12:08:29 2013
+++ src/sys/netinet6/in6.c	Thu Jun 20 13:56:29 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6.c,v 1.164 2013/06/11 12:08:29 roy Exp $	*/
+/*	$NetBSD: in6.c,v 1.165 2013/06/20 13:56:29 roy Exp $	*/
 /*	$KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $	*/
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.164 2013/06/11 12:08:29 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.165 2013/06/20 13:56:29 roy Exp $");
 
 #include "opt_inet.h"
 #include "opt_pfil_hooks.h"
@@ -2165,7 +2165,7 @@ in6_ifawithifp(struct ifnet *ifp, struct
  * perform DAD when interface becomes IFF_UP.
  */
 void
-in6_if_up(struct ifnet *ifp)
+in6_if_link_up(struct ifnet *ifp)
 {
 	struct ifaddr *ifa;
 	struct in6_ifaddr *ia;
@@ -2206,24 +2206,34 @@ in6_if_up(struct ifnet *ifp)
 		}
 	}
 
+	/* Restore any detached prefixes */
+	pfxlist_onlink_check();
+}
+
+void
+in6_if_up(struct ifnet *ifp)
+{
+
 	/*
 	 * special cases, like 6to4, are handled in in6_ifattach
 	 */
 	in6_ifattach(ifp, NULL);
 
-	/* Restore any detached prefixes */
-	pfxlist_onlink_check();
+	/* interface may not support link state, so bring it up also */
+	in6_if_link_up(ifp);
 }
-
 /*
  * Mark all addresses as detached.
  */
 void
-in6_if_down(struct ifnet *ifp)
+in6_if_link_down(struct ifnet *ifp)
 {
 	struct ifaddr *ifa;
 	struct in6_ifaddr *ia;
 
+	/* Any prefixes on this interface should be detached as well */
+	pfxlist_onlink_check();
+
 	IFADDR_FOREACH(ifa, ifp) {
 		if (ifa->ifa_addr->sa_family != AF_INET6)
 			continue;
@@ -2249,9 +2259,13 @@ in6_if_down(struct ifnet *ifp)
 			nd6_newaddrmsg(ifa);
 		}
 	}
+}
 
-	/* Any prefixes on this interface should be detached as well */
-	pfxlist_onlink_check();
+void
+in6_if_down(struct ifnet *ifp)
+{
+
+	in6_if_link_down(ifp);
 }
 
 int

Index: src/sys/netinet6/in6.h
diff -u src/sys/netinet6/in6.h:1.72 src/sys/netinet6/in6.h:1.73
--- src/sys/netinet6/in6.h:1.72	Tue Jun 11 12:08:29 2013
+++ src/sys/netinet6/in6.h	Thu Jun 20 13:56:29 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6.h,v 1.72 2013/06/11 12:08:29 roy Exp $	*/
+/*	$NetBSD: in6.h,v 1.73 2013/06/20 13:56:29 roy Exp $	*/
 /*	$KAME: in6.h,v 1.83 2001/03/29 02:55:07 jinmei Exp $	*/
 
 /*
@@ -700,6 +700,8 @@ void	in6_delayed_cksum(struct mbuf *);
 int	in6_localaddr(const struct in6_addr *);
 int	in6_addrscope(const struct in6_addr *);
 struct	in6_ifaddr *in6_ifawithifp(struct ifnet *, struct in6_addr *);
+extern void in6_if_link_up(struct ifnet *);
+extern void in6_if_link_down(struct ifnet *);
 extern void in6_if_up(struct ifnet *);
 extern void in6_if_down(struct ifnet *);
 #ifndef __FreeBSD__

Index: src/sys/netinet6/nd6_rtr.c
diff -u src/sys/netinet6/nd6_rtr.c:1.88 src/sys/netinet6/nd6_rtr.c:1.89
--- src/sys/netinet6/nd6_rtr.c:1.88	Tue Jun 11 12:08:29 2013
+++ src/sys/netinet6/nd6_rtr.c	Thu Jun 20 13:56:29 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: nd6_rtr.c,v 1.88 2013/06/11 12:08:29 roy Exp $	*/
+/*	$NetBSD: nd6_rtr.c,v 1.89 2013/06/20 13:56:29 roy Exp $	*/
 /*	$KAME: nd6_rtr.c,v 1.95 2001/02/07 08:09:47 itojun Exp $	*/
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.88 2013/06/11 12:08:29 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.89 2013/06/20 13:56:29 roy Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1404,11 +1404,12 @@ find_pfxlist_reachable_router(struct nd_
 
 	for (pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs); pfxrtr;
 	     pfxrtr = LIST_NEXT(pfxrtr, pfr_entry)) {
-		if ((rt = nd6_lookup(&pfxrtr->router->rtaddr, 0,
+		if (pfxrtr->router->ifp->if_flags & IFF_UP &&
+		    pfxrtr->router->ifp->if_link_state != LINK_STATE_DOWN &&
+		    (rt = nd6_lookup(&pfxrtr->router->rtaddr, 0,
 		    pfxrtr->router->ifp)) &&
 		    (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
-		    ND6_IS_LLINFO_PROBREACH(ln) &&
-		    pfxrtr->router->ifp->if_link_state != LINK_STATE_DOWN)
+		    ND6_IS_LLINFO_PROBREACH(ln))
 			break;	/* found */
 	}
 

Reply via email to