mirror of
https://github.com/slackhq/nebula.git
synced 2026-05-11 14:42:02 -07:00
70 lines
2 KiB
Go
70 lines
2 KiB
Go
package nebula
|
|
|
|
import "net/netip"
|
|
|
|
// sendBatchCap is the maximum number of encrypted packets accumulated before a
|
|
// flush is forced. TSO superpackets segment to at most ~45 packets on
|
|
// reasonable MTUs, so 128 leaves headroom without bloating the backing
|
|
// allocation.
|
|
const sendBatchCap = 128
|
|
|
|
// sendBatch accumulates encrypted UDP packets for a single sendmmsg flush.
|
|
// One sendBatch is owned by each listenIn goroutine; no locking is needed.
|
|
// The backing storage holds up to batchCap packets of slotCap bytes each;
|
|
// bufs and dsts are parallel slices of committed slots.
|
|
type sendBatch struct {
|
|
bufs [][]byte
|
|
dsts []netip.AddrPort
|
|
backing []byte
|
|
slotCap int
|
|
batchCap int
|
|
nextSlot int
|
|
}
|
|
|
|
func newSendBatch(batchCap, slotCap int) *sendBatch {
|
|
return &sendBatch{
|
|
bufs: make([][]byte, 0, batchCap),
|
|
dsts: make([]netip.AddrPort, 0, batchCap),
|
|
backing: make([]byte, batchCap*slotCap),
|
|
slotCap: slotCap,
|
|
batchCap: batchCap,
|
|
}
|
|
}
|
|
|
|
// Next returns a zero-length slice with slotCap capacity over the next unused
|
|
// slot's backing bytes. The caller writes into the returned slice and then
|
|
// calls Commit with the final length and destination. Next returns nil when
|
|
// the batch is full.
|
|
func (b *sendBatch) Next() []byte {
|
|
if b.nextSlot >= b.batchCap {
|
|
return nil
|
|
}
|
|
start := b.nextSlot * b.slotCap
|
|
return b.backing[start : start : start+b.slotCap]
|
|
}
|
|
|
|
// Commit records the slot just returned by Next as a packet of length n
|
|
// destined for dst.
|
|
func (b *sendBatch) Commit(n int, dst netip.AddrPort) {
|
|
start := b.nextSlot * b.slotCap
|
|
b.bufs = append(b.bufs, b.backing[start:start+n])
|
|
b.dsts = append(b.dsts, dst)
|
|
b.nextSlot++
|
|
}
|
|
|
|
// Reset clears committed slots; backing storage is retained for reuse.
|
|
func (b *sendBatch) Reset() {
|
|
b.bufs = b.bufs[:0]
|
|
b.dsts = b.dsts[:0]
|
|
b.nextSlot = 0
|
|
}
|
|
|
|
// Len returns the number of committed packets.
|
|
func (b *sendBatch) Len() int {
|
|
return len(b.bufs)
|
|
}
|
|
|
|
// Cap returns the maximum number of slots in the batch.
|
|
func (b *sendBatch) Cap() int {
|
|
return b.batchCap
|
|
}
|