mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Convey GSO capabilities through GSOEndpoint
...as all GSO capable endpoints must implement GSOEndpoint. PiperOrigin-RevId: 371804175
This commit is contained in:
committed by
gVisor bot
parent
4218ba6fb4
commit
f0b3298db0
@@ -123,6 +123,9 @@ func (q *queue) RemoveNotify(handle *NotificationHandle) {
|
||||
q.notify = notify
|
||||
}
|
||||
|
||||
var _ stack.LinkEndpoint = (*Endpoint)(nil)
|
||||
var _ stack.GSOEndpoint = (*Endpoint)(nil)
|
||||
|
||||
// Endpoint is link layer endpoint that stores outbound packets in a channel
|
||||
// and allows injection of inbound packets.
|
||||
type Endpoint struct {
|
||||
@@ -130,6 +133,7 @@ type Endpoint struct {
|
||||
mtu uint32
|
||||
linkAddr tcpip.LinkAddress
|
||||
LinkEPCapabilities stack.LinkEndpointCapabilities
|
||||
SupportedGSOKind stack.SupportedGSO
|
||||
|
||||
// Outbound packet queue.
|
||||
q *queue
|
||||
@@ -211,11 +215,16 @@ func (e *Endpoint) Capabilities() stack.LinkEndpointCapabilities {
|
||||
return e.LinkEPCapabilities
|
||||
}
|
||||
|
||||
// GSOMaxSize returns the maximum GSO packet size.
|
||||
// GSOMaxSize implements stack.GSOEndpoint.
|
||||
func (*Endpoint) GSOMaxSize() uint32 {
|
||||
return 1 << 15
|
||||
}
|
||||
|
||||
// SupportedGSO implements stack.GSOEndpoint.
|
||||
func (e *Endpoint) SupportedGSO() stack.SupportedGSO {
|
||||
return e.SupportedGSOKind
|
||||
}
|
||||
|
||||
// MaxHeaderLength returns the maximum size of the link layer header. Given it
|
||||
// doesn't have a header, it just returns 0.
|
||||
func (*Endpoint) MaxHeaderLength() uint16 {
|
||||
|
||||
@@ -97,6 +97,9 @@ func (p PacketDispatchMode) String() string {
|
||||
}
|
||||
}
|
||||
|
||||
var _ stack.LinkEndpoint = (*endpoint)(nil)
|
||||
var _ stack.GSOEndpoint = (*endpoint)(nil)
|
||||
|
||||
type endpoint struct {
|
||||
// fds is the set of file descriptors each identifying one inbound/outbound
|
||||
// channel. The endpoint will dispatch from all inbound channels as well as
|
||||
@@ -133,6 +136,9 @@ type endpoint struct {
|
||||
|
||||
// wg keeps track of running goroutines.
|
||||
wg sync.WaitGroup
|
||||
|
||||
// gsoKind is the supported kind of GSO.
|
||||
gsoKind stack.SupportedGSO
|
||||
}
|
||||
|
||||
// Options specify the details about the fd-based endpoint to be created.
|
||||
@@ -254,9 +260,9 @@ func New(opts *Options) (stack.LinkEndpoint, error) {
|
||||
if isSocket {
|
||||
if opts.GSOMaxSize != 0 {
|
||||
if opts.SoftwareGSOEnabled {
|
||||
e.caps |= stack.CapabilitySoftwareGSO
|
||||
e.gsoKind = stack.SWGSOSupported
|
||||
} else {
|
||||
e.caps |= stack.CapabilityHardwareGSO
|
||||
e.gsoKind = stack.HWGSOSupported
|
||||
}
|
||||
e.gsoMaxSize = opts.GSOMaxSize
|
||||
}
|
||||
@@ -469,7 +475,7 @@ func (e *endpoint) WritePacket(r stack.RouteInfo, protocol tcpip.NetworkProtocol
|
||||
var builder iovec.Builder
|
||||
|
||||
fd := e.fds[pkt.Hash%uint32(len(e.fds))]
|
||||
if e.Capabilities()&stack.CapabilityHardwareGSO != 0 {
|
||||
if e.gsoKind == stack.HWGSOSupported {
|
||||
vnetHdr := virtioNetHdr{}
|
||||
if pkt.GSOOptions.Type != stack.GSONone {
|
||||
vnetHdr.hdrLen = uint16(pkt.HeaderSize())
|
||||
@@ -510,7 +516,7 @@ func (e *endpoint) sendBatch(batchFD int, batch []*stack.PacketBuffer) (int, tcp
|
||||
}
|
||||
|
||||
var vnetHdrBuf []byte
|
||||
if e.Capabilities()&stack.CapabilityHardwareGSO != 0 {
|
||||
if e.gsoKind == stack.HWGSOSupported {
|
||||
vnetHdr := virtioNetHdr{}
|
||||
if pkt.GSOOptions.Type != stack.GSONone {
|
||||
vnetHdr.hdrLen = uint16(pkt.HeaderSize())
|
||||
@@ -630,11 +636,16 @@ func (e *endpoint) dispatchLoop(inboundDispatcher linkDispatcher) tcpip.Error {
|
||||
}
|
||||
}
|
||||
|
||||
// GSOMaxSize returns the maximum GSO packet size.
|
||||
// GSOMaxSize implements stack.GSOEndpoint.
|
||||
func (e *endpoint) GSOMaxSize() uint32 {
|
||||
return e.gsoMaxSize
|
||||
}
|
||||
|
||||
// SupportsHWGSO implements stack.GSOEndpoint.
|
||||
func (e *endpoint) SupportedGSO() stack.SupportedGSO {
|
||||
return e.gsoKind
|
||||
}
|
||||
|
||||
// ARPHardwareType implements stack.LinkEndpoint.ARPHardwareType.
|
||||
func (e *endpoint) ARPHardwareType() header.ARPHardwareType {
|
||||
if e.hdrSize > 0 {
|
||||
|
||||
@@ -128,7 +128,7 @@ type readVDispatcher struct {
|
||||
|
||||
func newReadVDispatcher(fd int, e *endpoint) (linkDispatcher, error) {
|
||||
d := &readVDispatcher{fd: fd, e: e}
|
||||
skipsVnetHdr := d.e.Capabilities()&stack.CapabilityHardwareGSO != 0
|
||||
skipsVnetHdr := d.e.gsoKind == stack.HWGSOSupported
|
||||
d.buf = newIovecBuffer(BufConfig, skipsVnetHdr)
|
||||
return d, nil
|
||||
}
|
||||
@@ -212,7 +212,7 @@ func newRecvMMsgDispatcher(fd int, e *endpoint) (linkDispatcher, error) {
|
||||
bufs: make([]*iovecBuffer, MaxMsgsPerRecv),
|
||||
msgHdrs: make([]rawfile.MMsgHdr, MaxMsgsPerRecv),
|
||||
}
|
||||
skipsVnetHdr := d.e.Capabilities()&stack.CapabilityHardwareGSO != 0
|
||||
skipsVnetHdr := d.e.gsoKind == stack.HWGSOSupported
|
||||
for i := range d.bufs {
|
||||
d.bufs[i] = newIovecBuffer(BufConfig, skipsVnetHdr)
|
||||
}
|
||||
|
||||
@@ -135,6 +135,14 @@ func (e *Endpoint) GSOMaxSize() uint32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// SupportedGSO implements stack.GSOEndpoint.
|
||||
func (e *Endpoint) SupportedGSO() stack.SupportedGSO {
|
||||
if e, ok := e.child.(stack.GSOEndpoint); ok {
|
||||
return e.SupportedGSO()
|
||||
}
|
||||
return stack.GSONotSupported
|
||||
}
|
||||
|
||||
// ARPHardwareType implements stack.LinkEndpoint.ARPHardwareType
|
||||
func (e *Endpoint) ARPHardwareType() header.ARPHardwareType {
|
||||
return e.child.ARPHardwareType()
|
||||
|
||||
@@ -25,6 +25,9 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
)
|
||||
|
||||
var _ stack.LinkEndpoint = (*endpoint)(nil)
|
||||
var _ stack.GSOEndpoint = (*endpoint)(nil)
|
||||
|
||||
// endpoint represents a LinkEndpoint which implements a FIFO queue for all
|
||||
// outgoing packets. endpoint can have 1 or more underlying queueDispatchers.
|
||||
// All outgoing packets are consistenly hashed to a single underlying queue
|
||||
@@ -141,7 +144,7 @@ func (e *endpoint) LinkAddress() tcpip.LinkAddress {
|
||||
return e.lower.LinkAddress()
|
||||
}
|
||||
|
||||
// GSOMaxSize returns the maximum GSO packet size.
|
||||
// GSOMaxSize implements stack.GSOEndpoint.
|
||||
func (e *endpoint) GSOMaxSize() uint32 {
|
||||
if gso, ok := e.lower.(stack.GSOEndpoint); ok {
|
||||
return gso.GSOMaxSize()
|
||||
@@ -149,6 +152,14 @@ func (e *endpoint) GSOMaxSize() uint32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// SupportedGSO implements stack.GSOEndpoint.
|
||||
func (e *endpoint) SupportedGSO() stack.SupportedGSO {
|
||||
if gso, ok := e.lower.(stack.GSOEndpoint); ok {
|
||||
return gso.SupportedGSO()
|
||||
}
|
||||
return stack.GSONotSupported
|
||||
}
|
||||
|
||||
// WritePacket implements stack.LinkEndpoint.WritePacket.
|
||||
//
|
||||
// The packet must have the following fields populated:
|
||||
|
||||
@@ -264,6 +264,8 @@ type fwdTestPacketInfo struct {
|
||||
Pkt *PacketBuffer
|
||||
}
|
||||
|
||||
var _ LinkEndpoint = (*fwdTestLinkEndpoint)(nil)
|
||||
|
||||
type fwdTestLinkEndpoint struct {
|
||||
dispatcher NetworkDispatcher
|
||||
mtu uint32
|
||||
@@ -306,11 +308,6 @@ func (e fwdTestLinkEndpoint) Capabilities() LinkEndpointCapabilities {
|
||||
return caps | CapabilityResolutionRequired
|
||||
}
|
||||
|
||||
// GSOMaxSize returns the maximum GSO packet size.
|
||||
func (*fwdTestLinkEndpoint) GSOMaxSize() uint32 {
|
||||
return 1 << 15
|
||||
}
|
||||
|
||||
// MaxHeaderLength returns the maximum size of the link layer header. Given it
|
||||
// doesn't have a header, it just returns 0.
|
||||
func (*fwdTestLinkEndpoint) MaxHeaderLength() uint16 {
|
||||
|
||||
@@ -756,11 +756,6 @@ const (
|
||||
CapabilitySaveRestore
|
||||
CapabilityDisconnectOk
|
||||
CapabilityLoopback
|
||||
CapabilityHardwareGSO
|
||||
|
||||
// CapabilitySoftwareGSO indicates the link endpoint supports of sending
|
||||
// multiple packets using a single call (LinkEndpoint.WritePackets).
|
||||
CapabilitySoftwareGSO
|
||||
)
|
||||
|
||||
// NetworkLinkEndpoint is a data-link layer that supports sending network
|
||||
@@ -1047,10 +1042,29 @@ type GSO struct {
|
||||
MaxSize uint32
|
||||
}
|
||||
|
||||
// SupportedGSO returns 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
|
||||
|
||||
// SWGSOSupported indicates that segmentation offloading may be performed in
|
||||
// software.
|
||||
SWGSOSupported
|
||||
)
|
||||
|
||||
// GSOEndpoint provides access to GSO properties.
|
||||
type GSOEndpoint interface {
|
||||
// GSOMaxSize returns the maximum GSO packet size.
|
||||
GSOMaxSize() uint32
|
||||
|
||||
// SupportedGSO returns the supported segmentation offloading.
|
||||
SupportedGSO() SupportedGSO
|
||||
}
|
||||
|
||||
// SoftwareGSOMaxSize is a maximum allowed size of a software GSO segment.
|
||||
|
||||
@@ -300,12 +300,18 @@ func (r *Route) RequiresTXTransportChecksum() bool {
|
||||
|
||||
// HasSoftwareGSOCapability returns true if the route supports software GSO.
|
||||
func (r *Route) HasSoftwareGSOCapability() bool {
|
||||
return r.outgoingNIC.LinkEndpoint.Capabilities()&CapabilitySoftwareGSO != 0
|
||||
if gso, ok := r.outgoingNIC.LinkEndpoint.(GSOEndpoint); ok {
|
||||
return gso.SupportedGSO() == SWGSOSupported
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// HasHardwareGSOCapability returns true if the route supports hardware GSO.
|
||||
func (r *Route) HasHardwareGSOCapability() bool {
|
||||
return r.outgoingNIC.LinkEndpoint.Capabilities()&CapabilityHardwareGSO != 0
|
||||
if gso, ok := r.outgoingNIC.LinkEndpoint.(GSOEndpoint); ok {
|
||||
return gso.SupportedGSO() == HWGSOSupported
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// HasSaveRestoreCapability returns true if the route supports save/restore.
|
||||
|
||||
@@ -1214,9 +1214,9 @@ func (c *Context) SACKEnabled() bool {
|
||||
// SetGSOEnabled enables or disables generic segmentation offload.
|
||||
func (c *Context) SetGSOEnabled(enable bool) {
|
||||
if enable {
|
||||
c.linkEP.LinkEPCapabilities |= stack.CapabilityHardwareGSO
|
||||
c.linkEP.SupportedGSOKind = stack.HWGSOSupported
|
||||
} else {
|
||||
c.linkEP.LinkEPCapabilities &^= stack.CapabilityHardwareGSO
|
||||
c.linkEP.SupportedGSOKind = stack.GSONotSupported
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user