Index: dev/mii/brgphy.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/mii/brgphy.c,v
retrieving revision 1.28
diff -u -p -r1.28 brgphy.c
--- dev/mii/brgphy.c	31 Oct 2003 18:32:02 -0000	1.28
+++ dev/mii/brgphy.c	26 Apr 2004 17:23:29 -0000
@@ -362,8 +362,8 @@ setit:
 		/*
 		 * Only retry autonegotiation every 5 seconds.
 		 */
-		if (++sc->mii_ticks != 5)
-			return (0);
+		if (++sc->mii_ticks <= 5)
+			break;
 		
 		sc->mii_ticks = 0;
 		brgphy_mii_phy_auto(sc);
@@ -381,7 +381,6 @@ setit:
 	if (sc->mii_media_active != mii->mii_media_active || 
 	    sc->mii_media_status != mii->mii_media_status ||
 	    cmd == MII_MEDIACHG) {
-		mii_phy_update(sc, cmd);
 		switch (brgphy_mii_model) {
 		case MII_MODEL_xxBROADCOM_BCM5401:
 			bcm5401_load_dspcode(sc);
@@ -391,6 +390,7 @@ setit:
 			break;
 		}
 	}
+	mii_phy_update(sc, cmd);
 	return (0);
 }
 
Index: dev/mii/dcphy.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/mii/dcphy.c,v
retrieving revision 1.23
diff -u -p -r1.23 dcphy.c
--- dev/mii/dcphy.c	24 Aug 2003 17:54:10 -0000	1.23
+++ dev/mii/dcphy.c	26 Apr 2004 17:23:30 -0000
@@ -324,7 +324,7 @@ dcphy_service(sc, mii, cmd)
 		 * successful autonegotation is never recognised on
 		 * these chips.
                  */
-                if (++sc->mii_ticks != 50)
+                if (++sc->mii_ticks <= 50)
 			break;
 
 		sc->mii_ticks = 0;
Index: dev/mii/e1000phy.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/mii/e1000phy.c,v
retrieving revision 1.10
diff -u -p -r1.10 e1000phy.c
--- dev/mii/e1000phy.c	20 Sep 2003 10:53:08 -0000	1.10
+++ dev/mii/e1000phy.c	26 Apr 2004 17:23:30 -0000
@@ -333,8 +333,8 @@ e1000phy_service(struct mii_softc *sc, s
 		/*
 		 * Only retry autonegotiation every 5 seconds.
 		 */
-		if (++sc->mii_ticks != 5)
-			return (0);
+		if (++sc->mii_ticks <= 5)
+			break;
 
 		sc->mii_ticks = 0;
 		e1000phy_reset(sc);
Index: dev/mii/mii.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/mii/mii.c,v
retrieving revision 1.17
diff -u -p -r1.17 mii.c
--- dev/mii/mii.c	24 Aug 2003 17:54:10 -0000	1.17
+++ dev/mii/mii.c	26 Apr 2004 17:23:30 -0000
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD: src/sys/dev/mii/mii.
 
 #include <net/if.h>
 #include <net/if_media.h>
+#include <net/route.h>
 
 #include <dev/mii/mii.h>
 #include <dev/mii/miivar.h>
@@ -230,6 +231,8 @@ miibus_statchg(dev)
 	return;
 }
 
+void	(*vlan_link_state_p)(struct ifnet *);	/* XXX: private from if_vlan */
+
 static void
 miibus_linkchg(dev)
 	device_t dev;
@@ -237,7 +240,7 @@ miibus_linkchg(dev)
 	struct mii_data *mii;
 	struct ifnet *ifp;
 	device_t parent;
-	int link;
+	int link, link_state;
 
 	parent = device_get_parent(dev);
 	MIIBUS_LINKCHG(parent);
