lagg: change hash logic to generate the same value

when pairs of source and destination are the same
This commit is contained in:
yamaguchi 2021-10-22 06:20:47 +00:00
parent 317dcfdb56
commit e903d516ab
1 changed files with 36 additions and 34 deletions

View File

@ -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 <reyk@openbsd.org> * Copyright (c) 2005, 2006 Reyk Floeter <reyk@openbsd.org>
@ -20,7 +20,7 @@
*/ */
#include <sys/cdefs.h> #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 #ifdef _KERNEL_OPT
#include "opt_inet.h" #include "opt_inet.h"
@ -876,7 +876,7 @@ lagg_hashmbuf(struct lagg_softc *sc, struct mbuf *m)
const struct ip6_hdr *ip6; const struct ip6_hdr *ip6;
const struct tcphdr *th; const struct tcphdr *th;
const struct udphdr *uh; const struct udphdr *uh;
uint32_t hash = HASH32_BUF_INIT; uint32_t hash, hash_src, hash_dst;
uint32_t flowlabel; uint32_t flowlabel;
uint16_t etype, vlantag; uint16_t etype, vlantag;
uint8_t proto; uint8_t proto;
@ -884,9 +884,17 @@ lagg_hashmbuf(struct lagg_softc *sc, struct mbuf *m)
KASSERT(ISSET(m->m_flags, M_PKTHDR)); 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); eh = lagg_m_extract(m, 0, sizeof(*eh), &buf);
if (eh == NULL) { if (eh == NULL) {
return hash; goto out;
} }
off = ETHER_HDR_LEN; off = ETHER_HDR_LEN;
etype = ntohs(eh->ether_type); etype = ntohs(eh->ether_type);
@ -894,7 +902,7 @@ lagg_hashmbuf(struct lagg_softc *sc, struct mbuf *m)
if (etype == ETHERTYPE_VLAN) { if (etype == ETHERTYPE_VLAN) {
evl = lagg_m_extract(m, 0, sizeof(*evl), &buf); evl = lagg_m_extract(m, 0, sizeof(*evl), &buf);
if (evl == NULL) { if (evl == NULL) {
return hash; goto out;
} }
vlantag = ntohs(evl->evl_tag); vlantag = ntohs(evl->evl_tag);
@ -907,26 +915,22 @@ lagg_hashmbuf(struct lagg_softc *sc, struct mbuf *m)
} }
if (sc->sc_hash_mac) { if (sc->sc_hash_mac) {
hash = hash32_buf(&eh->ether_dhost, LAGG_HASH_ADD(&hash_dst, eh->ether_dhost);
sizeof(eh->ether_dhost), hash); LAGG_HASH_ADD(&hash_src, eh->ether_shost);
hash = hash32_buf(&eh->ether_shost, LAGG_HASH_ADD(&hash, vlantag);
sizeof(eh->ether_shost), hash);
hash = hash32_buf(&vlantag, sizeof(vlantag), hash);
} }
switch (etype) { switch (etype) {
case ETHERTYPE_IP: case ETHERTYPE_IP:
ip = lagg_m_extract(m, off, sizeof(*ip), &buf); ip = lagg_m_extract(m, off, sizeof(*ip), &buf);
if (ip == NULL) { if (ip == NULL) {
return hash; goto out;
} }
if (sc->sc_hash_ipaddr) { if (sc->sc_hash_ipaddr) {
hash = hash32_buf(&ip->ip_src, LAGG_HASH_ADD(&hash_src, ip->ip_src);
sizeof(ip->ip_src), hash); LAGG_HASH_ADD(&hash_dst, ip->ip_dst);
hash = hash32_buf(&ip->ip_dst, LAGG_HASH_ADD(&hash, ip->ip_p);
sizeof(ip->ip_dst), hash);
hash = hash32_buf(&ip->ip_p, sizeof(ip->ip_p), hash);
} }
off += ip->ip_hl << 2; off += ip->ip_hl << 2;
proto = ip->ip_p; proto = ip->ip_p;
@ -934,22 +938,19 @@ lagg_hashmbuf(struct lagg_softc *sc, struct mbuf *m)
case ETHERTYPE_IPV6: case ETHERTYPE_IPV6:
ip6 = lagg_m_extract(m, off, sizeof(*ip6), &buf); ip6 = lagg_m_extract(m, off, sizeof(*ip6), &buf);
if (ip6 == NULL) { if (ip6 == NULL) {
return hash; goto out;
} }
if (sc->sc_hash_ip6addr) { if (sc->sc_hash_ip6addr) {
hash = hash32_buf(&ip6->ip6_src, LAGG_HASH_ADD(&hash_src, ip6->ip6_src);
sizeof(ip6->ip6_src), hash); LAGG_HASH_ADD(&hash_dst, ip6->ip6_dst);
hash = hash32_buf(&ip6->ip6_dst,
sizeof(ip6->ip6_dst), hash);
flowlabel = ip6->ip6_flow & IPV6_FLOWLABEL_MASK; flowlabel = ip6->ip6_flow & IPV6_FLOWLABEL_MASK;
hash = hash32_buf(&flowlabel, sizeof(flowlabel), hash); LAGG_HASH_ADD(&hash, flowlabel);
} }
proto = ip6->ip6_nxt; proto = ip6->ip6_nxt;
off += sizeof(*ip6); off += sizeof(*ip6);
break;
/* L4 header is not supported */
return hash;
default: default:
return hash; return hash;
} }
@ -958,31 +959,32 @@ lagg_hashmbuf(struct lagg_softc *sc, struct mbuf *m)
case IPPROTO_TCP: case IPPROTO_TCP:
th = lagg_m_extract(m, off, sizeof(*th), &buf); th = lagg_m_extract(m, off, sizeof(*th), &buf);
if (th == NULL) { if (th == NULL) {
return hash; goto out;
} }
if (sc->sc_hash_tcp) { if (sc->sc_hash_tcp) {
hash = hash32_buf(&th->th_sport, LAGG_HASH_ADD(&hash_src, th->th_sport);
sizeof(th->th_sport), hash); LAGG_HASH_ADD(&hash_dst, th->th_dport);
hash = hash32_buf(&th->th_dport,
sizeof(th->th_dport), hash);
} }
break; break;
case IPPROTO_UDP: case IPPROTO_UDP:
uh = lagg_m_extract(m, off, sizeof(*uh), &buf); uh = lagg_m_extract(m, off, sizeof(*uh), &buf);
if (uh == NULL) { if (uh == NULL) {
return hash; goto out;
} }
if (sc->sc_hash_udp) { if (sc->sc_hash_udp) {
hash = hash32_buf(&uh->uh_sport, LAGG_HASH_ADD(&hash_src, uh->uh_sport);
sizeof(uh->uh_sport), hash); LAGG_HASH_ADD(&hash_dst, uh->uh_dport);
hash = hash32_buf(&uh->uh_dport,
sizeof(uh->uh_dport), hash);
} }
break; break;
} }
out:
hash_src ^= hash_dst;
LAGG_HASH_ADD(&hash, hash_src);
#undef LAGG_HASH_ADD
return hash; return hash;
} }