At the time of this writing (circa EmberZNet 3.3.1), the logic behind the EmberZNet neighbor table aging (as returned in the EmberNeighborTableEntry struct from emberGetNeighbor()) is as follows. Note that the numeric values here may be subject to change in the future (although they will likely remain as is for some time to come as part of maintaining interoperability)...
The age field measures the amount of time since the last neighbor
exchange message was received. A new entry starts at age 0.
The age is incremented every 16 seconds (give or take 1 second for jitter). Entries whose age is less than 3 are in an initial synchronization period also known as â€œprobationâ€ .
If a neighbor exchange packet is received that provides a non-zero
outgoing cost for that entry, the age is set back to 3. Entries on probation are not evicted as they attempt to establish a bidirectional link with the neighbor, which reduces thrashing in a dense network.
If an entry ages up to 3 without receiving a trueoutgoing cost, its outgoing cost is reset to zero. Mature entries with age at least 3 reset their age to 3 and set their outgoing cost upon receipt of a neighbor exchange. If the age exceeds 6, the entry is considered stale and the outgoing cost is reset to 0 (putting it back on probation ).
Note that stale neighbors (cost 7) are not placed into the Link Status frame.