net/tstun: support ts_omit_netstack

Updates #17283

Change-Id: I1134bb15b3e39a3fa26c0621512aae9181de2210
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2025-09-26 11:15:05 -07:00
committed by Brad Fitzpatrick
parent 0b994ef2fe
commit 09a33b9262
4 changed files with 119 additions and 19 deletions

View File

@@ -61,20 +61,15 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
💣 gvisor.dev/gvisor/pkg/gohacks from gvisor.dev/gvisor/pkg/state/wire+
gvisor.dev/gvisor/pkg/linewriter from gvisor.dev/gvisor/pkg/log
gvisor.dev/gvisor/pkg/log from gvisor.dev/gvisor/pkg/context+
gvisor.dev/gvisor/pkg/rand from gvisor.dev/gvisor/pkg/tcpip+
gvisor.dev/gvisor/pkg/refs from gvisor.dev/gvisor/pkg/buffer+
gvisor.dev/gvisor/pkg/rand from gvisor.dev/gvisor/pkg/tcpip
gvisor.dev/gvisor/pkg/refs from gvisor.dev/gvisor/pkg/buffer
💣 gvisor.dev/gvisor/pkg/state from gvisor.dev/gvisor/pkg/atomicbitops+
gvisor.dev/gvisor/pkg/state/wire from gvisor.dev/gvisor/pkg/state
💣 gvisor.dev/gvisor/pkg/sync from gvisor.dev/gvisor/pkg/atomicbitops+
💣 gvisor.dev/gvisor/pkg/sync/locking from gvisor.dev/gvisor/pkg/tcpip/stack
gvisor.dev/gvisor/pkg/tcpip from gvisor.dev/gvisor/pkg/tcpip/header+
💣 gvisor.dev/gvisor/pkg/tcpip/checksum from gvisor.dev/gvisor/pkg/buffer+
gvisor.dev/gvisor/pkg/tcpip/hash/jenkins from gvisor.dev/gvisor/pkg/tcpip/stack
gvisor.dev/gvisor/pkg/tcpip/header from gvisor.dev/gvisor/pkg/tcpip/ports+
gvisor.dev/gvisor/pkg/tcpip/ports from gvisor.dev/gvisor/pkg/tcpip/stack
gvisor.dev/gvisor/pkg/tcpip/seqnum from gvisor.dev/gvisor/pkg/tcpip/header+
💣 gvisor.dev/gvisor/pkg/tcpip/stack from tailscale.com/net/tstun
gvisor.dev/gvisor/pkg/tcpip/transport/tcpconntrack from gvisor.dev/gvisor/pkg/tcpip/stack
gvisor.dev/gvisor/pkg/tcpip/header from tailscale.com/net/packet/checksum+
gvisor.dev/gvisor/pkg/tcpip/seqnum from gvisor.dev/gvisor/pkg/tcpip/header
gvisor.dev/gvisor/pkg/waiter from gvisor.dev/gvisor/pkg/context+
tailscale.com from tailscale.com/version
tailscale.com/appc from tailscale.com/ipn/ipnlocal

View File

@@ -0,0 +1,69 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
//go:build ts_omit_netstack
package tstun
type netstack_PacketBuffer struct {
GSOOptions netstack_GSO
}
func (*netstack_PacketBuffer) DecRef() { panic("unreachable") }
func (*netstack_PacketBuffer) Size() int { panic("unreachable") }
type netstack_GSOType int
const (
netstack_GSONone netstack_GSOType = iota
netstack_GSOTCPv4
netstack_GSOTCPv6
netstack_GSOGvisor
)
type netstack_GSO struct {
// Type is one of GSONone, GSOTCPv4, etc.
Type netstack_GSOType
// NeedsCsum is set if the checksum offload is enabled.
NeedsCsum bool
// CsumOffset is offset after that to place checksum.
CsumOffset uint16
// Mss is maximum segment size.
MSS uint16
// L3Len is L3 (IP) header length.
L3HdrLen uint16
// MaxSize is maximum GSO packet size.
MaxSize uint32
}
func (p *netstack_PacketBuffer) NetworkHeader() slicer {
panic("unreachable")
}
func (p *netstack_PacketBuffer) TransportHeader() slicer {
panic("unreachable")
}
func (p *netstack_PacketBuffer) ToBuffer() netstack_Buffer { panic("unreachable") }
func (p *netstack_PacketBuffer) Data() asRanger {
panic("unreachable")
}
type asRanger struct{}
func (asRanger) AsRange() toSlicer { panic("unreachable") }
type toSlicer struct{}
func (toSlicer) ToSlice() []byte { panic("unreachable") }
type slicer struct{}
func (s slicer) Slice() []byte { panic("unreachable") }
type netstack_Buffer struct{}
func (netstack_Buffer) Flatten() []byte { panic("unreachable") }

View File

