inet.af/netstack@v0.0.0-20220214151720-7585b01ddccf/tcpip/link/nested/nested.go (about) 1 // Copyright 2020 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package nested provides helpers to implement the pattern of nested 16 // stack.LinkEndpoints. 17 package nested 18 19 import ( 20 "inet.af/netstack/sync" 21 "inet.af/netstack/tcpip" 22 "inet.af/netstack/tcpip/header" 23 "inet.af/netstack/tcpip/stack" 24 ) 25 26 // Endpoint is a wrapper around stack.LinkEndpoint and stack.NetworkDispatcher 27 // that can be used to implement nesting safely by providing lifecycle 28 // concurrency guards. 29 // 30 // See the tests in this package for example usage. 31 type Endpoint struct { 32 child stack.LinkEndpoint 33 embedder stack.NetworkDispatcher 34 35 // mu protects dispatcher. 36 mu sync.RWMutex 37 dispatcher stack.NetworkDispatcher 38 } 39 40 var _ stack.GSOEndpoint = (*Endpoint)(nil) 41 var _ stack.LinkEndpoint = (*Endpoint)(nil) 42 var _ stack.NetworkDispatcher = (*Endpoint)(nil) 43 44 // Init initializes a nested.Endpoint that uses embedder as the dispatcher for 45 // child on Attach. 46 // 47 // See the tests in this package for example usage. 48 func (e *Endpoint) Init(child stack.LinkEndpoint, embedder stack.NetworkDispatcher) { 49 e.child = child 50 e.embedder = embedder 51 } 52 53 // DeliverNetworkPacket implements stack.NetworkDispatcher. 54 func (e *Endpoint) DeliverNetworkPacket(remote, local tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) { 55 e.mu.RLock() 56 d := e.dispatcher 57 e.mu.RUnlock() 58 if d != nil { 59 d.DeliverNetworkPacket(remote, local, protocol, pkt) 60 } 61 } 62 63 // Attach implements stack.LinkEndpoint. 64 func (e *Endpoint) Attach(dispatcher stack.NetworkDispatcher) { 65 e.mu.Lock() 66 e.dispatcher = dispatcher 67 e.mu.Unlock() 68 // If we're attaching to a valid dispatcher, pass embedder as the dispatcher 69 // to our child, otherwise detach the child by giving it a nil dispatcher. 70 var pass stack.NetworkDispatcher 71 if dispatcher != nil { 72 pass = e.embedder 73 } 74 e.child.Attach(pass) 75 } 76 77 // IsAttached implements stack.LinkEndpoint. 78 func (e *Endpoint) IsAttached() bool { 79 e.mu.RLock() 80 isAttached := e.dispatcher != nil 81 e.mu.RUnlock() 82 return isAttached 83 } 84 85 // MTU implements stack.LinkEndpoint. 86 func (e *Endpoint) MTU() uint32 { 87 return e.child.MTU() 88 } 89 90 // Capabilities implements stack.LinkEndpoint. 91 func (e *Endpoint) Capabilities() stack.LinkEndpointCapabilities { 92 return e.child.Capabilities() 93 } 94 95 // MaxHeaderLength implements stack.LinkEndpoint. 96 func (e *Endpoint) MaxHeaderLength() uint16 { 97 return e.child.MaxHeaderLength() 98 } 99 100 // LinkAddress implements stack.LinkEndpoint. 101 func (e *Endpoint) LinkAddress() tcpip.LinkAddress { 102 return e.child.LinkAddress() 103 } 104 105 // WritePacket implements stack.LinkEndpoint. 106 func (e *Endpoint) WritePacket(r stack.RouteInfo, protocol tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) tcpip.Error { 107 return e.child.WritePacket(r, protocol, pkt) 108 } 109 110 // WritePackets implements stack.LinkEndpoint. 111 func (e *Endpoint) WritePackets(r stack.RouteInfo, pkts stack.PacketBufferList, protocol tcpip.NetworkProtocolNumber) (int, tcpip.Error) { 112 return e.child.WritePackets(r, pkts, protocol) 113 } 114 115 // Wait implements stack.LinkEndpoint. 116 func (e *Endpoint) Wait() { 117 e.child.Wait() 118 } 119 120 // GSOMaxSize implements stack.GSOEndpoint. 121 func (e *Endpoint) GSOMaxSize() uint32 { 122 if e, ok := e.child.(stack.GSOEndpoint); ok { 123 return e.GSOMaxSize() 124 } 125 return 0 126 } 127 128 // SupportedGSO implements stack.GSOEndpoint. 129 func (e *Endpoint) SupportedGSO() stack.SupportedGSO { 130 if e, ok := e.child.(stack.GSOEndpoint); ok { 131 return e.SupportedGSO() 132 } 133 return stack.GSONotSupported 134 } 135 136 // ARPHardwareType implements stack.LinkEndpoint.ARPHardwareType 137 func (e *Endpoint) ARPHardwareType() header.ARPHardwareType { 138 return e.child.ARPHardwareType() 139 } 140 141 // AddHeader implements stack.LinkEndpoint.AddHeader. 142 func (e *Endpoint) AddHeader(local, remote tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) { 143 e.child.AddHeader(local, remote, protocol, pkt) 144 } 145 146 // WriteRawPacket implements stack.LinkEndpoint. 147 func (e *Endpoint) WriteRawPacket(pkt *stack.PacketBuffer) tcpip.Error { 148 return e.child.WriteRawPacket(pkt) 149 }