github.com/flowerwrong/netstack@v0.0.0-20191009141956-e5848263af28/tcpip/link/muxed/injectable.go (about) 1 // Copyright 2019 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 muxed provides a muxed link endpoints. 16 package muxed 17 18 import ( 19 "github.com/FlowerWrong/netstack/tcpip" 20 "github.com/FlowerWrong/netstack/tcpip/buffer" 21 "github.com/FlowerWrong/netstack/tcpip/stack" 22 ) 23 24 // InjectableEndpoint is an injectable multi endpoint. The endpoint has 25 // trivial routing rules that determine which InjectableEndpoint a given packet 26 // will be written to. Note that HandleLocal works differently for this 27 // endpoint (see WritePacket). 28 type InjectableEndpoint struct { 29 routes map[tcpip.Address]stack.InjectableLinkEndpoint 30 dispatcher stack.NetworkDispatcher 31 } 32 33 // MTU implements stack.LinkEndpoint. 34 func (m *InjectableEndpoint) MTU() uint32 { 35 minMTU := ^uint32(0) 36 for _, endpoint := range m.routes { 37 if endpointMTU := endpoint.MTU(); endpointMTU < minMTU { 38 minMTU = endpointMTU 39 } 40 } 41 return minMTU 42 } 43 44 // Capabilities implements stack.LinkEndpoint. 45 func (m *InjectableEndpoint) Capabilities() stack.LinkEndpointCapabilities { 46 minCapabilities := stack.LinkEndpointCapabilities(^uint(0)) 47 for _, endpoint := range m.routes { 48 minCapabilities &= endpoint.Capabilities() 49 } 50 return minCapabilities 51 } 52 53 // MaxHeaderLength implements stack.LinkEndpoint. 54 func (m *InjectableEndpoint) MaxHeaderLength() uint16 { 55 minHeaderLen := ^uint16(0) 56 for _, endpoint := range m.routes { 57 if headerLen := endpoint.MaxHeaderLength(); headerLen < minHeaderLen { 58 minHeaderLen = headerLen 59 } 60 } 61 return minHeaderLen 62 } 63 64 // LinkAddress implements stack.LinkEndpoint. 65 func (m *InjectableEndpoint) LinkAddress() tcpip.LinkAddress { 66 return "" 67 } 68 69 // Attach implements stack.LinkEndpoint. 70 func (m *InjectableEndpoint) Attach(dispatcher stack.NetworkDispatcher) { 71 for _, endpoint := range m.routes { 72 endpoint.Attach(dispatcher) 73 } 74 m.dispatcher = dispatcher 75 } 76 77 // IsAttached implements stack.LinkEndpoint. 78 func (m *InjectableEndpoint) IsAttached() bool { 79 return m.dispatcher != nil 80 } 81 82 // Inject implements stack.InjectableLinkEndpoint. 83 func (m *InjectableEndpoint) Inject(protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) { 84 m.dispatcher.DeliverNetworkPacket(m, "" /* remote */, "" /* local */, protocol, vv) 85 } 86 87 // WritePacket writes outbound packets to the appropriate LinkInjectableEndpoint 88 // based on the RemoteAddress. HandleLocal only works if r.RemoteAddress has a 89 // route registered in this endpoint. 90 func (m *InjectableEndpoint) WritePacket(r *stack.Route, _ *stack.GSO, hdr buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { 91 if endpoint, ok := m.routes[r.RemoteAddress]; ok { 92 return endpoint.WritePacket(r, nil /* gso */, hdr, payload, protocol) 93 } 94 return tcpip.ErrNoRoute 95 } 96 97 // WriteRawPacket writes outbound packets to the appropriate 98 // LinkInjectableEndpoint based on the dest address. 99 func (m *InjectableEndpoint) WriteRawPacket(dest tcpip.Address, packet []byte) *tcpip.Error { 100 endpoint, ok := m.routes[dest] 101 if !ok { 102 return tcpip.ErrNoRoute 103 } 104 return endpoint.WriteRawPacket(dest, packet) 105 } 106 107 // Wait implements stack.LinkEndpoint.Wait. 108 func (m *InjectableEndpoint) Wait() { 109 for _, ep := range m.routes { 110 ep.Wait() 111 } 112 } 113 114 // NewInjectableEndpoint creates a new multi-endpoint injectable endpoint. 115 func NewInjectableEndpoint(routes map[tcpip.Address]stack.InjectableLinkEndpoint) *InjectableEndpoint { 116 return &InjectableEndpoint{ 117 routes: routes, 118 } 119 }