net/traffic: switch rendezvous hashing from SHA256 to FNV-1a (#19821)

In PR tailscale/corp#30448, we originally decided to break ties using
SHA256 for our rendezvous hashing algorithm. Now that we’ve had some
experience with it, we think that FNV-1a is a better choice. It
distributes bits evenly, it’s much faster, and it doesn’t need to be
cryptographically secure. The FNV designers recommend FNV-1a over the
deprecated FNV-1.

This PR makes the switch and updates the related tests, since changing
the algorithm changes which stable pick gets selected. As of 2026-05,
this is the best time to make this change, since there are almost no
clients in the wild with traffic steering enabled.

Updates #17366
Updates tailscale/corp#29964
Updates tailscale/corp#29966
Updates tailscale/corp#33033

Signed-off-by: Simon Law <sfllaw@tailscale.com>
This commit is contained in:
Simon Law
2026-05-21 10:11:59 -07:00
committed by GitHub
parent aa5da2e5f2
commit 7dabebc691
8 changed files with 22 additions and 8 deletions
+11 -3
View File
@@ -7,8 +7,8 @@ package traffic
import (
"cmp"
"crypto/sha256"
"encoding/binary"
"hash/fnv"
"iter"
"maps"
"slices"
@@ -107,8 +107,16 @@ func MakeRendezvousHasher(seed tailcfg.NodeID) NodeHasher {
var b [16]byte
en.PutUint64(b[:], uint64(seed))
en.PutUint64(b[8:], uint64(n))
v := sha256.Sum256(b[:])
return en.Uint64(v[:])
// FNV-1a is more modern and distributes bits more evenly,
// so it is recommended by the designers.
//
// Note that we dont use a global hasher and h.Reset
// because this closure could be called concurrently.
// This is cheap because hash/fnv doesnt need to allocate.
h := fnv.New64a()
h.Write(b[:])
return h.Sum64()
}
}