mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 11:15:07 +03:00 
			
		
		
		
	comment the switch a little better and limit how much uptime can affect which peer is used as a parent
This commit is contained in:
		
							parent
							
								
									ae4107a3b2
								
							
						
					
					
						commit
						e9cff0506c
					
				
					 1 changed files with 32 additions and 15 deletions
				
			
		| 
						 | 
					@ -21,6 +21,7 @@ import (
 | 
				
			||||||
const switch_timeout = time.Minute
 | 
					const switch_timeout = time.Minute
 | 
				
			||||||
const switch_updateInterval = switch_timeout / 2
 | 
					const switch_updateInterval = switch_timeout / 2
 | 
				
			||||||
const switch_throttle = switch_updateInterval / 2
 | 
					const switch_throttle = switch_updateInterval / 2
 | 
				
			||||||
 | 
					const switch_max_time = time.Hour
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The switch locator represents the topology and network state dependent info about a node, minus the signatures that go with it.
 | 
					// The switch locator represents the topology and network state dependent info about a node, minus the signatures that go with it.
 | 
				
			||||||
// Nodes will pick the best root they see, provided that the root continues to push out updates with new timestamps.
 | 
					// Nodes will pick the best root they see, provided that the root continues to push out updates with new timestamps.
 | 
				
			||||||
| 
						 | 
					@ -390,39 +391,55 @@ func (t *switchTable) unlockedHandleMsg(msg *switchMsg, fromPort switchPort) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return true
 | 
							return true
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
 | 
						// Get the time we've known about the sender (or old parent's) current coords, up to a maximum of `switch_max_time`.
 | 
				
			||||||
	sTime := now.Sub(sender.firstSeen)
 | 
						sTime := now.Sub(sender.firstSeen)
 | 
				
			||||||
	pTime := oldParent.time.Sub(oldParent.firstSeen) + switch_timeout
 | 
						if sTime > switch_max_time {
 | 
				
			||||||
 | 
							sTime = switch_max_time
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pTime := now.Sub(oldParent.firstSeen)
 | 
				
			||||||
 | 
						if pTime > switch_max_time {
 | 
				
			||||||
 | 
							pTime = switch_max_time
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	// Really want to compare sLen/sTime and pLen/pTime
 | 
						// Really want to compare sLen/sTime and pLen/pTime
 | 
				
			||||||
	// Cross multiplied to avoid divide-by-zero
 | 
						// Cross multiplied to avoid divide-by-zero
 | 
				
			||||||
	cost := len(sender.locator.coords) * int(pTime.Seconds())
 | 
						cost := float64(len(sender.locator.coords)) * pTime.Seconds()
 | 
				
			||||||
	pCost := len(t.data.locator.coords) * int(sTime.Seconds())
 | 
						pCost := float64(len(t.data.locator.coords)) * sTime.Seconds()
 | 
				
			||||||
	dropTstamp, isIn := t.drop[sender.locator.root]
 | 
						dropTstamp, isIn := t.drop[sender.locator.root]
 | 
				
			||||||
	// Here be dragons
 | 
					 | 
				
			||||||
	switch {
 | 
						switch {
 | 
				
			||||||
	case !noLoop: // do nothing
 | 
						case !noLoop:
 | 
				
			||||||
	case isIn && dropTstamp >= sender.locator.tstamp: // do nothing
 | 
							// This route loops, so we can't use the sender as our parent.
 | 
				
			||||||
 | 
						case isIn && dropTstamp >= sender.locator.tstamp:
 | 
				
			||||||
 | 
							// This is a known root with a timestamp older than a known timeout, so we can't trust it to be a new announcement.
 | 
				
			||||||
	case firstIsBetter(&sender.locator.root, &t.data.locator.root):
 | 
						case firstIsBetter(&sender.locator.root, &t.data.locator.root):
 | 
				
			||||||
 | 
							// This is a better root than what we're currently using, so we should update.
 | 
				
			||||||
		updateRoot = true
 | 
							updateRoot = true
 | 
				
			||||||
	case t.data.locator.root != sender.locator.root: // do nothing
 | 
						case t.data.locator.root != sender.locator.root:
 | 
				
			||||||
	case t.data.locator.tstamp > sender.locator.tstamp: // do nothing
 | 
							// This is not the same root, and it's apparently not better (from the above), so we should ignore it.
 | 
				
			||||||
 | 
						case t.data.locator.tstamp > sender.locator.tstamp:
 | 
				
			||||||
 | 
							// This timetsamp is older than the most recently seen one from this root, so we should ignore it.
 | 
				
			||||||
	case noParent:
 | 
						case noParent:
 | 
				
			||||||
 | 
							// We currently have no working parent, and at this point in the switch statement, anything is better than nothing.
 | 
				
			||||||
		updateRoot = true
 | 
							updateRoot = true
 | 
				
			||||||
	case cost < pCost:
 | 
						case cost < pCost:
 | 
				
			||||||
 | 
							// The sender has a better combination of path length and reliability than the current parent.
 | 
				
			||||||
		updateRoot = true
 | 
							updateRoot = true
 | 
				
			||||||
	case sender.port != t.parent: // do nothing
 | 
						case sender.port != t.parent:
 | 
				
			||||||
 | 
							// Ignore further cases if the sender isn't our parent.
 | 
				
			||||||
	case !equiv(&sender.locator, &t.data.locator):
 | 
						case !equiv(&sender.locator, &t.data.locator):
 | 
				
			||||||
		// Special case
 | 
							// Special case:
 | 
				
			||||||
		// If coords changed, then this may now be a worse parent than before
 | 
							// If coords changed, then this may now be a worse parent than before.
 | 
				
			||||||
		// Re-parent the node (de-parent and reprocess the message)
 | 
							// Re-parent the node (de-parent and reprocess the message).
 | 
				
			||||||
		// Then reprocess *all* messages to look for a better parent
 | 
							// Then reprocess *all* messages to look for a better parent.
 | 
				
			||||||
		// This is so we don't keep using this node as our parent if there's something better
 | 
							// This is so we don't keep using this node as our parent if there's something better.
 | 
				
			||||||
		t.parent = 0
 | 
							t.parent = 0
 | 
				
			||||||
		t.unlockedHandleMsg(msg, fromPort)
 | 
							t.unlockedHandleMsg(msg, fromPort)
 | 
				
			||||||
		for _, info := range t.data.peers {
 | 
							for _, info := range t.data.peers {
 | 
				
			||||||
			t.unlockedHandleMsg(&info.msg, info.port)
 | 
								t.unlockedHandleMsg(&info.msg, info.port)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case now.Sub(t.time) < switch_throttle: // do nothing
 | 
						case now.Sub(t.time) < switch_throttle:
 | 
				
			||||||
 | 
							// We've already gotten an update from this root recently, so ignore this one to avoid flooding.
 | 
				
			||||||
	case sender.locator.tstamp > t.data.locator.tstamp:
 | 
						case sender.locator.tstamp > t.data.locator.tstamp:
 | 
				
			||||||
 | 
							// The timestamp was updated, so we need to update locally and send to our peers.
 | 
				
			||||||
		updateRoot = true
 | 
							updateRoot = true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if updateRoot {
 | 
						if updateRoot {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue