summaryrefslogtreecommitdiff
path: root/node/Path.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'node/Path.hpp')
-rw-r--r--node/Path.hpp71
1 files changed, 47 insertions, 24 deletions
diff --git a/node/Path.hpp b/node/Path.hpp
index cb7622d3..c039f9db 100644
--- a/node/Path.hpp
+++ b/node/Path.hpp
@@ -31,14 +31,22 @@
/**
* Flag indicating that this path is suboptimal
*
- * This is used in cluster mode to indicate that the peer has been directed
- * to a better path. This path can continue to be used but shouldn't be kept
- * or advertised to other cluster members. Not used if clustering is not
- * built and enabled.
+ * Clusters set this flag on remote paths if GeoIP or other routing decisions
+ * indicate that a peer should be handed off to another cluster member.
*/
#define ZT_PATH_FLAG_CLUSTER_SUBOPTIMAL 0x0001
/**
+ * Flag indicating that this path is optimal
+ *
+ * Peers set this flag on paths that are pushed by a cluster and indicated as
+ * optimal. A second flag is needed since we want to prioritize cluster optimal
+ * paths and de-prioritize sub-optimal paths and for new paths we don't know
+ * which one they are. So we want a trinary state: optimal, suboptimal, unknown.
+ */
+#define ZT_PATH_FLAG_CLUSTER_OPTIMAL 0x0002
+
+/**
* Maximum return value of preferenceRank()
*/
#define ZT_PATH_MAX_PREFERENCE_RANK ((ZT_INETADDRESS_MAX_SCOPE << 1) | 1)
@@ -177,16 +185,38 @@ public:
inline InetAddress::IpScope ipScope() const throw() { return _ipScope; }
/**
+ * @param f Valuve of ZT_PATH_FLAG_CLUSTER_SUBOPTIMAL and inverse of ZT_PATH_FLAG_CLUSTER_OPTIMAL (both are changed)
+ */
+ inline void setClusterSuboptimal(bool f)
+ {
+ if (f) {
+ _flags = (_flags | ZT_PATH_FLAG_CLUSTER_SUBOPTIMAL) & ~ZT_PATH_FLAG_CLUSTER_OPTIMAL;
+ } else {
+ _flags = (_flags | ZT_PATH_FLAG_CLUSTER_OPTIMAL) & ~ZT_PATH_FLAG_CLUSTER_SUBOPTIMAL;
+ }
+ }
+
+ /**
+ * @return True if ZT_PATH_FLAG_CLUSTER_SUBOPTIMAL is set
+ */
+ inline bool isClusterSuboptimal() const { return ((_flags & ZT_PATH_FLAG_CLUSTER_SUBOPTIMAL) != 0); }
+
+ /**
+ * @return True if ZT_PATH_FLAG_CLUSTER_OPTIMAL is set
+ */
+ inline bool isClusterOptimal() const { return ((_flags & ZT_PATH_FLAG_CLUSTER_OPTIMAL) != 0); }
+
+ /**
* @return Preference rank, higher == better (will be less than 255)
*/
inline unsigned int preferenceRank() const throw()
{
- // First, since the scope enum values in InetAddress.hpp are in order of
- // use preference rank, we take that. Then we multiple by two, yielding
- // a sequence like 0, 2, 4, 6, etc. Then if it's IPv6 we add one. This
- // makes IPv6 addresses of a given scope outrank IPv4 addresses of the
- // same scope -- e.g. 1 outranks 0. This makes us prefer IPv6, but not
- // if the address scope/class is of a fundamentally lower rank.
+ /* First, since the scope enum values in InetAddress.hpp are in order of
+ * use preference rank, we take that. Then we multiple by two, yielding
+ * a sequence like 0, 2, 4, 6, etc. Then if it's IPv6 we add one. This
+ * makes IPv6 addresses of a given scope outrank IPv4 addresses of the
+ * same scope -- e.g. 1 outranks 0. This makes us prefer IPv6, but not
+ * if the address scope/class is of a fundamentally lower rank. */
return ( ((unsigned int)_ipScope << 1) | (unsigned int)(_addr.ss_family == AF_INET6) );
}
@@ -199,8 +229,13 @@ public:
* received something) scaled/corrected by the preference rank within the
* ping keepalive window. That way higher ranking paths are preferred but
* not to the point of overriding timeouts and choosing potentially dead
- * paths. */
- return (_lastReceived + (preferenceRank() * (ZT_PEER_DIRECT_PING_DELAY / ZT_PATH_MAX_PREFERENCE_RANK)));
+ * paths. Finally we increase the score for known to be cluster optimal
+ * paths and decrease it for paths known to be suboptimal. */
+ uint64_t score = _lastReceived + ZT_PEER_DIRECT_PING_DELAY; // make sure it's never less than ZT_PEER_DIRECT_PING_DELAY to prevent integer underflow
+ score += preferenceRank() * (ZT_PEER_DIRECT_PING_DELAY / ZT_PATH_MAX_PREFERENCE_RANK);
+ score += (uint64_t)(_flags & ZT_PATH_FLAG_CLUSTER_OPTIMAL) * (ZT_PEER_DIRECT_PING_DELAY / 2); // /2 because CLUSTER_OPTIMAL is flag 0x0002
+ score -= (uint64_t)(_flags & ZT_PATH_FLAG_CLUSTER_SUBOPTIMAL) * ZT_PEER_DIRECT_PING_DELAY;
+ return score;
}
/**
@@ -259,18 +294,6 @@ public:
return false;
}
-#ifdef ZT_ENABLE_CLUSTER
- /**
- * @param f New value of ZT_PATH_FLAG_CLUSTER_SUBOPTIMAL
- */
- inline void setClusterSuboptimal(bool f) { _flags = ((f) ? (_flags | ZT_PATH_FLAG_CLUSTER_SUBOPTIMAL) : (_flags & (~ZT_PATH_FLAG_CLUSTER_SUBOPTIMAL))); }
-
- /**
- * @return True if ZT_PATH_FLAG_CLUSTER_SUBOPTIMAL is set
- */
- inline bool isClusterSuboptimal() const { return ((_flags & ZT_PATH_FLAG_CLUSTER_SUBOPTIMAL) != 0); }
-#endif
-
/**
* @return Current path probation count (for dead path detect)
*/