Skip to content

Commit 0cb2c92

Browse files
authored
[connect-ip] batched tun reads atleast (#44)
1 parent 89aa099 commit 0cb2c92

File tree

1 file changed

+34
-19
lines changed

1 file changed

+34
-19
lines changed

pkg/tunnel/connection/splice.go

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,55 +18,70 @@ const (
1818
tunOffset = device.MessageTransportHeaderSize
1919
)
2020

21-
func Splice(tun tun.Device, conn Connection) error {
21+
func Splice(tunDev tun.Device, conn Connection) error {
2222
var g errgroup.Group
2323

24+
batchSize := tunDev.BatchSize()
25+
2426
g.Go(func() error {
2527
defer conn.Close()
2628

27-
var pkt [netstack.IPv6MinMTU]byte
28-
sizes := make([]int, 1)
29+
sizes := make([]int, batchSize)
30+
pkts := make([][]byte, batchSize)
31+
for i := range pkts {
32+
pkts[i] = make([]byte, netstack.IPv6MinMTU)
33+
}
2934

3035
for {
31-
_, err := tun.Read([][]byte{pkt[:]}, sizes, 0)
36+
n, err := tunDev.Read(pkts, sizes, 0)
3237
if err != nil {
38+
if errors.Is(err, tun.ErrTooManySegments) {
39+
slog.Warn("Dropped packets from multi-segment TUN read", slog.Any("error", err))
40+
continue
41+
}
3342
if strings.Contains(err.Error(), "closed") {
3443
slog.Debug("TUN device closed")
3544
return nil
3645
}
37-
3846
return fmt.Errorf("failed to read from TUN: %w", err)
3947
}
4048

41-
slog.Debug("Read packet from TUN", slog.Int("len", sizes[0]))
49+
for i := 0; i < n; i++ {
50+
slog.Debug("Read packet from TUN", slog.Int("len", sizes[i]))
4251

43-
icmp, err := conn.WritePacket(pkt[:sizes[0]])
44-
if err != nil {
45-
slog.Error("Failed to write to connection", slog.Any("error", err))
46-
continue
47-
}
48-
if len(icmp) > 0 {
49-
slog.Debug("Sending ICMP packet")
50-
51-
if _, err := tun.Write([][]byte{icmp}, 0); err != nil {
52-
slog.Error("Failed to write ICMP packet", slog.Any("error", err))
52+
icmp, err := conn.WritePacket(pkts[i][:sizes[i]])
53+
if err != nil {
54+
slog.Error("Failed to write to connection", slog.Any("error", err))
55+
continue
56+
}
57+
if len(icmp) > 0 {
58+
slog.Debug("Sending ICMP packet")
59+
if _, err := tunDev.Write([][]byte{icmp}, 0); err != nil {
60+
slog.Error("Failed to write ICMP packet", slog.Any("error", err))
61+
}
5362
}
5463
}
5564
}
5665
})
5766

5867
g.Go(func() error {
59-
var pkt [netstack.IPv6MinMTU + tunOffset]byte
68+
pkts := make([][]byte, batchSize)
69+
for i := range pkts {
70+
pkts[i] = make([]byte, netstack.IPv6MinMTU+tunOffset)
71+
}
72+
73+
// TODO: batched write to TUN device, unfortunately ReadPacket() is blocking
74+
// and not batched which makes this tricky.
6075

6176
for {
62-
n, err := conn.ReadPacket(pkt[tunOffset:])
77+
n, err := conn.ReadPacket(pkts[0][tunOffset:])
6378
if err != nil {
6479
return fmt.Errorf("failed to read from connection: %w", err)
6580
}
6681

6782
slog.Debug("Read from connection", slog.Int("bytes", n))
6883

69-
if _, err := tun.Write([][]byte{pkt[:n+tunOffset]}, tunOffset); err != nil {
84+
if _, err := tunDev.Write([][]byte{pkts[0][:n+tunOffset]}, tunOffset); err != nil {
7085
slog.Error("Failed to write to TUN", slog.Any("error", err))
7186
continue
7287
}

0 commit comments

Comments
 (0)