67 lines
1.9 KiB
Go
67 lines
1.9 KiB
Go
/* SPDX-License-Identifier: MIT
|
|
*
|
|
* Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
|
|
*/
|
|
|
|
package device
|
|
|
|
import (
|
|
"fmt"
|
|
"sync/atomic"
|
|
|
|
"github.com/tailscale/wireguard-go/tun"
|
|
"golang.org/x/crypto/poly1305"
|
|
)
|
|
|
|
const (
|
|
outboundPlaintextHeadroom = MessageEncapsulatingTransportSize + MessageTransportHeaderSize
|
|
|
|
outboundPlaintextTailroom = PaddingMultiple - 1 + poly1305.TagSize
|
|
|
|
outboundPlaintextSpacing = max(outboundPlaintextHeadroom+outboundPlaintextTailroom, tun.ReadPacketSpacing)
|
|
|
|
// singlePacketSlabSize is the size to be used for [packetBuf.slab] when
|
|
// neither [tun.Device] nor [conn.Bind] support batched reads.
|
|
singlePacketSlabSize = MaxContentSize + 2*tun.ReadPacketSpacing
|
|
|
|
// batchingSlabSize is the size to be used for [packetBuf.slab] when either
|
|
// [tun.Device] or [conn.Bind] support batched reads. This covers the
|
|
// [tun.GSOSplit] worst case for minimum-sized MTU/MSS, which is documented
|
|
// in [tun.TestGSOSplitMinimumGSOSize].
|
|
batchingSlabSize = 2 * (1<<16 - 1)
|
|
)
|
|
|
|
// The tun package cannot import device, so we assert [tun.ReadPacketSpacing] is
|
|
// greater than or equal to [outboundPlaintextSpacing] instead.
|
|
const _ = uint(tun.ReadPacketSpacing - outboundPlaintextSpacing)
|
|
|
|
// packetBuf is a reference counted packet buffer.
|
|
type packetBuf struct {
|
|
slab []byte
|
|
refCount atomic.Int32
|
|
cleanup func(*packetBuf)
|
|
}
|
|
|
|
// newPacketBuf returns a new [*packetBuf] of the provided size with its
|
|
// reference count set to zero. cleanup runs for the returned [*packetBuf] when
|
|
// its ref count moves 1->0.
|
|
func newPacketBuf(size int, cleanup func(*packetBuf)) *packetBuf {
|
|
return &packetBuf{
|
|
slab: make([]byte, size),
|
|
cleanup: cleanup,
|
|
}
|
|
}
|
|
|
|
func (p *packetBuf) incRef() {
|
|
p.refCount.Add(1)
|
|
}
|
|
|
|
func (p *packetBuf) decRef() {
|
|
c := p.refCount.Add(-1)
|
|
if c == 0 {
|
|
p.cleanup(p)
|
|
} else if c < 0 {
|
|
panic(fmt.Sprintf("packetBuf.decRef below zero (%d)", c))
|
|
}
|
|
}
|