From 25b1d7134115373c56db235ae4eb9d57e0738d4f Mon Sep 17 00:00:00 2001 From: Lucas Manning Date: Wed, 15 Jan 2025 17:41:24 -0800 Subject: [PATCH] Add constants and types related to the implementation of PACKET_MMAP. This is the first in a series of changes that implements PACKET_MMAP. PiperOrigin-RevId: 716014872 --- pkg/abi/linux/socket.go | 66 +++++++++++++++++++++++++++++++++++++++++ pkg/syserr/netstack.go | 3 ++ pkg/tcpip/errors.go | 18 +++++++++++ pkg/tcpip/tcpip.go | 13 ++++++++ 4 files changed, 100 insertions(+) diff --git a/pkg/abi/linux/socket.go b/pkg/abi/linux/socket.go index 2905f73ed..2efd17c60 100644 --- a/pkg/abi/linux/socket.go +++ b/pkg/abi/linux/socket.go @@ -144,6 +144,72 @@ const ( PACKET_OUTGOING = 4 // Outgoing of any type ) +// Packet socket options from +const ( + PACKET_RX_RING = 5 +) + +// Statuses for a frame in a packet_mmap ring buffer from . +const ( + TP_STATUS_KERNEL = 0 + TP_STATUS_USER = 0x1 + TP_STATUS_COPY = 0x2 + TP_STATUS_LOSING = 0x4 + TP_STATUS_CSUM_NOT_READY = 0x8 + TP_STATUS_VLAN_VALID = 0x10 + TP_STATUS_BLK_TMO = 0x20 + TP_STATUS_VLAN_TPID_VALID = 0x40 + TP_STATUS_CSUM_VALID = 0x80 + TP_STATUS_GSO_TCP = 0x100 +) + +// TpacketReq is the request for a packet_mmap ring buffer from +// . +// +// +marshal +type TpacketReq struct { + TpBlockSize uint32 + TpBlockNr uint32 + TpFrameSize uint32 + TpFrameNr uint32 +} + +// TpacketHdr is the header for a frame in a packet_mmap ring buffer from +// . +// +// +marshal +type TpacketHdr struct { + TpStatus uint64 + TpLen uint32 + TpSnaplen uint32 + TpMac uint16 + TpNet uint16 + TpSec uint32 + TpUsec uint32 `marshal:"unaligned"` +} + +// TpacketAlignment is the alignment of a frame in a packet_mmap ring buffer +// from . +const ( + TPACKET_ALIGNMENT = 16 +) + +// TPACKET_V1 is the version of a packet_mmap ring buffer from +// that is implemented in gVisor. +const ( + TPACKET_V1 = iota +) + +// TPACKET_HDRLEN is the length of a TpacketHdr from . +var ( + TPACKET_HDRLEN = TPacketAlign(uint32((*TpacketHdr)(nil).SizeBytes()) + uint32((*SockAddrLink)(nil).SizeBytes())) +) + +// TPacketAlign aligns a value to the alignment of a TPacket. +func TPacketAlign(x uint32) uint32 { + return (x + TPACKET_ALIGNMENT - 1) &^ (TPACKET_ALIGNMENT - 1) +} + // Socket options from socket.h. const ( SO_DEBUG = 1 diff --git a/pkg/syserr/netstack.go b/pkg/syserr/netstack.go index 3928106da..0cbcdd595 100644 --- a/pkg/syserr/netstack.go +++ b/pkg/syserr/netstack.go @@ -55,6 +55,7 @@ var ( ErrMulticastInputCannotBeOutput = New((&tcpip.ErrMulticastInputCannotBeOutput{}).String(), errno.EINVAL) ErrMissingRequiredFields = New((&tcpip.ErrMissingRequiredFields{}).String(), errno.EINVAL) ErrNoNet = New((&tcpip.ErrNoNet{}).String(), errno.ENONET) + ErrEndpointBusy = New((&tcpip.ErrEndpointBusy{}).String(), errno.EBUSY) ) // TranslateNetstackError converts an error from the tcpip package to a sentry @@ -149,6 +150,8 @@ func TranslateNetstackError(err tcpip.Error) *Error { return ErrMulticastInputCannotBeOutput case *tcpip.ErrMissingRequiredFields: return ErrMissingRequiredFields + case *tcpip.ErrEndpointBusy: + return ErrEndpointBusy default: panic(fmt.Sprintf("unknown error %T", err)) } diff --git a/pkg/tcpip/errors.go b/pkg/tcpip/errors.go index 0df3d8857..f6ed36176 100644 --- a/pkg/tcpip/errors.go +++ b/pkg/tcpip/errors.go @@ -620,4 +620,22 @@ func (*ErrMulticastInputCannotBeOutput) IgnoreStats() bool { } func (*ErrMulticastInputCannotBeOutput) String() string { return "output cannot contain input" } +// ErrEndpointBusy indicates that the operation cannot be completed because the +// endpoint is busy. +// +// +stateify savable +type ErrEndpointBusy struct{} + +// isError implements Error. +func (*ErrEndpointBusy) isError() {} + +// IgnoreStats implements Error. +func (*ErrEndpointBusy) IgnoreStats() bool { + return true +} + +func (*ErrEndpointBusy) String() string { + return "operation cannot be completed because the endpoint is busy" +} + // LINT.ThenChange(../syserr/netstack.go) diff --git a/pkg/tcpip/tcpip.go b/pkg/tcpip/tcpip.go index cea7530c2..970fe21d2 100644 --- a/pkg/tcpip/tcpip.go +++ b/pkg/tcpip/tcpip.go @@ -1185,6 +1185,19 @@ func (*ICMPv6Filter) isGettableSocketOption() {} func (*ICMPv6Filter) isSettableSocketOption() {} +// TpacketReq is the tpacket_req structure as described in +// https://www.kernel.org/doc/Documentation/networking/packet_mmap.txt +// +// +stateify savable +type TpacketReq struct { + TpBlockSize uint32 + TpBlockNr uint32 + TpFrameSize uint32 + TpFrameNr uint32 +} + +func (*TpacketReq) isSettableSocketOption() {} + // EndpointState represents the state of an endpoint. type EndpointState uint8