github.com/koomox/wireguard-go@v0.0.0-20230722134753-17a50b2f22a3/tun/checksum.go (about)

     1  package tun
     2  
     3  import "encoding/binary"
     4  
     5  // TODO: Explore SIMD and/or other assembly optimizations.
     6  func checksumNoFold(b []byte, initial uint64) uint64 {
     7  	ac := initial
     8  	i := 0
     9  	n := len(b)
    10  	for n >= 4 {
    11  		ac += uint64(binary.BigEndian.Uint32(b[i : i+4]))
    12  		n -= 4
    13  		i += 4
    14  	}
    15  	for n >= 2 {
    16  		ac += uint64(binary.BigEndian.Uint16(b[i : i+2]))
    17  		n -= 2
    18  		i += 2
    19  	}
    20  	if n == 1 {
    21  		ac += uint64(b[i]) << 8
    22  	}
    23  	return ac
    24  }
    25  
    26  func checksum(b []byte, initial uint64) uint16 {
    27  	ac := checksumNoFold(b, initial)
    28  	ac = (ac >> 16) + (ac & 0xffff)
    29  	ac = (ac >> 16) + (ac & 0xffff)
    30  	ac = (ac >> 16) + (ac & 0xffff)
    31  	ac = (ac >> 16) + (ac & 0xffff)
    32  	return uint16(ac)
    33  }
    34  
    35  func pseudoHeaderChecksumNoFold(protocol uint8, srcAddr, dstAddr []byte, totalLen uint16) uint64 {
    36  	sum := checksumNoFold(srcAddr, 0)
    37  	sum = checksumNoFold(dstAddr, sum)
    38  	sum = checksumNoFold([]byte{0, protocol}, sum)
    39  	tmp := make([]byte, 2)
    40  	binary.BigEndian.PutUint16(tmp, totalLen)
    41  	return checksumNoFold(tmp, sum)
    42  }