aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAndrew Thompson <thompsa@FreeBSD.org>2010-01-18 20:34:00 +0000
committerAndrew Thompson <thompsa@FreeBSD.org>2010-01-18 20:34:00 +0000
commitea4ca115b7b110ada3d657044c19fab4c8766a52 (patch)
treedd7afcb5b04be71754018029b851f7d8237827cf /sys
parent0424a37bea49fce9ca1da4919621db242ddc52ec (diff)
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/net/if.c1
-rw-r--r--sys/net/if_bridge.c2
-rw-r--r--sys/net/if_lagg.c1
-rw-r--r--sys/net/if_var.h3
-rw-r--r--sys/net/if_vlan.c42
-rw-r--r--sys/netgraph/ng_eiface.c1
-rw-r--r--sys/netgraph/ng_ether.c1
-rw-r--r--sys/netgraph/ng_fec.c1
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;