Skip to content

Commit

Permalink
Add GSO support
Browse files Browse the repository at this point in the history
  • Loading branch information
nekohasekai committed Dec 9, 2023
1 parent 012e605 commit bbd5287
Show file tree
Hide file tree
Showing 17 changed files with 1,000 additions and 383 deletions.
17 changes: 10 additions & 7 deletions stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@ type Stack interface {
type StackOptions struct {
Context context.Context
Tun Tun
Name string
MTU uint32
Inet4Address []netip.Prefix
Inet6Address []netip.Prefix
TunOptions Options
EndpointIndependentNat bool
UDPTimeout int64
Handler Handler
Expand All @@ -31,13 +28,21 @@ type StackOptions struct {
InterfaceFinder control.InterfaceFinder
}

func (o *StackOptions) BufferSize() uint32 {
if o.TunOptions.GSO {
return o.TunOptions.GSOMaxSize
} else {
return o.TunOptions.MTU
}
}

func NewStack(
stack string,
options StackOptions,
) (Stack, error) {
switch stack {
case "":
if WithGVisor {
if WithGVisor && !options.TunOptions.GSO {
return NewMixed(options)
} else {
return NewSystem(options)
Expand All @@ -48,8 +53,6 @@ func NewStack(
return NewMixed(options)
case "system":
return NewSystem(options)
case "lwip":
return NewLWIP(options)
default:
return nil, E.New("unknown stack: ", stack)
}
Expand Down
6 changes: 2 additions & 4 deletions stack_gvisor.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ const defaultNIC tcpip.NICID = 1
type GVisor struct {
ctx context.Context
tun GVisorTun
tunMtu uint32
endpointIndependentNat bool
udpTimeout int64
broadcastAddr netip.Addr
Expand All @@ -57,10 +56,9 @@ func NewGVisor(
gStack := &GVisor{
ctx: options.Context,
tun: gTun,
tunMtu: options.MTU,
endpointIndependentNat: options.EndpointIndependentNat,
udpTimeout: options.UDPTimeout,
broadcastAddr: BroadcastAddr(options.Inet4Address),
broadcastAddr: BroadcastAddr(options.TunOptions.Inet4Address),
handler: options.Handler,
logger: options.Logger,
}
Expand All @@ -72,7 +70,7 @@ func (t *GVisor) Start() error {
if err != nil {
return err
}
linkEndpoint = &LinkEndpointFilter{linkEndpoint, t.broadcastAddr, t.tun.CreateVectorisedWriter()}
linkEndpoint = &LinkEndpointFilter{linkEndpoint, t.broadcastAddr, bufio.NewVectorisedWriter(t.tun)}
ipStack, err := newGVisorStack(linkEndpoint)
if err != nil {
return err
Expand Down
7 changes: 0 additions & 7 deletions stack_gvisor_udp.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ type UDPBackWriter struct {
source tcpip.Address
sourcePort uint16
sourceNetwork tcpip.NetworkProtocolNumber
packet stack.PacketBufferPtr
}

func (w *UDPBackWriter) WritePacket(packetBuffer *buf.Buffer, destination M.Socksaddr) error {
Expand Down Expand Up @@ -149,12 +148,6 @@ func (w *UDPBackWriter) WritePacket(packetBuffer *buf.Buffer, destination M.Sock
return nil
}

type gRequest struct {
stack *stack.Stack
id stack.TransportEndpointID
pkt stack.PacketBufferPtr
}

type gUDPConn struct {
*gonet.UDPConn
}
Expand Down
144 changes: 0 additions & 144 deletions stack_lwip.go

This file was deleted.

11 changes: 0 additions & 11 deletions stack_lwip_stub.go

This file was deleted.

43 changes: 24 additions & 19 deletions stack_mixed.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func NewMixed(
}
return &Mixed{
System: system.(*System),
writer: options.Tun.CreateVectorisedWriter(),
writer: bufio.NewVectorisedWriter(options.Tun),
endpointIndependentNat: options.EndpointIndependentNat,
}, nil
}
Expand Down Expand Up @@ -95,21 +95,26 @@ func (m *Mixed) tunLoop() {
m.wintunLoop(winTun)
return
}
packetBuffer := make([]byte, m.mtu+PacketOffset)
frontHeadroom := m.tun.FrontHeadroom()
packetBuffer := make([]byte, m.bufferSize+frontHeadroom+PacketOffset)
for {
n, err := m.tun.Read(packetBuffer)
n, err := m.tun.Read(packetBuffer[frontHeadroom:])
if err != nil {
return
if E.IsClosed(err) {
return
}
m.logger.Error(E.Cause(err, "read packet"))
}
if n < clashtcpip.IPv4PacketMinLength {
continue
}
packet := packetBuffer[PacketOffset:n]
rawPacket := packetBuffer[:frontHeadroom+n]
packet := packetBuffer[frontHeadroom+PacketOffset : frontHeadroom+n]
switch ipVersion := packet[0] >> 4; ipVersion {
case 4:
err = m.processIPv4(packet)
err = m.processIPv4(rawPacket, packet)
case 6:
err = m.processIPv6(packet)
err = m.processIPv6(rawPacket, packet)
default:
err = E.New("ip: unknown version: ", ipVersion)
}
Expand All @@ -131,9 +136,9 @@ func (m *Mixed) wintunLoop(winTun WinTun) {
}
switch ipVersion := packet[0] >> 4; ipVersion {
case 4:
err = m.processIPv4(packet)
err = m.processIPv4(packet, packet)
case 6:
err = m.processIPv6(packet)
err = m.processIPv6(packet, packet)
default:
err = E.New("ip: unknown version: ", ipVersion)
}
Expand All @@ -144,14 +149,14 @@ func (m *Mixed) wintunLoop(winTun WinTun) {
}
}

func (m *Mixed) processIPv4(packet clashtcpip.IPv4Packet) error {
func (m *Mixed) processIPv4(rawPacket []byte, packet clashtcpip.IPv4Packet) error {
destination := packet.DestinationIP()
if destination == m.broadcastAddr || !destination.IsGlobalUnicast() {
return common.Error(m.tun.Write(packet))
return common.Error(m.tun.Write(rawPacket))
}
switch packet.Protocol() {
case clashtcpip.TCP:
return m.processIPv4TCP(packet, packet.Payload())
return m.processIPv4TCP(rawPacket, packet, packet.Payload())
case clashtcpip.UDP:
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
Payload: buffer.MakeWithData(packet),
Expand All @@ -160,19 +165,19 @@ func (m *Mixed) processIPv4(packet clashtcpip.IPv4Packet) error {
pkt.DecRef()
return nil
case clashtcpip.ICMP:
return m.processIPv4ICMP(packet, packet.Payload())
return m.processIPv4ICMP(rawPacket, packet, packet.Payload())
default:
return common.Error(m.tun.Write(packet))
return common.Error(m.tun.Write(rawPacket))
}
}

func (m *Mixed) processIPv6(packet clashtcpip.IPv6Packet) error {
func (m *Mixed) processIPv6(rawPacket []byte, packet clashtcpip.IPv6Packet) error {
if !packet.DestinationIP().IsGlobalUnicast() {
return common.Error(m.tun.Write(packet))
return common.Error(m.tun.Write(rawPacket))
}
switch packet.Protocol() {
case clashtcpip.TCP:
return m.processIPv6TCP(packet, packet.Payload())
return m.processIPv6TCP(rawPacket, packet, packet.Payload())
case clashtcpip.UDP:
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
Payload: buffer.MakeWithData(packet),
Expand All @@ -181,9 +186,9 @@ func (m *Mixed) processIPv6(packet clashtcpip.IPv6Packet) error {
pkt.DecRef()
return nil
case clashtcpip.ICMPv6:
return m.processIPv6ICMP(packet, packet.Payload())
return m.processIPv6ICMP(rawPacket, packet, packet.Payload())
default:
return common.Error(m.tun.Write(packet))
return common.Error(m.tun.Write(rawPacket))
}
}

Expand Down
Loading

0 comments on commit bbd5287

Please sign in to comment.