Skip to content

Commit aad7fca

Browse files
jwhitedzx2c4
authored andcommitted
tun: disqualify tcp4 packets w/IP options from coalescing
IP options were not being compared prior to coalescing. They are not commonly used. Disqualification due to nonzero options is in line with the kernel. Reviewed-by: Denton Gentry <[email protected]> Signed-off-by: Jordan Whited <[email protected]> Signed-off-by: Jason A. Donenfeld <[email protected]>
1 parent 6f895be commit aad7fca

File tree

2 files changed

+55
-5
lines changed

2 files changed

+55
-5
lines changed

tun/tcp_offload_linux.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -397,9 +397,6 @@ func tcpGRO(bufs [][]byte, offset int, pktI int, table *tcpGROTable, isV6 bool)
397397
if totalLen != len(pkt) {
398398
return false
399399
}
400-
if iphLen < 20 || iphLen > 60 {
401-
return false
402-
}
403400
}
404401
if len(pkt) < iphLen {
405402
return false
@@ -474,13 +471,16 @@ func tcpGRO(bufs [][]byte, offset int, pktI int, table *tcpGROTable, isV6 bool)
474471
return false
475472
}
476473

477-
func isTCP4(b []byte) bool {
474+
func isTCP4NoIPOptions(b []byte) bool {
478475
if len(b) < 40 {
479476
return false
480477
}
481478
if b[0]>>4 != 4 {
482479
return false
483480
}
481+
if b[0]&0x0F != 5 {
482+
return false
483+
}
484484
if b[9] != unix.IPPROTO_TCP {
485485
return false
486486
}
@@ -511,7 +511,7 @@ func handleGRO(bufs [][]byte, offset int, tcp4Table, tcp6Table *tcpGROTable, toW
511511
}
512512
var coalesced bool
513513
switch {
514-
case isTCP4(bufs[i][offset:]):
514+
case isTCP4NoIPOptions(bufs[i][offset:]): // ipv4 packets w/IP options do not coalesce
515515
coalesced = tcpGRO(bufs, offset, i, tcp4Table, false)
516516
case isTCP6NoEH(bufs[i][offset:]): // ipv6 packets w/extension headers do not coalesce
517517
coalesced = tcpGRO(bufs, offset, i, tcp6Table, true)

tun/tcp_offload_linux_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,3 +271,53 @@ func Test_handleGRO(t *testing.T) {
271271
})
272272
}
273273
}
274+
275+
func Test_isTCP4NoIPOptions(t *testing.T) {
276+
valid := tcp4Packet(ip4PortA, ip4PortB, header.TCPFlagAck, 100, 1)[virtioNetHdrLen:]
277+
invalidLen := valid[:39]
278+
invalidHeaderLen := make([]byte, len(valid))
279+
copy(invalidHeaderLen, valid)
280+
invalidHeaderLen[0] = 0x46
281+
invalidProtocol := make([]byte, len(valid))
282+
copy(invalidProtocol, valid)
283+
invalidProtocol[9] = unix.IPPROTO_TCP + 1
284+
285+
tests := []struct {
286+
name string
287+
b []byte
288+
want bool
289+
}{
290+
{
291+
"valid",
292+
valid,
293+
true,
294+
},
295+
{
296+
"invalid length",
297+
invalidLen,
298+
false,
299+
},
300+
{
301+
"invalid version",
302+
[]byte{0x00},
303+
false,
304+
},
305+
{
306+
"invalid header len",
307+
invalidHeaderLen,
308+
false,
309+
},
310+
{
311+
"invalid protocol",
312+
invalidProtocol,
313+
false,
314+
},
315+
}
316+
for _, tt := range tests {
317+
t.Run(tt.name, func(t *testing.T) {
318+
if got := isTCP4NoIPOptions(tt.b); got != tt.want {
319+
t.Errorf("isTCP4NoIPOptions() = %v, want %v", got, tt.want)
320+
}
321+
})
322+
}
323+
}

0 commit comments

Comments
 (0)