Module Name: src Committed By: snj Date: Fri Jun 5 18:49:43 UTC 2009
Modified Files: src/sys/dev/pci [netbsd-5]: if_wm.c src/sys/net [netbsd-5]: if_ethersubr.c src/sys/net/agr [netbsd-5]: ieee8023ad_lacp.c if_agr.c if_agrether.c if_agrvar_impl.h Log Message: Pull up following revision(s) (requested by 792): sys/dev/pci/if_wm.c: revision 1.175 via patch sys/net/if_ethersubr.c: revision 1.172 via patch sys/net/agr/ieee8023ad_lacp.c: revision 1.9 via patch sys/net/agr/if_agr.c: revision 1.23 via patch sys/net/agr/if_agrether.c: revision 1.7 via patch sys/net/agr/if_agrvar_impl.h: revision 1.8 via patch Add vlan support and hardware offload capabilities to agr. These changes allow vlans to be layered above agr, with the attach and detach propogated to the member ports in the aggregation. Note the agr interface must be up before the vlan is attached. Adds SIOCSIFADDR support to the wm driver for setting the AF_LINK address, necessary for agr to be able to set the mac addresses of each port to the agr address (i.e. so it can receive all intended traffic at the hardware level). Adds support for disabling the LACP protocol by setting LINK1 on the agr interface (e.g. ifconfig agr0 link1). In consultation with t...@. To generate a diff of this commit: cvs rdiff -u -r1.162.4.9 -r1.162.4.10 src/sys/dev/pci/if_wm.c cvs rdiff -u -r1.169 -r1.169.4.1 src/sys/net/if_ethersubr.c cvs rdiff -u -r1.8 -r1.8.36.1 src/sys/net/agr/ieee8023ad_lacp.c cvs rdiff -u -r1.21 -r1.21.8.1 src/sys/net/agr/if_agr.c cvs rdiff -u -r1.6 -r1.6.36.1 src/sys/net/agr/if_agrether.c cvs rdiff -u -r1.7 -r1.7.44.1 src/sys/net/agr/if_agrvar_impl.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/if_wm.c diff -u src/sys/dev/pci/if_wm.c:1.162.4.9 src/sys/dev/pci/if_wm.c:1.162.4.10 --- src/sys/dev/pci/if_wm.c:1.162.4.9 Thu May 21 01:13:49 2009 +++ src/sys/dev/pci/if_wm.c Fri Jun 5 18:49:42 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wm.c,v 1.162.4.9 2009/05/21 01:13:49 snj Exp $ */ +/* $NetBSD: if_wm.c,v 1.162.4.10 2009/06/05 18:49:42 snj Exp $ */ /* * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. @@ -76,7 +76,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.162.4.9 2009/05/21 01:13:49 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.162.4.10 2009/06/05 18:49:42 snj Exp $"); #include "bpfilter.h" #include "rnd.h" @@ -2366,6 +2366,8 @@ { struct wm_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *) data; + struct ifaddr *ifa = (struct ifaddr *)data; + struct sockaddr_dl *sdl; int s, error; s = splnet(); @@ -2387,6 +2389,18 @@ } error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd); break; + case SIOCSIFADDR: + if (ifa->ifa_addr->sa_family == AF_LINK) { + sdl = satosdl(ifp->if_dl->ifa_addr); + (void)sockaddr_dl_setaddr(sdl, sdl->sdl_len, + LLADDR(satosdl(ifa->ifa_addr)), + ifp->if_addrlen); + /* unicast address is first multicast entry */ + wm_set_filter(sc); + error = 0; + break; + } + /* Fall through for rest */ default: if ((error = ether_ioctl(ifp, cmd, data)) != ENETRESET) break; Index: src/sys/net/if_ethersubr.c diff -u src/sys/net/if_ethersubr.c:1.169 src/sys/net/if_ethersubr.c:1.169.4.1 --- src/sys/net/if_ethersubr.c:1.169 Wed Jul 23 06:34:31 2008 +++ src/sys/net/if_ethersubr.c Fri Jun 5 18:49:42 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: if_ethersubr.c,v 1.169 2008/07/23 06:34:31 dyoung Exp $ */ +/* $NetBSD: if_ethersubr.c,v 1.169.4.1 2009/06/05 18:49:42 snj Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -61,7 +61,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.169 2008/07/23 06:34:31 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.169.4.1 2009/06/05 18:49:42 snj Exp $"); #include "opt_inet.h" #include "opt_atalk.h" @@ -735,6 +735,15 @@ } #endif +#if NAGR > 0 + if (ifp->if_agrprivate && + __predict_true(etype != ETHERTYPE_SLOWPROTOCOLS)) { + m->m_flags &= ~M_PROMISC; + agr_input(ifp, m); + return; + } +#endif /* NAGR > 0 */ + /* * If VLANs are configured on the interface, check to * see if the device performed the decapsulation and @@ -753,15 +762,6 @@ return; } -#if NAGR > 0 - if (ifp->if_agrprivate && - __predict_true(etype != ETHERTYPE_SLOWPROTOCOLS)) { - m->m_flags &= ~M_PROMISC; - agr_input(ifp, m); - return; - } -#endif /* NAGR > 0 */ - /* * Handle protocols that expect to have the Ethernet header * (and possibly FCS) intact. Index: src/sys/net/agr/ieee8023ad_lacp.c diff -u src/sys/net/agr/ieee8023ad_lacp.c:1.8 src/sys/net/agr/ieee8023ad_lacp.c:1.8.36.1 --- src/sys/net/agr/ieee8023ad_lacp.c:1.8 Sun Aug 26 22:59:09 2007 +++ src/sys/net/agr/ieee8023ad_lacp.c Fri Jun 5 18:49:43 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: ieee8023ad_lacp.c,v 1.8 2007/08/26 22:59:09 dyoung Exp $ */ +/* $NetBSD: ieee8023ad_lacp.c,v 1.8.36.1 2009/06/05 18:49:43 snj Exp $ */ /*- * Copyright (c)2005 YAMAMOTO Takashi, @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ieee8023ad_lacp.c,v 1.8 2007/08/26 22:59:09 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ieee8023ad_lacp.c,v 1.8.36.1 2009/06/05 18:49:43 snj Exp $"); #include <sys/param.h> #include <sys/callout.h> @@ -104,6 +104,13 @@ sc = AGR_SC_FROM_PORT(port); KASSERT(port); + /* running static config? */ + if (AGR_STATIC(sc)) { + /* static config, no lacp */ + goto bad; + } + + if (m->m_pkthdr.len != sizeof(*du)) { goto bad; } @@ -192,6 +199,12 @@ struct lacpdu *du; int error; + /* running static config? */ + if (AGR_STATIC(AGR_SC_FROM_PORT(port))) { + /* static config, no lacp transmit */ + return 0; + } + KDASSERT(MHLEN >= sizeof(*du)); m = m_gethdr(M_DONTWAIT, MT_DATA); Index: src/sys/net/agr/if_agr.c diff -u src/sys/net/agr/if_agr.c:1.21 src/sys/net/agr/if_agr.c:1.21.8.1 --- src/sys/net/agr/if_agr.c:1.21 Mon May 19 02:53:47 2008 +++ src/sys/net/agr/if_agr.c Fri Jun 5 18:49:43 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: if_agr.c,v 1.21 2008/05/19 02:53:47 yamt Exp $ */ +/* $NetBSD: if_agr.c,v 1.21.8.1 2009/06/05 18:49:43 snj Exp $ */ /*- * Copyright (c)2005 YAMAMOTO Takashi, @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_agr.c,v 1.21 2008/05/19 02:53:47 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_agr.c,v 1.21.8.1 2009/06/05 18:49:43 snj Exp $"); #include "bpfilter.h" #include "opt_inet.h" @@ -49,6 +49,7 @@ #include <net/if.h> #include <net/if_dl.h> #include <net/if_types.h> +#include <net/if_ether.h> #if defined(INET) #include <netinet/in.h> @@ -61,6 +62,11 @@ #include <net/agr/if_agrsubr.h> #include <net/agr/if_agrethervar.h> +#include "vlan.h" +#if NVLAN > 0 +#include <net/if_vlanvar.h> +#endif + void agrattach(int); static int agr_clone_create(struct if_clone *, int); @@ -81,6 +87,9 @@ static int agrport_config_promisc_callback(struct agr_port *, void *); static int agrport_config_promisc(struct agr_port *, bool); static int agrport_cleanup(struct agr_softc *, struct agr_port *); +static int agr_vlan_add(struct agr_port *, void *); +static int agr_vlan_del(struct agr_port *, void *); +static void agr_vlan_check(struct ifnet *, struct agr_softc *); static struct if_clone agr_cloner = IF_CLONE_INITIALIZER("agr", agr_clone_create, agr_clone_destroy); @@ -109,6 +118,9 @@ { struct agr_port *port; struct ifnet *ifp; +#if NVLAN > 0 + struct m_tag *mtag; +#endif port = ifp_port->if_agrprivate; KASSERT(port); @@ -128,6 +140,15 @@ } #endif +#if NVLAN > 0 + /* got a vlan packet? */ + if ((mtag = m_tag_find(m, PACKET_TAG_VLAN, NULL)) != NULL) { + /* vlan_input will call ether_input */ + vlan_input(ifp, m); + return; + } +#endif + (*ifp->if_input)(ifp, m); } @@ -213,6 +234,96 @@ * INTERNAL FUNCTIONS */ +/* + * Enable vlan hardware assist for the specified port. + */ +static int +agr_vlan_add(struct agr_port *port, void *arg) +{ + struct ifnet *ifp = port->port_ifp; + struct ethercom *ec_port = (void *)ifp; + struct ifreq ifr; + int error=0; + + if (ec_port->ec_nvlans++ == 0 && + (ec_port->ec_capabilities & ETHERCAP_VLAN_MTU) != 0) { + struct ifnet *p = port->port_ifp; + /* + * Enable Tx/Rx of VLAN-sized frames. + */ + ec_port->ec_capenable |= ETHERCAP_VLAN_MTU; + if (p->if_flags & IFF_UP) { + ifr.ifr_flags = p->if_flags; + error = (*p->if_ioctl)(p, SIOCSIFFLAGS, + (void *) &ifr); + if (error) { + if (ec_port->ec_nvlans-- == 1) + ec_port->ec_capenable &= + ~ETHERCAP_VLAN_MTU; + return (error); + } + } + } + + return error; +} + +/* + * Disable vlan hardware assist for the specified port. + */ +static int +agr_vlan_del(struct agr_port *port, void *arg) +{ + struct ethercom *ec_port = (void *)port->port_ifp; + struct ifreq ifr; + + /* Disable vlan support */ + if (ec_port->ec_nvlans-- == 1) { + /* + * Disable Tx/Rx of VLAN-sized frames. + */ + ec_port->ec_capenable &= ~ETHERCAP_VLAN_MTU; + if (port->port_ifp->if_flags & IFF_UP) { + ifr.ifr_flags = port->port_ifp->if_flags; + (void) (*port->port_ifp->if_ioctl)(port->port_ifp, + SIOCSIFFLAGS, (void *) &ifr); + } + } + + return 0; +} + + +/* + * Check for vlan attach/detach. + * ec->ec_nvlans is directly modified by the vlan driver. + * We keep a local count in sc (sc->sc_nvlans) to detect + * when the vlan driver attaches or detaches. + * Note the agr interface must be up for this to work. + */ +static void +agr_vlan_check(struct ifnet *ifp, struct agr_softc *sc) +{ + struct ethercom *ec = (void *)ifp; + int error; + + /* vlans in sync? */ + if (sc->sc_nvlans == ec->ec_nvlans) { + return; + } + + if (sc->sc_nvlans == 0) { + /* vlan added */ + error = agr_port_foreach(sc, agr_vlan_add, NULL); + sc->sc_nvlans = ec->ec_nvlans; + } else if (ec->ec_nvlans == 0) { + /* vlan removed */ + error = agr_port_foreach(sc, agr_vlan_del, NULL); + sc->sc_nvlans = 0; + } +} + + static int agr_clone_create(struct if_clone *ifc, int unit) { @@ -801,6 +912,7 @@ struct agr_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *)data; struct ifaddr *ifa = (struct ifaddr *)data; + struct ifcapreq *ifcr; struct sockaddr *sa; struct agrreq ar; int error = 0; @@ -839,6 +951,18 @@ case SIOCSIFFLAGS: agr_config_promisc(sc); + + /* Check for a change in vlan status. This ioctl is the + * only way we can tell that a vlan has attached or detached. + * Note the agr interface must be up. + */ + agr_vlan_check(ifp, sc); + break; + + case SIOCSIFCAP: + ifcr = data; + if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET) + error = 0; break; case SIOCSETAGR: Index: src/sys/net/agr/if_agrether.c diff -u src/sys/net/agr/if_agrether.c:1.6 src/sys/net/agr/if_agrether.c:1.6.36.1 --- src/sys/net/agr/if_agrether.c:1.6 Sun Aug 26 22:59:09 2007 +++ src/sys/net/agr/if_agrether.c Fri Jun 5 18:49:43 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: if_agrether.c,v 1.6 2007/08/26 22:59:09 dyoung Exp $ */ +/* $NetBSD: if_agrether.c,v 1.6.36.1 2009/06/05 18:49:43 snj Exp $ */ /*- * Copyright (c)2005 YAMAMOTO Takashi, @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_agrether.c,v 1.6 2007/08/26 22:59:09 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_agrether.c,v 1.6.36.1 2009/06/05 18:49:43 snj Exp $"); #include <sys/param.h> #include <sys/callout.h> @@ -98,6 +98,18 @@ agr_mc_init(sc, &priv->aep_multiaddrs); sc->sc_iftprivate = priv; + /* inherit ports capabilities + * XXX this really needs to be the intersection of all + * ports capabilities, not just the latest port. + * Okay if ports are the same. + */ + ifp->if_capabilities = ifp_port->if_capabilities & + (IFCAP_TSOv4 | IFCAP_TSOv6 | + IFCAP_CSUM_IPv4_Tx | IFCAP_CSUM_IPv4_Rx | + IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_TCPv4_Rx | + IFCAP_CSUM_UDPv4_Tx | IFCAP_CSUM_UDPv4_Rx | + IFCAP_CSUM_TCPv6_Tx | IFCAP_CSUM_TCPv6_Rx | + IFCAP_CSUM_UDPv6_Tx | IFCAP_CSUM_UDPv6_Rx); ether_ifattach(ifp, CLLADDR(ifp_port->if_sadl)); ec->ec_capabilities = @@ -149,9 +161,30 @@ } ec->ec_capabilities &= ec_port->ec_capabilities | - ~(ETHERCAP_VLAN_MTU | ETHERCAP_VLAN_MTU); + ~(ETHERCAP_VLAN_MTU | ETHERCAP_VLAN_HWTAGGING); } + /* Enable vlan support */ + if ((ec->ec_nvlans > 0) && + ec_port->ec_nvlans++ == 0 && + (ec_port->ec_capabilities & ETHERCAP_VLAN_MTU) != 0) { + struct ifnet *p = port->port_ifp; + /* + * Enable Tx/Rx of VLAN-sized frames. + */ + ec_port->ec_capenable |= ETHERCAP_VLAN_MTU; + if (p->if_flags & IFF_UP) { + ifr.ifr_flags = p->if_flags; + error = (*p->if_ioctl)(p, SIOCSIFFLAGS, + (void *) &ifr); + if (error) { + if (ec_port->ec_nvlans-- == 1) + ec_port->ec_capenable &= + ~ETHERCAP_VLAN_MTU; + return (error); + } + } + } /* XXX ETHERCAP_JUMBO_MTU */ priv = malloc(sizeof(*priv), M_DEVBUF, M_WAITOK | M_ZERO); @@ -185,12 +218,27 @@ agrether_portfini(struct agr_softc *sc, struct agr_port *port) { struct ifreq ifr; + struct ethercom *ec_port = (void *)port->port_ifp; int error; if (port->port_iftprivate == NULL) { return 0; } + if (ec_port->ec_nvlans > 0) { + /* Disable vlan support */ + ec_port->ec_nvlans = 0; + /* + * Disable Tx/Rx of VLAN-sized frames. + */ + ec_port->ec_capenable &= ~ETHERCAP_VLAN_MTU; + if (port->port_ifp->if_flags & IFF_UP) { + ifr.ifr_flags = port->port_ifp->if_flags; + (void) (*port->port_ifp->if_ioctl)(port->port_ifp, + SIOCSIFFLAGS, (void *) &ifr); + } + } + memset(&ifr, 0, sizeof(ifr)); ifr.ifr_addr.sa_len = sizeof(ifr.ifr_addr); ifr.ifr_addr.sa_family = AF_UNSPEC; Index: src/sys/net/agr/if_agrvar_impl.h diff -u src/sys/net/agr/if_agrvar_impl.h:1.7 src/sys/net/agr/if_agrvar_impl.h:1.7.44.1 --- src/sys/net/agr/if_agrvar_impl.h:1.7 Sun May 20 07:57:04 2007 +++ src/sys/net/agr/if_agrvar_impl.h Fri Jun 5 18:49:43 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: if_agrvar_impl.h,v 1.7 2007/05/20 07:57:04 yamt Exp $ */ +/* $NetBSD: if_agrvar_impl.h,v 1.7.44.1 2009/06/05 18:49:43 snj Exp $ */ /*- * Copyright (c)2005 YAMAMOTO Takashi, @@ -111,6 +111,7 @@ const struct agr_iftype_ops *sc_iftop; uint32_t sc_rr_counter; /* distributor algorithm specific */ void *sc_iftprivate; + int sc_nvlans; /* number of vlans attached */ struct ifnet sc_if; /* should be the last. see agr_alloc_softc(). */ }; @@ -135,6 +136,7 @@ int agr_xmit_frame(struct ifnet *, struct mbuf *); /* XXX */ #define AGR_ROUNDROBIN(sc) (((sc)->sc_if.if_flags & IFF_LINK0) != 0) +#define AGR_STATIC(sc) (((sc)->sc_if.if_flags & IFF_LINK1) != 0) void agrtimer_init(struct agr_softc *); void agrtimer_start(struct agr_softc *);