@@ -0,0 +1,22 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
//go:build !ts_omit_netstack
package tstun
import (
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
type (
netstack_PacketBuffer = stack.PacketBuffer
netstack_GSO = stack.GSO
)
const (
netstack_GSONone = stack.GSONone
netstack_GSOTCPv4 = stack.GSOTCPv4
netstack_GSOTCPv6 = stack.GSOTCPv6
netstack_GSOGvisor = stack.GSOGvisor
)

View File

@@ -22,7 +22,6 @@ import (
"github.com/tailscale/wireguard-go/device"
"github.com/tailscale/wireguard-go/tun"
"go4.org/mem"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"tailscale.com/disco"
"tailscale.com/feature/buildfeatures"
tsmetrics "tailscale.com/metrics"
@@ -229,7 +228,7 @@ func registerMetrics(reg *usermetric.Registry) *metrics {
type tunInjectedRead struct {
// Only one of packet or data should be set, and are read in that order of
// precedence.
packet *stack.PacketBuffer
packet *netstack_PacketBuffer
data []byte
}
@@ -999,7 +998,10 @@ const (
minTCPHeaderSize = 20
)
func stackGSOToTunGSO(pkt []byte, gso stack.GSO) (tun.GSOOptions, error) {
func stackGSOToTunGSO(pkt []byte, gso netstack_GSO) (tun.GSOOptions, error) {
if !buildfeatures.HasNetstack {
panic("unreachable")
}
options := tun.GSOOptions{
CsumStart: gso.L3HdrLen,
CsumOffset: gso.CsumOffset,
@@ -1007,12 +1009,12 @@ func stackGSOToTunGSO(pkt []byte, gso stack.GSO) (tun.GSOOptions, error) {
NeedsCsum: gso.NeedsCsum,
}
switch gso.Type {
case stack.GSONone:
case netstack_GSONone:
options.GSOType = tun.GSONone
return options, nil
case stack.GSOTCPv4:
case netstack_GSOTCPv4:
options.GSOType = tun.GSOTCPv4
case stack.GSOTCPv6:
case netstack_GSOTCPv6:
options.GSOType = tun.GSOTCPv6
default:
return tun.GSOOptions{}, fmt.Errorf("unsupported gVisor GSOType: %v", gso.Type)
@@ -1035,7 +1037,10 @@ func stackGSOToTunGSO(pkt []byte, gso stack.GSO) (tun.GSOOptions, error) {
// both before and after partial checksum updates where later checksum
// offloading still expects a partial checksum.
// TODO(jwhited): plumb partial checksum awareness into net/packet/checksum.
func invertGSOChecksum(pkt []byte, gso stack.GSO) {
func invertGSOChecksum(pkt []byte, gso netstack_GSO) {
if !buildfeatures.HasNetstack {
panic("unreachable")
}
if gso.NeedsCsum != true {
return
}
@@ -1049,10 +1054,13 @@ func invertGSOChecksum(pkt []byte, gso stack.GSO) {
// injectedRead handles injected reads, which bypass filters.
func (t *Wrapper) injectedRead(res tunInjectedRead, outBuffs [][]byte, sizes []int, offset int) (n int, err error) {
var gso stack.GSO
var gso netstack_GSO
pkt := outBuffs[0][offset:]
if res.packet != nil {
if !buildfeatures.HasNetstack {
panic("unreachable")
}
bufN := copy(pkt, res.packet.NetworkHeader().Slice())
bufN += copy(pkt[bufN:], res.packet.TransportHeader().Slice())
bufN += copy(pkt[bufN:], res.packet.Data().AsRange().ToSlice())
@@ -1298,7 +1306,10 @@ func (t *Wrapper) SetJailedFilter(filt *filter.Filter) {
//
// This path is typically used to deliver synthesized packets to the
// host networking stack.
func (t *Wrapper) InjectInboundPacketBuffer(pkt *stack.PacketBuffer, buffs [][]byte, sizes []int) error {
func (t *Wrapper) InjectInboundPacketBuffer(pkt *netstack_PacketBuffer, buffs [][]byte, sizes []int) error {
if !buildfeatures.HasNetstack {
panic("unreachable")
}
buf := buffs[0][PacketStartOffset:]
bufN := copy(buf, pkt.NetworkHeader().Slice())
@@ -1437,7 +1448,10 @@ func (t *Wrapper) InjectOutbound(pkt []byte) error {
// InjectOutboundPacketBuffer logically behaves as InjectOutbound. It takes ownership of one
// reference count on the packet, and the packet may be mutated. The packet refcount will be
// decremented after the injected buffer has been read.
func (t *Wrapper) InjectOutboundPacketBuffer(pkt *stack.PacketBuffer) error {
func (t *Wrapper) InjectOutboundPacketBuffer(pkt *netstack_PacketBuffer) error {
if !buildfeatures.HasNetstack {
panic("unreachable")
}
size := pkt.Size()
if size > MaxPacketSize {
pkt.DecRef()