package tio import ( "io" ) // QueueSet holds one or many Queue objects and helps close them in an orderly way. type QueueSet interface { io.Closer Queues() []Queue // Add takes a tun fd, adds it to the set, and prepares it for use as a Queue. Add(fd int) error } // Capabilities advertises which kernel offload features a Queue // successfully negotiated. Callers consult this to decide which coalescers // to wire onto the write path — a Queue without TSO can't usefully accept a // TCPCoalescer, and a Queue without USO can't accept a UDPCoalescer. type Capabilities struct { // TSO means the FD was opened with IFF_VNET_HDR and the kernel agreed // to TUN_F_TSO4|TSO6 — i.e. WriteGSO with GSOProtoTCP is safe. TSO bool // USO means the kernel additionally agreed to TUN_F_USO4|USO6, so // WriteGSO with GSOProtoUDP is safe. Linux ≥ 6.2. USO bool } // Queue is a readable/writable Poll queue. One Queue is driven by a single // read goroutine plus a single writer (see Write below). type Queue interface { io.Closer // Read returns one or more packets. The returned Packet.Bytes slices // are borrowed from the Queue's internal buffer and are only valid // until the next Read or Close on this Queue - callers must encrypt // or copy each slice before the next call. A Packet may carry a // GSO/USO superpacket (see GSOInfo); when GSO.IsSuperpacket() is // true the caller must segment Bytes before treating it as a single // IP datagram. Not safe for concurrent Reads. Read() ([]Packet, error) // Write emits a single packet on the plaintext (outside→inside) // delivery path. Not safe for concurrent Writes. Write(p []byte) (int, error) } // Packet is the unit Queue.Read returns. Bytes points into the queue's // internal buffer and is only valid until the next Read or Close on the // queue that produced it. GSO is the zero value for an already-segmented // IP datagram; when non-zero it describes a kernel-supplied TSO/USO // superpacket the caller must segment before consuming. type Packet struct { Bytes []byte GSO GSOInfo } // GSOInfo describes a kernel-supplied superpacket sitting in Packet.Bytes. // The zero value means "not a superpacket" — Bytes is one regular IP // datagram and no segmentation is required. type GSOInfo struct { // Size is the GSO segment size: max payload bytes per segment // (== TCP MSS for TSO, == UDP payload chunk for USO). Zero means // not a superpacket. Size uint16 // HdrLen is the total L3+L4 header length within Bytes (already // corrected via correctHdrLen, so safe to slice on). HdrLen uint16 // CsumStart is the L4 header offset inside Bytes (== L3 header // length). CsumStart uint16 // Proto picks the L4 protocol (TCP or UDP) so the segmenter knows // which checksum/header layout to apply. Proto GSOProto } // IsSuperpacket reports whether g describes a multi-segment GSO/USO // superpacket that needs segmentation before its bytes can be encrypted // and sent on the wire. func (g GSOInfo) IsSuperpacket() bool { return g.Size > 0 } // Clone returns a Packet whose Bytes is a freshly allocated copy of p.Bytes, // safe to retain past the next Read or Close on the originating Queue. // GSO metadata is copied verbatim. Use this only when a caller genuinely // needs to outlive the borrowed-slice contract — the hot path reads should // continue to consume the borrow synchronously to avoid the allocation. func (p Packet) Clone() Packet { if p.Bytes == nil { return p } cp := make([]byte, len(p.Bytes)) copy(cp, p.Bytes) return Packet{Bytes: cp, GSO: p.GSO} } // CapsProvider is an optional interface implemented by Queues that // successfully negotiated kernel offload features at open time. Callers // pick a write-path coalescer based on the result. Queues that don't // implement it are treated as having no offload capability — callers must // fall back to plain per-packet writes. type CapsProvider interface { Capabilities() Capabilities } // QueueCapabilities returns q's negotiated offload capabilities, or the // zero value when q does not advertise any. func QueueCapabilities(q Queue) Capabilities { if cp, ok := q.(CapsProvider); ok { return cp.Capabilities() } return Capabilities{} } // GSOProto selects the L4 protocol for a GSO superpacket. Determines which // VIRTIO_NET_HDR_GSO_* type the writer stamps and which checksum offset // inside the transport header virtio NEEDS_CSUM expects. type GSOProto uint8 const ( GSOProtoNone GSOProto = iota GSOProtoTCP GSOProtoUDP )