72 Commits
Author SHA1 Message Date
Nayana BidariandgVisor bot e6b6f2aa11 Allow IPv6 addresses to be enabled/disabled in runsc based on the sysctl.
By default in runsc, we have both IPv4 and IPv6 addresses enabled on all the
interfaces. However, in runc this is based on the sysctl
net.ipv6.conf.all.disable_ipv6. This CL will make runsc behave similar to runc.
- If net.ipv6.conf.all.disable_ipv6 is > 0, then only IPv4 addresses will be
enabled on the interfaces including loopback when network mode is "sandbox".

PiperOrigin-RevId: 737656607
2025-03-17 10:10:46 -07:00
Kevin KrakauerandgVisor bot 47dade3f98 runsc: don't error with --reproduce-nftables when there are no nftables rules
It's not an error for there to be no rules worth scraping. It just means we
don't have to do anything.

PiperOrigin-RevId: 683815384
2024-10-08 17:15:01 -07:00
gVisor bot 079c1a937b Merge pull request #9551 from amysaq2023:support-external-stack
PiperOrigin-RevId: 677933413
2024-09-23 14:12:32 -07:00
Ayush RanjanandgVisor bot 19f6b0c07f Use /proc/sys/net/core/dev_weight to determine if we are in the root netns.
After 19249c0724f2 ("net: make net.core.{r,w}mem_{default,max} namespaced")
/proc/sys/net/core/rmem_default is present in non-initial netns as well.

/proc/sys/net/core/dev_weight has existed from the beginning of Linux git repo
in 1da177e4c3f4 ("Linux-2.6.12-rc2"). So it should be safe to use this file.

Demo:
```
$ sudo ip netns add foo
$ sudo ip netns exec foo stat /proc/sys/net/core/dev_weight
stat: cannot statx '/proc/sys/net/core/dev_weight': No such file or directory
$ sudo ip netns delete foo
```

Fixes #10704

PiperOrigin-RevId: 658087447
2024-07-31 11:50:13 -07:00
Anqi Shen 56f2530dad Support plugin network stack
This commit supports a third-party network stack as a plugin stack for
gVisor.

The overall plugin package structure is the following:

- pkg/sentry/socket/plugin:
  Interfaces for initializing plugin network stack. It will be used
  in network setting up during sandbox creating.

- pkg/sentry/socket/plugin/stack:
  Glue layer for plugin stack's socket and stack ops with sentry. It
  will also register plugin stack operations if imported.

- pkg/sentry/socket/plugin/cgo:
  Interfaces defined in C for plugin network stack to support.

To build target runsc-plugin-stack, which imports
pkg/sentry/socket/plugin/stack package and enables CGO:

bazel build --config=plugin-tldk runsc:runsc-plugin-stack

(i.e. --config=plugin-tldk indicates that using TLDK as plugin stack)

By using runsc-plugin-stack binary and setting "--network=plugin" in
runtimeArgs, user can use third-party network stack instead of
netstack embedded in gVisor to get better network performance.

Redis benchmark with following setups:
1. KVM platform
2. 4 physical cores for target pod
3. target pod as redis server

Runc:
$redis-benchmark -h [target ip] -n 100000 -t get,set -q
SET: 115207.38 requests per second, p50=0.215 msec
GET: 92336.11 requests per second, p50=0.279 msec

$redis-benchmark -h [target ip] -n 100000 -t get,set -q
SET: 113895.21 requests per second, p50=0.247 msec
GET: 96899.23 requests per second, p50=0.271 msec

$redis-benchmark -h [target ip] -n 100000 -t get,set -q
SET: 126582.27 requests per second, p50=0.199 msec
GET: 95969.28 requests per second, p50=0.271 msec

Runsc with plugin stack:
$redis-benchmark -h [target ip] -n 100000 -t get,set -q
SET: 123915.74 requests per second, p50=0.343 msec
GET: 115473.45 requests per second, p50=0.335 msec

$redis-benchmark -h [target ip] -n 100000 -t get,set -q
SET: 120918.98 requests per second, p50=0.351 msec
GET: 117647.05 requests per second, p50=0.351 msec

$redis-benchmark -h [target ip] -n 100000 -t get,set -q
SET: 119904.08 requests per second, p50=0.367 msec
GET: 112739.57 requests per second, p50=0.375 msec

Runsc with netstack:
$redis-benchmark -h [target ip] -n 100000 -t get,set -q
SET: 59952.04 requests per second, p50=0.759 msec
GET: 61162.08 requests per second, p50=0.631 msec

