Allow packet forwarding with address-less interfaces
This should fix #7184 by allowing packet forwarding to take place even if the interface doesn't have an address assigned.
This is done by:
- accepting the route, using the remote address as a gateway, if there's no address endpoint;
- ensuring that we find the route with the longest prefix length, given that there might be more than one route available that covers the address — we always want the most specific route;
- making finding the local address endpoint optional in a couple of places so we don't panic if it is
nil.
First PR here — go easy on me. 😄
cc @hbhasker
Apologies, I've apparently done something terrible to the PR trying to rebase from a working commit on the go branch. Trying to revert.
Any chance we can get a re-review on this? I think I've addressed the concerns.
@ghanan94 Sorry to nag, but trying to push this forward so we can use it in a project.
This change needs tests, see stack_test.go and tests/integration/forward_test.go for examples
@ghanan94 Thanks for looking over it again, I'll take another look.
As for unit tests, I'd gladly write some, but I have never been able to get your unit tests to run successfully. For example, on the master branch:
sh-3.2$ go test ./pkg/tcpip/stack/
# gvisor.dev/gvisor/pkg/buffer
pkg/buffer/buffer.go:28:2: undefined: bufferEntry
pkg/buffer/view.go:31:7: undefined: bufferList
# gvisor.dev/gvisor/pkg/waiter
pkg/waiter/waiter.go:139:2: undefined: waiterEntry
pkg/waiter/waiter.go:210:7: undefined: waiterList
FAIL gvisor.dev/gvisor/pkg/tcpip/stack [build failed]
FAIL
... and trying to run anything under bazel test yields a whole load of errors about malformed module path and countless gazelle errors. Is there some secret I should know here? I'm working on macOS if that helps.
Are you building on MacOS? Or are you using a VM ( I am assuming a VM on MacOS?). if you can provide more details on what errors you are seeing with bazel we can help.
@hbhasker I am working (or trying to work) on macOS natively.
go test ./... is completely unusable because the build tags across the project are seemingly all over the place:
% go test ./pkg/tcpip/...
pkg/tcpip/transport/raw/endpoint.go:38:2: found packages transport (datagram.go) and datagram (datagram_test.go) in /workspaces/gvisor/pkg/tcpip/transport
found packages fifo (fifo.go) and qdisc (qdisc_test.go) in /workspaces/gvisor/pkg/tcpip/link/qdisc/fifo
found packages sharedmem (queuepair.go) and sharedmem_server (sharedmem_server_test.go) in /workspaces/gvisor/pkg/tcpip/link/sharedmem
found packages forward (forward_test.go) and iptables (iptables_test.go) in /workspaces/gvisor/pkg/tcpip/tests/integration
pkg/tcpip/transport/raw/endpoint.go:38:2: found packages transport (datagram.go) and datagram (datagram_test.go) in /workspaces/gvisor/pkg/tcpip/transport
found packages dual_stack (dual_stack_test.go) and e2e (e2e.go) in /workspaces/gvisor/pkg/tcpip/transport/tcp/test/e2e
pkg/tcpip/transport/testing/context/context.go:25:2: found packages refsvfs2 (refs.go) and refs_template (refs_template.go) in /workspaces/gvisor/pkg/refsvfs2
make unit-tests yields:
% make unit-tests
readlink: illegal option -- m
usage: readlink [-fn] [file ...]
readlink: illegal option -- m
usage: readlink [-fn] [file ...]
readlink: illegal option -- m
usage: readlink [-fn] [file ...]
stat: illegal option -- c
usage: stat [-FLnq] [-f format | -l | -r | -s | -x] [-t timefmt] [file ...]
--- PULL default
55d79ad85b9aa103: Pulling from gvisor-presubmit/default_x86_64
Digest: sha256:0e40a2903c3de1adde1b3389cc7a604c7af5fe981e2cddf6dc63d1d5991c1ff4
Status: Image is up to date for gcr.io/gvisor-presubmit/default_x86_64:55d79ad85b9aa103
gcr.io/gvisor-presubmit/default_x86_64:55d79ad85b9aa103
--- DOCKER BUILD
gvisor-builder-d41d8cd9-x86_64
groupadd: invalid group ID '--non-unique'
--- TEST --build_tag_filters=-nogo --test_tag_filters=-nogo --test_filter=-//runsc/container/... //:all pkg/... tools/... runsc/... vdso/...
Error: No such container: gvisor-bazel-d41d8cd9-x86_64
make: *** [unit-tests] Error 1
... and that's after installing Docker for Mac brew install coreutils — if you don't do that, you don't even get that far because of missing sha256sum for example.
bazel test pkg/tcpip yields:
% bazel test pkg/tcpip
DEBUG: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/bazel_toolchains/rules/rbe_repo/version_check.bzl:68:14:
Current running Bazel is ahead of bazel-toolchains repo. Please update your pin to bazel-toolchains repo in your WORKSPACE file.
DEBUG: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/bazel_toolchains/rules/rbe_repo/checked_in.bzl:125:14: rbe_default not using checked in configs; Bazel version 5.1.1 was picked/selected but no checked in config was found in map {"0.20.0": ["8.0.0"], "0.21.0": ["8.0.0"], "0.22.0": ["8.0.0", "9.0.0"], "0.23.0": ["8.0.0", "9.0.0"], "0.23.1": ["8.0.0", "9.0.0"], "0.23.2": ["9.0.0"], "0.24.0": ["9.0.0"], "0.24.1": ["9.0.0"], "0.25.0": ["9.0.0"], "0.25.1": ["9.0.0"], "0.25.2": ["9.0.0"], "0.26.0": ["9.0.0"], "0.26.1": ["9.0.0"], "0.27.0": ["9.0.0"], "0.27.1": ["9.0.0"], "0.28.0": ["9.0.0"], "0.28.1": ["9.0.0"], "0.29.0": ["9.0.0"], "0.29.1": ["9.0.0", "10.0.0"], "1.0.0": ["9.0.0", "10.0.0"], "1.0.1": ["10.0.0"], "1.1.0": ["10.0.0"], "1.2.0": ["10.0.0"], "1.2.1": ["10.0.0"], "2.0.0": ["10.0.0"], "2.1.0": ["10.0.0"], "2.1.1": ["10.0.0", "11.0.0"], "2.2.0": ["11.0.0"], "3.0.0": ["11.0.0"], "3.1.0": ["11.0.0"], "3.2.0": ["11.0.0"], "3.3.0": ["11.0.0"], "3.3.1": ["11.0.0"], "3.4.1": ["11.0.0"], "3.5.0": ["11.0.0"], "3.5.1": ["11.0.0"], "3.6.0": ["11.0.0"], "3.7.0": ["11.0.0"], "3.7.1": ["11.0.0"], "3.7.2": ["11.0.0"], "4.0.0": ["11.0.0"]}
WARNING: Download from https://mirror.bazel.build/github.com/bazelbuild/rules_cc/archive/b7fe9697c0c76ab2fd431a891dbb9a6a32ed7c3e.zip failed: class java.io.FileNotFoundException GET returned 404 Not Found
DEBUG: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/bazel_gazelle/internal/go_repository.bzl:209:18: org_golang_x_tools: gazelle: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/cmd/fiximports/testdata/src/old.com/bad/bad.go: error reading go file: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/cmd/fiximports/testdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF'
gazelle: found packages conversions (conversions.go) and notinheap (notinheap.go) in /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/go/internal/gccgoimporter/testdata
gazelle: found packages exports (exports.go) and p (issue15920.go) in /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/go/internal/gcimporter/testdata
gazelle: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/go/loader/testdata/badpkgdecl.go: error reading go file: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/go/loader/testdata/badpkgdecl.go:1:34: expected 'package', found 'EOF'
gazelle: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/go/packages/packagestest/testdata/groups/two/modules/example.com/extra/geez/help.go: error reading go file: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/go/packages/packagestest/testdata/groups/two/modules/example.com/extra/geez/help.go:1:16: expected ';', found '.'
gazelle: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/go/packages/packagestest/testdata/groups/two/modules/example.com/extra/v2/geez/help.go: error reading go file: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/go/packages/packagestest/testdata/groups/two/modules/example.com/extra/v2/geez/help.go:1:16: expected ';', found '.'
gazelle: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/go/packages/packagestest/testdata/groups/two/modules/example.com/extra/v2/me.go: error reading go file: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/go/packages/packagestest/testdata/groups/two/modules/example.com/extra/v2/me.go:1:16: expected ';', found '.'
gazelle: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/go/packages/packagestest/testdata/groups/two/modules/example.com/extra/yo.go: error reading go file: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/go/packages/packagestest/testdata/groups/two/modules/example.com/extra/yo.go:1:16: expected ';', found '.'
gazelle: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/go/packages/packagestest/testdata/groups/two/modules/example.com/tempmod/main.go: error reading go file: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/go/packages/packagestest/testdata/groups/two/modules/example.com/tempmod/main.go:1:16: expected ';', found '.'
gazelle: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/go/packages/packagestest/testdata/groups/two/modules/example.com/[email protected]/main.go: error reading go file: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/go/packages/packagestest/testdata/groups/two/modules/example.com/[email protected]/main.go:1:16: expected ';', found '.'
gazelle: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/go/packages/packagestest/testdata/groups/two/modules/example.com/[email protected]/main.go: error reading go file: /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/go/packages/packagestest/testdata/groups/two/modules/example.com/[email protected]/main.go:1:16: expected ';', found '.'
gazelle: found packages A1 (A1.go) and A2 (A2.go) in /private/var/tmp/_bazel_neilalexander/0da0b4403ea0d47357628deafc2cb8f2/external/org_golang_x_tools/refactor/eg/testdata
gazelle: finding module path for import domain.name/importdecl: go get: unrecognized import path "domain.name/importdecl": https fetch: Get "https://domain.name/importdecl?go-get=1": dial tcp: lookup domain.name: no such host
gazelle: finding module path for import old.com/one: go get: unrecognized import path "old.com/one": https fetch: Get "http://www.old.com/one?go-get=1": redirected from secure URL https://old.com/one?go-get=1 to insecure URL http://www.old.com/one?go-get=1
gazelle: finding module path for import titanic.biz/bar: go get: unrecognized import path "titanic.biz/bar": reading https://titanic.biz/bar?go-get=1: 403 Forbidden
gazelle: finding module path for import titanic.biz/foo: go get: unrecognized import path "titanic.biz/foo": reading https://titanic.biz/foo?go-get=1: 403 Forbidden
gazelle: finding module path for import fruit.io/pear: go get: unrecognized import path "fruit.io/pear": https fetch: Get "https://fruit.io/pear?go-get=1": x509: certificate is valid for *.gridserver.com, gridserver.com, not fruit.io
gazelle: finding module path for import fruit.io/banana: go get: unrecognized import path "fruit.io/banana": https fetch: Get "https://fruit.io/banana?go-get=1": x509: certificate is valid for *.gridserver.com, gridserver.com, not fruit.io
gazelle: finding module path for import lib: go get: malformed module path "lib": missing dot in first path element
gazelle: finding module path for import nosuchpkg: go get: malformed module path "nosuchpkg": missing dot in first path element
gazelle: finding module path for import lib: go get: malformed module path "lib": missing dot in first path element
gazelle: finding module path for import nosuchpkg: go get: malformed module path "nosuchpkg": missing dot in first path element
gazelle: finding module path for import lib: go get: malformed module path "lib": missing dot in first path element
gazelle: finding module path for import lib: go get: malformed module path "lib": missing dot in first path element
gazelle: finding module path for import lib: go get: malformed module path "lib": missing dot in first path element
gazelle: finding module path for import lib: go get: malformed module path "lib": missing dot in first path element
gazelle: finding module path for import lib: go get: malformed module path "lib": missing dot in first path element
gazelle: finding module path for import lib: go get: malformed module path "lib": missing dot in first path element
gazelle: finding module path for import lib: go get: malformed module path "lib": missing dot in first path element
gazelle: finding module path for import referrers: go get: malformed module path "referrers": missing dot in first path element
gazelle: finding module path for import lib: go get: malformed module path "lib": missing dot in first path element
gazelle: finding module path for import lib: go get: malformed module path "lib": missing dot in first path element
gazelle: finding module path for import typeparams/lib: go get: malformed module path "typeparams/lib": missing dot in first path element
gazelle: finding module path for import lib: go get: malformed module path "lib": missing dot in first path element
gazelle: finding module path for import a: go get: malformed module path "a": missing dot in first path element
gazelle: finding module path for import b: go get: malformed module path "b": missing dot in first path element
gazelle: finding module path for import b: go get: malformed module path "b": missing dot in first path element
gazelle: finding module path for import a: go get: malformed module path "a": missing dot in first path element
gazelle: finding module path for import a: go get: malformed module path "a": missing dot in first path element
gazelle: finding module path for import a: go get: malformed module path "a": missing dot in first path element
gazelle: finding module path for import b: go get: malformed module path "b": missing dot in first path element
gazelle: finding module path for import typeparams/userdefs: go get: malformed module path "typeparams/userdefs": missing dot in first path element
gazelle: finding module path for import a: go get: malformed module path "a": missing dot in first path element
gazelle: finding module path for import b: go get: malformed module path "b": missing dot in first path element
gazelle: finding module path for import testdata/groups/two/expect: go get: malformed module path "testdata/groups/two/expect": missing dot in first path element
gazelle: finding module path for import b: go get: malformed module path "b": missing dot in first path element
gazelle: finding module path for import a: go get: malformed module path "a": missing dot in first path element
gazelle: finding module path for import encoding/utf8: go get: malformed module path "encoding/utf8": missing dot in first path element
INFO: Analyzed target //pkg/tcpip:tcpip (0 packages loaded, 0 targets configured).
INFO: Found 1 target and 0 test targets...
Target //pkg/tcpip:tcpip up-to-date:
bazel-bin/pkg/tcpip/tcpip.a
INFO: Elapsed time: 0.191s, Critical Path: 0.03s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
INFO: Build completed successfully, 1 total action
@ghanan94
We do bestLocalAddr = localAddr now but localAddr is never updated. Am i missing something?
Can we test this scenario?
I don't understand the question here. localAddr is supplied as an argument into the function. Why would we mutate it?
what is "closer source address"
If i'm parsing this CL correctly, bestLocalAddr will only ever be "" or localAddr
am i missing something?
edit: It is growing more apparent that I don't understand the shape of FindRoute and constructAndValidateRoute as a whole — this code is not well commented/documented at all. You are probably right.
What I am trying to express is that if the chosen interface as per the routing table doesn't have an IP address of its own, we should choose the closest source address to the destination address from our other interfaces. That way we have a source address for local TCP or UDP sockets, even if the chosen interface by longest-prefix match against the routing table doesn't have an address of its own.
The point here though is that the longest-prefix match from the routing table should always win, irrespective of the IP addresses on each interface.
Is this blocked on something?
@neilalexander Do you need anything from us to move this forward?
Is this blocked on something?
@neilalexander Do you need anything from us to move this forward?
Hi @hbhasker, at this point I’m not at all sure how to progress. I don’t think I understand the many side effects of FindRoute and constructAndValidateRoute on source address selection and I still haven’t been able to wrangle bazel and the tests. I’m not sure whether to just abandon the PR.
I do not believe our builds can run natively on macos at all. You would need to use a linux VM to do the builds. That said, if you think that you won't have the time to move this forward then we could find someone on our team to take this over and get this done as the route selection is a requirement for us as well especially for IPv4.
https://github.com/google/gvisor/pull/7281#issuecomment-1119405316
Pretty much see this error at master:7dbe1e6, too. I am building gvisor with gomobile on Linux cross-compiling it for android/arm64 with go1.18. Note that, go:9638e18 builds just fine, but go:e8883fa doesn't.
Btw, go install gvisor.dev/gvisor@go doesn't work and complains package's missing; but go get gvisor.dev/gvisor@latest does.
A friendly reminder that this PR had no activity for 120 days.
This PR has been closed due to lack of activity.