Skip to content

Commit

Permalink
Update gVisor to release-20230605.0-21-g457c1c36d
Browse files Browse the repository at this point in the history
  • Loading branch information
nekohasekai committed Jun 10, 2023
1 parent b02f252 commit e881f21
Show file tree
Hide file tree
Showing 20 changed files with 71 additions and 550 deletions.
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ require (
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97
github.com/sagernet/sing v0.2.4
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9
golang.org/x/net v0.9.0
golang.org/x/sys v0.7.0
gvisor.dev/gvisor v0.0.0-20230415003630-3981d5d5e523
golang.org/x/net v0.10.0
golang.org/x/sys v0.8.0
gvisor.dev/gvisor v0.0.0-20230609002524-f143e1baf0bb
)

require (
Expand Down
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
gvisor.dev/gvisor v0.0.0-20230415003630-3981d5d5e523 h1:zUQYeyyPLnSR6yMvLSOmLH37xDWCZ7BqlpE69fE5K3Q=
gvisor.dev/gvisor v0.0.0-20230415003630-3981d5d5e523/go.mod h1:pzr6sy8gDLfVmDAg8OYrlKvGEHw5C3PGTiBXBTCx76Q=
gvisor.dev/gvisor v0.0.0-20230609002524-f143e1baf0bb h1:A5Zr25mHIiXEZUjN92wAopvMv2XL4jTbl2/+9D4ATgE=
gvisor.dev/gvisor v0.0.0-20230609002524-f143e1baf0bb/go.mod h1:sQuqOkxbfJq/GS2uSnqHphtXclHyk/ZrAGhZBxxsq6g=
102 changes: 19 additions & 83 deletions gvisor.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ package tun

import (
"context"
"net"
"syscall"
"net/netip"
"time"

"github.com/sagernet/sing/common/bufio"
Expand Down Expand Up @@ -36,12 +35,10 @@ type GVisor struct {
tunMtu uint32
endpointIndependentNat bool
udpTimeout int64
router Router
handler Handler
logger logger.Logger
stack *stack.Stack
endpoint stack.LinkEndpoint
routeMapping *RouteMapping
}

type GVisorTun interface {
Expand All @@ -63,13 +60,9 @@ func NewGVisor(
tunMtu: options.MTU,
endpointIndependentNat: options.EndpointIndependentNat,
udpTimeout: options.UDPTimeout,
router: options.Router,
handler: options.Handler,
logger: options.Logger,
}
if gStack.router != nil {
gStack.routeMapping = NewRouteMapping(options.UDPTimeout)
}
return gStack, nil
}

Expand Down Expand Up @@ -155,44 +148,7 @@ func (t *GVisor) Start() error {
}
}()
})
ipStack.SetTransportProtocolHandler(tcp.ProtocolNumber, func(id stack.TransportEndpointID, buffer stack.PacketBufferPtr) bool {
if t.router != nil {
var routeSession RouteSession
routeSession.Network = syscall.IPPROTO_TCP
var ipHdr header.Network
if buffer.NetworkProtocolNumber == header.IPv4ProtocolNumber {
routeSession.IPVersion = 4
ipHdr = header.IPv4(buffer.NetworkHeader().Slice())
} else {
routeSession.IPVersion = 6
ipHdr = header.IPv6(buffer.NetworkHeader().Slice())
}
tcpHdr := header.TCP(buffer.TransportHeader().Slice())
routeSession.Source = M.AddrPortFrom(net.IP(ipHdr.SourceAddress()), tcpHdr.SourcePort())
routeSession.Destination = M.AddrPortFrom(net.IP(ipHdr.DestinationAddress()), tcpHdr.DestinationPort())
action := t.routeMapping.Lookup(routeSession, func() RouteAction {
if routeSession.IPVersion == 4 {
return t.router.RouteConnection(routeSession, &systemTCPDirectPacketWriter4{t.tun, routeSession.Source})
} else {
return t.router.RouteConnection(routeSession, &systemTCPDirectPacketWriter6{t.tun, routeSession.Source})
}
})
switch actionType := action.(type) {
case *ActionBlock:
// TODO: send icmp unreachable
return true
case *ActionDirect:
buffer.IncRef()
err = actionType.WritePacketBuffer(buffer)
if err != nil {
t.logger.Trace("route gvisor tcp packet: ", err)
}
return true
}
}
return tcpForwarder.HandlePacket(id, buffer)
})

