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