summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/stack
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/tcpip/stack')
-rw-r--r--pkg/tcpip/stack/linkaddrcache_test.go10
-rw-r--r--pkg/tcpip/stack/packet_buffer.go11
-rw-r--r--pkg/tcpip/stack/pending_packets.go8
-rw-r--r--pkg/tcpip/stack/registration.go21
-rw-r--r--pkg/tcpip/stack/transport_test.go14
5 files changed, 36 insertions, 28 deletions
diff --git a/pkg/tcpip/stack/linkaddrcache_test.go b/pkg/tcpip/stack/linkaddrcache_test.go
index 6883045b5..03b2f2d6f 100644
--- a/pkg/tcpip/stack/linkaddrcache_test.go
+++ b/pkg/tcpip/stack/linkaddrcache_test.go
@@ -83,7 +83,7 @@ func getBlocking(c *linkAddrCache, addr tcpip.FullAddress, linkRes LinkAddressRe
got, ch, err := c.get(addr, linkRes, "", nil, nil)
if err == tcpip.ErrWouldBlock {
if attemptedResolution {
- return got, tcpip.ErrNoLinkAddress
+ return got, tcpip.ErrTimeout
}
attemptedResolution = true
<-ch
@@ -253,8 +253,8 @@ func TestCacheResolutionFailed(t *testing.T) {
before := atomic.LoadUint32(&requestCount)
e.addr.Addr += "2"
- if _, err := getBlocking(c, e.addr, linkRes); err != tcpip.ErrNoLinkAddress {
- t.Errorf("c.get(%q), got error: %v, want: error ErrNoLinkAddress", string(e.addr.Addr), err)
+ if a, err := getBlocking(c, e.addr, linkRes); err != tcpip.ErrTimeout {
+ t.Errorf("got getBlocking(_, %#v, _) = (%s, %s), want = (_, %s)", e.addr, a, err, tcpip.ErrTimeout)
}
if got, want := int(atomic.LoadUint32(&requestCount)-before), c.resolutionAttempts; got != want {
@@ -269,8 +269,8 @@ func TestCacheResolutionTimeout(t *testing.T) {
linkRes := &testLinkAddressResolver{cache: c, delay: resolverDelay}
e := testAddrs[0]
- if _, err := getBlocking(c, e.addr, linkRes); err != tcpip.ErrNoLinkAddress {
- t.Errorf("c.get(%q), got error: %v, want: error ErrNoLinkAddress", string(e.addr.Addr), err)
+ if a, err := getBlocking(c, e.addr, linkRes); err != tcpip.ErrTimeout {
+ t.Errorf("got getBlocking(_, %#v, _) = (%s, %s), want = (_, %s)", e.addr, a, err, tcpip.ErrTimeout)
}
}
diff --git a/pkg/tcpip/stack/packet_buffer.go b/pkg/tcpip/stack/packet_buffer.go
index 664cc6fa0..5f216ca21 100644
--- a/pkg/tcpip/stack/packet_buffer.go
+++ b/pkg/tcpip/stack/packet_buffer.go
@@ -268,17 +268,6 @@ func (pk *PacketBuffer) Clone() *PacketBuffer {
}
}
-// SourceLinkAddress returns the source link address of the packet.
-func (pk *PacketBuffer) SourceLinkAddress() tcpip.LinkAddress {
- link := pk.LinkHeader().View()
-
- if link.IsEmpty() {
- return ""
- }
-
- return header.Ethernet(link).SourceAddress()
-}
-
// Network returns the network header as a header.Network.
//
// Network should only be called when NetworkHeader has been set.
diff --git a/pkg/tcpip/stack/pending_packets.go b/pkg/tcpip/stack/pending_packets.go
index 4a3adcf33..bded8814e 100644
--- a/pkg/tcpip/stack/pending_packets.go
+++ b/pkg/tcpip/stack/pending_packets.go
@@ -101,10 +101,12 @@ func (f *packetsPendingLinkResolution) enqueue(ch <-chan struct{}, r *Route, pro
}
for _, p := range packets {
- if cancelled {
- p.route.Stats().IP.OutgoingPacketErrors.Increment()
- } else if p.route.IsResolutionRequired() {
+ if cancelled || p.route.IsResolutionRequired() {
p.route.Stats().IP.OutgoingPacketErrors.Increment()
+
+ if linkResolvableEP, ok := p.route.outgoingNIC.getNetworkEndpoint(p.route.NetProto).(LinkResolvableNetworkEndpoint); ok {
+ linkResolvableEP.HandleLinkResolutionFailure(pkt)
+ }
} else {
p.route.outgoingNIC.writePacket(p.route, nil /* gso */, p.proto, p.pkt)
}
diff --git a/pkg/tcpip/stack/registration.go b/pkg/tcpip/stack/registration.go
index 4795208b4..924790779 100644
--- a/pkg/tcpip/stack/registration.go
+++ b/pkg/tcpip/stack/registration.go
@@ -55,7 +55,19 @@ type ControlType int
// The following are the allowed values for ControlType values.
// TODO(http://gvisor.dev/issue/3210): Support time exceeded messages.
const (
- ControlNetworkUnreachable ControlType = iota
+ // 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
@@ -503,6 +515,13 @@ type NetworkInterface interface {
WritePacketToRemote(tcpip.LinkAddress, *GSO, tcpip.NetworkProtocolNumber, *PacketBuffer) *tcpip.Error
}
+// LinkResolvableNetworkEndpoint handles link resolution events.
+type LinkResolvableNetworkEndpoint interface {
+ // HandleLinkResolutionFailure is called when link resolution prevents the
+ // argument from having been sent.
+ HandleLinkResolutionFailure(*PacketBuffer)
+}
+
// NetworkEndpoint is the interface that needs to be implemented by endpoints
// of network layer protocols (e.g., ipv4, ipv6).
type NetworkEndpoint interface {
diff --git a/pkg/tcpip/stack/transport_test.go b/pkg/tcpip/stack/transport_test.go
index 0ff32c6ea..a2ab7537c 100644
--- a/pkg/tcpip/stack/transport_test.go
+++ b/pkg/tcpip/stack/transport_test.go
@@ -90,14 +90,14 @@ func (*fakeTransportEndpoint) Read(io.Writer, int, tcpip.ReadOptions) (tcpip.Rea
return tcpip.ReadResult{}, nil
}
-func (f *fakeTransportEndpoint) Write(p tcpip.Payloader, opts tcpip.WriteOptions) (int64, <-chan struct{}, *tcpip.Error) {
+func (f *fakeTransportEndpoint) Write(p tcpip.Payloader, opts tcpip.WriteOptions) (int64, *tcpip.Error) {
if len(f.route.RemoteAddress) == 0 {
- return 0, nil, tcpip.ErrNoRoute
+ return 0, tcpip.ErrNoRoute
}
v, err := p.FullPayload()
if err != nil {
- return 0, nil, err
+ return 0, err
}
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
ReserveHeaderBytes: int(f.route.MaxHeaderLength()) + fakeTransHeaderLen,
@@ -105,10 +105,10 @@ func (f *fakeTransportEndpoint) Write(p tcpip.Payloader, opts tcpip.WriteOptions
})
_ = pkt.TransportHeader().Push(fakeTransHeaderLen)
if err := f.route.WritePacket(nil /* gso */, stack.NetworkHeaderParams{Protocol: fakeTransNumber, TTL: 123, TOS: stack.DefaultTOS}, pkt); err != nil {
- return 0, nil, err
+ return 0, err
}
- return int64(len(v)), nil, nil
+ return int64(len(v)), nil
}
// SetSockOpt sets a socket option. Currently not supported.
@@ -222,7 +222,6 @@ func (f *fakeTransportEndpoint) HandlePacket(id stack.TransportEndpointID, pkt *
if err != nil {
return
}
- route.ResolveWith(pkt.SourceLinkAddress())
ep := &fakeTransportEndpoint{
TransportEndpointInfo: stack.TransportEndpointInfo{
@@ -522,8 +521,7 @@ func TestTransportSend(t *testing.T) {
// Create buffer that will hold the payload.
view := buffer.NewView(30)
- _, _, err = ep.Write(tcpip.SlicePayload(view), tcpip.WriteOptions{})
- if err != nil {
+ if _, err := ep.Write(tcpip.SlicePayload(view), tcpip.WriteOptions{}); err != nil {
t.Fatalf("write failed: %v", err)
}