$redis-benchmark -h [target ip] -n 100000 -t get,set -q
SET: 52219.32 requests per second, p50=0.719 msec
GET: 58719.91 requests per second, p50=0.663 msec

$redis-benchmark -h [target ip] -n 100000 -t get,set -q
SET: 59952.04 requests per second, p50=0.751 msec
GET: 60827.25 requests per second, p50=0.751 msec

Updates https://github.com/google/gvisor/issues/9266

Co-developed-by: Tianyu Zhou <wentong.zty@antgroup.com>
Signed-off-by: Anqi Shen <amy.saq@antgroup.com>
2024-07-12 09:10:13 +00:00
Ayush RanjanandgVisor bot 94c5177409 Add net-disconnect-ok flag to enable CapabilityDisconnectOk for link endpoints.
This allows save to proceed while there are open TCP connections. Those
connections are closed upon save.

PiperOrigin-RevId: 634800042
2024-05-17 09:28:45 -07:00
Lucas ManningandgVisor bot 5cecdfbabd Create configuration for fdbased processor goroutines.
This configuration doesn't do anything right now, the implementation is
in the child change.

PiperOrigin-RevId: 627194527
2024-04-22 16:47:19 -07:00
Kevin KrakauerandgVisor bot 336193e33a make GRO/GSO variable names more consistent with Go style
PiperOrigin-RevId: 622294934
2024-04-05 15:24:04 -07:00
Kevin KrakauerandgVisor bot c9964aa985 netstack: remove GRO from ingress flow
GRO is getting moved and updated. This removes it in preparation for a
follow-up CL.

PiperOrigin-RevId: 621984030
2024-04-04 15:17:08 -07:00
Kevin KrakauerandgVisor bot ddb7a38802 netstack: remove several layers of interface nesting of LinkEndpoints
runsc's NICs will just have an fdbased LinkEndpoint to write to unless the user
asks for packet logging. Before, a write from the NIC to its endpoint would go
something like:

- sniffer.endpoint.WritePackets
- packetsocket.endpoint.WritePackets
- nested.Endpoint.WritePackets
- fdbased.endpoint.WritePackets

In addition to the extra work done in some of these steps, and the slowness of
interface calls in a hot path, directly calling into an fdbased.endpoint opens
up additional optimizations (see other CLs in this chain). For example, if the
qdisc knows it's talking to an fdbased.endpoint, it can pass in persistent
structs (iovecs, mmsghdrs) rather than re-allocating them in every call to
WritePackets.

PiperOrigin-RevId: 615499448
2024-03-13 12:07:50 -07:00
Kevin KrakauerandgVisor bot 9e2db2c131 xdp: add a tunnel mode to avoid sharing UMEM among sandboxes
The existing redirect mode uses XDP to maximize performance but is not suitably
secure: packets are copied directly from the driver into a userspace buffer
(UMEM). But because the UMEM is shared among all processes with a socket open
on a particular NIC queue, sandboxes using redirect mode all map the same UMEM
and thus can read each other's packets.

Tunnel mode instead installs an eBPF program that copies packets from the
host's NIC driver into a per-sandbox NIC driver. This incurs an additional
copy, but there is no longer memory shared between sandboxes.

Benchmarking tunnel mode with redis-benchmark shows a performance gain over
standard Docker networking of 20%. Redirect mode showed a 30% improvement.

PiperOrigin-RevId: 595746162
2024-01-04 10:45:43 -08:00
Kevin KrakauerandgVisor bot 0bb4cfdc4b xdp: clean up the XDP flag situation
A single flag now controls XDP. More modes will be added as we test XDP, and we
don't want to proliferate confusing flags.

PiperOrigin-RevId: 595502921
2024-01-03 14:26:18 -08:00
Kevin KrakauerandgVisor bot 6beb925dfd xdp: add flag for runsc to use an XDP socket on a host device
In combination with `xdp_loader redirect`, this allows `runsc` to receive
packets directly from any NIC. It is intended to be used with a machine's NIC
to avoid the Linux networking stack entirely.

PiperOrigin-RevId: 591090544
2023-12-14 17:02:25 -08:00
Kevin KrakauerandgVisor bot fc97f86c3b xdp: put runsc XDP code into its own file
This is just a copy-paste so that later CLs are more readable. There are no
behavior changes or other refactoring.

PiperOrigin-RevId: 591006056
2023-12-14 11:43:40 -08:00
Kevin KrakauerandgVisor bot e7e8d0f971 runsc: workaround for scraping nftables
This feature is flag-gated because it can increase runsc startup time by
spawning several child processes.

