gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/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 "gvisor.dev/gvisor/pkg/sync" 21 "gvisor.dev/gvisor/pkg/tcpip" 22 "gvisor.dev/gvisor/pkg/tcpip/header" 23 "gvisor.dev/gvisor/pkg/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(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(protocol, pkt) 60 } 61 } 62 63 // DeliverLinkPacket implements stack.NetworkDispatcher. 64 func (e *Endpoint) DeliverLinkPacket(protocol tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) { 65 e.mu.RLock() 66 d := e.dispatcher 67 e.mu.RUnlock() 68 if d != nil { 69 d.DeliverLinkPacket(protocol, pkt) 70 } 71 } 72 73 // Attach implements stack.LinkEndpoint. 74 func (e *Endpoint) Attach(dispatcher stack.NetworkDispatcher) { 75 e.mu.Lock() 76 e.dispatcher = dispatcher 77 e.mu.Unlock() 78 // If we're attaching to a valid dispatcher, pass embedder as the dispatcher 79 // to our child, otherwise detach the child by giving it a nil dispatcher. 80 var pass stack.NetworkDispatcher 81 if dispatcher != nil { 82 pass = e.embedder 83 } 84 e.child.Attach(pass) 85 } 86 87 // IsAttached implements stack.LinkEndpoint. 88 func (e *Endpoint) IsAttached() bool { 89 e.mu.RLock() 90 isAttached := e.dispatcher != nil 91 e.mu.RUnlock() 92 return isAttached 93 } 94 95 // MTU implements stack.LinkEndpoint. 96 func (e *Endpoint) MTU() uint32 { 97 return e.child.MTU() 98 } 99 100 // Capabilities implements stack.LinkEndpoint. 101 func (e *Endpoint) Capabilities() stack.LinkEndpointCapabilities { 102 return e.child.Capabilities() 103 } 104 105 // MaxHeaderLength implements stack.LinkEndpoint. 106 func (e *Endpoint) MaxHeaderLength() uint16 { 107 return e.child.MaxHeaderLength() 108 } 109 110 // LinkAddress implements stack.LinkEndpoint. 111 func (e *Endpoint) LinkAddress() tcpip.LinkAddress { 112 return e.child.LinkAddress() 113 } 114 115 // WritePackets implements stack.LinkEndpoint. 116 func (e *Endpoint) WritePackets(pkts stack.PacketBufferList) (int, tcpip.Error) { 117 return e.child.WritePackets(pkts) 118 } 119 120 // Wait implements stack.LinkEndpoint. 121 func (e *Endpoint) Wait() { 122 e.child.Wait() 123 } 124 125 // GSOMaxSize implements stack.GSOEndpoint. 126 func (e *Endpoint) GSOMaxSize() uint32 { 127 if e, ok := e.child.(stack.GSOEndpoint); ok { 128 return e.GSOMaxSize() 129 } 130 return 0 131 } 132 133 // SupportedGSO implements stack.GSOEndpoint. 134 func (e *Endpoint) SupportedGSO() stack.SupportedGSO { 135 if e, ok := e.child.(stack.GSOEndpoint); ok { 136 return e.SupportedGSO() 137 } 138 return stack.GSONotSupported 139 } 140 141 // ARPHardwareType implements stack.LinkEndpoint.ARPHardwareType 142 func (e *Endpoint) ARPHardwareType() header.ARPHardwareType { 143 return e.child.ARPHardwareType() 144 } 145 146 // AddHeader implements stack.LinkEndpoint.AddHeader. 147 func (e *Endpoint) AddHeader(pkt *stack.PacketBuffer) { 148 e.child.AddHeader(pkt) 149 } 150 151 // ParseHeader implements stack.LinkEndpoint.ParseHeader. 152 func (e *Endpoint) ParseHeader(pkt *stack.PacketBuffer) bool { 153 return e.child.ParseHeader(pkt) 154 }