Documentation
¶
Overview ¶
Package pool holds the free-frame list shared by packetio backends.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Frames ¶
type Frames struct {
// contains filtered or unexported fields
}
Frames is a LIFO free list of frame offsets for one direction of one queue.
It is not synchronized, by design. Each pool belongs to exactly one goroutine, and pools that a receive goroutine and a transmit goroutine touch concurrently must cover disjoint ranges of the region. That is what lets the packet path run without a lock. go-afxdp learned this the hard way: sharing one free list across both directions handed the same frame to a fill and a transmit at once, which corrupts packets on the wire and is invisible in local counters.
A LIFO rather than a FIFO because the most recently freed frame is the one most likely to still be in cache.
func New ¶
New builds a pool holding count frames of frameSize bytes each, starting at frame index base. The frames cover [base*frameSize, (base+count)*frameSize) of the region.
func (*Frames) Base ¶
Base rounds a descriptor address down to the start of its frame. Frames are laid out at fixed multiples of frameSize from the start of the region, so this recovers the frame a descriptor belongs to whatever headroom it used.
The frame size is a power of two, so this is a mask. It is called once per packet on the way back to the free list, where a divide would be pure waste.
func (*Frames) Owns ¶
Owns reports whether addr falls inside a frame of this pool. It is for assertions and tests, not for the packet path.
func (*Frames) Pop ¶
Pop removes up to n frames and appends their offsets to dst, returning the grown slice. It appends fewer than n when fewer are free, and allocates nothing when dst has the capacity.
func (*Frames) Push ¶
Push returns one frame. addr must be the start of a frame of this pool: callers hold a descriptor whose Addr may point past the frame start, so they round down with Base first.
A push is refused and counted, rather than appended, when the frame is not this pool's, when it is not the start of a frame, when it is already on the free list, or when the pool is already full. Every one of them is a caller returning a frame twice or to the wrong queue, and every one would otherwise hand a frame to two owners -- the corruption that is invisible in every other counter. A shift and a mask; not worth leaving out.