From owner-svn-src-head@FreeBSD.ORG Mon Jan 18 20:34:01 2010 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 546121065694; Mon, 18 Jan 2010 20:34:01 +0000 (UTC) (envelope-from thompsa@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 438C08FC20; Mon, 18 Jan 2010 20:34:01 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o0IKY1eT070560; Mon, 18 Jan 2010 20:34:01 GMT (envelope-from thompsa@svn.freebsd.org) Received: (from thompsa@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0IKY1p4070521; Mon, 18 Jan 2010 20:34:01 GMT (envelope-from thompsa@svn.freebsd.org) Message-Id: <201001182034.o0IKY1p4070521@svn.freebsd.org> From: Andrew Thompson Date: Mon, 18 Jan 2010 20:34:01 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r202588 - in head/sys: net netgraph X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 18 Jan 2010 20:34:01 -0000 Author: thompsa Date: Mon Jan 18 20:34:00 2010 New Revision: 202588 URL: http://svn.freebsd.org/changeset/base/202588 Log: Declare a new EVENTHANDLER called iflladdr_event which signals that the L2 address on an interface has changed. This lets stacked interfaces such as vlan(4) detect that their lower interface has changed and adjust things in order to keep working. Previously this situation broke at least vlan(4) and lagg(4) configurations. The EVENTHANDLER_INVOKE call was not placed within if_setlladdr() due to the risk of a loop. PR: kern/142927 Submitted by: Nikolay Denev Modified: head/sys/net/if.c head/sys/net/if_bridge.c head/sys/net/if_lagg.c head/sys/net/if_var.h head/sys/net/if_vlan.c head/sys/netgraph/ng_eiface.c head/sys/netgraph/ng_ether.c head/sys/netgraph/ng_fec.c Modified: head/sys/net/if.c ============================================================================== --- head/sys/net/if.c Mon Jan 18 20:25:29 2010 (r202587) +++ head/sys/net/if.c Mon Jan 18 20:34:00 2010 (r202588) @@ -2268,6 +2268,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, return (error); error = if_setlladdr(ifp, ifr->ifr_addr.sa_data, ifr->ifr_addr.sa_len); + EVENTHANDLER_INVOKE(iflladdr_event, ifp); break; case SIOCAIFGROUP: Modified: head/sys/net/if_bridge.c ============================================================================== --- head/sys/net/if_bridge.c Mon Jan 18 20:25:29 2010 (r202587) +++ head/sys/net/if_bridge.c Mon Jan 18 20:34:00 2010 (r202588) @@ -917,6 +917,7 @@ bridge_delete_member(struct bridge_softc 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 !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; Modified: head/sys/net/if_lagg.c ============================================================================== --- head/sys/net/if_lagg.c Mon Jan 18 20:25:29 2010 (r202587) +++ head/sys/net/if_lagg.c Mon Jan 18 20:34:00 2010 (r202588) @@ -305,6 +305,7 @@ lagg_lladdr(struct lagg_softc *sc, uint8 /* Let the protocol know the MAC has changed */ if (sc->sc_lladdr != NULL) (*sc->sc_lladdr)(sc); + EVENTHANDLER_INVOKE(iflladdr_event, ifp); } static void Modified: head/sys/net/if_var.h ============================================================================== --- head/sys/net/if_var.h Mon Jan 18 20:25:29 2010 (r202587) +++ head/sys/net/if_var.h Mon Jan 18 20:34:00 2010 (r202588) @@ -339,6 +339,9 @@ void if_maddr_runlock(struct ifnet *ifp) } 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); Modified: head/sys/net/if_vlan.c ============================================================================== --- head/sys/net/if_vlan.c Mon Jan 18 20:25:29 2010 (r202587) +++ head/sys/net/if_vlan.c Mon Jan 18 20:34:00 2010 (r202588) @@ -138,6 +138,7 @@ SYSCTL_INT(_net_link_vlan, OID_AUTO, sof 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_c 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, vo 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, vo 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; Modified: head/sys/netgraph/ng_eiface.c ============================================================================== --- head/sys/netgraph/ng_eiface.c Mon Jan 18 20:25:29 2010 (r202587) +++ head/sys/netgraph/ng_eiface.c Mon Jan 18 20:34:00 2010 (r202588) @@ -431,6 +431,7 @@ ng_eiface_rcvmsg(node_p node, item_p ite } error = if_setlladdr(priv->ifp, (u_char *)msg->data, ETHER_ADDR_LEN); + EVENTHANDLER_INVOKE(iflladdr_event, priv->ifp); break; } Modified: head/sys/netgraph/ng_ether.c ============================================================================== --- head/sys/netgraph/ng_ether.c Mon Jan 18 20:25:29 2010 (r202587) +++ head/sys/netgraph/ng_ether.c Mon Jan 18 20:34:00 2010 (r202588) @@ -481,6 +481,7 @@ ng_ether_rcvmsg(node_p node, item_p item } error = if_setlladdr(priv->ifp, (u_char *)msg->data, ETHER_ADDR_LEN); + EVENTHANDLER_INVOKE(iflladdr_event, priv->ifp); break; } case NGM_ETHER_GET_PROMISC: Modified: head/sys/netgraph/ng_fec.c ============================================================================== --- head/sys/netgraph/ng_fec.c Mon Jan 18 20:25:29 2010 (r202587) +++ head/sys/netgraph/ng_fec.c Mon Jan 18 20:34:00 2010 (r202588) @@ -433,6 +433,7 @@ ng_fec_addport(struct ng_fec_private *pr /* 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;