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