Ok, I tried to implement this tonight but it doesn't work in FreeBSD. I don't get any notification when the cable is unplugged or plugged. I don't get it, maybe someone else sees it, I don't.
miibus_linkchg gets called pretty frequently but the detection logic seems to be flawed. For some reason it doesn't detect cable changes. When I change the media with ifconfig from auto to 100BaseTX and back it reports correctly. Tested with fxp and bge interfaces.
In OpenBSD it works perfectly (fxp interface). Unplug cable, message comes up, plug cable, message comes up. I can't see any logical difference between OpenBSD/NetBSD and or MII variant.
-- Andre
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 23 Apr 2004 01:16:06 -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> @@ -237,7 +238,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 +250,25 @@ 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 protocols that the link state has changed */ + if (link_state != ifp->if_link_state) { + ifp->if_link_state = link_state; + rt_ifmsg(ifp); + } }
static void 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 23 Apr 2004 01:16:06 -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_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 23 Apr 2004 01:16:06 -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
_______________________________________________ [EMAIL PROTECTED] mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-hackers To unsubscribe, send any mail to "[EMAIL PROTECTED]"