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/if_vlan.c | |
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/if_vlan.c')
-rw-r--r-- | sys/net/if_vlan.c | 25 |
1 files changed, 25 insertions, 0 deletions
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) { |