This commit is contained in:
bluepython508 committed 2026-10-22 12:27:19 +01:00
1 parent 3530afb854
commit 6903fcff27
2146 files changed
+112256 -190703

No files matched your search

+122 -9
View File
@@ -17,18 +17,55 @@ const (
EventMTUUpdate
)
type Device interface {
// File returns the file descriptor of the device.
// ReadPacket describes a packet read by [Reader.Read].
type ReadPacket struct {
// Offset is the starting byte offset.
Offset int
// Size is the size of the packet.
Size int
}
// ReadPacketSpacing is the number of bytes reserved before the first packet,
// between adjacent packets, and after the final packet filled by [Reader.Read].
const ReadPacketSpacing = 64
// Reader reads packets from a single queue of a [Device].
type Reader interface {
// Read reads one or more packets from the queue into slab. On return, it
// populates packets and returns the number of entries to evaluate. Those
// entries are valid even when err is non-nil. Callers must provide at least
// [Device.BatchSize] entries.
//
// Read reserves [ReadPacketSpacing] bytes before the first packet, between
// adjacent packets, and after the final packet. The contents of the reserved
// space are unspecified; the [Device] may use them while Read is executing.
// Callers must provide a slab of at least 2*[ReadPacketSpacing] bytes.
//
// Read returns [ErrTooManySegments] if packets or slab cannot accommodate
// all packets produced by the read.
Read(slab []byte, packets []ReadPacket) (n int, err error)
}
// Queue is a single read queue of a [Device]. Distinct Queues of one Device
// may be used concurrently.
//
// A [Device] implementation may return read-only Queues in addition to those
// backed by file descriptors. [MultiQueueDevice.WriteTo] is the way to
// dispatch writes to the queues that accept them.
type Queue interface {
Reader
// File returns the queue's file descriptor, or nil if the queue is not
// backed by one.
File() *os.File
}
// Read one or more packets from the Device (without any additional headers).
// On a successful read it returns the number of packets read, and sets
// packet lengths within the sizes slice. len(sizes) must be >= len(bufs).
// A nonzero offset can be used to instruct the Device on where to begin
// reading into each element of the bufs slice.
Read(bufs [][]byte, sizes []int, offset int) (n int, err error)
type Device interface {
// Queue is the Device's first queue. A [MultiQueueDevice] exposes the
// rest.
Queue
// Write one or more packets to the device (without any additional headers).
// Write one or more packets to the Device.
// On a successful write it returns the number of packets written. A nonzero
// offset can be used to instruct the Device on where to begin writing from
// each packet contained within the bufs slice.
@@ -52,6 +89,82 @@ type Device interface {
BatchSize() int
}
// MultiQueueDevice is a Device that exposes more than one kernel queue, each
// backed by its own file descriptor. The count is fixed for the Device's
// lifetime.
type MultiQueueDevice interface {
Device
// Queues returns one [Queue] per kernel queue with at least one entry.
// Entry 0 is equivalent to the Device's own [Reader.Read].
Queues() []Queue
// WriteTo is [Device.Write] directed at one of the Device's write queues.
// Data written with the same flow id lands on the same write queue.
WriteTo(flow int, bufs [][]byte, offset int) (int, error)
}
// WriteToOf returns dev's queue-aware write, or [Device.Write] for a Device
// with one write queue.
func WriteToOf(dev Device) func(flow int, bufs [][]byte, offset int) (int, error) {
if w, ok := dev.(MultiQueueDevice); ok {
return w.WriteTo
}
return func(_ int, bufs [][]byte, offset int) (int, error) {
return dev.Write(bufs, offset)
}
}
// QueuesOf returns dev's queues, or dev itself as the single queue. The result
// always has at least one entry.
func QueuesOf(dev Device) []Queue {
if mq, ok := dev.(MultiQueueDevice); ok {
if qs := mq.Queues(); len(qs) > 0 {
return qs
}
}
return []Queue{dev}
}
// An Option configures a [Device] at creation time.
type Option interface {
apply(*config)
}
type optionFunc func(*config)
func (f optionFunc) apply(config *config) {
f(config)
}
type config struct {
queues int // Tun fd's in IFF_MULTI_QUEUE group to open.
}
func defaultConfig() config {
return config{
queues: 1,
}
}
// WithQueues requests that the [Device] be created with n queues. n must be at
// least 1.
//
// Only Linux implements multiqueue TUN. Errors are returned if more queues
// are requested than the Linux kernel supports (at the time of writing,
// v7.0 has MAX_TAP_QUEUES at 256) or if the per-process limit was reached.
//
// Implementations may choose to return more read queues than was requested.
// Callers must consult [QueuesOf] rather than assume they got n.
//
// EXPERIMENTAL: Current implementation introduces nonce reordering with more
// than one queue.
func WithQueues(n int) Option {
return optionFunc(func(config *config) {
config.queues = n
})
}
// GRODevice is a Device extended with methods for disabling GRO. Certain OS
// versions may have offload bugs. Where these bugs negatively impact throughput
// or break connectivity entirely we can use these methods to disable the