Testing is done via shell script rather than the usually-preferred Go Docker
API because `docker network create` installs a bunch of iptables rules, whereas
the analagous API calls do not.

PiperOrigin-RevId: 582848436
2023-11-15 16:53:23 -08:00
Kevin KrakauerandgVisor bot 40ee36ac4c Automated rollback of changelist 580051079
PiperOrigin-RevId: 580649803
2023-11-08 14:04:04 -08:00
Kevin KrakauerandgVisor bot b988b57921 runsc: reproduce NAT table inside gVisor only when non-default
... instead of depending on a flag.

In most cases the NAT table is in an all-ACCEPT default state:

```
root@5a7ce3a6c623:/# iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
```

In such cases we leave iptables off in the sandbox as a performance
optimization.

But when the table contains anything else, we now install those rules inside
the sandbox.

Turns out packetdrill installes a rule, so support for that rules is also added
in this CL.

PiperOrigin-RevId: 580051079
2023-11-06 22:05:48 -08:00
Kevin KrakauerandgVisor bot c011b6ad79 runsc: use a pipe for the NAT blob
This is just a little easier than creating and deleting a temp file.

PiperOrigin-RevId: 578575893
2023-11-01 11:11:36 -07:00
Kevin KrakauerandgVisor bot b119cc3116 runsc: add flag --EXPERIMENTAL-reproduce-nat
PiperOrigin-RevId: 578393763
2023-10-31 21:52:13 -07:00
Kevin Krakauer 3a9134c2f0 netstack: benchmark xdp endpoint
This just swaps out the fdbased endpoint for an XDP one. Some related
changes in here:

- Moved the AF_XDP BPF program into its own Go package so it can be
  shared.
- Added a flag to tcp_benchmark to disable user namespaces. This helps
  when running as root, which is required to install BPF programs.
2023-08-31 11:09:15 -07:00
gVisor bot dc0093bb24 Merge pull request #9283 from tianyuzhou95:albert-socket
PiperOrigin-RevId: 557865949
2023-08-17 10:32:58 -07:00
Tianyu Zhou f29dc0a787 network: speed up createSocket() by giving protocal 0 in socket()
In practice, we found that createSocket() could cost up to 40ms,
which is an unacceptable overhead in FaaS(Function as a Service)
scenario. The root cause is the bind() syscall runs into the slow
path in kernel and invokes synchronize_net(), which is an expensive
call.

From kernel commit[1] we learned that we could bypass this slow
path by adjusting the socket() syscall before we call bind(). By
giving the empty protocal number, the packet_create() will not
call __register_prot_hook(), in which the kernel turn on the flag
packet_sock.running. So when it comes to packet_do_bind(), it
won't call synchronize_net() for there is no prot_hook to unregister.

Worst cost for bind() tested on Intel Xeon E5-2682 with Linux
kernel 5.4 over 100 times:

  * before: 39633.274 us
  * after:     25.098 us

Reference:
[1] https://github.com/torvalds/linux/commit/902fefb82ef72a50c78cb4a20cc954b037a98d1c

Signed-off-by: Tianyu Zhou <albert.zty@antgroup.com>
2023-08-17 02:03:04 +00:00
Kevin KrakauerandgVisor bot 2ec9f07a9d enable GRO in syscall tests
GRO should be totally transparent and should not affect behavior.

PiperOrigin-RevId: 518424809
2023-03-21 17:21:20 -07:00
Kevin KrakauerandgVisor bot 6f90845aec Automated rollback of changelist 516870932
PiperOrigin-RevId: 516937389
2023-03-15 14:56:55 -07:00
Kevin KrakauerandgVisor bot c122d8d6c8 gro: fix bug where handshake packets would be stuck waiting in GRO
Also enables GRO in syscall tests. GRO should be totally transparent and should
not affect behavior. This ensures it's tested and fixes the bug it uncovered.

GRO would not immediately flush the final ACK in the SYN-SYN/ACK-ACK handshake.
This could lead to a situation where

- Client A calls connect(), which returns once the final ACK of the handshake
  is sent and A reaches state ESTABLISHED
- The ACK gets GRO'd, delaying it from reaching the server
- Client B calls non-blocking connect()
- Client B's ACK gets GRO'd as well
- Client B is marked as ESTABLISHED
- The server, with accept queue size 1, is only going to accept one connection,
  but two clients are ESTABLISHED.

It now immediately flushes packets with no payload, as they are important to
TCP connection state and management.

PiperOrigin-RevId: 516870932
2023-03-15 10:54:43 -07:00