diff options
author | andre <andre@FreeBSD.org> | 2004-05-03 13:48:35 +0000 |
---|---|---|
committer | andre <andre@FreeBSD.org> | 2004-05-03 13:48:35 +0000 |
commit | 25ae331e1251bd9562a10f53fdb2f054f7b21dfe (patch) | |
tree | 26d69d96320d4278394e06ff25df74de9314a2fc /sys/net | |
parent | f8ee348f1d1b903d0b117c893b5f73aed4e5bce8 (diff) | |
download | FreeBSD-src-25ae331e1251bd9562a10f53fdb2f054f7b21dfe.zip FreeBSD-src-25ae331e1251bd9562a10f53fdb2f054f7b21dfe.tar.gz |
Link state change notification of ethernet media to the routing socket.
o Extend the if_data structure with an ifi_link_state field and
provide the corresponding defines for the valid states.
o The mii_linkchg() callback updates the ifi_link_state field
and calls rt_ifmsg() to notify listeners on the routing socket
in addition to the kqueue KNOTE.
o If vlans are configured on a physical interface notify and update
all vlan pseudo devices as well with the vlan_link_state() callback.
No objections by: sam, wpaul, ru, bms
Brucification by: bde
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if.h | 8 | ||||
-rw-r--r-- | sys/net/if_var.h | 1 | ||||
-rw-r--r-- | sys/net/if_vlan.c | 25 |
3 files changed, 34 insertions, 0 deletions
diff --git a/sys/net/if.h b/sys/net/if.h index 625dfe0..2266fee 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -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 */ @@ -155,6 +156,13 @@ struct if_data { 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. * XXX 1000 vs. 1024? --thorpej@netbsd.org */ diff --git a/sys/net/if_var.h b/sys/net/if_var.h index 3d3cad5..541f214 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -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 diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c index 87eabb7..25ca790 100644 --- a/sys/net/if_vlan.c +++ b/sys/net/if_vlan.c @@ -125,6 +125,7 @@ static int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr); 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, int link); 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 *, int); + static int vlan_modevent(module_t mod, int type, void *data) { @@ -218,11 +222,13 @@ vlan_modevent(module_t mod, int type, void *data) 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 ifnet *p) */ 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); @@ -657,6 +665,23 @@ 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, int link) +{ + 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)); + KNOTE(&ifp->if_klist, link); + } + } + VLAN_UNLOCK(); +} + static int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { |