From owner-svn-src-stable@FreeBSD.ORG Sat May 26 07:59:56 2012 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B2197106566B; Sat, 26 May 2012 07:59:56 +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 9B19B8FC12; Sat, 26 May 2012 07:59:56 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q4Q7xuHF060971; Sat, 26 May 2012 07:59:56 GMT (envelope-from thompsa@svn.freebsd.org) Received: (from thompsa@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q4Q7xupG060965; Sat, 26 May 2012 07:59:56 GMT (envelope-from thompsa@svn.freebsd.org) Message-Id: <201205260759.q4Q7xupG060965@svn.freebsd.org> From: Andrew Thompson Date: Sat, 26 May 2012 07:59:56 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r236057 - in stable/8: sbin/ifconfig sys/net X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 26 May 2012 07:59:56 -0000 Author: thompsa Date: Sat May 26 07:59:56 2012 New Revision: 236057 URL: http://svn.freebsd.org/changeset/base/236057 Log: MFC r232629,r232640 Add the ability to set which packet layers are used for the load balance hash calculation. Modified: stable/8/sbin/ifconfig/ifconfig.8 stable/8/sbin/ifconfig/iflagg.c stable/8/sys/net/ieee8023ad_lacp.c stable/8/sys/net/if_lagg.c stable/8/sys/net/if_lagg.h Directory Properties: stable/8/sbin/ifconfig/ (props changed) stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/boot/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/e1000/ (props changed) Modified: stable/8/sbin/ifconfig/ifconfig.8 ============================================================================== --- stable/8/sbin/ifconfig/ifconfig.8 Sat May 26 07:58:58 2012 (r236056) +++ stable/8/sbin/ifconfig/ifconfig.8 Sat May 26 07:59:56 2012 (r236057) @@ -2234,6 +2234,21 @@ Set the aggregation protocol. The default is failover. The available options are failover, fec, lacp, loadbalance, roundrobin and none. +.It Cm lagghash Ar option Ns Oo , Ns Ar option Oc +Set the packet layers to hash for aggregation protocols which load balance. +The default is +.Dq l2,l3,l4 . +The options can be combined using commas. +.Pp +.Bl -tag -width ".Cm l2" -compact +.It Cm l2 +src/dst mac address and optional vlan number. +.It Cm l3 +src/dst address for IPv4 or IPv6. +.It Cm l4 +src/dst port for TCP/UCP/SCTP. +.El +.Pp .El .Pp The following parameters are specific to IP tunnel interfaces, Modified: stable/8/sbin/ifconfig/iflagg.c ============================================================================== --- stable/8/sbin/ifconfig/iflagg.c Sat May 26 07:58:58 2012 (r236056) +++ stable/8/sbin/ifconfig/iflagg.c Sat May 26 07:59:56 2012 (r236057) @@ -81,6 +81,36 @@ setlaggproto(const char *val, int d, int err(1, "SIOCSLAGG"); } +static void +setlagghash(const char *val, int d, int s, const struct afswtch *afp) +{ + struct lagg_reqflags rf; + char *str, *tmp, *tok; + + + rf.rf_flags = 0; + str = tmp = strdup(val); + while ((tok = strsep(&tmp, ",")) != NULL) { + if (strcmp(tok, "l2") == 0) + rf.rf_flags |= LAGG_F_HASHL2; + else if (strcmp(tok, "l3") == 0) + rf.rf_flags |= LAGG_F_HASHL3; + else if (strcmp(tok, "l4") == 0) + rf.rf_flags |= LAGG_F_HASHL4; + else { + free(str); + errx(1, "Invalid lagghash option: %s", tok); + } + } + free(str); + if (rf.rf_flags == 0) + errx(1, "No lagghash options supplied"); + + strlcpy(rf.rf_ifname, name, sizeof(rf.rf_ifname)); + if (ioctl(s, SIOCSLAGGHASH, &rf)) + err(1, "SIOCSLAGGHASH"); +} + static char * lacp_format_mac(const uint8_t *mac, char *buf, size_t buflen) { @@ -115,6 +145,7 @@ lagg_status(int s) struct lagg_protos lpr[] = LAGG_PROTOS; struct lagg_reqport rp, rpbuf[LAGG_MAX_PORTS]; struct lagg_reqall ra; + struct lagg_reqflags rf; struct lacp_opreq *lp; const char *proto = ""; int i, isport = 0; @@ -132,6 +163,10 @@ lagg_status(int s) ra.ra_size = sizeof(rpbuf); ra.ra_port = rpbuf; + strlcpy(rf.rf_ifname, name, sizeof(rf.rf_ifname)); + if (ioctl(s, SIOCGLAGGFLAGS, &rf) != 0) + rf.rf_flags = 0; + if (ioctl(s, SIOCGLAGG, &ra) == 0) { lp = (struct lacp_opreq *)&ra.ra_lacpreq; @@ -143,6 +178,23 @@ lagg_status(int s) } printf("\tlaggproto %s", proto); + if (rf.rf_flags & LAGG_F_HASHMASK) { + const char *sep = ""; + + printf(" lagghash "); + if (rf.rf_flags & LAGG_F_HASHL2) { + printf("%sl2", sep); + sep = ","; + } + if (rf.rf_flags & LAGG_F_HASHL3) { + printf("%sl3", sep); + sep = ","; + } + if (rf.rf_flags & LAGG_F_HASHL4) { + printf("%sl4", sep); + sep = ","; + } + } if (isport) printf(" laggdev %s", rp.rp_ifname); putchar('\n'); @@ -174,6 +226,7 @@ static struct cmd lagg_cmds[] = { DEF_CMD_ARG("laggport", setlaggport), DEF_CMD_ARG("-laggport", unsetlaggport), DEF_CMD_ARG("laggproto", setlaggproto), + DEF_CMD_ARG("lagghash", setlagghash), }; static struct afswtch af_lagg = { .af_name = "af_lagg", Modified: stable/8/sys/net/ieee8023ad_lacp.c ============================================================================== --- stable/8/sys/net/ieee8023ad_lacp.c Sat May 26 07:58:58 2012 (r236056) +++ stable/8/sys/net/ieee8023ad_lacp.c Sat May 26 07:59:56 2012 (r236057) @@ -815,7 +815,7 @@ lacp_select_tx_port(struct lagg_softc *s if (sc->use_flowid && (m->m_flags & M_FLOWID)) hash = m->m_pkthdr.flowid; else - hash = lagg_hashmbuf(m, lsc->lsc_hashkey); + hash = lagg_hashmbuf(sc, m, lsc->lsc_hashkey); hash %= pm->pm_count; lp = pm->pm_map[hash]; Modified: stable/8/sys/net/if_lagg.c ============================================================================== --- stable/8/sys/net/if_lagg.c Sat May 26 07:58:58 2012 (r236056) +++ stable/8/sys/net/if_lagg.c Sat May 26 07:59:56 2012 (r236057) @@ -280,6 +280,8 @@ lagg_clone_create(struct if_clone *ifc, SYSCTL_ADD_INT(&sc->ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "use_flowid", CTLTYPE_INT|CTLFLAG_RW, &sc->use_flowid, sc->use_flowid, "Use flow id for load sharing"); + /* Hash all layers by default */ + sc->sc_flags = LAGG_F_HASHL2|LAGG_F_HASHL3|LAGG_F_HASHL4; sc->sc_proto = LAGG_PROTO_NONE; for (i = 0; lagg_protos[i].ti_proto != LAGG_PROTO_NONE; i++) { @@ -887,6 +889,7 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc; struct lagg_reqall *ra = (struct lagg_reqall *)data; struct lagg_reqport *rp = (struct lagg_reqport *)data, rpbuf; + struct lagg_reqflags *rf = (struct lagg_reqflags *)data; struct ifreq *ifr = (struct ifreq *)data; struct lagg_port *lp; struct ifnet *tpif; @@ -976,6 +979,22 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd } error = EPROTONOSUPPORT; break; + case SIOCGLAGGFLAGS: + rf->rf_flags = sc->sc_flags; + break; + case SIOCSLAGGHASH: + error = priv_check(td, PRIV_NET_LAGG); + if (error) + break; + if ((rf->rf_flags & LAGG_F_HASHMASK) == 0) { + error = EINVAL; + break; + } + LAGG_WLOCK(sc); + sc->sc_flags &= ~LAGG_F_HASHMASK; + sc->sc_flags |= rf->rf_flags & LAGG_F_HASHMASK; + LAGG_WUNLOCK(sc); + break; case SIOCGLAGGPORT: if (rp->rp_portname[0] == '\0' || (tpif = ifunit(rp->rp_portname)) == NULL) { @@ -1405,42 +1424,55 @@ lagg_gethdr(struct mbuf *m, u_int off, u } uint32_t -lagg_hashmbuf(struct mbuf *m, uint32_t key) +lagg_hashmbuf(struct lagg_softc *sc, struct mbuf *m, uint32_t key) { uint16_t etype; - uint32_t p = 0; + uint32_t p = key; int off; struct ether_header *eh; - struct ether_vlan_header vlanbuf; const struct ether_vlan_header *vlan; #ifdef INET const struct ip *ip; - struct ip ipbuf; + const uint32_t *ports; + int iphlen; #endif #ifdef INET6 const struct ip6_hdr *ip6; - struct ip6_hdr ip6buf; uint32_t flow; #endif + union { +#ifdef INET + struct ip ip; +#endif +#ifdef INET6 + struct ip6_hdr ip6; +#endif + struct ether_vlan_header vlan; + uint32_t port; + } buf; + off = sizeof(*eh); if (m->m_len < off) goto out; eh = mtod(m, struct ether_header *); etype = ntohs(eh->ether_type); - p = hash32_buf(&eh->ether_shost, ETHER_ADDR_LEN, key); - p = hash32_buf(&eh->ether_dhost, ETHER_ADDR_LEN, p); + if (sc->sc_flags & LAGG_F_HASHL2) { + p = hash32_buf(&eh->ether_shost, ETHER_ADDR_LEN, p); + p = hash32_buf(&eh->ether_dhost, ETHER_ADDR_LEN, p); + } /* Special handling for encapsulating VLAN frames */ - if (m->m_flags & M_VLANTAG) { + if ((m->m_flags & M_VLANTAG) && (sc->sc_flags & LAGG_F_HASHL2)) { p = hash32_buf(&m->m_pkthdr.ether_vtag, sizeof(m->m_pkthdr.ether_vtag), p); } else if (etype == ETHERTYPE_VLAN) { - vlan = lagg_gethdr(m, off, sizeof(*vlan), &vlanbuf); + vlan = lagg_gethdr(m, off, sizeof(*vlan), &buf); if (vlan == NULL) goto out; - p = hash32_buf(&vlan->evl_tag, sizeof(vlan->evl_tag), p); + if (sc->sc_flags & LAGG_F_HASHL2) + p = hash32_buf(&vlan->evl_tag, sizeof(vlan->evl_tag), p); etype = ntohs(vlan->evl_proto); off += sizeof(*vlan) - sizeof(*eh); } @@ -1448,17 +1480,37 @@ lagg_hashmbuf(struct mbuf *m, uint32_t k switch (etype) { #ifdef INET case ETHERTYPE_IP: - ip = lagg_gethdr(m, off, sizeof(*ip), &ipbuf); + ip = lagg_gethdr(m, off, sizeof(*ip), &buf); if (ip == NULL) goto out; - p = hash32_buf(&ip->ip_src, sizeof(struct in_addr), p); - p = hash32_buf(&ip->ip_dst, sizeof(struct in_addr), p); + if (sc->sc_flags & LAGG_F_HASHL3) { + p = hash32_buf(&ip->ip_src, sizeof(struct in_addr), p); + p = hash32_buf(&ip->ip_dst, sizeof(struct in_addr), p); + } + if (!(sc->sc_flags & LAGG_F_HASHL4)) + break; + switch (ip->ip_p) { + case IPPROTO_TCP: + case IPPROTO_UDP: + case IPPROTO_SCTP: + iphlen = ip->ip_hl << 2; + if (iphlen < sizeof(*ip)) + break; + off += iphlen; + ports = lagg_gethdr(m, off, sizeof(*ports), &buf); + if (ports == NULL) + break; + p = hash32_buf(ports, sizeof(*ports), p); + break; + } break; #endif #ifdef INET6 case ETHERTYPE_IPV6: - ip6 = lagg_gethdr(m, off, sizeof(*ip6), &ip6buf); + if (!(sc->sc_flags & LAGG_F_HASHL3)) + break; + ip6 = lagg_gethdr(m, off, sizeof(*ip6), &buf); if (ip6 == NULL) goto out; @@ -1688,7 +1740,7 @@ lagg_lb_start(struct lagg_softc *sc, str if (sc->use_flowid && (m->m_flags & M_FLOWID)) p = m->m_pkthdr.flowid; else - p = lagg_hashmbuf(m, lb->lb_key); + p = lagg_hashmbuf(sc, m, lb->lb_key); p %= sc->sc_count; lp = lb->lb_ports[p]; Modified: stable/8/sys/net/if_lagg.h ============================================================================== --- stable/8/sys/net/if_lagg.h Sat May 26 07:58:58 2012 (r236056) +++ stable/8/sys/net/if_lagg.h Sat May 26 07:59:56 2012 (r236057) @@ -31,6 +31,12 @@ #define LAGG_MAX_NAMESIZE 32 /* name of a protocol */ #define LAGG_MAX_STACKING 4 /* maximum number of stacked laggs */ +/* Lagg flags */ +#define LAGG_F_HASHL2 0x00000001 /* hash layer 2 */ +#define LAGG_F_HASHL3 0x00000002 /* hash layer 3 */ +#define LAGG_F_HASHL4 0x00000004 /* hash layer 4 */ +#define LAGG_F_HASHMASK 0x00000007 + /* Port flags */ #define LAGG_PORT_SLAVE 0x00000000 /* normal enslaved port */ #define LAGG_PORT_MASTER 0x00000001 /* primary port */ @@ -122,6 +128,14 @@ struct lagg_reqall { #define SIOCGLAGG _IOWR('i', 143, struct lagg_reqall) #define SIOCSLAGG _IOW('i', 144, struct lagg_reqall) +struct lagg_reqflags { + char rf_ifname[IFNAMSIZ]; /* name of the lagg */ + uint32_t rf_flags; /* lagg protocol */ +}; + +#define SIOCGLAGGFLAGS _IOWR('i', 145, struct lagg_reqflags) +#define SIOCSLAGGHASH _IOW('i', 146, struct lagg_reqflags) + #ifdef _KERNEL /* * Internal kernel part @@ -179,6 +193,7 @@ struct lagg_softc { struct ifmedia sc_media; /* media config */ caddr_t sc_psc; /* protocol data */ uint32_t sc_seq; /* sequence counter */ + uint32_t sc_flags; SLIST_HEAD(__tplhd, lagg_port) sc_ports; /* list of interfaces */ SLIST_ENTRY(lagg_softc) sc_entries; @@ -244,7 +259,7 @@ extern struct mbuf *(*lagg_input_p)(stru extern void (*lagg_linkstate_p)(struct ifnet *, int ); int lagg_enqueue(struct ifnet *, struct mbuf *); -uint32_t lagg_hashmbuf(struct mbuf *, uint32_t); +uint32_t lagg_hashmbuf(struct lagg_softc *, struct mbuf *, uint32_t); #endif /* _KERNEL */