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
This commit is contained in:
Kevin Krakauer
2024-01-03 14:26:18 -08:00
committed by gVisor bot
parent 9ea77eb8bc
commit 0bb4cfdc4b
4 changed files with 84 additions and 17 deletions
+74 -11
View File
@@ -282,17 +282,8 @@ type Config struct {
// Use pools to manage buffer memory instead of heap.
BufferPooling bool `flag:"buffer-pooling"`
// AFXDP defines whether to use an AF_XDP socket to receive packets
// (rather than AF_PACKET). Enabling it disables RX checksum offload.
AFXDP bool `flag:"EXPERIMENTAL-afxdp"`
// AFXDPRedirectHost is the name of a network interface. runsc will
// scrape the address, routes, and neighbors of that interface, and
// send packets via an AF_XDP socket on that interface.
//
// Requires use of `xdp_loader redirect` to setup the XDP program and
// eBPF map that runsc hooks into.
AFXDPRedirectHost string `flag:"EXPERIMENTAL-xdp-redirect-host"`
// XDP controls Whether and how to use XDP.
XDP XDP `flag:"EXPERIMENTAL-xdp"`
// AFXDPUseNeedWakeup determines whether XDP_USE_NEED_WAKEUP is set
// when using AF_XDP sockets.
@@ -924,3 +915,75 @@ func (o *Overlay2) SubMountOverlayMedium() OverlayMedium {
}
return o.medium
}
// XDP holds configuration for whether and how to use XDP.
type XDP struct {
Mode XDPMode
IfaceName string
}
// XDPMode specifies a particular use of XDP.
type XDPMode int
const (
// XDPModeOff doesn't use XDP.
XDPModeOff XDPMode = iota
// XDPModeNS uses an AF_XDP socket to read from the VETH device inside
// the container's network namespace.
XDPModeNS
// XDPModeRedirect uses an AF_XDP socket on the host NIC to bypass the
// Linux network stack.
XDPModeRedirect
)
const (
xdpModeStrOff = "off"
xdpModeStrNS = "ns"
xdpModeStrRedirect = "redirect"
)
var xdpConfig XDP
// Get implements flag.Getter.
func (xd *XDP) Get() any {
return *xd
}
// String implements flag.Getter.
func (xd *XDP) String() string {
switch xd.Mode {
case XDPModeOff:
return xdpModeStrOff
case XDPModeNS:
return xdpModeStrNS
case XDPModeRedirect:
return fmt.Sprintf("%s:%s", xdpModeStrRedirect, xd.IfaceName)
default:
panic(fmt.Sprintf("unknown mode %d", xd.Mode))
}
}
// Set implements flag.Getter.
func (xd *XDP) Set(input string) error {
parts := strings.Split(input, ":")
if len(parts) > 2 {
return fmt.Errorf("invalid --xdp value: %q", input)
}
switch {
case input == xdpModeStrOff:
xd.Mode = XDPModeOff
xd.IfaceName = ""
case input == xdpModeStrNS:
xd.Mode = XDPModeNS
xd.IfaceName = ""
case len(parts) == 2 && parts[0] == xdpModeStrRedirect && parts[1] != "":
xd.Mode = XDPModeRedirect
xd.IfaceName = parts[1]
default:
return fmt.Errorf("invalid --xdp value: %q", input)
}
return nil
}
+2 -3
View File
@@ -120,9 +120,8 @@ func RegisterFlags(flagSet *flag.FlagSet) {
flagSet.Var(queueingDisciplinePtr(QDiscFIFO), "qdisc", "specifies which queueing discipline to apply by default to the non loopback nics used by the sandbox.")
flagSet.Int("num-network-channels", 1, "number of underlying channels(FDs) to use for network link endpoints.")
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.Var(&xdpConfig, "EXPERIMENTAL-xdp", `whether and how to use XDP. Can be one of: "off" (default), "ns", or "redirect:<device name>"`)
flagSet.Bool("EXPERIMENTAL-xdp-need-wakeup", true, "EXPERIMENTAL. Use XDP_USE_NEED_WAKEUP with XDP sockets.") // TODO(b/240191988): Figure out whether this helps and remove it as a flag.
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.")
+7 -2
View File
@@ -120,11 +120,16 @@ func isRootNS() (bool, error) {
// net namespace with the given path, creates them in the sandbox, and removes
// them from the host.
func createInterfacesAndRoutesFromNS(conn *urpc.Client, nsPath string, conf *config.Config) error {
if conf.AFXDPRedirectHost != "" {
switch conf.XDP.Mode {
case config.XDPModeOff:
case config.XDPModeNS:
case config.XDPModeRedirect:
if err := createRedirectInterfacesAndRoutes(conn, conf); err != nil {
return fmt.Errorf("failed to create XDP redirect interface: %w", err)
}
return nil
default:
return fmt.Errorf("unknown XDP mode: %v", conf.XDP.Mode)
}
// Join the network namespace that we will be copying.
@@ -250,7 +255,7 @@ func createInterfacesAndRoutesFromNS(conn *urpc.Client, nsPath string, conf *con
}
}
if conf.AFXDP {
if conf.XDP.Mode == config.XDPModeNS {
xdpSockFDs, err := createSocketXDP(iface)
if err != nil {
return fmt.Errorf("failed to create XDP socket: %v", err)
+1 -1
View File
@@ -157,7 +157,7 @@ func prepareRedirectInterfaceArgs(conf *config.Config) (boot.CreateLinksAndRoute
continue
}
if iface.Name != conf.AFXDPRedirectHost {
if iface.Name != conf.XDP.IfaceName {
log.Infof("Skipping interface %q", iface.Name)
continue
}