@@ -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