ipStack.SetTransportProtocolHandler(tcp.ProtocolNumber, tcpForwarder.HandlePacket)
if !t.endpointIndependentNat {
udpForwarder := udp.NewForwarder(ipStack, func(request *udp.ForwarderRequest) {
var wq waiter.Queue
Expand All @@ -218,43 +174,7 @@ func (t *GVisor) Start() error {
}
}()
})
ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, func(id stack.TransportEndpointID, buffer stack.PacketBufferPtr) bool {
if t.router != nil {
var routeSession RouteSession
routeSession.Network = syscall.IPPROTO_UDP
var ipHdr header.Network
if buffer.NetworkProtocolNumber == header.IPv4ProtocolNumber {
routeSession.IPVersion = 4
ipHdr = header.IPv4(buffer.NetworkHeader().Slice())
} else {
routeSession.IPVersion = 6
ipHdr = header.IPv6(buffer.NetworkHeader().Slice())
}
udpHdr := header.UDP(buffer.TransportHeader().Slice())
routeSession.Source = M.AddrPortFrom(net.IP(ipHdr.SourceAddress()), udpHdr.SourcePort())
routeSession.Destination = M.AddrPortFrom(net.IP(ipHdr.DestinationAddress()), udpHdr.DestinationPort())
action := t.routeMapping.Lookup(routeSession, func() RouteAction {
if routeSession.IPVersion == 4 {
return t.router.RouteConnection(routeSession, &systemUDPDirectPacketWriter4{t.tun, routeSession.Source})
} else {
return t.router.RouteConnection(routeSession, &systemUDPDirectPacketWriter6{t.tun, routeSession.Source})
}
})
switch actionType := action.(type) {
case *ActionBlock:
// TODO: send icmp unreachable
return true
case *ActionDirect:
buffer.IncRef()
err = actionType.WritePacketBuffer(buffer)
if err != nil {
t.logger.Trace("route gvisor udp packet: ", err)
}
return true
}
}
return udpForwarder.HandlePacket(id, buffer)
})
ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, udpForwarder.HandlePacket)
} else {
ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, NewUDPForwarder(t.ctx, ipStack, t.handler, t.udpTimeout).HandlePacket)
}
Expand All @@ -272,3 +192,19 @@ func (t *GVisor) Close() error {
}
return nil
}

func AddressFromAddr(destination netip.Addr) tcpip.Address {
if destination.Is6() {
return tcpip.AddrFrom16(destination.As16())
} else {
return tcpip.AddrFrom4(destination.As4())
}
}

