slackhq/nebula · error

csum offsets out of range: start=%d offset=%d len=%d

Error message

csum offsets out of range: start=%d offset=%d len=%d

What it means

Range check in FinishChecksum: CsumStart+CsumOffset+2 exceeds the packet length, so the 16-bit checksum field the kernel asked us to finalize lies outside the buffer. The message reports start, offset, and length; it means the virtio header offsets and the actual segment size disagree.

Source

Thrown at overlay/tio/virtio/segment_linux.go:419

		}
		binary.BigEndian.PutUint16(seg[csumStart+udpChecksumOff:csumStart+udpChecksumOff+2], csum)

		if err := yield(seg); err != nil {
			return err
		}
	}

	return nil
}

// FinishChecksum computes the L4 checksum for a non-GSO packet that the kernel handed us with NEEDS_CSUM set.
// CsumStart / CsumOffset point at the 16-bit checksum field.
// We zero it, fold a full sum from the partial one that the kernel provided, and store the result.
func FinishChecksum(seg []byte, hdr Hdr) error {
	cs := int(hdr.CsumStart)
	co := int(hdr.CsumOffset)
	if cs+co+2 > len(seg) {
		return fmt.Errorf("csum offsets out of range: start=%d offset=%d len=%d", cs, co, len(seg))
	}
	// The kernel stores a partial pseudo-header sum at [cs+co:]; sum over the
	// L4 region starting at cs, folding the prior partial in as the seed.
	partial := binary.BigEndian.Uint16(seg[cs+co : cs+co+2])
	seg[cs+co] = 0
	seg[cs+co+1] = 0
	csum := ^checksum.Checksum(seg[cs:], partial)
	// RFC 768: UDP transmits a computed zero as all ones, since all-zero is the reserved "no checksum" value.
	if co == udpChecksumOff && csum == 0 {
		csum = 0xffff
	}
	binary.BigEndian.PutUint16(seg[cs+co:cs+co+2], csum)
	return nil
}

// foldComplement folds a 32-bit one's-complement partial sum to 16 bits and
// complements it, yielding the on-wire Internet checksum value.
func foldComplement(sum uint32) uint16 {

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Drop the malformed segment
  2. Check vnet header size negotiation (VIRTIO_NET_HDR size vs TUNSETOFFLOAD)
  3. Log hdr and seg length to find which peer/kernel produces the bad offsets
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at overlay/tio/virtio/segment_linux.go:419 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/679d2382240438eb. Report an issue: GitHub.