Skip to content

Commit 1ae5855

Browse files
mv nw engine to gvisor netstack, take 1
1 parent 4aaa204 commit 1ae5855

11 files changed

Lines changed: 981 additions & 42 deletions

File tree

go.mod

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/celzero/firestack
22

3-
go 1.15
3+
go 1.18
44

55
require (
66
github.com/Jigsaw-Code/getsni v1.0.0
@@ -14,9 +14,16 @@ require (
1414
github.com/miekg/dns v1.1.43
1515
github.com/txthinking/socks5 v0.0.0-20210716140126-fa1f52a8f2da
1616
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
17-
golang.org/x/net v0.0.0-20210825183410-e898025ed96a
18-
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf
19-
golang.org/x/mobile v0.0.0-20210716004757-34ab1303b554 // indirect
20-
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 // indirect
21-
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
17+
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f
18+
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654
19+
gvisor.dev/gvisor v0.0.0-20220329084425-9638e18d39b3
20+
)
21+
22+
require (
23+
github.com/google/btree v1.0.1 // indirect
24+
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
25+
github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf // indirect
26+
github.com/txthinking/x v0.0.0-20210326105829-476fab902fbe // indirect
27+
golang.org/x/mobile v0.0.0-20220325161704-447654d348e3 // indirect
28+
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
2229
)

go.sum

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=
21
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
32
github.com/Jigsaw-Code/getsni v1.0.0 h1:OUTIu7wTBi/7DMX+RkZrN7XhU3UDevTEsAWK4gsqSwE=
43
github.com/Jigsaw-Code/getsni v1.0.0/go.mod h1:Ps0Ec3fVMKLyAItVbMKoQFq1lDjtFQXZ+G5nRNNh/QE=
5-
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
6-
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635/go.mod h1:lmLxL+FV291OopO93Bwf9fQLQeLyt33VJRUg5VJ30us=
74
github.com/celzero/gotrie v0.0.0-20210413153406-d9d0dcea9cbd h1:hKeS1WzcKkGk/NfOIgTHHFhYgSvKpUEDTtg21VYbPVQ=
85
github.com/celzero/gotrie v0.0.0-20210413153406-d9d0dcea9cbd/go.mod h1:Qo0txkBFM3m4+mXbyY6Pd46jCEUUHRd5C3Y4cSdA7jM=
96
github.com/elazarl/goproxy v0.0.0-20210801061803-8e322dfb79c4 h1:lS3P5Nw3oPO05Lk2gFiYUOL3QPaH+fRoI1wFOc4G1UY=
@@ -12,6 +9,8 @@ github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2 h1:dWB6v3RcOy0
129
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
1310
github.com/eycorsican/go-tun2socks v1.16.11 h1:+hJDNgisrYaGEqoSxhdikMgMJ4Ilfwm/IZDrWRrbaH8=
1411
github.com/eycorsican/go-tun2socks v1.16.11/go.mod h1:wgB2BFT8ZaPKyKOQ/5dljMG/YIow+AIXyq4KBwJ5sGQ=
12+
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
13+
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
1514
github.com/jedisct1/go-clocksmith v0.0.0-20210101121932-da382b963868 h1:QZ79mRbNwYYYmiVjyv+X0NKgYE6nyN1yo3gtEFdzpiE=
1615
github.com/jedisct1/go-clocksmith v0.0.0-20210101121932-da382b963868/go.mod h1:SAINchklztk2jcLWJ4bpNF4KnwDUSUTX+cJbspWC2Rw=
1716
github.com/jedisct1/go-dnsstamps v0.0.0-20210810213811-61cc83d2a354 h1:sIB9mDh2spQdh95jeXF2h9uSNtObbehD0YbDCzmqbM8=
@@ -32,7 +31,7 @@ github.com/txthinking/socks5 v0.0.0-20210716140126-fa1f52a8f2da h1:7x8pJcBTdKTBp
3231
github.com/txthinking/socks5 v0.0.0-20210716140126-fa1f52a8f2da/go.mod h1:7NloQcrxaZYKURWph5HLxVDlIwMHJXCPkeWPtpftsIg=
3332
github.com/txthinking/x v0.0.0-20210326105829-476fab902fbe h1:gMWxZxBFRAXqoGkwkYlPX2zvyyKNWJpxOxCrjqJkm5A=
3433
github.com/txthinking/x v0.0.0-20210326105829-476fab902fbe/go.mod h1:WgqbSEmUYSjEV3B1qmee/PpP2NYEz4bL9/+mF1ma+s4=
35-
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
34+
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
3635
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
3736
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
3837
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -44,19 +43,19 @@ golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9t
4443
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
4544
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
4645
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
47-
golang.org/x/mobile v0.0.0-20210716004757-34ab1303b554 h1:3In5TnfvnuXTF/uflgpYxSCEGP2NdYT37KsPh3VjZYU=
48-
golang.org/x/mobile v0.0.0-20210716004757-34ab1303b554/go.mod h1:jFTmtFYCV0MFtXBU+J5V/+5AUeVS0ON/0WkE/KSrl6E=
46+
golang.org/x/mobile v0.0.0-20220325161704-447654d348e3 h1:ZDL7hDvJEQEcHVkoZawKmRUgbqn1pOIzb8EinBh5csU=
47+
golang.org/x/mobile v0.0.0-20220325161704-447654d348e3/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ=
4948
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
50-
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
5149
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
50+
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
5251
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
5352
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
5453
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
5554
golang.org/x/net v0.0.0-20191021144547-ec77196f6094/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
5655
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
57-
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
58-
golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw=
59-
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
56+
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
57+
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY=
58+
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
6059
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
6160
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
6261
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -65,22 +64,25 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
6564
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
6665
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
6766
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
68-
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
6967
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
70-
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
7168
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
72-
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k=
73-
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
69+
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
70+
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 h1:id054HUawV2/6IGm2IV8KZQjqtwAOo2CYlOToYqa0d0=
71+
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
7472
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
7573
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
7674
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
7775
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
76+
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
77+
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
7878
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
7979
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
8080
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
81-
golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA=
82-
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
81+
golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
82+
golang.org/x/tools v0.1.9 h1:j9KsMiaP1c3B0OTQGth0/k+miLGTgLsAFUCrF2vLcF8=
8383
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
8484
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
8585
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
8686
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
87+
gvisor.dev/gvisor v0.0.0-20220329084425-9638e18d39b3 h1:jeCqiJy17qxcrzQIwflJycPPc5aPa86YbtStTk0hQYU=
88+
gvisor.dev/gvisor v0.0.0-20220329084425-9638e18d39b3/go.mod h1:tWwEcFvJavs154OdjFCw78axNrsDlz4Zh8jvPqwcpGI=

intra/android/tun2socks.go

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@
2121
// See the License for the specific language governing permissions and
2222
// limitations under the License.
2323

24-
package tun2socks
24+
package intra
2525

2626
import (
27+
"errors"
28+
"os"
2729
"runtime/debug"
2830
"strings"
2931

@@ -57,20 +59,28 @@ func init() {
5759
//
5860
// Throws an exception if the TUN file descriptor cannot be opened, or if the tunnel fails to
5961
// connect.
60-
func ConnectIntraTunnel(fd int, fakedns string, dohdns doh.Transport, protector protect.Protector, flow protect.Flow, listener intra.Listener) (intra.Tunnel, error) {
61-
tun, err := tunnel.MakeTunFile(fd)
62+
const gvisor bool = true
63+
const mtu uint32 = 1500
64+
65+
func ConnectIntraTunnel(fd int, fakedns string, dohdns doh.Transport, protector protect.Protector, flow protect.Flow, listener intra.Listener) (t intra.Tunnel, err error) {
66+
dupfd, err := tunnel.Dup(fd)
6267
if err != nil {
6368
return nil, err
6469
}
65-
6670
dialer := protect.MakeDialer(protector)
6771
config := protect.MakeListenConfig(protector)
68-
t, err := intra.NewTunnel(fakedns, dohdns, tun, dialer, flow, config, listener)
69-
if err != nil {
70-
return nil, err
72+
if gvisor {
73+
return intra.NewGTunnel(fakedns, dohdns, fd, mtu, dialer, flow, config, listener)
74+
} else {
75+
// java-land gives up its ownership of fd
76+
tun := os.NewFile(uintptr(dupfd), "")
77+
if tun == nil {
78+
return nil, errors.New("failed to open TUN file descriptor")
79+
}
80+
t, err = intra.NewTunnel(fakedns, dohdns, tun, dialer, flow, config, listener)
81+
go tunnel.ProcessInputPackets(t, tun)
82+
return
7183
}
72-
go tunnel.ProcessInputPackets(t, tun)
73-
return t, nil
7484
}
7585

7686
// NewDoHTransport returns a DNSTransport that connects to the specified DoH server.

intra/netstack/dispatchers.go

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
// Copyright (c) 2022 RethinkDNS and its authors.
2+
//
3+
// This Source Code Form is subject to the terms of the Mozilla Public
4+
// License, v. 2.0. If a copy of the MPL was not distributed with this
5+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
//
7+
// This file incorporates work covered by the following copyright and
8+
// permission notice:
9+
//
10+
// Copyright 2018 The gVisor Authors.
11+
//
12+
// Licensed under the Apache License, Version 2.0 (the "License");
13+
// you may not use this file except in compliance with the License.
14+
// You may obtain a copy of the License at
15+
//
16+
// http://www.apache.org/licenses/LICENSE-2.0
17+
//
18+
// Unless required by applicable law or agreed to in writing, software
19+
// distributed under the License is distributed on an "AS IS" BASIS,
20+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21+
// See the License for the specific language governing permissions and
22+
// limitations under the License.
23+
24+
// Adopted from: github.com/google/gvisor/blob/f33d034/pkg/tcpip/link/fdbased/packet_dispatchers.go
25+
package netstack
26+
27+
import (
28+
"fmt"
29+
30+
"golang.org/x/sys/unix"
31+
"gvisor.dev/gvisor/pkg/tcpip"
32+
"gvisor.dev/gvisor/pkg/tcpip/buffer"
33+
"gvisor.dev/gvisor/pkg/tcpip/header"
34+
"gvisor.dev/gvisor/pkg/tcpip/link/rawfile"
35+
"gvisor.dev/gvisor/pkg/tcpip/stack"
36+
)
37+
38+
// BufConfig defines the shape of the vectorised view used to read packets from the NIC.
39+
var BufConfig = []int{128, 256, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768}
40+
41+
type iovecBuffer struct {
42+
// views are the actual buffers that hold the packet contents.
43+
views []buffer.View
44+
45+
// iovecs are initialized with base pointers/len of the corresponding
46+
// entries in the views defined above, except when GSO is enabled
47+
// (skipsVnetHdr) then the first iovec points to a buffer for the vnet header
48+
// which is stripped before the views are passed up the stack for further
49+
// processing.
50+
iovecs []unix.Iovec
51+
52+
// sizes is an array of buffer sizes for the underlying views. sizes is
53+
// immutable.
54+
sizes []int
55+
56+
// skipsVnetHdr is true if virtioNetHdr is to skipped.
57+
//skipsVnetHdr bool
58+
}
59+
60+
func newIovecBuffer(sizes []int) *iovecBuffer {
61+
b := &iovecBuffer{
62+
views: make([]buffer.View, len(sizes)),
63+
sizes: sizes,
64+
// skipsVnetHdr: skipsVnetHdr,
65+
}
66+
/*niov := len(b.views)
67+
if b.skipsVnetHdr {
68+
niov++
69+
}
70+
b.iovecs = make([]unix.Iovec, niov)*/
71+
b.iovecs = make([]unix.Iovec, len(b.views))
72+
return b
73+
}
74+
75+
func (b *iovecBuffer) nextIovecs() []unix.Iovec {
76+
vnetHdrOff := 0
77+
/* if b.skipsVnetHdr {
78+
var vnetHdr [virtioNetHdrSize]byte
79+
// The kernel adds virtioNetHdr before each packet, but
80+
// we don't use it, so so we allocate a buffer for it,
81+
// add it in iovecs but don't add it in a view.
82+
b.iovecs[0] = unix.Iovec{Base: &vnetHdr[0]}
83+
b.iovecs[0].SetLen(virtioNetHdrSize)
84+
vnetHdrOff++
85+
}
86+
*/for i := range b.views {
87+
if b.views[i] != nil {
88+
break
89+
}
90+
v := buffer.NewView(b.sizes[i])
91+
b.views[i] = v
92+
b.iovecs[i+vnetHdrOff] = unix.Iovec{Base: &v[0]}
93+
b.iovecs[i+vnetHdrOff].SetLen(len(v))
94+
}
95+
return b.iovecs
96+
}
97+
98+
func (b *iovecBuffer) pullViews(n int) buffer.VectorisedView {
99+
var views []buffer.View
100+
c := 0
101+
/* if b.skipsVnetHdr {
102+
c += virtioNetHdrSize
103+
if c >= n {
104+
// Nothing in the packet.
105+
return buffer.NewVectorisedView(0, nil)
106+
}
107+
}*/
108+
for i, v := range b.views {
109+
c += len(v)
110+
if c >= n {
111+
b.views[i].CapLength(len(v) - (c - n))
112+
views = append([]buffer.View(nil), b.views[:i+1]...)
113+
break
114+
}
115+
}
116+
// Remove the first len(views) used views from the state.
117+
for i := range views {
118+
b.views[i] = nil
119+
}
120+
/* if b.skipsVnetHdr {
121+
// Exclude the size of the vnet header.
122+
n -= virtioNetHdrSize
123+
}*/
124+
return buffer.NewVectorisedView(n, views)
125+
}
126+
127+
// stopFd is an eventfd used to signal the stop of a dispatcher.
128+
type stopFd struct {
129+
efd int
130+
}
131+
132+
func newStopFd() (stopFd, error) {
133+
efd, err := unix.Eventfd(0, unix.EFD_NONBLOCK)
134+
if err != nil {
135+
return stopFd{efd: -1}, fmt.Errorf("failed to create eventfd: %w", err)
136+
}
137+
return stopFd{efd: efd}, nil
138+
}
139+
140+
// stop writes to the eventfd and notifies the dispatcher to stop. It does not
141+
// block.
142+
func (s *stopFd) stop() {
143+
increment := []byte{1, 0, 0, 0, 0, 0, 0, 0}
144+
if n, err := unix.Write(s.efd, increment); n != len(increment) || err != nil {
145+
// There are two possible errors documented in eventfd(2) for writing:
146+
// 1. We are writing 8 bytes and not 0xffffffffffffff, thus no EINVAL.
147+
// 2. stop is only supposed to be called once, it can't reach the limit,
148+
// thus no EAGAIN.
149+
panic(fmt.Sprintf("write(efd) = (%d, %s), want (%d, nil)", n, err, len(increment)))
150+
}
151+
}
152+
153+
// readVDispatcher uses readv() system call to read inbound packets and
154+
// dispatches them.
155+
type readVDispatcher struct {
156+
stopFd
157+
// fd is the file descriptor used to send and receive packets.
158+
fd int
159+
160+
// e is the endpoint this dispatcher is attached to.
161+
e *endpoint
162+
163+
// buf is the iovec buffer that contains the packet contents.
164+
buf *iovecBuffer
165+
}
166+
167+
func newReadVDispatcher(fd int, e *endpoint) (linkDispatcher, error) {
168+
stopFd, err := newStopFd()
169+
if err != nil {
170+
return nil, err
171+
}
172+
d := &readVDispatcher{
173+
stopFd: stopFd,
174+
fd: fd,
175+
e: e,
176+
}
177+
178+
// skipsVnetHdr := d.e.gsoKind == stack.HWGSOSupported
179+
d.buf = newIovecBuffer(BufConfig)
180+
return d, nil
181+
}
182+
183+
// dispatch reads one packet from the file descriptor and dispatches it.
184+
func (d *readVDispatcher) dispatch() (bool, tcpip.Error) {
185+
n, err := rawfile.BlockingReadvUntilStopped(d.efd, d.fd, d.buf.nextIovecs())
186+
if n <= 0 || err != nil {
187+
return false, err
188+
}
189+
190+
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
191+
Data: d.buf.pullViews(n),
192+
})
193+
defer pkt.DecRef()
194+
195+
var p tcpip.NetworkProtocolNumber
196+
// hdrSize always zero; unused
197+
if d.e.hdrSize > 0 {
198+
hdr, ok := pkt.LinkHeader().Consume(d.e.hdrSize)
199+
if !ok {
200+
return false, nil
201+
}
202+
p = header.Ethernet(hdr).Type()
203+
} else {
204+
// We don't get any indication of what the packet is, so try to guess
205+
// if it's an IPv4 or IPv6 packet.
206+
// IP version information is at the first octet, so pulling up 1 byte.
207+
h, ok := pkt.Data().PullUp(1)
208+
if !ok {
209+
return true, nil
210+
}
211+
switch header.IPVersion(h) {
212+
case header.IPv4Version:
213+
p = header.IPv4ProtocolNumber
214+
case header.IPv6Version:
215+
p = header.IPv6ProtocolNumber
216+
default:
217+
return true, nil
218+
}
219+
}
220+
221+
d.e.dispatcher.DeliverNetworkPacket(p, pkt)
222+
223+
return true, nil
224+
}

0 commit comments

Comments
 (0)