github.com/google/netstack@v0.0.0-20191123085552-55fcc16cd0eb/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/google/netstack/tcpip" 20 "github.com/google/netstack/tcpip/buffer" 21 "github.com/google/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 // InjectInbound implements stack.InjectableLinkEndpoint. 83 func (m *InjectableEndpoint) InjectInbound(protocol tcpip.NetworkProtocolNumber, pkt tcpip.PacketBuffer) { 84 m.dispatcher.DeliverNetworkPacket(m, "" /* remote */, "" /* local */, protocol, pkt) 85 } 86 87 // WritePackets writes outbound packets to the appropriate 88 // LinkInjectableEndpoint based on the RemoteAddress. HandleLocal only works if 89 // r.RemoteAddress has a route registered in this endpoint. 90 func (m *InjectableEndpoint) WritePackets(r *stack.Route, gso *stack.GSO, hdrs []stack.PacketDescriptor, payload buffer.VectorisedView, protocol tcpip.NetworkProtocolNumber) (int, *tcpip.Error) { 91 endpoint, ok := m.routes[r.RemoteAddress] 92 if !ok { 93 return 0, tcpip.ErrNoRoute 94 } 95 return endpoint.WritePackets(r, gso, hdrs, payload, protocol) 96 } 97 98 // WritePacket writes outbound packets to the appropriate LinkInjectableEndpoint 99 // based on the RemoteAddress. HandleLocal only works if r.RemoteAddress has a 100 // route registered in this endpoint. 101 func (m *InjectableEndpoint) WritePacket(r *stack.Route, gso *stack.GSO, protocol tcpip.NetworkProtocolNumber, pkt tcpip.PacketBuffer) *tcpip.Error { 102 if endpoint, ok := m.routes[r.RemoteAddress]; ok { 103 return endpoint.WritePacket(r, gso, protocol, pkt) 104 } 105 return tcpip.ErrNoRoute 106 } 107 108 // WriteRawPacket implements stack.LinkEndpoint.WriteRawPacket. 109 func (m *InjectableEndpoint) WriteRawPacket(buffer.VectorisedView) *tcpip.Error { 110 // WriteRawPacket doesn't get a route or network address, so there's 111 // nowhere to write this. 112 return tcpip.ErrNoRoute 113 } 114 115 // InjectOutbound writes outbound packets to the appropriate 116 // LinkInjectableEndpoint based on the dest address. 117 func (m *InjectableEndpoint) InjectOutbound(dest tcpip.Address, packet []byte) *tcpip.Error { 118 endpoint, ok := m.routes[dest] 119 if !ok { 120 return tcpip.ErrNoRoute 121 } 122 return endpoint.InjectOutbound(dest, packet) 123 } 124 125 // Wait implements stack.LinkEndpoint.Wait. 126 func (m *InjectableEndpoint) Wait() { 127 for _, ep := range m.routes { 128 ep.Wait() 129 } 130 } 131 132 // NewInjectableEndpoint creates a new multi-endpoint injectable endpoint. 133 func NewInjectableEndpoint(routes map[tcpip.Address]stack.InjectableLinkEndpoint) *InjectableEndpoint { 134 return &InjectableEndpoint{ 135 routes: routes, 136 } 137 }