github.com/polevpn/netstack@v1.10.9/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/polevpn/netstack/sleep" 19 "github.com/polevpn/netstack/tcpip" 20 "github.com/polevpn/netstack/tcpip/buffer" 21 "github.com/polevpn/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, params NetworkHeaderParams, pkt tcpip.PacketBuffer) *tcpip.Error { 158 if !r.ref.isValidForOutgoing() { 159 return tcpip.ErrInvalidEndpointState 160 } 161 162 err := r.ref.ep.WritePacket(r, gso, params, r.Loop, pkt) 163 if err != nil { 164 r.Stats().IP.OutgoingPacketErrors.Increment() 165 } else { 166 r.ref.nic.stats.Tx.Packets.Increment() 167 r.ref.nic.stats.Tx.Bytes.IncrementBy(uint64(pkt.Header.UsedLength() + pkt.Data.Size())) 168 } 169 return err 170 } 171 172 // PacketDescriptor is a packet descriptor which contains a packet header and 173 // offset and size of packet data in a payload view. 174 type PacketDescriptor struct { 175 Hdr buffer.Prependable 176 Off int 177 Size int 178 } 179 180 // NewPacketDescriptors allocates a set of packet descriptors. 181 func NewPacketDescriptors(n int, hdrSize int) []PacketDescriptor { 182 buf := make([]byte, n*hdrSize) 183 hdrs := make([]PacketDescriptor, n) 184 for i := range hdrs { 185 hdrs[i].Hdr = buffer.NewEmptyPrependableFromView(buf[i*hdrSize:][:hdrSize]) 186 } 187 return hdrs 188 } 189 190 // WritePackets writes the set of packets through the given route. 191 func (r *Route) WritePackets(gso *GSO, hdrs []PacketDescriptor, payload buffer.VectorisedView, params NetworkHeaderParams) (int, *tcpip.Error) { 192 if !r.ref.isValidForOutgoing() { 193 return 0, tcpip.ErrInvalidEndpointState 194 } 195 196 n, err := r.ref.ep.WritePackets(r, gso, hdrs, payload, params, r.Loop) 197 if err != nil { 198 r.Stats().IP.OutgoingPacketErrors.IncrementBy(uint64(len(hdrs) - n)) 199 } 200 r.ref.nic.stats.Tx.Packets.IncrementBy(uint64(n)) 201 payloadSize := 0 202 for i := 0; i < n; i++ { 203 r.ref.nic.stats.Tx.Bytes.IncrementBy(uint64(hdrs[i].Hdr.UsedLength())) 204 payloadSize += hdrs[i].Size 205 } 206 r.ref.nic.stats.Tx.Bytes.IncrementBy(uint64(payloadSize)) 207 return n, err 208 } 209 210 // WriteHeaderIncludedPacket writes a packet already containing a network 211 // header through the given route. 212 func (r *Route) WriteHeaderIncludedPacket(pkt tcpip.PacketBuffer) *tcpip.Error { 213 if !r.ref.isValidForOutgoing() { 214 return tcpip.ErrInvalidEndpointState 215 } 216 217 if err := r.ref.ep.WriteHeaderIncludedPacket(r, r.Loop, pkt); err != nil { 218 r.Stats().IP.OutgoingPacketErrors.Increment() 219 return err 220 } 221 r.ref.nic.stats.Tx.Packets.Increment() 222 r.ref.nic.stats.Tx.Bytes.IncrementBy(uint64(pkt.Data.Size())) 223 return nil 224 } 225 226 // DefaultTTL returns the default TTL of the underlying network endpoint. 227 func (r *Route) DefaultTTL() uint8 { 228 return r.ref.ep.DefaultTTL() 229 } 230 231 // MTU returns the MTU of the underlying network endpoint. 232 func (r *Route) MTU() uint32 { 233 return r.ref.ep.MTU() 234 } 235 236 // Release frees all resources associated with the route. 237 func (r *Route) Release() { 238 if r.ref != nil { 239 r.ref.decRef() 240 r.ref = nil 241 } 242 } 243 244 // Clone Clone a route such that the original one can be released and the new 245 // one will remain valid. 246 func (r *Route) Clone() Route { 247 r.ref.incRef() 248 return *r 249 } 250 251 // MakeLoopedRoute duplicates the given route with special handling for routes 252 // used for sending multicast or broadcast packets. In those cases the 253 // multicast/broadcast address is the remote address when sending out, but for 254 // incoming (looped) packets it becomes the local address. Similarly, the local 255 // interface address that was the local address going out becomes the remote 256 // address coming in. This is different to unicast routes where local and 257 // remote addresses remain the same as they identify location (local vs remote) 258 // not direction (source vs destination). 259 func (r *Route) MakeLoopedRoute() Route { 260 l := r.Clone() 261 if r.RemoteAddress == header.IPv4Broadcast || header.IsV4MulticastAddress(r.RemoteAddress) || header.IsV6MulticastAddress(r.RemoteAddress) { 262 l.RemoteAddress, l.LocalAddress = l.LocalAddress, l.RemoteAddress 263 l.RemoteLinkAddress = l.LocalLinkAddress 264 } 265 return l 266 } 267 268 // Stack returns the instance of the Stack that owns this route. 269 func (r *Route) Stack() *Stack { 270 return r.ref.stack() 271 }