mirror of
https://github.com/impact-eintr/netstack.git
synced 2025-10-06 13:26:49 +08:00
71 lines
1.5 KiB
Go
71 lines
1.5 KiB
Go
package hash
|
||
|
||
import (
|
||
"crypto/rand"
|
||
"encoding/binary"
|
||
"netstack/tcpip/header"
|
||
)
|
||
|
||
var hashIV = RandN32(1)[0]
|
||
|
||
// RandN32 生成 n 个加密随机 32 位数字的切片
|
||
func RandN32(n int) []uint32 {
|
||
b := make([]byte, 4*n)
|
||
if _, err := rand.Read(b); err != nil {
|
||
panic("unable to get random numbers: " + err.Error())
|
||
}
|
||
r := make([]uint32, n)
|
||
for i := range r {
|
||
r[i] = binary.LittleEndian.Uint32(b[4*i : (4*i + 4)])
|
||
}
|
||
return r
|
||
}
|
||
|
||
func Hash3Words(a, b, c, initval uint32) uint32 {
|
||
const iv = 0xdeadbeef + (3 << 2)
|
||
initval += iv
|
||
|
||
a += initval
|
||
b += initval
|
||
c += initval
|
||
|
||
c ^= b
|
||
c -= rol32(b, 14)
|
||
a ^= c
|
||
a -= rol32(c, 11)
|
||
b ^= a
|
||
b -= rol32(a, 25)
|
||
c ^= b
|
||
c -= rol32(b, 16)
|
||
a ^= c
|
||
a -= rol32(c, 4)
|
||
b ^= a
|
||
b -= rol32(a, 14)
|
||
c ^= b
|
||
c -= rol32(b, 24)
|
||
|
||
return c
|
||
}
|
||
|
||
// 根据id,源ip,目的ip和协议类型得到hash值
|
||
func IPv4FragmentHash(h header.IPv4) uint32 {
|
||
x := uint32(h.ID())<<16 | uint32(h.Protocol())
|
||
t := h.SourceAddress()
|
||
y := uint32(t[0]) | uint32(t[1])<<8 | uint32(t[2])<<16 | uint32(t[3])<<24
|
||
t = h.DestinationAddress()
|
||
z := uint32(t[0]) | uint32(t[1])<<8 | uint32(t[2])<<16 | uint32(t[3])<<24
|
||
return Hash3Words(x, y, z, hashIV)
|
||
}
|
||
|
||
func IPv6FragmentHash(h header.IPv6, f header.IPv6Fragment) uint32 {
|
||
t := h.SourceAddress()
|
||
y := uint32(t[0]) | uint32(t[1])<<8 | uint32(t[2])<<16 | uint32(t[3])<<24
|
||
t = h.DestinationAddress()
|
||
z := uint32(t[0]) | uint32(t[1])<<8 | uint32(t[2])<<16 | uint32(t[3])<<24
|
||
return Hash3Words(f.ID(), y, z, hashIV)
|
||
}
|
||
|
||
func rol32(v, shift uint32) uint32 {
|
||
return (v << shift) | (v >> ((-shift) & 31))
|
||
}
|