|
@@ -31,13 +31,21 @@
|
|
|
/**
|
|
|
* 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()
|
|
|
*/
|
|
@@ -176,17 +184,39 @@ 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)
|
|
|
*/
|