slackhq/nebula · error
gso_size is zero
Error message
gso_size is zero
What it means
SegmentTCP walks a TSO/GSO superpacket and needs a nonzero gsoSize to compute each segment boundary (offset i*gsoSize). A zero gso_size would produce infinite/invalid segmentation, so the function rejects it up front with this error.
Source
Thrown at overlay/tio/virtio/segment_linux.go:216
flags := uint16(pkt[csumStart+tcpFlagsOff])
sum := uint32(checksum.Checksum(pkt[csumStart:headerLen], 0))
sum += uint32(^uint16(seq >> 16))
sum += uint32(^uint16(seq))
sum += uint32(^flags)
sum += uint32(^binary.BigEndian.Uint16(pkt[csumStart+tcpChecksumOff : csumStart+tcpChecksumOff+2]))
sum = (sum & 0xffff) + (sum >> 16)
sum = (sum & 0xffff) + (sum >> 16)
return sum
}
// SegmentTCP walks a TSO superpacket pkt, yielding each segment as a slice into pkt.
// Per-segment plaintext is laid out by stamping a copy of the original L3+L4 header into pkt at offset i*gsoSize,
// where it sits immediately before that segment's payload chunk in the original buffer.
// pkt is consumed by this call and must not be inspected by the caller after the final yield.
func SegmentTCP(pkt []byte, hdrLenU, csumStartU, gsoSizeU uint16, yield func(seg []byte) error) error {
if gsoSizeU == 0 {
return fmt.Errorf("gso_size is zero")
}
if csumStartU == 0 {
return fmt.Errorf("csum_start is zero")
}
headerLen := int(hdrLenU)
csumStart := int(csumStartU)
if headerLen > maxSegHdrLen {
return fmt.Errorf("header len %d exceeds max %d", headerLen, maxSegHdrLen)
}
isV4 := pkt[0]>>4 == 4
tcpHdrLen := int(pkt[csumStart+tcpDataOffOff]>>4) * 4
payLen := len(pkt) - headerLen
gsoSize := int(gsoSizeU)
numSeg := segCount(payLen, gsoSize)
origSeq := binary.BigEndian.Uint32(pkt[csumStart+tcpSeqOff : csumStart+tcpSeqOff+4])View on GitHub (pinned to dd8f660c0a)
Solutions
- Check the virtio-net header's gso_size before calling; if it is 0, send the packet through unsegmented instead.
- Verify you are reading gso_size at the correct offset for the header version (with/without num_buffers, little-endian).
- Ensure the packet really is a GSO superpacket (mss/gso info present) before invoking SegmentTCP.
- Guard the call: if gsoSizeU == 0 { return pkt unchanged }.
Example fix
// before
err := seg.SegmentTCP(pkt, hdrLen, csumStart, gsoHdr.GsoSize, yield) // GsoSize may be 0
// after
if gsoHdr.GsoSize == 0 {
return yield(pkt) // not a GSO packet; handle as single segment
}
err := seg.SegmentTCP(pkt, hdrLen, csumStart, gsoHdr.GsoSize, yield) Defensive patterns
Strategy: validation
Validate before calling
func canSegmentTCP(gsoSize, csumStart, hdrLen uint16) bool {
return gsoSize > 0 && csumStart > 0 && hdrLen <= 128
}
// if !canSegmentTCP(gsoHdr.GsoSize, gsoHdr.CsumStart, hdrLen) { handle as plain packet } Type guard
func isGsoTCP(vhdr VirtioNetHdr) bool { return vhdr.GsoSize > 0 && vhdr.CsumStart > 0 } Try / catch
err := segmenter.SegmentTCP(pkt, hdrLen, csumStart, gsoSize, yield)
if err != nil {
if strings.Contains(err.Error(), "gso_size is zero") {
return yield(pkt) // fall back to unsegmented delivery
}
return err
} Prevention
- Only call SegmentTCP when the virtio-net header reports GSO (gso_size > 0).
- Validate gso_size right after parsing the virtio-net header, before any segmentation work.
- Use the same struct/offsets as the kernel (check VIRTIO_F_VERSION_1 / endian) when reading gso_size.
- Fall back to delivering the superpacket unsegmented when GSO metadata is absent.
When it happens
Trigger: Calling SegmentTCP with gsoSizeU == 0 — typically because the virtio-net header's gso_size field was not populated (packet not actually GSO), or the caller read the field from the wrong struct offset and got 0.
Common situations: Passing a non-GSO (ordinary) packet to the segmentation path; reading gso_size from an unparsed or zeroed virtio-net header; a driver/kernel path that skipped TSO so gso_size stayed 0; copying only part of the virtio-net header.
Related errors
- csum_start is zero
- header len %d exceeds max %d
- queue set already closed
- errPacketTooShort
- packet is too short
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/c0b32d4aabf84d5a.
Report an issue: GitHub.