summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip
diff options
context:
space:
mode:
authorAyush Ranjan <ayushranjan@google.com>2020-12-17 08:45:38 -0800
committergVisor bot <gvisor-bot@google.com>2020-12-17 08:47:24 -0800
commit74788b1b6194ef62f8355f7e4721c00f615d16ad (patch)
tree87a4089f292401c74ee2abf560b55219dbaa63a4 /pkg/tcpip
parent4640fc4f359440609664b3f3349bd782694f0f4a (diff)
[netstack] Implement MSG_ERRQUEUE flag for recvmsg(2).
Introduces the per-socket error queue and the necessary cmsg mechanisms. PiperOrigin-RevId: 348028508
Diffstat (limited to 'pkg/tcpip')
-rw-r--r--pkg/tcpip/BUILD14
-rw-r--r--pkg/tcpip/socketops.go63
-rw-r--r--pkg/tcpip/tcpip.go3
3 files changed, 79 insertions, 1 deletions
diff --git a/pkg/tcpip/BUILD b/pkg/tcpip/BUILD
index 27f96a3ac..89b765f1b 100644
--- a/pkg/tcpip/BUILD
+++ b/pkg/tcpip/BUILD
@@ -1,10 +1,24 @@
load("//tools:defs.bzl", "go_library", "go_test")
+load("//tools/go_generics:defs.bzl", "go_template_instance")
package(licenses = ["notice"])
+go_template_instance(
+ name = "sock_err_list",
+ out = "sock_err_list.go",
+ package = "tcpip",
+ prefix = "sockError",
+ template = "//pkg/ilist:generic_list",
+ types = {
+ "Element": "*SockError",
+ "Linker": "*SockError",
+ },
+)
+
go_library(
name = "tcpip",
srcs = [
+ "sock_err_list.go",
"socketops.go",
"tcpip.go",
"time_unsafe.go",
diff --git a/pkg/tcpip/socketops.go b/pkg/tcpip/socketops.go
index b60a5fd76..eb63d735f 100644
--- a/pkg/tcpip/socketops.go
+++ b/pkg/tcpip/socketops.go
@@ -104,7 +104,7 @@ type SocketOptions struct {
keepAliveEnabled uint32
// multicastLoopEnabled determines whether multicast packets sent over a
- // non-loopback interface will be looped back. Analogous to inet->mc_loop.
+ // non-loopback interface will be looped back.
multicastLoopEnabled uint32
// receiveTOSEnabled is used to specify if the TOS ancillary message is
@@ -145,6 +145,10 @@ type SocketOptions struct {
// the incoming packet should be returned as an ancillary message.
receiveOriginalDstAddress uint32
+ // errQueue is the per-socket error queue. It is protected by errQueueMu.
+ errQueueMu sync.Mutex `state:"nosave"`
+ errQueue sockErrorList
+
// mu protects the access to the below fields.
mu sync.Mutex `state:"nosave"`
@@ -362,3 +366,60 @@ func (so *SocketOptions) SetLinger(linger LingerOption) {
so.linger = linger
so.mu.Unlock()
}
+
+// SockErrOrigin represents the constants for error origin.
+type SockErrOrigin uint8
+
+const (
+ // SockExtErrorOriginNone represents an unknown error origin.
+ SockExtErrorOriginNone SockErrOrigin = iota
+
+ // SockExtErrorOriginLocal indicates a local error.
+ SockExtErrorOriginLocal
+
+ // SockExtErrorOriginICMP indicates an IPv4 ICMP error.
+ SockExtErrorOriginICMP
+
+ // SockExtErrorOriginICMP6 indicates an IPv6 ICMP error.
+ SockExtErrorOriginICMP6
+)
+
+// SockError represents a queue entry in the per-socket error queue.
+//
+// +stateify savable
+type SockError struct {
+ sockErrorEntry
+
+ // Err is the error caused by the errant packet.
+ Err *Error
+ // ErrOrigin indicates the error origin.
+ ErrOrigin SockErrOrigin
+ // ErrType is the type in the ICMP header.
+ ErrType uint8
+ // ErrCode is the code in the ICMP header.
+ ErrCode uint8
+ // ErrInfo is additional info about the error.
+ ErrInfo uint32
+
+ // Payload is the errant packet's payload.
+ Payload []byte
+ // Dst is the original destination address of the errant packet.
+ Dst FullAddress
+ // Offender is the original sender address of the errant packet.
+ Offender FullAddress
+ // NetProto is the network protocol being used to transmit the packet.
+ NetProto NetworkProtocolNumber
+}
+
+// DequeueErr dequeues a socket extended error from the error queue and returns
+// it. Returns nil if queue is empty.
+func (so *SocketOptions) DequeueErr() *SockError {
+ so.errQueueMu.Lock()
+ defer so.errQueueMu.Unlock()
+
+ err := so.errQueue.Front()
+ if err != nil {
+ so.errQueue.Remove(err)
+ }
+ return err
+}
diff --git a/pkg/tcpip/tcpip.go b/pkg/tcpip/tcpip.go
index 45fa62720..a488cc108 100644
--- a/pkg/tcpip/tcpip.go
+++ b/pkg/tcpip/tcpip.go
@@ -500,6 +500,9 @@ type ControlMessages struct {
// OriginalDestinationAddress holds the original destination address
// and port of the incoming packet.
OriginalDstAddress FullAddress
+
+ // SockErr is the dequeued socket error on recvmsg(MSG_ERRQUEUE).
+ SockErr *SockError
}
// PacketOwner is used to get UID and GID of the packet.