Fix udp/icmp not work on gso with mixed stack

This commit is contained in:
wwqgtxx
2026-03-03 23:48:15 +08:00
committed by 世界
parent 6ee3db839d
commit 90ea7a0b69
2 changed files with 34 additions and 0 deletions
+1
View File
@@ -39,6 +39,7 @@ type NativeTun struct {
writeAccess sync.Mutex writeAccess sync.Mutex
vnetHdr bool vnetHdr bool
writeBuffer []byte writeBuffer []byte
vnetHdrWriteBuf []byte
gsoToWrite []int gsoToWrite []int
tcpGROTable *tcpGROTable tcpGROTable *tcpGROTable
udpGroAccess sync.Mutex udpGroAccess sync.Mutex
+33
View File
@@ -3,6 +3,8 @@
package tun package tun
import ( import (
"fmt"
"github.com/sagernet/gvisor/pkg/rawfile" "github.com/sagernet/gvisor/pkg/rawfile"
"github.com/sagernet/gvisor/pkg/tcpip/link/fdbased" "github.com/sagernet/gvisor/pkg/tcpip/link/fdbased"
"github.com/sagernet/gvisor/pkg/tcpip/stack" "github.com/sagernet/gvisor/pkg/tcpip/stack"
@@ -18,6 +20,37 @@ var _ GVisorTun = (*NativeTun)(nil)
func (t *NativeTun) WritePacket(pkt *stack.PacketBuffer) (int, error) { func (t *NativeTun) WritePacket(pkt *stack.PacketBuffer) (int, error) {
iovecs := t.iovecsOutputDefault iovecs := t.iovecsOutputDefault
if t.vnetHdr {
if t.vnetHdrWriteBuf == nil {
t.vnetHdrWriteBuf = make([]byte, virtioNetHdrLen)
}
vnetHdr := virtioNetHdr{}
if pkt.GSOOptions.Type != stack.GSONone {
vnetHdr.hdrLen = uint16(pkt.HeaderSize())
if pkt.GSOOptions.NeedsCsum {
vnetHdr.flags = unix.VIRTIO_NET_HDR_F_NEEDS_CSUM
vnetHdr.csumStart = pkt.GSOOptions.L3HdrLen
vnetHdr.csumOffset = pkt.GSOOptions.CsumOffset
}
if uint16(pkt.Data().Size()) > pkt.GSOOptions.MSS {
switch pkt.GSOOptions.Type {
case stack.GSOTCPv4:
vnetHdr.gsoType = unix.VIRTIO_NET_HDR_GSO_TCPV4
case stack.GSOTCPv6:
vnetHdr.gsoType = unix.VIRTIO_NET_HDR_GSO_TCPV6
default:
panic(fmt.Sprintf("Unknown gso type: %v", pkt.GSOOptions.Type))
}
vnetHdr.gsoSize = pkt.GSOOptions.MSS
}
}
if err := vnetHdr.encode(t.vnetHdrWriteBuf); err != nil {
return 0, err
}
iovec := unix.Iovec{Base: &t.vnetHdrWriteBuf[0]}
iovec.SetLen(virtioNetHdrLen)
iovecs = append(iovecs, iovec)
}
var dataLen int var dataLen int
for _, packetSlice := range pkt.AsSlices() { for _, packetSlice := range pkt.AsSlices() {
dataLen += len(packetSlice) dataLen += len(packetSlice)