@@ -249,15 +252,26 @@ miibus_linkchg(dev)
 	ifp = device_get_softc(parent);
 	
 	if (mii->mii_media_status & IFM_AVALID) {
-		if (mii->mii_media_status & IFM_ACTIVE)
+		if (mii->mii_media_status & IFM_ACTIVE) {
 			link = NOTE_LINKUP;
-		else
+			link_state = LINK_STATE_UP;
+		} else {
 			link = NOTE_LINKDOWN;
+			link_state = LINK_STATE_DOWN;
+		}
 	} else {
 		link = NOTE_LINKINV;
+		link_state = LINK_STATE_UNKNOWN;
 	}
 
-	KNOTE(&ifp->if_klist, link);
+	/* Notify that the link state has changed */
+	if (ifp->if_link_state != link_state) {
+		ifp->if_link_state = link_state;
+		KNOTE(&ifp->if_klist, link);
+		rt_ifmsg(ifp);
+		if (ifp->if_nvlans)
+			(*vlan_link_state_p)(ifp);
+	}
 }
 
 static void
Index: dev/mii/mii_physubr.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/mii/mii_physubr.c,v
retrieving revision 1.19
diff -u -p -r1.19 mii_physubr.c
--- dev/mii/mii_physubr.c	24 Aug 2003 17:54:10 -0000	1.19
+++ dev/mii/mii_physubr.c	26 Apr 2004 17:23:30 -0000
@@ -231,9 +231,11 @@ mii_phy_tick(struct mii_softc *sc)
 	/*
 	 * Only retry autonegotiation every N seconds.
 	 */
-	if (sc->mii_anegticks == 0)
+	if (sc->mii_anegticks == 0) {
 		sc->mii_anegticks = 17;
-	if (++sc->mii_ticks != sc->mii_anegticks)
+		return (0);
+	}
+	if (++sc->mii_ticks <= sc->mii_anegticks)
 		return (EJUSTRETURN);
 
 	sc->mii_ticks = 0;
Index: dev/mii/mlphy.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/mii/mlphy.c,v
retrieving revision 1.18
diff -u -p -r1.18 mlphy.c
--- dev/mii/mlphy.c	24 Aug 2003 17:54:10 -0000	1.18
+++ dev/mii/mlphy.c	26 Apr 2004 17:23:30 -0000
@@ -337,8 +337,8 @@ mlphy_service(xsc, mii, cmd)
 		/*
 		 * Only retry autonegotiation every 5 seconds.
 		 */
-		if (++sc->mii_ticks != 5)
-			return (0);
+		if (++sc->mii_ticks <= 5)
+			break;
 		
 		sc->mii_ticks = 0;
 		msc->ml_linked = 0;
Index: dev/mii/rgephy.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/mii/rgephy.c,v
retrieving revision 1.2
diff -u -p -r1.2 rgephy.c
--- dev/mii/rgephy.c	11 Sep 2003 08:28:38 -0000	1.2
+++ dev/mii/rgephy.c	26 Apr 2004 17:23:31 -0000
@@ -298,8 +298,8 @@ setit:
 		/*
 		 * Only retry autonegotiation every 5 seconds.
 		 */
-		if (++sc->mii_ticks != 5/*10*/)
-			return (0);
+		if (++sc->mii_ticks <= 5/*10*/)
+			break;
 		
 		sc->mii_ticks = 0;
 		rgephy_mii_phy_auto(sc);
@@ -317,9 +317,9 @@ setit:
 	if (sc->mii_media_active != mii->mii_media_active || 
 	    sc->mii_media_status != mii->mii_media_status ||
 	    cmd == MII_MEDIACHG) {
-		mii_phy_update(sc, cmd);
 		rgephy_load_dspcode(sc);
 	}
+	mii_phy_update(sc, cmd);
 	return (0);
 }
 
