route.go raw

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