github.com/FlowerWrong/netstack@v0.0.0-20191009141956-e5848263af28/tcpip/stack/route.go (about) 1 // Copyright 2018 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 stack 16 17 import ( 18 "github.com/FlowerWrong/netstack/sleep" 19 "github.com/FlowerWrong/netstack/tcpip" 20 "github.com/FlowerWrong/netstack/tcpip/buffer" 21 "github.com/FlowerWrong/netstack/tcpip/header" 22 ) 23 24 // Route represents a route through the networking stack to a given destination. 25 type Route struct { 26 // RemoteAddress is the final destination of the route. 27 RemoteAddress tcpip.Address 28 29 // RemoteLinkAddress is the link-layer (MAC) address of the 30 // final destination of the route. 31 RemoteLinkAddress tcpip.LinkAddress 32 33 // LocalAddress is the local address where the route starts. 34 LocalAddress tcpip.Address 35 36 // LocalLinkAddress is the link-layer (MAC) address of the 37 // where the route starts. 38 LocalLinkAddress tcpip.LinkAddress 39 40 // NextHop is the next node in the path to the destination. 41 NextHop tcpip.Address 42 43 // NetProto is the network-layer protocol. 44 NetProto tcpip.NetworkProtocolNumber 45 46 // ref a reference to the network endpoint through which the route 47 // starts. 48 ref *referencedNetworkEndpoint 49 50 // loop controls where WritePacket should send packets. 51 loop PacketLooping 52 } 53 54 // makeRoute initializes a new route. It takes ownership of the provided 55 // reference to a network endpoint. 56 func makeRoute(netProto tcpip.NetworkProtocolNumber, localAddr, remoteAddr tcpip.Address, localLinkAddr tcpip.LinkAddress, ref *referencedNetworkEndpoint, handleLocal, multicastLoop bool) Route { 57 loop := PacketOut 58 if handleLocal && localAddr != "" && remoteAddr == localAddr { 59 loop = PacketLoop 60 } else if multicastLoop && (header.IsV4MulticastAddress(remoteAddr) || header.IsV6MulticastAddress(remoteAddr)) { 61 loop |= PacketLoop 62 } else if remoteAddr == header.IPv4Broadcast { 63 loop |= PacketLoop 64 } 65 66 return Route{ 67 NetProto: netProto, 68 LocalAddress: localAddr, 69 LocalLinkAddress: localLinkAddr, 70 RemoteAddress: remoteAddr, 71 ref: ref, 72 loop: loop, 73 } 74 } 75 76 // NICID returns the id of the NIC from which this route originates. 77 func (r *Route) NICID() tcpip.NICID { 78 return r.ref.ep.NICID() 79 } 80 81 // MaxHeaderLength forwards the call to the network endpoint's implementation. 82 func (r *Route) MaxHeaderLength() uint16 { 83 return r.ref.ep.MaxHeaderLength() 84 } 85 86 // Stats returns a mutable copy of current stats. 87 func (r *Route) Stats() tcpip.Stats { 88 return r.ref.nic.stack.Stats() 89 } 90 91 // PseudoHeaderChecksum forwards the call to the network endpoint's 92 // implementation. 93 func (r *Route) PseudoHeaderChecksum(protocol tcpip.TransportProtocolNumber, totalLen uint16) uint16 { 94 return header.PseudoHeaderChecksum(protocol, r.LocalAddress, r.RemoteAddress, totalLen) 95 } 96 97 // Capabilities returns the link-layer capabilities of the route. 98 func (r *Route) Capabilities() LinkEndpointCapabilities { 99 return r.ref.ep.Capabilities() 100 } 101 102 // GSOMaxSize returns the maximum GSO packet size. 103 func (r *Route) GSOMaxSize() uint32 { 104 if gso, ok := r.ref.ep.(GSOEndpoint); ok { 105 return gso.GSOMaxSize() 106 } 107 return 0 108 } 109 110 // Resolve attempts to resolve the link address if necessary. Returns ErrWouldBlock in 111 // case address resolution requires blocking, e.g. wait for ARP reply. Waker is 112 // notified when address resolution is complete (success or not). 113 // 114 // If address resolution is required, ErrNoLinkAddress and a notification channel is 115 // returned for the top level caller to block. Channel is closed once address resolution 116 // is complete (success or not). 117 func (r *Route) Resolve(waker *sleep.Waker) (<-chan struct{}, *tcpip.Error) { 118 if !r.IsResolutionRequired() { 119 // Nothing to do if there is no cache (which does the resolution on cache miss) or 120 // link address is already known. 121 return nil, nil 122 } 123 124 nextAddr := r.NextHop 125 if nextAddr == "" { 126 // Local link address is already known. 127 if r.RemoteAddress == r.LocalAddress { 128 r.RemoteLinkAddress = r.LocalLinkAddress 129 return nil, nil 130 } 131 nextAddr = r.RemoteAddress 132 } 133 linkAddr, ch, err := r.ref.linkCache.GetLinkAddress(r.ref.nic.ID(), nextAddr, r.LocalAddress, r.NetProto, waker) 134 if err != nil { 135 return ch, err 136 } 137 r.RemoteLinkAddress = linkAddr 138 return nil, nil 139 } 140 141 // RemoveWaker removes a waker that has been added in Resolve(). 142 func (r *Route) RemoveWaker(waker *sleep.Waker) { 143 nextAddr := r.NextHop 144 if nextAddr == "" { 145 nextAddr = r.RemoteAddress 146 } 147 r.ref.linkCache.RemoveWaker(r.ref.nic.ID(), nextAddr, waker) 148 } 149 150 // IsResolutionRequired returns true if Resolve() must be called to resolve 151 // the link address before the this route can be written to. 152 func (r *Route) IsResolutionRequired() bool { 153 return r.ref.isValidForOutgoing() && r.ref.linkCache != nil && r.RemoteLinkAddress == "" 154 } 155 156 // WritePacket writes the packet through the given route. 157 func (r *Route) WritePacket(gso *GSO, hdr buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.TransportProtocolNumber, ttl uint8, useDefaultTTL bool) *tcpip.Error { 158 if !r.ref.isValidForOutgoing() { 159 return tcpip.ErrInvalidEndpointState 160 } 161 162 if useDefaultTTL { 163 ttl = r.DefaultTTL() 164 } 165 166 err := r.ref.ep.WritePacket(r, gso, hdr, payload, protocol, ttl, r.loop) 167 if err != nil { 168 r.Stats().IP.OutgoingPacketErrors.Increment() 169 } else { 170 r.ref.nic.stats.Tx.Packets.Increment() 171 r.ref.nic.stats.Tx.Bytes.IncrementBy(uint64(hdr.UsedLength() + payload.Size())) 172 } 173 return err 174 } 175 176 // WriteHeaderIncludedPacket writes a packet already containing a network 177 // header through the given route. 178 func (r *Route) WriteHeaderIncludedPacket(payload buffer.VectorisedView) *tcpip.Error { 179 if !r.ref.isValidForOutgoing() { 180 return tcpip.ErrInvalidEndpointState 181 } 182 183 if err := r.ref.ep.WriteHeaderIncludedPacket(r, payload, r.loop); err != nil { 184 r.Stats().IP.OutgoingPacketErrors.Increment() 185 return err 186 } 187 r.ref.nic.stats.Tx.Packets.Increment() 188 r.ref.nic.stats.Tx.Bytes.IncrementBy(uint64(payload.Size())) 189 return nil 190 } 191 192 // DefaultTTL returns the default TTL of the underlying network endpoint. 193 func (r *Route) DefaultTTL() uint8 { 194 return r.ref.ep.DefaultTTL() 195 } 196 197 // MTU returns the MTU of the underlying network endpoint. 198 func (r *Route) MTU() uint32 { 199 return r.ref.ep.MTU() 200 } 201 202 // Release frees all resources associated with the route. 203 func (r *Route) Release() { 204 if r.ref != nil { 205 r.ref.decRef() 206 r.ref = nil 207 } 208 } 209 210 // Clone Clone a route such that the original one can be released and the new 211 // one will remain valid. 212 func (r *Route) Clone() Route { 213 r.ref.incRef() 214 return *r 215 } 216 217 // MakeLoopedRoute duplicates the given route with special handling for routes 218 // used for sending multicast or broadcast packets. In those cases the 219 // multicast/broadcast address is the remote address when sending out, but for 220 // incoming (looped) packets it becomes the local address. Similarly, the local 221 // interface address that was the local address going out becomes the remote 222 // address coming in. This is different to unicast routes where local and 223 // remote addresses remain the same as they identify location (local vs remote) 224 // not direction (source vs destination). 225 func (r *Route) MakeLoopedRoute() Route { 226 l := r.Clone() 227 if r.RemoteAddress == header.IPv4Broadcast || header.IsV4MulticastAddress(r.RemoteAddress) || header.IsV6MulticastAddress(r.RemoteAddress) { 228 l.RemoteAddress, l.LocalAddress = l.LocalAddress, l.RemoteAddress 229 l.RemoteLinkAddress = l.LocalLinkAddress 230 } 231 return l 232 } 233 234 // Stack returns the instance of the Stack that owns this route. 235 func (r *Route) Stack() *Stack { 236 return r.ref.stack() 237 }