github.com/noisysockets/netstack@v0.6.0/pkg/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 "fmt" 19 20 "github.com/noisysockets/netstack/pkg/tcpip" 21 "github.com/noisysockets/netstack/pkg/tcpip/header" 22 ) 23 24 // Route represents a route through the networking stack to a given destination. 25 // 26 // It is safe to call Route's methods from multiple goroutines. 27 type Route struct { 28 routeInfo routeInfo 29 30 // localAddressNIC is the interface the address is associated with. 31 // TODO(gvisor.dev/issue/4548): Remove this field once we can query the 32 // address's assigned status without the NIC. 33 localAddressNIC *nic 34 35 // mu protects annotated fields below. 36 mu routeRWMutex 37 38 // localAddressEndpoint is the local address this route is associated with. 39 // +checklocks:mu 40 localAddressEndpoint AssignableAddressEndpoint 41 42 // remoteLinkAddress is the link-layer (MAC) address of the next hop. 43 // +checklocks:mu 44 remoteLinkAddress tcpip.LinkAddress 45 46 // outgoingNIC is the interface this route uses to write packets. 47 outgoingNIC *nic 48 49 // linkRes is set if link address resolution is enabled for this protocol on 50 // the route's NIC. 51 linkRes *linkResolver 52 53 // neighborEntry is the cached result of fetching a neighbor entry from the 54 // neighbor cache. 55 // +checklocks:mu 56 neighborEntry *neighborEntry 57 } 58 59 // +stateify savable 60 type routeInfo struct { 61 RemoteAddress tcpip.Address 62 63 LocalAddress tcpip.Address 64 65 LocalLinkAddress tcpip.LinkAddress 66 67 NextHop tcpip.Address 68 69 NetProto tcpip.NetworkProtocolNumber 70 71 Loop PacketLooping 72 } 73 74 // RemoteAddress returns the route's destination. 75 func (r *Route) RemoteAddress() tcpip.Address { 76 return r.routeInfo.RemoteAddress 77 } 78 79 // LocalAddress returns the route's local address. 80 func (r *Route) LocalAddress() tcpip.Address { 81 return r.routeInfo.LocalAddress 82 } 83 84 // LocalLinkAddress returns the route's local link-layer address. 85 func (r *Route) LocalLinkAddress() tcpip.LinkAddress { 86 return r.routeInfo.LocalLinkAddress 87 } 88 89 // NextHop returns the next node in the route's path to the destination. 90 func (r *Route) NextHop() tcpip.Address { 91 return r.routeInfo.NextHop 92 } 93 94 // NetProto returns the route's network-layer protocol number. 95 func (r *Route) NetProto() tcpip.NetworkProtocolNumber { 96 return r.routeInfo.NetProto 97 } 98 99 // Loop returns the route's required packet looping. 100 func (r *Route) Loop() PacketLooping { 101 return r.routeInfo.Loop 102 } 103 104 // OutgoingNIC returns the route's outgoing NIC. 105 func (r *Route) OutgoingNIC() tcpip.NICID { 106 return r.outgoingNIC.id 107 } 108 109 // RouteInfo contains all of Route's exported fields. 110 // 111 // +stateify savable 112 type RouteInfo struct { 113 routeInfo 114 115 // RemoteLinkAddress is the link-layer (MAC) address of the next hop in the 116 // route. 117 RemoteLinkAddress tcpip.LinkAddress 118 } 119 120 // Fields returns a RouteInfo with all of the known values for the route's 121 // fields. 122 // 123 // If any fields are unknown (e.g. remote link address when it is waiting for 124 // link address resolution), they will be unset. 125 func (r *Route) Fields() RouteInfo { 126 r.mu.RLock() 127 defer r.mu.RUnlock() 128 return r.fieldsLocked() 129 } 130 131 // +checklocksread:r.mu 132 func (r *Route) fieldsLocked() RouteInfo { 133 return RouteInfo{ 134 routeInfo: r.routeInfo, 135 RemoteLinkAddress: r.remoteLinkAddress, 136 } 137 } 138 139 // constructAndValidateRoute validates and initializes a route. It takes 140 // ownership of the provided local address. 141 // 142 // Returns an empty route if validation fails. 143 func constructAndValidateRoute(netProto tcpip.NetworkProtocolNumber, addressEndpoint AssignableAddressEndpoint, localAddressNIC, outgoingNIC *nic, gateway, localAddr, remoteAddr tcpip.Address, handleLocal, multicastLoop bool) *Route { 144 if localAddr.BitLen() == 0 { 145 localAddr = addressEndpoint.AddressWithPrefix().Address 146 } 147 148 if localAddressNIC != outgoingNIC && header.IsV6LinkLocalUnicastAddress(localAddr) { 149 addressEndpoint.DecRef() 150 return nil 151 } 152 153 // If no remote address is provided, use the local address. 154 if remoteAddr.BitLen() == 0 { 155 remoteAddr = localAddr 156 } 157 158 r := makeRoute( 159 netProto, 160 gateway, 161 localAddr, 162 remoteAddr, 163 outgoingNIC, 164 localAddressNIC, 165 addressEndpoint, 166 handleLocal, 167 multicastLoop, 168 ) 169 170 return r 171 } 172 173 // makeRoute initializes a new route. It takes ownership of the provided 174 // AssignableAddressEndpoint. 175 func makeRoute(netProto tcpip.NetworkProtocolNumber, gateway, localAddr, remoteAddr tcpip.Address, outgoingNIC, localAddressNIC *nic, localAddressEndpoint AssignableAddressEndpoint, handleLocal, multicastLoop bool) *Route { 176 if localAddressNIC.stack != outgoingNIC.stack { 177 panic(fmt.Sprintf("cannot create a route with NICs from different stacks")) 178 } 179 180 if localAddr.BitLen() == 0 { 181 localAddr = localAddressEndpoint.AddressWithPrefix().Address 182 } 183 184 loop := PacketOut 185 186 // TODO(gvisor.dev/issue/4689): Loopback interface loops back packets at the 187 // link endpoint level. We can remove this check once loopback interfaces 188 // loop back packets at the network layer. 189 if !outgoingNIC.IsLoopback() { 190 if handleLocal && localAddr != (tcpip.Address{}) && remoteAddr == localAddr { 191 loop = PacketLoop 192 } else if multicastLoop && (header.IsV4MulticastAddress(remoteAddr) || header.IsV6MulticastAddress(remoteAddr)) { 193 loop |= PacketLoop 194 } else if remoteAddr == header.IPv4Broadcast { 195 loop |= PacketLoop 196 } else if subnet := localAddressEndpoint.AddressWithPrefix().Subnet(); subnet.IsBroadcast(remoteAddr) { 197 loop |= PacketLoop 198 } 199 } 200 201 r := makeRouteInner(netProto, localAddr, remoteAddr, outgoingNIC, localAddressNIC, localAddressEndpoint, loop) 202 if r.Loop()&PacketOut == 0 { 203 // Packet will not leave the stack, no need for a gateway or a remote link 204 // address. 205 return r 206 } 207 208 if r.outgoingNIC.NetworkLinkEndpoint.Capabilities()&CapabilityResolutionRequired != 0 { 209 if linkRes, ok := r.outgoingNIC.linkAddrResolvers[r.NetProto()]; ok { 210 r.linkRes = linkRes 211 } 212 } 213 214 if gateway.BitLen() > 0 { 215 r.routeInfo.NextHop = gateway 216 return r 217 } 218 219 if r.linkRes == nil { 220 return r 221 } 222 223 if linkAddr, ok := r.linkRes.resolver.ResolveStaticAddress(r.RemoteAddress()); ok { 224 r.ResolveWith(linkAddr) 225 return r 226 } 227 228 if subnet := localAddressEndpoint.Subnet(); subnet.IsBroadcast(remoteAddr) { 229 r.ResolveWith(header.EthernetBroadcastAddress) 230 return r 231 } 232 233 if r.RemoteAddress() == r.LocalAddress() { 234 // Local link address is already known. 235 r.ResolveWith(r.LocalLinkAddress()) 236 } 237 238 return r 239 } 240 241 func makeRouteInner(netProto tcpip.NetworkProtocolNumber, localAddr, remoteAddr tcpip.Address, outgoingNIC, localAddressNIC *nic, localAddressEndpoint AssignableAddressEndpoint, loop PacketLooping) *Route { 242 r := &Route{ 243 routeInfo: routeInfo{ 244 NetProto: netProto, 245 LocalAddress: localAddr, 246 LocalLinkAddress: outgoingNIC.NetworkLinkEndpoint.LinkAddress(), 247 RemoteAddress: remoteAddr, 248 Loop: loop, 249 }, 250 localAddressNIC: localAddressNIC, 251 outgoingNIC: outgoingNIC, 252 } 253 254 r.mu.Lock() 255 r.localAddressEndpoint = localAddressEndpoint 256 r.mu.Unlock() 257 258 return r 259 } 260 261 // makeLocalRoute initializes a new local route. It takes ownership of the 262 // provided AssignableAddressEndpoint. 263 // 264 // A local route is a route to a destination that is local to the stack. 265 func makeLocalRoute(netProto tcpip.NetworkProtocolNumber, localAddr, remoteAddr tcpip.Address, outgoingNIC, localAddressNIC *nic, localAddressEndpoint AssignableAddressEndpoint) *Route { 266 loop := PacketLoop 267 // TODO(gvisor.dev/issue/4689): Loopback interface loops back packets at the 268 // link endpoint level. We can remove this check once loopback interfaces 269 // loop back packets at the network layer. 270 if outgoingNIC.IsLoopback() { 271 loop = PacketOut 272 } 273 return makeRouteInner(netProto, localAddr, remoteAddr, outgoingNIC, localAddressNIC, localAddressEndpoint, loop) 274 } 275 276 // RemoteLinkAddress returns the link-layer (MAC) address of the next hop in 277 // the route. 278 func (r *Route) RemoteLinkAddress() tcpip.LinkAddress { 279 r.mu.RLock() 280 defer r.mu.RUnlock() 281 return r.remoteLinkAddress 282 } 283 284 // NICID returns the id of the NIC from which this route originates. 285 func (r *Route) NICID() tcpip.NICID { 286 return r.outgoingNIC.ID() 287 } 288 289 // MaxHeaderLength forwards the call to the network endpoint's implementation. 290 func (r *Route) MaxHeaderLength() uint16 { 291 return r.outgoingNIC.getNetworkEndpoint(r.NetProto()).MaxHeaderLength() 292 } 293 294 // Stats returns a mutable copy of current stats. 295 func (r *Route) Stats() tcpip.Stats { 296 return r.outgoingNIC.stack.Stats() 297 } 298 299 // PseudoHeaderChecksum forwards the call to the network endpoint's 300 // implementation. 301 func (r *Route) PseudoHeaderChecksum(protocol tcpip.TransportProtocolNumber, totalLen uint16) uint16 { 302 return header.PseudoHeaderChecksum(protocol, r.LocalAddress(), r.RemoteAddress(), totalLen) 303 } 304 305 // RequiresTXTransportChecksum returns false if the route does not require 306 // transport checksums to be populated. 307 func (r *Route) RequiresTXTransportChecksum() bool { 308 if r.local() { 309 return false 310 } 311 return r.outgoingNIC.NetworkLinkEndpoint.Capabilities()&CapabilityTXChecksumOffload == 0 312 } 313 314 // HasGVisorGSOCapability returns true if the route supports gVisor GSO. 315 func (r *Route) HasGVisorGSOCapability() bool { 316 if gso, ok := r.outgoingNIC.NetworkLinkEndpoint.(GSOEndpoint); ok { 317 return gso.SupportedGSO() == GVisorGSOSupported 318 } 319 return false 320 } 321 322 // HasHostGSOCapability returns true if the route supports host GSO. 323 func (r *Route) HasHostGSOCapability() bool { 324 if gso, ok := r.outgoingNIC.NetworkLinkEndpoint.(GSOEndpoint); ok { 325 return gso.SupportedGSO() == HostGSOSupported 326 } 327 return false 328 } 329 330 // HasSaveRestoreCapability returns true if the route supports save/restore. 331 func (r *Route) HasSaveRestoreCapability() bool { 332 return r.outgoingNIC.NetworkLinkEndpoint.Capabilities()&CapabilitySaveRestore != 0 333 } 334 335 // HasDisconnectOkCapability returns true if the route supports disconnecting. 336 func (r *Route) HasDisconnectOkCapability() bool { 337 return r.outgoingNIC.NetworkLinkEndpoint.Capabilities()&CapabilityDisconnectOk != 0 338 } 339 340 // GSOMaxSize returns the maximum GSO packet size. 341 func (r *Route) GSOMaxSize() uint32 { 342 if gso, ok := r.outgoingNIC.NetworkLinkEndpoint.(GSOEndpoint); ok { 343 return gso.GSOMaxSize() 344 } 345 return 0 346 } 347 348 // ResolveWith immediately resolves a route with the specified remote link 349 // address. 350 func (r *Route) ResolveWith(addr tcpip.LinkAddress) { 351 r.mu.Lock() 352 defer r.mu.Unlock() 353 r.remoteLinkAddress = addr 354 } 355 356 // ResolvedFieldsResult is the result of a route resolution attempt. 357 type ResolvedFieldsResult struct { 358 RouteInfo RouteInfo 359 Err tcpip.Error 360 } 361 362 // ResolvedFields attempts to resolve the remote link address if it is not 363 // known. 364 // 365 // If a callback is provided, it will be called before ResolvedFields returns 366 // when address resolution is not required. If address resolution is required, 367 // the callback will be called once address resolution is complete, regardless 368 // of success or failure. 369 // 370 // Note, the route will not cache the remote link address when address 371 // resolution completes. 372 func (r *Route) ResolvedFields(afterResolve func(ResolvedFieldsResult)) tcpip.Error { 373 _, _, err := r.resolvedFields(afterResolve) 374 return err 375 } 376 377 // resolvedFields is like ResolvedFields but also returns a notification channel 378 // when address resolution is required. This channel will become readable once 379 // address resolution is complete. 380 // 381 // The route's fields will also be returned, regardless of whether address 382 // resolution is required or not. 383 func (r *Route) resolvedFields(afterResolve func(ResolvedFieldsResult)) (RouteInfo, <-chan struct{}, tcpip.Error) { 384 r.mu.RLock() 385 fields := r.fieldsLocked() 386 resolutionRequired := r.isResolutionRequiredRLocked() 387 r.mu.RUnlock() 388 if !resolutionRequired { 389 if afterResolve != nil { 390 afterResolve(ResolvedFieldsResult{RouteInfo: fields, Err: nil}) 391 } 392 return fields, nil, nil 393 } 394 395 // If specified, the local address used for link address resolution must be an 396 // address on the outgoing interface. 397 var linkAddressResolutionRequestLocalAddr tcpip.Address 398 if r.localAddressNIC == r.outgoingNIC { 399 linkAddressResolutionRequestLocalAddr = r.LocalAddress() 400 } 401 402 nEntry := r.getCachedNeighborEntry() 403 if nEntry != nil { 404 if addr, ok := nEntry.getRemoteLinkAddress(); ok { 405 fields.RemoteLinkAddress = addr 406 if afterResolve != nil { 407 afterResolve(ResolvedFieldsResult{RouteInfo: fields, Err: nil}) 408 } 409 return fields, nil, nil 410 } 411 } 412 afterResolveFields := fields 413 entry, ch, err := r.linkRes.neigh.entry(r.nextHop(), linkAddressResolutionRequestLocalAddr, func(lrr LinkResolutionResult) { 414 if afterResolve != nil { 415 if lrr.Err == nil { 416 afterResolveFields.RemoteLinkAddress = lrr.LinkAddress 417 } 418 419 afterResolve(ResolvedFieldsResult{RouteInfo: afterResolveFields, Err: lrr.Err}) 420 } 421 }) 422 if err == nil { 423 fields.RemoteLinkAddress, _ = entry.getRemoteLinkAddress() 424 } 425 r.setCachedNeighborEntry(entry) 426 return fields, ch, err 427 } 428 429 func (r *Route) getCachedNeighborEntry() *neighborEntry { 430 r.mu.RLock() 431 defer r.mu.RUnlock() 432 return r.neighborEntry 433 } 434 435 func (r *Route) setCachedNeighborEntry(entry *neighborEntry) { 436 r.mu.Lock() 437 defer r.mu.Unlock() 438 r.neighborEntry = entry 439 } 440 441 func (r *Route) nextHop() tcpip.Address { 442 if r.NextHop().BitLen() == 0 { 443 return r.RemoteAddress() 444 } 445 return r.NextHop() 446 } 447 448 // local returns true if the route is a local route. 449 func (r *Route) local() bool { 450 return r.Loop() == PacketLoop || r.outgoingNIC.IsLoopback() 451 } 452 453 // IsResolutionRequired returns true if Resolve() must be called to resolve 454 // the link address before the route can be written to. 455 // 456 // The NICs the route is associated with must not be locked. 457 func (r *Route) IsResolutionRequired() bool { 458 r.mu.RLock() 459 defer r.mu.RUnlock() 460 return r.isResolutionRequiredRLocked() 461 } 462 463 // +checklocksread:r.mu 464 func (r *Route) isResolutionRequiredRLocked() bool { 465 return len(r.remoteLinkAddress) == 0 && r.linkRes != nil && r.isValidForOutgoingRLocked() && !r.local() 466 } 467 468 func (r *Route) isValidForOutgoing() bool { 469 r.mu.RLock() 470 defer r.mu.RUnlock() 471 return r.isValidForOutgoingRLocked() 472 } 473 474 // +checklocksread:r.mu 475 func (r *Route) isValidForOutgoingRLocked() bool { 476 if !r.outgoingNIC.Enabled() { 477 return false 478 } 479 480 localAddressEndpoint := r.localAddressEndpoint 481 if localAddressEndpoint == nil || !r.localAddressNIC.isValidForOutgoing(localAddressEndpoint) { 482 return false 483 } 484 485 // If the source NIC and outgoing NIC are different, make sure the stack has 486 // forwarding enabled, or the packet will be handled locally. 487 if r.outgoingNIC != r.localAddressNIC && !isNICForwarding(r.localAddressNIC, r.NetProto()) && (!r.outgoingNIC.stack.handleLocal || !r.outgoingNIC.hasAddress(r.NetProto(), r.RemoteAddress())) { 488 return false 489 } 490 491 return true 492 } 493 494 // WritePacket writes the packet through the given route. 495 func (r *Route) WritePacket(params NetworkHeaderParams, pkt *PacketBuffer) tcpip.Error { 496 if !r.isValidForOutgoing() { 497 return &tcpip.ErrInvalidEndpointState{} 498 } 499 500 return r.outgoingNIC.getNetworkEndpoint(r.NetProto()).WritePacket(r, params, pkt) 501 } 502 503 // WriteHeaderIncludedPacket writes a packet already containing a network 504 // header through the given route. 505 func (r *Route) WriteHeaderIncludedPacket(pkt *PacketBuffer) tcpip.Error { 506 if !r.isValidForOutgoing() { 507 return &tcpip.ErrInvalidEndpointState{} 508 } 509 510 return r.outgoingNIC.getNetworkEndpoint(r.NetProto()).WriteHeaderIncludedPacket(r, pkt) 511 } 512 513 // DefaultTTL returns the default TTL of the underlying network endpoint. 514 func (r *Route) DefaultTTL() uint8 { 515 return r.outgoingNIC.getNetworkEndpoint(r.NetProto()).DefaultTTL() 516 } 517 518 // MTU returns the MTU of the underlying network endpoint. 519 func (r *Route) MTU() uint32 { 520 return r.outgoingNIC.getNetworkEndpoint(r.NetProto()).MTU() 521 } 522 523 // Release decrements the reference counter of the resources associated with the 524 // route. 525 func (r *Route) Release() { 526 r.mu.Lock() 527 defer r.mu.Unlock() 528 529 if ep := r.localAddressEndpoint; ep != nil { 530 ep.DecRef() 531 } 532 } 533 534 // Acquire increments the reference counter of the resources associated with the 535 // route. 536 func (r *Route) Acquire() { 537 r.mu.RLock() 538 defer r.mu.RUnlock() 539 r.acquireLocked() 540 } 541 542 // +checklocksread:r.mu 543 func (r *Route) acquireLocked() { 544 if ep := r.localAddressEndpoint; ep != nil { 545 if !ep.TryIncRef() { 546 panic(fmt.Sprintf("failed to increment reference count for local address endpoint = %s", r.LocalAddress())) 547 } 548 } 549 } 550 551 // Stack returns the instance of the Stack that owns this route. 552 func (r *Route) Stack() *Stack { 553 return r.outgoingNIC.stack 554 } 555 556 func (r *Route) isV4Broadcast(addr tcpip.Address) bool { 557 if addr == header.IPv4Broadcast { 558 return true 559 } 560 561 r.mu.RLock() 562 localAddressEndpoint := r.localAddressEndpoint 563 r.mu.RUnlock() 564 if localAddressEndpoint == nil { 565 return false 566 } 567 568 subnet := localAddressEndpoint.Subnet() 569 return subnet.IsBroadcast(addr) 570 } 571 572 // IsOutboundBroadcast returns true if the route is for an outbound broadcast 573 // packet. 574 func (r *Route) IsOutboundBroadcast() bool { 575 // Only IPv4 has a notion of broadcast. 576 return r.isV4Broadcast(r.RemoteAddress()) 577 } 578 579 // ConfirmReachable informs the network/link layer that the neighbour used for 580 // the route is reachable. 581 // 582 // "Reachable" is defined as having full-duplex communication between the 583 // local and remote ends of the route. 584 func (r *Route) ConfirmReachable() { 585 if entry := r.getCachedNeighborEntry(); entry != nil { 586 entry.handleUpperLevelConfirmation() 587 } 588 }