diff options
| author | Andrew Thompson <thompsa@FreeBSD.org> | 2010-01-18 20:34:00 +0000 |
|---|---|---|
| committer | Andrew Thompson <thompsa@FreeBSD.org> | 2010-01-18 20:34:00 +0000 |
| commit | ea4ca115b7b110ada3d657044c19fab4c8766a52 (patch) | |
| tree | dd7afcb5b04be71754018029b851f7d8237827cf /sys | |
| parent | 0424a37bea49fce9ca1da4919621db242ddc52ec (diff) | |
Notes
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/net/if.c | 1 | ||||
| -rw-r--r-- | sys/net/if_bridge.c | 2 | ||||
| -rw-r--r-- | sys/net/if_lagg.c | 1 | ||||
| -rw-r--r-- | sys/net/if_var.h | 3 | ||||
| -rw-r--r-- | sys/net/if_vlan.c | 42 | ||||
| -rw-r--r-- | sys/netgraph/ng_eiface.c | 1 | ||||
| -rw-r--r-- | sys/netgraph/ng_ether.c | 1 | ||||
| -rw-r--r-- | sys/netgraph/ng_fec.c | 1 |
8 files changed, 52 insertions, 0 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index ad77d654c5a1..aa04eff7a4b7 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -2268,6 +2268,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) return (error); error = if_setlladdr(ifp, ifr->ifr_addr.sa_data, ifr->ifr_addr.sa_len); + EVENTHANDLER_INVOKE(iflladdr_event, ifp); break; case SIOCAIFGROUP: diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 36fb9d8a7a21..7084fe6cb5f0 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -917,6 +917,7 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif, IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN); sc->sc_ifaddr = fif; } + EVENTHANDLER_INVOKE(iflladdr_event, sc->sc_ifp); } bridge_mutecaps(sc); /* recalcuate now this interface is removed */ @@ -1033,6 +1034,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) !memcmp(IF_LLADDR(sc->sc_ifp), sc->sc_defaddr, ETHER_ADDR_LEN)) { bcopy(IF_LLADDR(ifs), IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN); sc->sc_ifaddr = ifs; + EVENTHANDLER_INVOKE(iflladdr_event, sc->sc_ifp); } ifs->if_bridge = sc; diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c index 0682d43c9761..c01718555170 100644 --- a/sys/net/if_lagg.c +++ b/sys/net/if_lagg.c @@ -305,6 +305,7 @@ lagg_lladdr(struct lagg_softc *sc, uint8_t *lladdr) /* Let the protocol know the MAC has changed */ if (sc->sc_lladdr != NULL) (*sc->sc_lladdr)(sc); + EVENTHANDLER_INVOKE(iflladdr_event, ifp); } static void diff --git a/sys/net/if_var.h b/sys/net/if_var.h index 28b5571e6a69..87ad1a2393b4 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -339,6 +339,9 @@ void if_maddr_runlock(struct ifnet *ifp); /* if_multiaddrs */ } while(0) #ifdef _KERNEL +/* interface link layer address change event */ +typedef void (*iflladdr_event_handler_t)(void *, struct ifnet *); +EVENTHANDLER_DECLARE(iflladdr_event, iflladdr_event_handler_t); /* interface address change event */ typedef void (*ifaddr_event_handler_t)(void *, struct ifnet *); EVENTHANDLER_DECLARE(ifaddr_event, ifaddr_event_handler_t); diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c index 6a8595642d6f..84edf1b538ca 100644 --- a/sys/net/if_vlan.c +++ b/sys/net/if_vlan.c @@ -138,6 +138,7 @@ SYSCTL_INT(_net_link_vlan, OID_AUTO, soft_pad, CTLFLAG_RW, &soft_pad, 0, static MALLOC_DEFINE(M_VLAN, VLANNAME, "802.1Q Virtual LAN Interface"); static eventhandler_tag ifdetach_tag; +static eventhandler_tag iflladdr_tag; /* * We have a global mutex, that is used to serialize configuration @@ -199,6 +200,7 @@ static int vlan_clone_create(struct if_clone *, char *, size_t, caddr_t); static int vlan_clone_destroy(struct if_clone *, struct ifnet *); static void vlan_ifdetach(void *arg, struct ifnet *ifp); +static void vlan_iflladdr(void *arg, struct ifnet *ifp); static struct if_clone vlan_cloner = IFC_CLONE_INITIALIZER(VLANNAME, NULL, IF_MAXUNIT, NULL, vlan_clone_match, vlan_clone_create, vlan_clone_destroy); @@ -463,6 +465,41 @@ vlan_setmulti(struct ifnet *ifp) } /* + * A handler for parent interface link layer address changes. + * If the parent interface link layer address is changed we + * should also change it on all children vlans. + */ +static void +vlan_iflladdr(void *arg __unused, struct ifnet *ifp) +{ + struct ifvlan *ifv; + int i; + + /* + * Check if it's a trunk interface first of all + * to avoid needless locking. + */ + if (ifp->if_vlantrunk == NULL) + return; + + VLAN_LOCK(); + /* + * OK, it's a trunk. Loop over and change all vlan's lladdrs on it. + */ +#ifdef VLAN_ARRAY + for (i = 0; i < VLAN_ARRAY_SIZE; i++) + if ((ifv = ifp->if_vlantrunk->vlans[i])) + if_setlladdr(ifv->ifv_ifp, IF_LLADDR(ifp), ETHER_ADDR_LEN); +#else /* VLAN_ARRAY */ + for (i = 0; i < (1 << ifp->if_vlantrunk->hwidth); i++) + LIST_FOREACH(ifv, &ifp->if_vlantrunk->hash[i], ifv_list) + if_setlladdr(ifv->ifv_ifp, IF_LLADDR(ifp), ETHER_ADDR_LEN); +#endif /* VLAN_ARRAY */ + VLAN_UNLOCK(); + +} + +/* * A handler for network interface departure events. * Track departure of trunks here so that we don't access invalid * pointers or whatever if a trunk is ripped from under us, e.g., @@ -537,6 +574,10 @@ vlan_modevent(module_t mod, int type, void *data) vlan_ifdetach, NULL, EVENTHANDLER_PRI_ANY); if (ifdetach_tag == NULL) return (ENOMEM); + iflladdr_tag = EVENTHANDLER_REGISTER(iflladdr_event, + vlan_iflladdr, NULL, EVENTHANDLER_PRI_ANY); + if (iflladdr_tag == NULL) + return (ENOMEM); VLAN_LOCK_INIT(); vlan_input_p = vlan_input; vlan_link_state_p = vlan_link_state; @@ -555,6 +596,7 @@ vlan_modevent(module_t mod, int type, void *data) case MOD_UNLOAD: if_clone_detach(&vlan_cloner); EVENTHANDLER_DEREGISTER(ifnet_departure_event, ifdetach_tag); + EVENTHANDLER_DEREGISTER(iflladdr_event, iflladdr_tag); vlan_input_p = NULL; vlan_link_state_p = NULL; vlan_trunk_cap_p = NULL; diff --git a/sys/netgraph/ng_eiface.c b/sys/netgraph/ng_eiface.c index 5c91b81a0a68..72cc55caae22 100644 --- a/sys/netgraph/ng_eiface.c +++ b/sys/netgraph/ng_eiface.c @@ -431,6 +431,7 @@ ng_eiface_rcvmsg(node_p node, item_p item, hook_p lasthook) } error = if_setlladdr(priv->ifp, (u_char *)msg->data, ETHER_ADDR_LEN); + EVENTHANDLER_INVOKE(iflladdr_event, priv->ifp); break; } diff --git a/sys/netgraph/ng_ether.c b/sys/netgraph/ng_ether.c index dc38d4157db6..5abc5aaebcba 100644 --- a/sys/netgraph/ng_ether.c +++ b/sys/netgraph/ng_ether.c @@ -481,6 +481,7 @@ ng_ether_rcvmsg(node_p node, item_p item, hook_p lasthook) } error = if_setlladdr(priv->ifp, (u_char *)msg->data, ETHER_ADDR_LEN); + EVENTHANDLER_INVOKE(iflladdr_event, priv->ifp); break; } case NGM_ETHER_GET_PROMISC: diff --git a/sys/netgraph/ng_fec.c b/sys/netgraph/ng_fec.c index c1760d1cc3e3..919947acab42 100644 --- a/sys/netgraph/ng_fec.c +++ b/sys/netgraph/ng_fec.c @@ -433,6 +433,7 @@ ng_fec_addport(struct ng_fec_private *priv, char *iface) /* Set up phony MAC address. */ if_setlladdr(bifp, IF_LLADDR(ifp), ETHER_ADDR_LEN); + EVENTHANDLER_INVOKE(iflladdr_event, bifp); /* Save original input vector */ new->fec_if_input = bifp->if_input; |
