mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
xdp: control USE_NEED_WAKEUP via flag for benchmarking
PiperOrigin-RevId: 591382575
This commit is contained in:
committed by
gVisor bot
parent
54e02c3c56
commit
c1aef9f901
+34
-25
@@ -67,10 +67,11 @@ type ControlBlock struct {
|
||||
|
||||
// ReadOnlySocketOpts configure a read-only AF_XDP socket.
|
||||
type ReadOnlySocketOpts struct {
|
||||
NFrames uint32
|
||||
FrameSize uint32
|
||||
NDescriptors uint32
|
||||
Bind bool
|
||||
NFrames uint32
|
||||
FrameSize uint32
|
||||
NDescriptors uint32
|
||||
Bind bool
|
||||
UseNeedWakeup bool
|
||||
}
|
||||
|
||||
// DefaultReadOnlyOpts provides recommended default options for initializing a
|
||||
@@ -287,30 +288,38 @@ func ReadOnlyFromSocket(sockfd int, ifaceIdx, queueID uint32, opts ReadOnlySocke
|
||||
// device. In those cases, another process with the same socket will
|
||||
// bind for us.
|
||||
if opts.Bind {
|
||||
addr := unix.SockaddrXDP{
|
||||
// XDP_USE_NEED_WAKEUP lets the driver sleep if there is no
|
||||
// work to do. It will need to be woken by poll. It is expected
|
||||
// that this improves performance by preventing the driver from
|
||||
// burning cycles.
|
||||
//
|
||||
// By not setting either XDP_COPY or XDP_ZEROCOPY, we instruct
|
||||
// the kernel to use zerocopy if available and then fallback to
|
||||
// copy mode.
|
||||
Flags: unix.XDP_USE_NEED_WAKEUP,
|
||||
Ifindex: ifaceIdx,
|
||||
// AF_XDP sockets are per device RX queue, although multiple
|
||||
// sockets on multiple queues (or devices) can share a single
|
||||
// UMEM.
|
||||
QueueID: queueID,
|
||||
// We're not using shared mode, so the value here is irrelevant.
|
||||
SharedUmemFD: 0,
|
||||
}
|
||||
|
||||
if err := unix.Bind(sockfd, &addr); err != nil {
|
||||
return nil, fmt.Errorf("failed to bind with addr %+v: %v", addr, err)
|
||||
if err := Bind(sockfd, ifaceIdx, queueID, opts.UseNeedWakeup); err != nil {
|
||||
return nil, fmt.Errorf("failed to bind to interface %d: %v", ifaceIdx, err)
|
||||
}
|
||||
}
|
||||
|
||||
cleanup.Release()
|
||||
return &cb, nil
|
||||
}
|
||||
|
||||
// Bind binds a socket to a particular network interface and queue.
|
||||
func Bind(sockfd int, ifindex, queueID uint32, useNeedWakeup bool) error {
|
||||
var flags uint16
|
||||
if useNeedWakeup {
|
||||
flags |= unix.XDP_USE_NEED_WAKEUP
|
||||
}
|
||||
addr := unix.SockaddrXDP{
|
||||
// XDP_USE_NEED_WAKEUP lets the driver sleep if there is no
|
||||
// work to do. It will need to be woken by poll. It is expected
|
||||
// that this improves performance by preventing the driver from
|
||||
// burning cycles.
|
||||
//
|
||||
// By not setting either XDP_COPY or XDP_ZEROCOPY, we instruct
|
||||
// the kernel to use zerocopy if available and then fallback to
|
||||
// copy mode.
|
||||
Flags: flags,
|
||||
Ifindex: ifindex,
|
||||
// AF_XDP sockets are per device RX queue, although multiple
|
||||
// sockets on multiple queues (or devices) can share a single
|
||||
// UMEM.
|
||||
QueueID: queueID,
|
||||
// We're not using shared mode, so the value here is irrelevant.
|
||||
SharedUmemFD: 0,
|
||||
}
|
||||
return unix.Bind(sockfd, &addr)
|
||||
}
|
||||
|
||||
@@ -284,6 +284,10 @@ type Config struct {
|
||||
// eBPF map that runsc hooks into.
|
||||
AFXDPRedirectHost string `flag:"EXPERIMENTAL-xdp-redirect-host"`
|
||||
|
||||
// AFXDPUseNeedWakeup determines whether XDP_USE_NEED_WAKEUP is set
|
||||
// when using AF_XDP sockets.
|
||||
AFXDPUseNeedWakeup bool `flag:"EXPERIMENTAL-xdp-need-wakeup"`
|
||||
|
||||
// FDLimit specifies a limit on the number of host file descriptors that can
|
||||
// be open simultaneously by the sentry and gofer. It applies separately to
|
||||
// each.
|
||||
|
||||
@@ -121,6 +121,7 @@ func RegisterFlags(flagSet *flag.FlagSet) {
|
||||
flagSet.Bool("buffer-pooling", true, "enable allocation of buffers from a shared pool instead of the heap.")
|
||||
flagSet.Bool("EXPERIMENTAL-afxdp", false, "EXPERIMENTAL. Use an AF_XDP socket to receive packets.")
|
||||
flagSet.String("EXPERIMENTAL-xdp-redirect-host", "", "EXPERIMENTAL. Use an AF_XDP socket attached to <interface name>. Use the IP of that interface.")
|
||||
flagSet.Bool("EXPERIMENTAL-xdp-need-wakeup", true, "EXPERIMENTAL. Use XDP_USE_NEED_WAKEUP with XDP sockets.")
|
||||
flagSet.Bool("reproduce-nat", false, "Scrape the host netns NAT table and reproduce it in the sandbox.")
|
||||
flagSet.Bool("reproduce-nftables", false, "Attempt to scrape and reproduce nftable rules inside the sandbox. Overrides reproduce-nat when true.")
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ go_library(
|
||||
"//pkg/tcpip/header",
|
||||
"//pkg/tcpip/stack",
|
||||
"//pkg/urpc",
|
||||
"//pkg/xdp",
|
||||
"//runsc/boot",
|
||||
"//runsc/boot/procfs",
|
||||
"//runsc/cgroup",
|
||||
|
||||
+5
-23
@@ -26,6 +26,7 @@ import (
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
"gvisor.dev/gvisor/pkg/urpc"
|
||||
"gvisor.dev/gvisor/pkg/xdp"
|
||||
"gvisor.dev/gvisor/runsc/boot"
|
||||
"gvisor.dev/gvisor/runsc/config"
|
||||
"gvisor.dev/gvisor/runsc/sandbox/bpf"
|
||||
@@ -114,29 +115,10 @@ func createRedirectInterfacesAndRoutes(conn *urpc.Client, conf *config.Config) e
|
||||
}
|
||||
|
||||
// Bind to the device.
|
||||
sockAddr := unix.SockaddrXDP{
|
||||
// XDP_USE_NEED_WAKEUP lets the driver sleep if there is no
|
||||
// work to do. It will need to be woken by poll. It is expected
|
||||
// that this improves performance by preventing the driver from
|
||||
// burning cycles.
|
||||
//
|
||||
// By not setting either XDP_COPY or XDP_ZEROCOPY, we instruct
|
||||
// the kernel to use zerocopy if available and then fallback to
|
||||
// copy mode.
|
||||
Flags: unix.XDP_USE_NEED_WAKEUP,
|
||||
Ifindex: uint32(iface.Index),
|
||||
// AF_XDP sockets are per device RX queue, although multiple
|
||||
// sockets on multiple queues (or devices) can share a single
|
||||
// UMEM.
|
||||
//
|
||||
// TODO(b/240191988): We can't assume there's only one queue,
|
||||
// but this appears to be the case on gVNIC instances.
|
||||
QueueID: 0,
|
||||
// We're not using shared mode, so the value here is irrelevant.
|
||||
SharedUmemFD: 0,
|
||||
}
|
||||
if err := unix.Bind(xdpSockFD, &sockAddr); err != nil {
|
||||
return fmt.Errorf("failed to bind to interface %q with addr %+v: %v", iface.Name, sockAddr, err)
|
||||
// TODO(b/240191988): We can't assume there's only one queue, but this
|
||||
// appears to be the case on gVNIC instances.
|
||||
if err := xdp.Bind(xdpSockFD, uint32(iface.Index), 0 /* queueID */, conf.AFXDPUseNeedWakeup); err != nil {
|
||||
return fmt.Errorf("failed to bind to interface %q: %v", iface.Name, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user