summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/stack
diff options
context:
space:
mode:
authorGhanan Gowripalan <ghanan@google.com>2021-02-01 12:01:49 -0800
committergVisor bot <gvisor-bot@google.com>2021-02-01 12:04:03 -0800
commitebd3912c0f7e4255f100a00d2ab27304dac70daa (patch)
tree89e28a48e7fcd6015d2c2af25a565937cb1d61c9 /pkg/tcpip/stack
parentcbcebfea80bd59091e142cc6dad4192915194550 (diff)
Refactor HandleControlPacket/SockError
...to remove the need for the transport layer to deduce the type of error it received. Rename HandleControlPacket to HandleError as HandleControlPacket only handles errors. tcpip.SockError now holds a tcpip.SockErrorCause interface that different errors can implement. PiperOrigin-RevId: 354994306
Diffstat (limited to 'pkg/tcpip/stack')
-rw-r--r--pkg/tcpip/stack/nic.go7
-rw-r--r--pkg/tcpip/stack/registration.go77
-rw-r--r--pkg/tcpip/stack/stack_test.go7
-rw-r--r--pkg/tcpip/stack/transport_demuxer.go17
-rw-r--r--pkg/tcpip/stack/transport_test.go2
5 files changed, 59 insertions, 51 deletions
diff --git a/pkg/tcpip/stack/nic.go b/pkg/tcpip/stack/nic.go
index 693ea064a..41a489047 100644
--- a/pkg/tcpip/stack/nic.go
+++ b/pkg/tcpip/stack/nic.go
@@ -911,9 +911,8 @@ func (n *NIC) DeliverTransportPacket(protocol tcpip.TransportProtocolNumber, pkt
}
}
-// DeliverTransportControlPacket delivers control packets to the appropriate
-// transport protocol endpoint.
-func (n *NIC) DeliverTransportControlPacket(local, remote tcpip.Address, net tcpip.NetworkProtocolNumber, trans tcpip.TransportProtocolNumber, typ ControlType, extra uint32, pkt *PacketBuffer) {
+// DeliverTransportError implements TransportDispatcher.
+func (n *NIC) DeliverTransportError(local, remote tcpip.Address, net tcpip.NetworkProtocolNumber, trans tcpip.TransportProtocolNumber, transErr TransportError, pkt *PacketBuffer) {
state, ok := n.stack.transportProtocols[trans]
if !ok {
return
@@ -935,7 +934,7 @@ func (n *NIC) DeliverTransportControlPacket(local, remote tcpip.Address, net tcp
}
id := TransportEndpointID{srcPort, local, dstPort, remote}
- if n.stack.demux.deliverControlPacket(n, net, trans, typ, extra, pkt, id) {
+ if n.stack.demux.deliverError(n, net, trans, transErr, pkt, id) {
return
}
}
diff --git a/pkg/tcpip/stack/registration.go b/pkg/tcpip/stack/registration.go
index e02f7190c..d589f798d 100644
--- a/pkg/tcpip/stack/registration.go
+++ b/pkg/tcpip/stack/registration.go
@@ -49,31 +49,6 @@ type TransportEndpointID struct {
RemoteAddress tcpip.Address
}
-// ControlType is the type of network control message.
-type ControlType int
-
-// The following are the allowed values for ControlType values.
-// TODO(http://gvisor.dev/issue/3210): Support time exceeded messages.
-const (
- // ControlAddressUnreachable indicates that an IPv6 packet did not reach its
- // destination as the destination address was unreachable.
- //
- // This maps to the ICMPv6 Destination Ureachable Code 3 error; see
- // RFC 4443 section 3.1 for more details.
- ControlAddressUnreachable ControlType = iota
- ControlNetworkUnreachable
- // ControlNoRoute indicates that an IPv4 packet did not reach its destination
- // because the destination host was unreachable.
- //
- // This maps to the ICMPv4 Destination Ureachable Code 1 error; see
- // RFC 791's Destination Unreachable Message section (page 4) for more
- // details.
- ControlNoRoute
- ControlPacketTooBig
- ControlPortUnreachable
- ControlUnknown
-)
-
// NetworkPacketInfo holds information about a network layer packet.
type NetworkPacketInfo struct {
// LocalAddressBroadcast is true if the packet's local address is a broadcast
@@ -81,6 +56,39 @@ type NetworkPacketInfo struct {
LocalAddressBroadcast bool
}
+// TransportErrorKind enumerates error types that are handled by the transport
+// layer.
+type TransportErrorKind int
+
+const (
+ // PacketTooBigTransportError indicates that a packet did not reach its
+ // destination because a link on the path to the destination had an MTU that
+ // was too small to carry the packet.
+ PacketTooBigTransportError TransportErrorKind = iota
+
+ // DestinationHostUnreachableTransportError indicates that the destination
+ // host was unreachable.
+ DestinationHostUnreachableTransportError
+
+ // DestinationPortUnreachableTransportError indicates that a packet reached
+ // the destination host, but the transport protocol was not active on the
+ // destination port.
+ DestinationPortUnreachableTransportError
+
+ // DestinationNetworkUnreachableTransportError indicates that the destination
+ // network was unreachable.
+ DestinationNetworkUnreachableTransportError
+)
+
+// TransportError is a marker interface for errors that may be handled by the
+// transport layer.
+type TransportError interface {
+ tcpip.SockErrorCause
+
+ // Kind returns the type of the transport error.
+ Kind() TransportErrorKind
+}
+
// TransportEndpoint is the interface that needs to be implemented by transport
// protocol (e.g., tcp, udp) endpoints that can handle packets.
type TransportEndpoint interface {
@@ -93,10 +101,10 @@ type TransportEndpoint interface {
// HandlePacket takes ownership of the packet.
HandlePacket(TransportEndpointID, *PacketBuffer)
- // HandleControlPacket is called by the stack when new control (e.g.
- // ICMP) packets arrive to this transport endpoint.
- // HandleControlPacket takes ownership of pkt.
- HandleControlPacket(typ ControlType, extra uint32, pkt *PacketBuffer)
+ // HandleError is called when the transport endpoint receives an error.
+ //
+ // HandleError takes ownership of the packet buffer.
+ HandleError(TransportError, *PacketBuffer)
// Abort initiates an expedited endpoint teardown. It puts the endpoint
// in a closed state and frees all resources associated with it. This
@@ -248,14 +256,11 @@ type TransportDispatcher interface {
// DeliverTransportPacket takes ownership of the packet.
DeliverTransportPacket(tcpip.TransportProtocolNumber, *PacketBuffer) TransportPacketDisposition
- // DeliverTransportControlPacket delivers control packets to the
- // appropriate transport protocol endpoint.
- //
- // pkt.NetworkHeader must be set before calling
- // DeliverTransportControlPacket.
+ // DeliverTransportError delivers an error to the appropriate transport
+ // endpoint.
//
- // DeliverTransportControlPacket takes ownership of pkt.
- DeliverTransportControlPacket(local, remote tcpip.Address, net tcpip.NetworkProtocolNumber, trans tcpip.TransportProtocolNumber, typ ControlType, extra uint32, pkt *PacketBuffer)
+ // DeliverTransportError takes ownership of the packet buffer.
+ DeliverTransportError(local, remote tcpip.Address, _ tcpip.NetworkProtocolNumber, _ tcpip.TransportProtocolNumber, _ TransportError, _ *PacketBuffer)
}
// PacketLooping specifies where an outbound packet should be sent.
diff --git a/pkg/tcpip/stack/stack_test.go b/pkg/tcpip/stack/stack_test.go
index 375cd3080..b641a4aaa 100644
--- a/pkg/tcpip/stack/stack_test.go
+++ b/pkg/tcpip/stack/stack_test.go
@@ -138,12 +138,15 @@ func (f *fakeNetworkEndpoint) HandlePacket(pkt *stack.PacketBuffer) {
return
}
pkt.Data.TrimFront(fakeNetHeaderLen)
- f.dispatcher.DeliverTransportControlPacket(
+ f.dispatcher.DeliverTransportError(
tcpip.Address(nb[srcAddrOffset:srcAddrOffset+1]),
tcpip.Address(nb[dstAddrOffset:dstAddrOffset+1]),
fakeNetNumber,
tcpip.TransportProtocolNumber(nb[protocolNumberOffset]),
- stack.ControlPortUnreachable, 0, pkt)
+ // Nothing checks the error.
+ nil, /* transport error */
+ pkt,
+ )
return
}
diff --git a/pkg/tcpip/stack/transport_demuxer.go b/pkg/tcpip/stack/transport_demuxer.go
index 26eceb804..7d8d0851e 100644
--- a/pkg/tcpip/stack/transport_demuxer.go
+++ b/pkg/tcpip/stack/transport_demuxer.go
@@ -182,9 +182,8 @@ func (epsByNIC *endpointsByNIC) handlePacket(id TransportEndpointID, pkt *Packet
epsByNIC.mu.RUnlock() // Don't use defer for performance reasons.
}
-// handleControlPacket delivers a control packet to the transport endpoint
-// identified by id.
-func (epsByNIC *endpointsByNIC) handleControlPacket(n *NIC, id TransportEndpointID, typ ControlType, extra uint32, pkt *PacketBuffer) {
+// handleError delivers an error to the transport endpoint identified by id.
+func (epsByNIC *endpointsByNIC) handleError(n *NIC, id TransportEndpointID, transErr TransportError, pkt *PacketBuffer) {
epsByNIC.mu.RLock()
defer epsByNIC.mu.RUnlock()
@@ -200,7 +199,7 @@ func (epsByNIC *endpointsByNIC) handleControlPacket(n *NIC, id TransportEndpoint
// broadcast like we are doing with handlePacket above?
// multiPortEndpoints are guaranteed to have at least one element.
- selectEndpoint(id, mpep, epsByNIC.seed).HandleControlPacket(typ, extra, pkt)
+ selectEndpoint(id, mpep, epsByNIC.seed).HandleError(transErr, pkt)
}
// registerEndpoint returns true if it succeeds. It fails and returns
@@ -596,9 +595,11 @@ func (d *transportDemuxer) deliverRawPacket(protocol tcpip.TransportProtocolNumb
return foundRaw
}
-// deliverControlPacket attempts to deliver the given control packet. Returns
-// true if it found an endpoint, false otherwise.
-func (d *transportDemuxer) deliverControlPacket(n *NIC, net tcpip.NetworkProtocolNumber, trans tcpip.TransportProtocolNumber, typ ControlType, extra uint32, pkt *PacketBuffer, id TransportEndpointID) bool {
+// deliverError attempts to deliver the given error to the appropriate transport
+// endpoint.
+//
+// Returns true if the error was delivered.
+func (d *transportDemuxer) deliverError(n *NIC, net tcpip.NetworkProtocolNumber, trans tcpip.TransportProtocolNumber, transErr TransportError, pkt *PacketBuffer, id TransportEndpointID) bool {
eps, ok := d.protocol[protocolIDs{net, trans}]
if !ok {
return false
@@ -611,7 +612,7 @@ func (d *transportDemuxer) deliverControlPacket(n *NIC, net tcpip.NetworkProtoco
return false
}
- ep.handleControlPacket(n, id, typ, extra, pkt)
+ ep.handleError(n, id, transErr, pkt)
return true
}
diff --git a/pkg/tcpip/stack/transport_test.go b/pkg/tcpip/stack/transport_test.go
index cf5de747b..bebf4e6b5 100644
--- a/pkg/tcpip/stack/transport_test.go
+++ b/pkg/tcpip/stack/transport_test.go
@@ -237,7 +237,7 @@ func (f *fakeTransportEndpoint) HandlePacket(id stack.TransportEndpointID, pkt *
f.acceptQueue = append(f.acceptQueue, ep)
}
-func (f *fakeTransportEndpoint) HandleControlPacket(stack.ControlType, uint32, *stack.PacketBuffer) {
+func (f *fakeTransportEndpoint) HandleError(stack.TransportError, *stack.PacketBuffer) {
// Increment the number of received control packets.
f.proto.controlCount++
}