diff options
Diffstat (limited to 'pkg/tcpip/header/checksum.go')
-rw-r--r-- | pkg/tcpip/header/checksum.go | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/pkg/tcpip/header/checksum.go b/pkg/tcpip/header/checksum.go index 12f208fde..2c2fcbd9b 100644 --- a/pkg/tcpip/header/checksum.go +++ b/pkg/tcpip/header/checksum.go @@ -18,12 +18,11 @@ package header import ( "gvisor.googlesource.com/gvisor/pkg/tcpip" + "gvisor.googlesource.com/gvisor/pkg/tcpip/buffer" ) -// Checksum calculates the checksum (as defined in RFC 1071) of the bytes in the -// given byte array. -func Checksum(buf []byte, initial uint16) uint16 { - v := uint32(initial) +func calculateChecksum(buf []byte, initial uint32) uint16 { + v := initial l := len(buf) if l&1 != 0 { @@ -38,8 +37,40 @@ func Checksum(buf []byte, initial uint16) uint16 { return ChecksumCombine(uint16(v), uint16(v>>16)) } +// Checksum calculates the checksum (as defined in RFC 1071) of the bytes in the +// given byte array. +// +// The initial checksum must have been computed on an even number of bytes. +func Checksum(buf []byte, initial uint16) uint16 { + return calculateChecksum(buf, uint32(initial)) +} + +// ChecksumVV calculates the checksum (as defined in RFC 1071) of the bytes in +// the given VectorizedView. +// +// The initial checksum must have been computed on an even number of bytes. +func ChecksumVV(vv buffer.VectorisedView, initial uint16) uint16 { + var odd bool + sum := initial + for _, v := range vv.Views() { + if len(v) == 0 { + continue + } + s := uint32(sum) + if odd { + s += uint32(v[0]) + v = v[1:] + } + odd = len(v)&1 != 0 + sum = calculateChecksum(v, s) + } + return sum +} + // ChecksumCombine combines the two uint16 to form their checksum. This is done // by adding them and the carry. +// +// Note that checksum a must have been computed on an even number of bytes. func ChecksumCombine(a, b uint16) uint16 { v := uint32(a) + uint32(b) return uint16(v + v>>16) |