Skip to content

Commit 03c5a0c

Browse files
committed
tun: implement API for disabling UDP GRO on Linux
Certain device drivers (e.g. vxlan, geneve) do not properly handle coalesced UDP packets later in the stack, resulting in packet loss. Signed-off-by: Jordan Whited <[email protected]>
1 parent 64040e6 commit 03c5a0c

File tree

2 files changed

+18
-2
lines changed

2 files changed

+18
-2
lines changed

tun/tun.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,11 @@ type Device interface {
5151
// lifetime of a Device.
5252
BatchSize() int
5353
}
54+
55+
type LinuxDevice interface {
56+
Device
57+
// DisableUDPGRO disables UDP GRO if it is enabled. Certain device drivers
58+
// (e.g. vxlan, geneve) do not properly handle coalesced UDP packets later
59+
// in the stack, resulting in packet loss.
60+
DisableUDPGRO()
61+
}

tun/tun_linux.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,11 @@ type NativeTun struct {
4949
readOpMu sync.Mutex // readOpMu guards readBuff
5050
readBuff [virtioNetHdrLen + 65535]byte // if vnetHdr every read() is prefixed by virtioNetHdr
5151

52-
writeOpMu sync.Mutex // writeOpMu guards toWrite, tcpGROTable
52+
writeOpMu sync.Mutex // writeOpMu guards the following fields
5353
toWrite []int
5454
tcpGROTable *tcpGROTable
5555
udpGROTable *udpGROTable
56+
udpGRO bool
5657
}
5758

5859
func (tun *NativeTun) File() *os.File {
@@ -345,7 +346,7 @@ func (tun *NativeTun) Write(bufs [][]byte, offset int) (int, error) {
345346
)
346347
tun.toWrite = tun.toWrite[:0]
347348
if tun.vnetHdr {
348-
err := handleGRO(bufs, offset, tun.tcpGROTable, tun.udpGROTable, tun.udpGSO, &tun.toWrite)
349+
err := handleGRO(bufs, offset, tun.tcpGROTable, tun.udpGROTable, tun.udpGRO, &tun.toWrite)
349350
if err != nil {
350351
return 0, err
351352
}
@@ -502,6 +503,12 @@ func (tun *NativeTun) BatchSize() int {
502503
return tun.batchSize
503504
}
504505

506+
func (tun *NativeTun) DisableUDPGRO() {
507+
tun.writeOpMu.Lock()
508+
tun.udpGRO = false
509+
tun.writeOpMu.Unlock()
510+
}
511+
505512
const (
506513
// TODO: support TSO with ECN bits
507514
tunTCPOffloads = unix.TUN_F_CSUM | unix.TUN_F_TSO4 | unix.TUN_F_TSO6
@@ -538,6 +545,7 @@ func (tun *NativeTun) initFromFlags(name string) error {
538545
// tunUDPOffloads were added in Linux v6.2. We do not return an
539546
// error if they are unsupported at runtime.
540547
tun.udpGSO = unix.IoctlSetInt(int(fd), unix.TUNSETOFFLOAD, tunTCPOffloads|tunUDPOffloads) == nil
548+
tun.udpGRO = tun.udpGSO
541549
} else {
542550
tun.batchSize = 1
543551
}

0 commit comments

Comments
 (0)