func AddrFromAddress(address tcpip.Address) netip.Addr {
if address.Len() == 16 {
return netip.AddrFrom16(address.As16())
} else {
return netip.AddrFrom4(address.As4())
}
}
15 changes: 7 additions & 8 deletions gvisor_udp.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ package tun
import (
"context"
"math"
"net"
"net/netip"

"github.com/sagernet/sing/common/buf"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/udpnat"

"gvisor.dev/gvisor/pkg/bufferv2"
"gvisor.dev/gvisor/pkg/buffer"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/checksum"
"gvisor.dev/gvisor/pkg/tcpip/header"
Expand All @@ -36,8 +35,8 @@ func NewUDPForwarder(ctx context.Context, stack *stack.Stack, handler Handler, u

func (f *UDPForwarder) HandlePacket(id stack.TransportEndpointID, pkt stack.PacketBufferPtr) bool {
var upstreamMetadata M.Metadata
upstreamMetadata.Source = M.SocksaddrFrom(M.AddrFromIP(net.IP(id.RemoteAddress)), id.RemotePort)
upstreamMetadata.Destination = M.SocksaddrFrom(M.AddrFromIP(net.IP(id.LocalAddress)), id.LocalPort)
upstreamMetadata.Source = M.SocksaddrFrom(AddrFromAddress(id.RemoteAddress), id.RemotePort)
upstreamMetadata.Destination = M.SocksaddrFrom(AddrFromAddress(id.LocalAddress), id.LocalPort)
var netProto tcpip.NetworkProtocolNumber
if upstreamMetadata.Source.IsIPv4() {
netProto = header.IPv4ProtocolNumber
Expand All @@ -63,12 +62,12 @@ type UDPBackWriter struct {
sourceNetwork tcpip.NetworkProtocolNumber
}

func (w *UDPBackWriter) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
defer buffer.Release()
func (w *UDPBackWriter) WritePacket(packetBuffer *buf.Buffer, destination M.Socksaddr) error {
defer packetBuffer.Release()

route, err := w.stack.FindRoute(
defaultNIC,
tcpip.Address(destination.Addr.AsSlice()),
AddressFromAddr(destination.Addr),
w.source,
w.sourceNetwork,
false,
Expand All @@ -80,7 +79,7 @@ func (w *UDPBackWriter) WritePacket(buffer *buf.Buffer, destination M.Socksaddr)

packet := stack.NewPacketBuffer(stack.PacketBufferOptions{
ReserveHeaderBytes: header.UDPMinimumSize + int(route.MaxHeaderLength()),
Payload: bufferv2.MakeWithData(buffer.Bytes()),
Payload: buffer.MakeWithData(packetBuffer.Bytes()),
})
defer packet.DecRef()

Expand Down
2 changes: 1 addition & 1 deletion internal/fdbased/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# fdbased

Version: release-20230417.0
Version: release-20230605.0-21-g457c1c36d
8 changes: 4 additions & 4 deletions internal/fdbased/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import (

"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/atomicbitops"
"gvisor.dev/gvisor/pkg/bufferv2"
"gvisor.dev/gvisor/pkg/buffer"
"gvisor.dev/gvisor/pkg/sync"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
Expand Down Expand Up @@ -545,7 +545,7 @@ func (e *endpoint) writePacket(pkt stack.PacketBufferPtr) tcpip.Error {
vnetHdr.csumStart = header.EthernetMinimumSize + pkt.GSOOptions.L3HdrLen
vnetHdr.csumOffset = pkt.GSOOptions.CsumOffset
}
if pkt.GSOOptions.Type != stack.GSONone && uint16(pkt.Data().Size()) > pkt.GSOOptions.MSS {
if uint16(pkt.Data().Size()) > pkt.GSOOptions.MSS {
switch pkt.GSOOptions.Type {
case stack.GSOTCPv4:
vnetHdr.gsoType = _VIRTIO_NET_HDR_GSO_TCPV4
Expand Down Expand Up @@ -732,7 +732,7 @@ func (e *endpoint) WritePackets(pkts stack.PacketBufferList) (int, tcpip.Error)
}

// InjectOutbound implements stack.InjectableEndpoint.InjectOutbound.
func (e *endpoint) InjectOutbound(dest tcpip.Address, packet *bufferv2.View) tcpip.Error {
func (e *endpoint) InjectOutbound(dest tcpip.Address, packet *buffer.View) tcpip.Error {
return rawfile.NonBlockingWrite(e.fds[0].fd, packet.AsSlice())
}

Expand All @@ -756,7 +756,7 @@ func (e *endpoint) GSOMaxSize() uint32 {
return e.gsoMaxSize
}

// SupportsHWGSO implements stack.GSOEndpoint.
// SupportedGSO implements stack.GSOEndpoint.
func (e *endpoint) SupportedGSO() stack.SupportedGSO {
return e.gsoKind
}
Expand Down
8 changes: 4 additions & 4 deletions internal/fdbased/mmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
"github.com/sagernet/sing-tun/internal/fdbased/stopfd"

"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/bufferv2"
"gvisor.dev/gvisor/pkg/buffer"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/link/rawfile"
Expand Down Expand Up @@ -135,7 +135,7 @@ type packetMMapDispatcher struct {

func (*packetMMapDispatcher) release() {}

func (d *packetMMapDispatcher) readMMappedPacket() (*bufferv2.View, bool, tcpip.Error) {
func (d *packetMMapDispatcher) readMMappedPacket() (*buffer.View, bool, tcpip.Error) {
hdr := tPacketHdr(d.ringBuffer[d.ringOffset*tpFrameSize:])
for hdr.tpStatus()&tpStatusUser == 0 {
stopped, errno := rawfile.BlockingPollUntilStopped(d.EFD, d.fd, unix.POLLIN|unix.POLLERR)
Expand All @@ -159,7 +159,7 @@ func (d *packetMMapDispatcher) readMMappedPacket() (*bufferv2.View, bool, tcpip.
}

// Copy out the packet from the mmapped frame to a locally owned buffer.
pkt := bufferv2.NewView(int(hdr.tpSnapLen()))
pkt := buffer.NewView(int(hdr.tpSnapLen()))
pkt.Write(hdr.Payload())
// Release packet to kernel.
hdr.setTPStatus(tpStatusKernel)
Expand Down Expand Up @@ -191,7 +191,7 @@ func (d *packetMMapDispatcher) dispatch() (bool, tcpip.Error) {
}

pbuf := stack.NewPacketBuffer(stack.PacketBufferOptions{
Payload: bufferv2.MakeWithView(pkt),
Payload: buffer.MakeWithView(pkt),
})
defer pbuf.DecRef()
if d.e.hdrSize > 0 {
Expand Down
16 changes: 8 additions & 8 deletions internal/fdbased/packet_dispatchers.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"github.com/sagernet/sing-tun/internal/fdbased/stopfd"

"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/bufferv2"
"gvisor.dev/gvisor/pkg/buffer"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/link/rawfile"
Expand All @@ -35,7 +35,7 @@ type iovecBuffer struct {
// buffer is the actual buffer that holds the packet contents. Some contents
// are reused across calls to pullBuffer if number of requested bytes is
// smaller than the number of bytes allocated in the buffer.
views []*bufferv2.View
views []*buffer.View

// iovecs are initialized with base pointers/len of the corresponding
// entries in the views defined above, except when GSO is enabled
Expand All @@ -59,7 +59,7 @@ type iovecBuffer struct {

func newIovecBuffer(sizes []int, skipsVnetHdr bool) *iovecBuffer {
b := &iovecBuffer{
views: make([]*bufferv2.View, len(sizes)),
views: make([]*buffer.View, len(sizes)),
sizes: sizes,
skipsVnetHdr: skipsVnetHdr,
}
Expand Down Expand Up @@ -87,7 +87,7 @@ func (b *iovecBuffer) nextIovecs() []unix.Iovec {
if b.views[i] != nil {
break
}
v := bufferv2.NewViewSize(b.sizes[i])
v := buffer.NewViewSize(b.sizes[i])
b.views[i] = v
b.iovecs[i+vnetHdrOff] = unix.Iovec{Base: v.BasePtr()}
b.iovecs[i+vnetHdrOff].SetLen(v.Size())
Expand All @@ -100,14 +100,14 @@ func (b *iovecBuffer) nextIovecs() []unix.Iovec {
// that holds the storage, and updates pulledIndex to indicate which part
// of b.buffer's storage must be reallocated during the next call to
// nextIovecs.
func (b *iovecBuffer) pullBuffer(n int) bufferv2.Buffer {
var views []*bufferv2.View
func (b *iovecBuffer) pullBuffer(n int) buffer.Buffer {
var views []*buffer.View
c := 0
if b.skipsVnetHdr {
c += virtioNetHdrSize
if c >= n {
// Nothing in the packet.
return bufferv2.Buffer{}
return buffer.Buffer{}
}
}
// Remove the used views from the buffer.
Expand All @@ -126,7 +126,7 @@ func (b *iovecBuffer) pullBuffer(n int) bufferv2.Buffer {
// Exclude the size of the vnet header.
n -= virtioNetHdrSize
}
pulled := bufferv2.Buffer{}
pulled := buffer.Buffer{}
for _, v := range views {
pulled.Append(v)
}
Expand Down
6 changes: 0 additions & 6 deletions internal/fdbased/stopfd/stopfd_state_autogen.go

This file was deleted.

Loading

0 comments on commit e881f21

Please sign in to comment.