I'm wondering what reception this will get. It feeds TCP/UDP port numbers into the hash for trunk(4) load balancing, so connections between a single pair of hosts will get distributed across NICs. Taken from FreeBSD r232629, they also added SIOC[CS]LAGGHASH ioctls so that the hash type can be configured in ifconfig (l2/l3/l4), I haven't done that but could if there's no general objection to this.
This method is used on some switches too (e.g. "trunk-load-balance L4-based" on HP 2530 and 5400zl). Index: if_trunk.c =================================================================== RCS file: /cvs/src/sys/net/if_trunk.c,v retrieving revision 1.93 diff -u -p -r1.93 if_trunk.c --- if_trunk.c 4 Dec 2014 00:01:53 -0000 1.93 +++ if_trunk.c 11 Dec 2014 23:45:20 -0000 @@ -978,12 +978,23 @@ trunk_hashmbuf(struct mbuf *m, SIPHASH_K int off; struct ether_header *eh; #ifdef INET - struct ip *ip, ipbuf; + struct ip *ip; + u_int32_t *ports; + int iphlen; #endif #ifdef INET6 u_int32_t flow; struct ip6_hdr *ip6, ip6buf; #endif + union { +#ifdef INET + struct ip ip; +#endif +#ifdef INET6 + struct ip6_hdr ip6; +#endif + uint32_t port; + } buf; SIPHASH_CTX ctx; SipHash24_Init(&ctx, key); @@ -1013,10 +1024,25 @@ trunk_hashmbuf(struct mbuf *m, SIPHASH_K #ifdef INET case ETHERTYPE_IP: if ((ip = (struct ip *) - trunk_gethdr(m, off, sizeof(*ip), &ipbuf)) == NULL) + trunk_gethdr(m, off, sizeof(*ip), &buf)) == NULL) return (p); SipHash24_Update(&ctx, &ip->ip_src, sizeof(struct in_addr)); SipHash24_Update(&ctx, &ip->ip_dst, sizeof(struct in_addr)); + + /* l4 hash */ + switch (ip->ip_p) { + case IPPROTO_TCP: + case IPPROTO_UDP: + iphlen = ip->ip_hl << 2; + if (iphlen < sizeof(*ip)) + break; + off += iphlen; + ports = (u_int32_t *) trunk_gethdr(m, off, sizeof(*ports), &buf); + if (ports == NULL) + break; + SipHash24_Update(&ctx, ports, sizeof(*ports)); + break; + } break; #endif #ifdef INET6