Module Name: src Committed By: yamaguchi Date: Fri Oct 22 06:20:47 UTC 2021
Modified Files: src/sys/net/lagg: if_lagg.c Log Message: lagg: change hash logic to generate the same value when pairs of source and destination are the same To generate a diff of this commit: cvs rdiff -u -r1.16 -r1.17 src/sys/net/lagg/if_lagg.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/net/lagg/if_lagg.c diff -u src/sys/net/lagg/if_lagg.c:1.16 src/sys/net/lagg/if_lagg.c:1.17 --- src/sys/net/lagg/if_lagg.c:1.16 Tue Oct 19 08:02:42 2021 +++ src/sys/net/lagg/if_lagg.c Fri Oct 22 06:20:47 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: if_lagg.c,v 1.16 2021/10/19 08:02:42 yamaguchi Exp $ */ +/* $NetBSD: if_lagg.c,v 1.17 2021/10/22 06:20:47 yamaguchi Exp $ */ /* * Copyright (c) 2005, 2006 Reyk Floeter <r...@openbsd.org> @@ -20,7 +20,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.16 2021/10/19 08:02:42 yamaguchi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.17 2021/10/22 06:20:47 yamaguchi Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -876,7 +876,7 @@ lagg_hashmbuf(struct lagg_softc *sc, str const struct ip6_hdr *ip6; const struct tcphdr *th; const struct udphdr *uh; - uint32_t hash = HASH32_BUF_INIT; + uint32_t hash, hash_src, hash_dst; uint32_t flowlabel; uint16_t etype, vlantag; uint8_t proto; @@ -884,9 +884,17 @@ lagg_hashmbuf(struct lagg_softc *sc, str KASSERT(ISSET(m->m_flags, M_PKTHDR)); + hash = HASH32_BUF_INIT; + hash_src = HASH32_BUF_INIT; + hash_dst = HASH32_BUF_INIT; + +#define LAGG_HASH_ADD(hp, v) do { \ + *(hp) = hash32_buf(&(v), sizeof(v), *(hp)); \ +} while(0) + eh = lagg_m_extract(m, 0, sizeof(*eh), &buf); if (eh == NULL) { - return hash; + goto out; } off = ETHER_HDR_LEN; etype = ntohs(eh->ether_type); @@ -894,7 +902,7 @@ lagg_hashmbuf(struct lagg_softc *sc, str if (etype == ETHERTYPE_VLAN) { evl = lagg_m_extract(m, 0, sizeof(*evl), &buf); if (evl == NULL) { - return hash; + goto out; } vlantag = ntohs(evl->evl_tag); @@ -907,26 +915,22 @@ lagg_hashmbuf(struct lagg_softc *sc, str } if (sc->sc_hash_mac) { - hash = hash32_buf(&eh->ether_dhost, - sizeof(eh->ether_dhost), hash); - hash = hash32_buf(&eh->ether_shost, - sizeof(eh->ether_shost), hash); - hash = hash32_buf(&vlantag, sizeof(vlantag), hash); + LAGG_HASH_ADD(&hash_dst, eh->ether_dhost); + LAGG_HASH_ADD(&hash_src, eh->ether_shost); + LAGG_HASH_ADD(&hash, vlantag); } switch (etype) { case ETHERTYPE_IP: ip = lagg_m_extract(m, off, sizeof(*ip), &buf); if (ip == NULL) { - return hash; + goto out; } if (sc->sc_hash_ipaddr) { - hash = hash32_buf(&ip->ip_src, - sizeof(ip->ip_src), hash); - hash = hash32_buf(&ip->ip_dst, - sizeof(ip->ip_dst), hash); - hash = hash32_buf(&ip->ip_p, sizeof(ip->ip_p), hash); + LAGG_HASH_ADD(&hash_src, ip->ip_src); + LAGG_HASH_ADD(&hash_dst, ip->ip_dst); + LAGG_HASH_ADD(&hash, ip->ip_p); } off += ip->ip_hl << 2; proto = ip->ip_p; @@ -934,22 +938,19 @@ lagg_hashmbuf(struct lagg_softc *sc, str case ETHERTYPE_IPV6: ip6 = lagg_m_extract(m, off, sizeof(*ip6), &buf); if (ip6 == NULL) { - return hash; + goto out; } if (sc->sc_hash_ip6addr) { - hash = hash32_buf(&ip6->ip6_src, - sizeof(ip6->ip6_src), hash); - hash = hash32_buf(&ip6->ip6_dst, - sizeof(ip6->ip6_dst), hash); + LAGG_HASH_ADD(&hash_src, ip6->ip6_src); + LAGG_HASH_ADD(&hash_dst, ip6->ip6_dst); flowlabel = ip6->ip6_flow & IPV6_FLOWLABEL_MASK; - hash = hash32_buf(&flowlabel, sizeof(flowlabel), hash); + LAGG_HASH_ADD(&hash, flowlabel); } proto = ip6->ip6_nxt; off += sizeof(*ip6); + break; - /* L4 header is not supported */ - return hash; default: return hash; } @@ -958,31 +959,32 @@ lagg_hashmbuf(struct lagg_softc *sc, str case IPPROTO_TCP: th = lagg_m_extract(m, off, sizeof(*th), &buf); if (th == NULL) { - return hash; + goto out; } if (sc->sc_hash_tcp) { - hash = hash32_buf(&th->th_sport, - sizeof(th->th_sport), hash); - hash = hash32_buf(&th->th_dport, - sizeof(th->th_dport), hash); + LAGG_HASH_ADD(&hash_src, th->th_sport); + LAGG_HASH_ADD(&hash_dst, th->th_dport); } break; case IPPROTO_UDP: uh = lagg_m_extract(m, off, sizeof(*uh), &buf); if (uh == NULL) { - return hash; + goto out; } if (sc->sc_hash_udp) { - hash = hash32_buf(&uh->uh_sport, - sizeof(uh->uh_sport), hash); - hash = hash32_buf(&uh->uh_dport, - sizeof(uh->uh_dport), hash); + LAGG_HASH_ADD(&hash_src, uh->uh_sport); + LAGG_HASH_ADD(&hash_dst, uh->uh_dport); } break; } +out: + hash_src ^= hash_dst; + LAGG_HASH_ADD(&hash, hash_src); +#undef LAGG_HASH_ADD + return hash; }