diff --git a/.buildkite/pipeline.yaml b/.buildkite/pipeline.yaml index 1cc0481dd..ac9bebb23 100644 --- a/.buildkite/pipeline.yaml +++ b/.buildkite/pipeline.yaml @@ -209,7 +209,7 @@ steps: arch: "amd64" os: "ubuntu" - <<: *common - label: ":satellite: SWGSO tests" + label: ":satellite: gVisor GSO tests" command: make swgso-tests agents: arch: "amd64" diff --git a/pkg/tcpip/link/fdbased/endpoint.go b/pkg/tcpip/link/fdbased/endpoint.go index a3fa225d7..736895cca 100644 --- a/pkg/tcpip/link/fdbased/endpoint.go +++ b/pkg/tcpip/link/fdbased/endpoint.go @@ -192,8 +192,8 @@ type Options struct { // disabled. GSOMaxSize uint32 - // SoftwareGSOEnabled indicates whether software GSO is enabled or not. - SoftwareGSOEnabled bool + // GvisorGSOEnabled indicates whether Gvisor GSO is enabled or not. + GvisorGSOEnabled bool // PacketDispatchMode specifies the type of inbound dispatcher to be // used for this endpoint. @@ -295,10 +295,10 @@ func New(opts *Options) (stack.LinkEndpoint, error) { e.fds = append(e.fds, fdInfo{fd: fd, isSocket: isSocket}) if isSocket { if opts.GSOMaxSize != 0 { - if opts.SoftwareGSOEnabled { - e.gsoKind = stack.SWGSOSupported + if opts.GvisorGSOEnabled { + e.gsoKind = stack.GvisorGSOSupported } else { - e.gsoKind = stack.HWGSOSupported + e.gsoKind = stack.HostGSOSupported } e.gsoMaxSize = opts.GSOMaxSize } @@ -506,7 +506,7 @@ func (e *endpoint) writePacket(pkt *stack.PacketBuffer) tcpip.Error { fdInfo := e.fds[pkt.Hash%uint32(len(e.fds))] fd := fdInfo.fd var vnetHdrBuf []byte - if e.gsoKind == stack.HWGSOSupported { + if e.gsoKind == stack.HostGSOSupported { vnetHdr := virtioNetHdr{} if pkt.GSOOptions.Type != stack.GSONone { vnetHdr.hdrLen = uint16(pkt.HeaderSize()) @@ -577,7 +577,7 @@ func (e *endpoint) sendBatch(batchFDInfo fdInfo, pkts []*stack.PacketBuffer) (in syscallHeaderBytes := uintptr(0) for _, pkt := range batch { var vnetHdrBuf []byte - if e.gsoKind == stack.HWGSOSupported { + if e.gsoKind == stack.HostGSOSupported { vnetHdr := virtioNetHdr{} if pkt.GSOOptions.Type != stack.GSONone { vnetHdr.hdrLen = uint16(pkt.HeaderSize()) @@ -670,7 +670,7 @@ func (e *endpoint) sendBatch(batchFDInfo fdInfo, pkts []*stack.PacketBuffer) (in // - pkt.NetworkProtocolNumber func (e *endpoint) WritePackets(pkts stack.PacketBufferList) (int, tcpip.Error) { // Preallocate to avoid repeated reallocation as we append to batch. - // batchSz is 47 because when SWGSO is in use then a single 65KB TCP + // batchSz is 47 because when GvisorGSO is in use then a single 65KB TCP // segment can get split into 46 segments of 1420 bytes and a single 216 // byte segment. const batchSz = 47 diff --git a/pkg/tcpip/link/fdbased/packet_dispatchers.go b/pkg/tcpip/link/fdbased/packet_dispatchers.go index b600974f2..16399d2fb 100644 --- a/pkg/tcpip/link/fdbased/packet_dispatchers.go +++ b/pkg/tcpip/link/fdbased/packet_dispatchers.go @@ -184,7 +184,7 @@ func newReadVDispatcher(fd int, e *endpoint) (linkDispatcher, error) { fd: fd, e: e, } - skipsVnetHdr := d.e.gsoKind == stack.HWGSOSupported + skipsVnetHdr := d.e.gsoKind == stack.HostGSOSupported d.buf = newIovecBuffer(BufConfig, skipsVnetHdr) return d, nil } @@ -269,7 +269,7 @@ func newRecvMMsgDispatcher(fd int, e *endpoint) (linkDispatcher, error) { bufs: make([]*iovecBuffer, MaxMsgsPerRecv), msgHdrs: make([]rawfile.MMsgHdr, MaxMsgsPerRecv), } - skipsVnetHdr := d.e.gsoKind == stack.HWGSOSupported + skipsVnetHdr := d.e.gsoKind == stack.HostGSOSupported for i := range d.bufs { d.bufs[i] = newIovecBuffer(BufConfig, skipsVnetHdr) } diff --git a/pkg/tcpip/stack/registration.go b/pkg/tcpip/stack/registration.go index 64a438993..3b09ab8d6 100644 --- a/pkg/tcpip/stack/registration.go +++ b/pkg/tcpip/stack/registration.go @@ -1168,9 +1168,9 @@ const ( GSOTCPv4 GSOTCPv6 - // GSOSW is used for software GSO segments which have to be sent by + // GSOGvisor is used for gVisor GSO segments which have to be sent by // endpoint.WritePackets. - GSOSW + GSOGvisor ) // GSO contains generic segmentation offload properties. @@ -1193,20 +1193,22 @@ type GSO struct { MaxSize uint32 } -// SupportedGSO returns the type of segmentation offloading supported. +// SupportedGSO is the type of segmentation offloading supported. type SupportedGSO int const ( // GSONotSupported indicates that segmentation offloading is not supported. GSONotSupported SupportedGSO = iota - // HWGSOSupported indicates that segmentation offloading may be performed by - // the hardware. - HWGSOSupported + // HostGSOSupported indicates that segmentation offloading may be performed + // by the host. This is typically true when netstack is attached to a host + // AF_PACKET socket, and not true when attached to a unix socket or other + // non-networking data layer. + HostGSOSupported - // SWGSOSupported indicates that segmentation offloading may be performed in - // software. - SWGSOSupported + // GvisorGSOSupported indicates that segmentation offloading may be performed + // in gVisor. + GvisorGSOSupported ) // GSOEndpoint provides access to GSO properties. @@ -1218,6 +1220,6 @@ type GSOEndpoint interface { SupportedGSO() SupportedGSO } -// SoftwareGSOMaxSize is a maximum allowed size of a software GSO segment. +// GvisorGSOMaxSize is a maximum allowed size of a software GSO segment. // This isn't a hard limit, because it is never set into packet headers. -const SoftwareGSOMaxSize = 1 << 16 +const GvisorGSOMaxSize = 1 << 16 diff --git a/pkg/tcpip/stack/route.go b/pkg/tcpip/stack/route.go index e1349e05d..407d11aef 100644 --- a/pkg/tcpip/stack/route.go +++ b/pkg/tcpip/stack/route.go @@ -302,18 +302,18 @@ func (r *Route) RequiresTXTransportChecksum() bool { return r.outgoingNIC.NetworkLinkEndpoint.Capabilities()&CapabilityTXChecksumOffload == 0 } -// HasSoftwareGSOCapability returns true if the route supports software GSO. -func (r *Route) HasSoftwareGSOCapability() bool { +// HasGvisorGSOCapability returns true if the route supports gVisor GSO. +func (r *Route) HasGvisorGSOCapability() bool { if gso, ok := r.outgoingNIC.NetworkLinkEndpoint.(GSOEndpoint); ok { - return gso.SupportedGSO() == SWGSOSupported + return gso.SupportedGSO() == GvisorGSOSupported } return false } -// HasHardwareGSOCapability returns true if the route supports hardware GSO. -func (r *Route) HasHardwareGSOCapability() bool { +// HasHostGSOCapability returns true if the route supports host GSO. +func (r *Route) HasHostGSOCapability() bool { if gso, ok := r.outgoingNIC.NetworkLinkEndpoint.(GSOEndpoint); ok { - return gso.SupportedGSO() == HWGSOSupported + return gso.SupportedGSO() == HostGSOSupported } return false } diff --git a/pkg/tcpip/transport/tcp/connect.go b/pkg/tcpip/transport/tcp/connect.go index 484418572..4164c25ed 100644 --- a/pkg/tcpip/transport/tcp/connect.go +++ b/pkg/tcpip/transport/tcp/connect.go @@ -900,7 +900,7 @@ func sendTCP(r *stack.Route, tf tcpFields, pkt *stack.PacketBuffer, gso stack.GS tf.rcvWnd = math.MaxUint16 } - if r.Loop()&stack.PacketLoop == 0 && gso.Type == stack.GSOSW && int(gso.MSS) < pkt.Data().Size() { + if r.Loop()&stack.PacketLoop == 0 && gso.Type == stack.GSOGvisor && int(gso.MSS) < pkt.Data().Size() { return sendTCPBatch(r, tf, pkt, gso, owner) } diff --git a/pkg/tcpip/transport/tcp/endpoint.go b/pkg/tcpip/transport/tcp/endpoint.go index af603b15d..a43f7d815 100644 --- a/pkg/tcpip/transport/tcp/endpoint.go +++ b/pkg/tcpip/transport/tcp/endpoint.go @@ -3088,7 +3088,7 @@ func (e *endpoint) completeStateLocked(s *stack.TCPEndpointState) { s.Sender.SpuriousRecovery = e.snd.spuriousRecovery } -func (e *endpoint) initHardwareGSO() { +func (e *endpoint) initHostGSO() { switch e.route.NetProto() { case header.IPv4ProtocolNumber: e.gso.Type = stack.GSOTCPv4 @@ -3105,12 +3105,12 @@ func (e *endpoint) initHardwareGSO() { } func (e *endpoint) initGSO() { - if e.route.HasHardwareGSOCapability() { - e.initHardwareGSO() - } else if e.route.HasSoftwareGSOCapability() { + if e.route.HasHostGSOCapability() { + e.initHostGSO() + } else if e.route.HasGvisorGSOCapability() { e.gso = stack.GSO{ MaxSize: e.route.GSOMaxSize(), - Type: stack.GSOSW, + Type: stack.GSOGvisor, NeedsCsum: false, } } diff --git a/pkg/tcpip/transport/tcp/testing/context/context.go b/pkg/tcpip/transport/tcp/testing/context/context.go index 19c8b5a95..27608ba82 100644 --- a/pkg/tcpip/transport/tcp/testing/context/context.go +++ b/pkg/tcpip/transport/tcp/testing/context/context.go @@ -1268,7 +1268,7 @@ func (c *Context) SACKEnabled() bool { // SetGSOEnabled enables or disables generic segmentation offload. func (c *Context) SetGSOEnabled(enable bool) { if enable { - c.linkEP.SupportedGSOKind = stack.HWGSOSupported + c.linkEP.SupportedGSOKind = stack.HostGSOSupported } else { c.linkEP.SupportedGSOKind = stack.GSONotSupported } diff --git a/runsc/boot/network.go b/runsc/boot/network.go index 02212a642..7094632c9 100644 --- a/runsc/boot/network.go +++ b/runsc/boot/network.go @@ -86,17 +86,17 @@ type Neighbor struct { // FDBasedLink configures an fd-based link. type FDBasedLink struct { - Name string - MTU int - Addresses []IPWithPrefix - Routes []Route - GSOMaxSize uint32 - SoftwareGSOEnabled bool - TXChecksumOffload bool - RXChecksumOffload bool - LinkAddress net.HardwareAddr - QDisc config.QueueingDiscipline - Neighbors []Neighbor + Name string + MTU int + Addresses []IPWithPrefix + Routes []Route + GSOMaxSize uint32 + GvisorGSOEnabled bool + TXChecksumOffload bool + RXChecksumOffload bool + LinkAddress net.HardwareAddr + QDisc config.QueueingDiscipline + Neighbors []Neighbor // NumChannels controls how many underlying FD's are to be used to // create this endpoint. @@ -221,7 +221,7 @@ func (n *Network) CreateLinksAndRoutes(args *CreateLinksAndRoutesArgs, _ *struct Address: mac, PacketDispatchMode: fdbased.RecvMMsg, GSOMaxSize: link.GSOMaxSize, - SoftwareGSOEnabled: link.SoftwareGSOEnabled, + GvisorGSOEnabled: link.GvisorGSOEnabled, TXChecksumOffload: link.TXChecksumOffload, RXChecksumOffload: link.RXChecksumOffload, }) diff --git a/runsc/config/config.go b/runsc/config/config.go index d99b56ab2..08e9fad0e 100644 --- a/runsc/config/config.go +++ b/runsc/config/config.go @@ -88,11 +88,12 @@ type Config struct { // AllowPacketEndpointWrite enables write operations on packet endpoints. AllowPacketEndpointWrite bool `flag:"TESTONLY-allow-packet-endpoint-write"` - // HardwareGSO indicates that hardware segmentation offload is enabled. - HardwareGSO bool `flag:"gso"` + // HostGSO indicates that host segmentation offload is enabled. + HostGSO bool `flag:"gso"` - // SoftwareGSO indicates that software segmentation offload is enabled. - SoftwareGSO bool `flag:"software-gso"` + // GvisorGSO indicates that gVisor segmentation offload is enabled. The flag + // retains its old name of "software" GSO for API consistency. + GvisorGSO bool `flag:"software-gso"` // TXChecksumOffload indicates that TX Checksum Offload is enabled. TXChecksumOffload bool `flag:"tx-checksum-offload"` diff --git a/runsc/config/flags.go b/runsc/config/flags.go index 794e89cbf..fab012546 100644 --- a/runsc/config/flags.go +++ b/runsc/config/flags.go @@ -90,8 +90,8 @@ func RegisterFlags(flagSet *flag.FlagSet) { // Flags that control sandbox runtime behavior: network related. flagSet.Var(networkTypePtr(NetworkSandbox), "network", "specifies which network to use: sandbox (default), host, none. Using network inside the sandbox is more secure because it's isolated from the host network.") flagSet.Bool("net-raw", false, "enable raw sockets. When false, raw sockets are disabled by removing CAP_NET_RAW from containers (`runsc exec` will still be able to utilize raw sockets). Raw sockets allow malicious containers to craft packets and potentially attack the network.") - flagSet.Bool("gso", true, "enable hardware segmentation offload if it is supported by a network device.") - flagSet.Bool("software-gso", true, "enable software segmentation offload when hardware offload can't be enabled.") + flagSet.Bool("gso", true, "enable host segmentation offload if it is supported by a network device.") + flagSet.Bool("software-gso", true, "enable gVisor segmentation offload when host offload can't be enabled.") flagSet.Bool("tx-checksum-offload", false, "enable TX checksum offload.") flagSet.Bool("rx-checksum-offload", true, "enable RX checksum offload.") flagSet.Var(queueingDisciplinePtr(QDiscFIFO), "qdisc", "specifies which queueing discipline to apply by default to the non loopback nics used by the sandbox.") diff --git a/runsc/sandbox/network.go b/runsc/sandbox/network.go index 613f6cdec..aa52189f1 100644 --- a/runsc/sandbox/network.go +++ b/runsc/sandbox/network.go @@ -63,7 +63,7 @@ func setupNetwork(conn *urpc.Client, pid int, conf *config.Config) error { // Build the path to the net namespace of the sandbox process. // This is what we will copy. nsPath := filepath.Join("/proc", strconv.Itoa(pid), "ns/net") - if err := createInterfacesAndRoutesFromNS(conn, nsPath, conf.HardwareGSO, conf.SoftwareGSO, conf.TXChecksumOffload, conf.RXChecksumOffload, conf.NumNetworkChannels, conf.QDisc); err != nil { + if err := createInterfacesAndRoutesFromNS(conn, nsPath, conf.HostGSO, conf.GvisorGSO, conf.TXChecksumOffload, conf.RXChecksumOffload, conf.NumNetworkChannels, conf.QDisc); err != nil { return fmt.Errorf("creating interfaces from net namespace %q: %v", nsPath, err) } case config.NetworkHost: @@ -116,7 +116,7 @@ func isRootNS() (bool, error) { // createInterfacesAndRoutesFromNS scrapes the interface and routes from the // net namespace with the given path, creates them in the sandbox, and removes // them from the host. -func createInterfacesAndRoutesFromNS(conn *urpc.Client, nsPath string, hardwareGSO bool, softwareGSO bool, txChecksumOffload bool, rxChecksumOffload bool, numNetworkChannels int, qDisc config.QueueingDiscipline) error { +func createInterfacesAndRoutesFromNS(conn *urpc.Client, nsPath string, hostGSO bool, gvisorGSO bool, txChecksumOffload bool, rxChecksumOffload bool, numNetworkChannels int, qDisc config.QueueingDiscipline) error { // Join the network namespace that we will be copying. restore, err := joinNetNS(nsPath) if err != nil { @@ -235,7 +235,7 @@ func createInterfacesAndRoutesFromNS(conn *urpc.Client, nsPath string, hardwareG // Create the socket for the device. for i := 0; i < link.NumChannels; i++ { log.Debugf("Creating Channel %d", i) - socketEntry, err := createSocket(iface, ifaceLink, hardwareGSO) + socketEntry, err := createSocket(iface, ifaceLink, hostGSO) if err != nil { return fmt.Errorf("failed to createSocket for %s : %w", iface.Name, err) } @@ -250,10 +250,10 @@ func createInterfacesAndRoutesFromNS(conn *urpc.Client, nsPath string, hardwareG args.FilePayload.Files = append(args.FilePayload.Files, socketEntry.deviceFile) } - if link.GSOMaxSize == 0 && softwareGSO { - // Hardware GSO is disabled. Let's enable software GSO. - link.GSOMaxSize = stack.SoftwareGSOMaxSize - link.SoftwareGSOEnabled = true + if link.GSOMaxSize == 0 && gvisorGSO { + // Host GSO is disabled. Let's enable gVisor GSO. + link.GSOMaxSize = stack.GvisorGSOMaxSize + link.GvisorGSOEnabled = true } // Collect the addresses for the interface, enable forwarding, diff --git a/test/benchmarks/tcp/tcp_proxy.go b/test/benchmarks/tcp/tcp_proxy.go index b0879fe82..3d5fa9961 100644 --- a/test/benchmarks/tcp/tcp_proxy.go +++ b/test/benchmarks/tcp/tcp_proxy.go @@ -59,7 +59,7 @@ var ( moderateRecvBuf = flag.Bool("moderate_recv_buf", false, "enable TCP Receive Buffer Auto-tuning") cubic = flag.Bool("cubic", false, "enable use of CUBIC congestion control for netstack") gso = flag.Int("gso", 0, "GSO maximum size") - swgso = flag.Bool("swgso", false, "software-level GSO") + swgso = flag.Bool("swgso", false, "gVisor-level GSO") clientTCPProbeFile = flag.String("client_tcp_probe_file", "", "if specified, installs a tcp probe to dump endpoint state to the specified file.") serverTCPProbeFile = flag.String("server_tcp_probe_file", "", "if specified, installs a tcp probe to dump endpoint state to the specified file.") cpuprofile = flag.String("cpuprofile", "", "write cpu profile to the specified file.") @@ -200,7 +200,7 @@ func newNetstackImpl(mode string) (impl, error) { RXChecksumOffload: true, PacketDispatchMode: fdbased.RecvMMsg, GSOMaxSize: uint32(*gso), - SoftwareGSOEnabled: *swgso, + GvisorGSOEnabled: *swgso, }) if err != nil { return nil, fmt.Errorf("failed to create FD endpoint: %v", err)