Index: dev/mii/ruephy.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/mii/ruephy.c,v
retrieving revision 1.2
diff -u -p -r1.2 ruephy.c
--- dev/mii/ruephy.c	24 Aug 2003 17:54:10 -0000	1.2
+++ dev/mii/ruephy.c	26 Apr 2004 17:23:31 -0000
@@ -226,8 +226,8 @@ ruephy_service(struct mii_softc *sc, str
 		/*
 		 * Only retry autonegotiation every 5 seconds.
 		 */
-		if (++sc->mii_ticks != 5)
-			return (0);
+		if (++sc->mii_ticks <= 5)
+			break;
 
 		sc->mii_ticks = 0;
 		ruephy_reset(sc);
Index: dev/mii/tlphy.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/mii/tlphy.c,v
retrieving revision 1.15
diff -u -p -r1.15 tlphy.c
--- dev/mii/tlphy.c	24 Aug 2003 17:54:10 -0000	1.15
+++ dev/mii/tlphy.c	26 Apr 2004 17:23:32 -0000
@@ -325,8 +325,8 @@ tlphy_service(self, mii, cmd)
 		/*
 		 * Only retry autonegotiation every 5 seconds.
 		 */
-		if (++sc->sc_mii.mii_ticks != 5)
-			return (0);
+		if (++sc->sc_mii.mii_ticks <= 5)
+			break;
 
 		sc->sc_mii.mii_ticks = 0;
 		mii_phy_reset(&sc->sc_mii);
Index: dev/mii/xmphy.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/mii/xmphy.c,v
retrieving revision 1.13
diff -u -p -r1.13 xmphy.c
--- dev/mii/xmphy.c	24 Aug 2003 17:54:10 -0000	1.13
+++ dev/mii/xmphy.c	26 Apr 2004 17:23:32 -0000
@@ -255,8 +255,8 @@ xmphy_service(sc, mii, cmd)
 		/*
 		 * Only retry autonegotiation every 5 seconds.
 		 */
-		if (++sc->mii_ticks != 5)
-			return (0);
+		if (++sc->mii_ticks <= 5)
+			break;
 		
 		sc->mii_ticks = 0;
 
Index: net/if.h
===================================================================
RCS file: /home/ncvs/src/sys/net/if.h,v
retrieving revision 1.85
diff -u -p -r1.85 if.h
--- net/if.h	11 Apr 2004 13:36:52 -0000	1.85
+++ net/if.h	26 Apr 2004 17:23:32 -0000
@@ -104,6 +104,7 @@ struct if_data {
 	u_char	ifi_physical;		/* e.g., AUI, Thinnet, 10base-T, etc */
 	u_char	ifi_addrlen;		/* media address length */
 	u_char	ifi_hdrlen;		/* media header length */
+	u_char	ifi_link_state;		/* current link state */
 	u_char	ifi_recvquota;		/* polling quota for receive intrs */
 	u_char	ifi_xmitquota;		/* polling quota for xmit intrs */
 	u_long	ifi_mtu;		/* maximum transmission unit */
@@ -153,6 +154,13 @@ struct if_data {
 	(IFF_BROADCAST|IFF_POINTOPOINT|IFF_RUNNING|IFF_OACTIVE|\
 	    IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI|IFF_SMART|IFF_PROMISC|\
 	    IFF_POLLING)
+
+/*
+ * Values for if_link_state.
+ */
+#define LINK_STATE_UNKNOWN	0	/* link invalid/unknown */
+#define LINK_STATE_DOWN		1	/* link is down */
+#define LINK_STATE_UP		2	/* link is up */
 
 /*
  * Some convenience macros used for setting ifi_baudrate.
Index: net/if_atmsubr.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_atmsubr.c,v
retrieving revision 1.35
diff -u -p -r1.35 if_atmsubr.c
--- net/if_atmsubr.c	25 Apr 2004 09:24:51 -0000	1.35
+++ net/if_atmsubr.c	26 Apr 2004 17:23:33 -0000
@@ -475,10 +475,21 @@ atm_getvccs(struct atmio_vcc **table, u_
 void
 atm_event(struct ifnet *ifp, u_int event, void *arg)
 {
+	int link_state = LINK_STATE_UNKNOWN;
+
 	if (ng_atm_event_p != NULL)
 		(*ng_atm_event_p)(ifp, event, arg);
 	if (atm_harp_event_p != NULL)
 		(*atm_harp_event_p)(ifp, event, arg);
+	if (event == ATMEV_IFSTATE_CHANGED) {
+		struct atmev_ifstate_changed aifc = (atmev_ifstate_changed *)arg;
+
+		if (aifc->running && aifc->carrier)
+			link_state = LINK_STATE_UP;
+		else
+			link_state = LINK_STATE_DOWN;
+		rt_ifmsg(ifp);
+	}
 }
 
 static moduledata_t atm_mod = {
Index: net/if_var.h
===================================================================
RCS file: /home/ncvs/src/sys/net/if_var.h,v
retrieving revision 1.73
diff -u -p -r1.73 if_var.h
--- net/if_var.h	18 Apr 2004 18:59:44 -0000	1.73
+++ net/if_var.h	26 Apr 2004 17:23:33 -0000
@@ -197,6 +197,7 @@ typedef void if_init_f_t(void *);
 #define	if_addrlen	if_data.ifi_addrlen
 #define	if_hdrlen	if_data.ifi_hdrlen
 #define	if_metric	if_data.ifi_metric
+#define	if_link_state	if_data.ifi_link_state
 #define	if_baudrate	if_data.ifi_baudrate
 #define	if_hwassist	if_data.ifi_hwassist
 #define	if_ipackets	if_data.ifi_ipackets
Index: net/if_vlan.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_vlan.c,v
retrieving revision 1.58
diff -u -p -r1.58 if_vlan.c
--- net/if_vlan.c	24 Apr 2004 22:24:48 -0000	1.58
+++ net/if_vlan.c	26 Apr 2004 17:23:33 -0000
@@ -125,6 +125,7 @@ static	int vlan_ioctl(struct ifnet *ifp,
 static	int vlan_setmulti(struct ifnet *ifp);
 static	int vlan_unconfig(struct ifnet *ifp);
 static	int vlan_config(struct ifvlan *ifv, struct ifnet *p);
+static	void vlan_link_state(struct ifnet *ifp);
 
 struct if_clone vlan_cloner = IF_CLONE_INITIALIZER(VLANNAME,
     vlan_clone_create, vlan_clone_destroy, 0, IF_MAXUNIT);
@@ -209,6 +210,9 @@ vlan_setmulti(struct ifnet *ifp)
  */
 extern	void (*vlan_input_p)(struct ifnet *, struct mbuf *);
 
+/* For MII eyes only... */
+extern	void (*vlan_link_state_p)(struct ifnet *);
+
 static int
 vlan_modevent(module_t mod, int type, void *data) 
 { 
@@ -218,11 +222,13 @@ vlan_modevent(module_t mod, int type, vo
 		LIST_INIT(&ifv_list);
 		VLAN_LOCK_INIT();
 		vlan_input_p = vlan_input;
+		vlan_link_state_p = vlan_link_state;
 		if_clone_attach(&vlan_cloner);
 		break; 
 	case MOD_UNLOAD: 
 		if_clone_detach(&vlan_cloner);
 		vlan_input_p = NULL;
+		vlan_link_state_p = NULL;
 		while (!LIST_EMPTY(&ifv_list))
 			vlan_clone_destroy(&LIST_FIRST(&ifv_list)->ifv_if);
 		VLAN_LOCK_DESTROY();
@@ -532,6 +538,7 @@ vlan_config(struct ifvlan *ifv, struct i
 	 */
 	ifv->ifv_if.if_flags = (p->if_flags &
 	    (IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX | IFF_POINTOPOINT));
+	ifv->ifv_if.if_link_state = p->if_link_state;
 
 	/*
 	 * If the parent interface can do hardware-assisted
@@ -622,6 +629,7 @@ vlan_unconfig(struct ifnet *ifp)
 	ifv->ifv_p = NULL;
 	ifv->ifv_if.if_mtu = ETHERMTU;		/* XXX why not 0? */
 	ifv->ifv_flags = 0;
+	ifv->ifv_if.if_link_state = LINK_STATE_UNKNOWN;
 
 	/* Clear our MAC address. */
 	ifa = ifaddr_byindex(ifv->ifv_if.if_index);
@@ -655,6 +663,22 @@ vlan_set_promisc(struct ifnet *ifp)
 	}
 
 	return (error);
+}
+
+/* Inform all vlans that their parent has changed link state */
+static void
+vlan_link_state(struct ifnet *ifp)
+{
+	struct ifvlan *ifv;
+
+	VLAN_LOCK();
+	LIST_FOREACH(ifv, &ifv_list, ifv_list) {
+		if (ifv->ifv_p == ifp) {
+			ifv->ifv_if.if_link_state = ifv->ifv_p->if_link_state;
+			rt_ifmsg(&(ifv->ifv_if));
+		}
+	}
+	VLAN_UNLOCK();
 }
 
 static int
Index: net80211/ieee80211.c
===================================================================
RCS file: /home/ncvs/src/sys/net80211/ieee80211.c,v
retrieving revision 1.11
diff -u -p -r1.11 ieee80211.c
--- net80211/ieee80211.c	2 Apr 2004 20:19:20 -0000	1.11
+++ net80211/ieee80211.c	26 Apr 2004 17:23:34 -0000
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD: src/sys/net80211/iee
 #include <net/if_arp.h>
 #include <net/ethernet.h>
 #include <net/if_llc.h>
+#include <net/route.h>
 
 #include <net80211/ieee80211_var.h>
 
@@ -534,11 +535,15 @@ ieee80211_media_status(struct ifnet *ifp
 {
 	struct ieee80211com *ic = (void *)ifp;
 	struct ieee80211_node *ni = NULL;
+	int old_status = imr->ifm_status;
 
 	imr->ifm_status = IFM_AVALID;
 	imr->ifm_active = IFM_IEEE80211;
-	if (ic->ic_state == IEEE80211_S_RUN)
+	if (ic->ic_state == IEEE80211_S_RUN) {
 		imr->ifm_status |= IFM_ACTIVE;
+		ifp->if_link_state = LINK_STATE_UP;
+	} else
+		ifp->if_link_state = LINK_STATE_DOWN;
 	imr->ifm_active |= IFM_AUTO;
 	switch (ic->ic_opmode) {
 	case IEEE80211_M_STA:
@@ -578,6 +583,10 @@ ieee80211_media_status(struct ifnet *ifp
 				|  IFM_IEEE80211_TURBO;
 		break;
 	}
+
+	/* Notify that the link state has changed */
+	if (imr->ifm_status != old_status)
+		rt_ifmsg(ifp);
 }
 
 void
Index: sbin/route/route.c
===================================================================
RCS file: /home/ncvs/src/sbin/route/route.c,v
retrieving revision 1.72
diff -u -p -r1.72 route.c
--- sbin/route/route.c	13 Apr 2004 11:23:13 -0000	1.72
+++ sbin/route/route.c	26 Apr 2004 17:24:07 -0000
@@ -1300,6 +1300,7 @@ print_rtmsg(rtm, msglen)
 	struct ifma_msghdr *ifmam;
 #endif
 	struct if_announcemsghdr *ifan;
+	const char *state = "unknown";
 
 	if (verbose == 0)
 		return;
@@ -1316,7 +1317,16 @@ print_rtmsg(rtm, msglen)
 	switch (rtm->rtm_type) {
 	case RTM_IFINFO:
 		ifm = (struct if_msghdr *)rtm;
-		(void) printf("if# %d, flags:", ifm->ifm_index);
+		(void) printf("if# %d, ", ifm->ifm_index);
+		switch (ifm->ifm_data.ifi_link_state) {
+		case LINK_STATE_DOWN:
+			state = "down";
+			break;
+		case LINK_STATE_UP:
+			state = "up";
+			break;
+		}
+		(void) printf("link: %s, flags:", state);
 		bprintf(stdout, ifm->ifm_flags, ifnetflags);
 		pmsg_addrs((char *)(ifm + 1), ifm->ifm_addrs);
 		break;
