diff --git a/pkg/tcpip/header/checksum.go b/pkg/tcpip/header/checksum.go index 1cdda6b90..060b4a86c 100644 --- a/pkg/tcpip/header/checksum.go +++ b/pkg/tcpip/header/checksum.go @@ -57,6 +57,9 @@ func checksumUpdate2ByteAlignedUint16(xsum, old, new uint16) uint16 { // checksum C, the new checksum C' is: // // C' = C + (-m) + m' = C + (m' - m) + if old == new { + return xsum + } return checksum.Combine(xsum, checksum.Combine(new, ^old)) } diff --git a/pkg/tcpip/header/checksum_test.go b/pkg/tcpip/header/checksum_test.go index 984508d32..0776f58b1 100644 --- a/pkg/tcpip/header/checksum_test.go +++ b/pkg/tcpip/header/checksum_test.go @@ -17,6 +17,7 @@ package header_test import ( + "bytes" "fmt" "math/rand" "sync" @@ -89,6 +90,24 @@ func TestICMPv4Checksum(t *testing.T) { }, want, fmt.Sprintf("header: {% x} data {% x}", h, b.Flatten())) } +func TestICMPv4ChecksumUpdate(t *testing.T) { + const icmpIdent = 0 + + data := make([]byte, header.ICMPv4MinimumSize) + h := header.ICMPv4(data) + h.SetType(header.ICMPv4EchoReply) + h.SetCode(header.ICMPv4UnusedCode) + h.SetIdent(icmpIdent) + h.SetChecksum(^checksum.Checksum(data, 0)) + + updated := header.ICMPv4(bytes.Clone(data)) + // Perform an incremental checksum update where we aren't actually changing the ID. + updated.SetIdentWithChecksumUpdate(icmpIdent) + if updated.Checksum() != h.Checksum() { + t.Errorf("got updated.Checksum() = %x, want = %x", updated.Checksum(), h.Checksum()) + } +} + func TestICMPv6Checksum(t *testing.T) { rnd := rand.New(rand.NewSource(42))