mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2026-09-22 15:29:03 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e46c83592 | ||
|
|
ba74abb753 | ||
|
|
c34325fee7 | ||
|
|
db8443ef7d | ||
|
|
6c85f8c7a7 | ||
|
|
eea93d2607 | ||
|
|
e9f8ecbf7e | ||
|
|
48852e8cb4 | ||
|
|
55ec325961 | ||
|
|
59151fbf86 | ||
|
|
1c700b7b41 | ||
|
|
ff18bacd94 | ||
|
|
caf1de3bcf | ||
|
|
a9ad2924ac |
No files matched your search
@@ -1,6 +1,10 @@
|
||||
ZeroTier Release Notes
|
||||
======
|
||||
|
||||
# 2022-05-10 -- Version 1.8.10
|
||||
|
||||
* Fixed a bug preventing SSO sign-on on Windows.
|
||||
|
||||
# 2022-04-25 -- Version 1.8.9
|
||||
|
||||
* Fixed a long-standing and strange bug that was causing sporadic "phantom" packet authentication failures. Not a security problem but could be behind spordaic reports of link failures under some conditions.
|
||||
|
||||
@@ -25,4 +25,5 @@ case $GOARCH in
|
||||
esac
|
||||
|
||||
docker run --privileged --rm tonistiigi/binfmt --install all
|
||||
docker pull registry.sean.farm/sid-builder
|
||||
docker buildx build --platform ${GOOS}/${ARCH} -f ci/Dockerfile.sid --target export -t test . --output out/${GOOS}/${GOARCH}
|
||||
+16
-13
@@ -28,7 +28,7 @@
|
||||
#include <chrono>
|
||||
|
||||
|
||||
// #define ZT_TRACE 1
|
||||
// #define REDIS_TRACE 1
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
@@ -937,30 +937,31 @@ void PostgreSQL::_membersWatcher_Postgres() {
|
||||
void PostgreSQL::_membersWatcher_Redis() {
|
||||
char buf[11] = {0};
|
||||
std::string key = "member-stream:{" + std::string(_myAddress.toString(buf)) + "}";
|
||||
std::string lastID = "0";
|
||||
fprintf(stderr, "Listening to member stream: %s\n", key.c_str());
|
||||
while (_run == 1) {
|
||||
try {
|
||||
json tmp;
|
||||
std::unordered_map<std::string, ItemStream> result;
|
||||
if (_rc->clusterMode) {
|
||||
_cluster->xread(key, "$", std::chrono::seconds(1), 0, std::inserter(result, result.end()));
|
||||
_cluster->xread(key, lastID, std::chrono::seconds(1), 0, std::inserter(result, result.end()));
|
||||
} else {
|
||||
_redis->xread(key, "$", std::chrono::seconds(1), 0, std::inserter(result, result.end()));
|
||||
_redis->xread(key, lastID, std::chrono::seconds(1), 0, std::inserter(result, result.end()));
|
||||
}
|
||||
if (!result.empty()) {
|
||||
for (auto element : result) {
|
||||
#ifdef ZT_TRACE
|
||||
#ifdef REDIS_TRACE
|
||||
fprintf(stdout, "Received notification from: %s\n", element.first.c_str());
|
||||
#endif
|
||||
for (auto rec : element.second) {
|
||||
std::string id = rec.first;
|
||||
auto attrs = rec.second;
|
||||
#ifdef ZT_TRACE
|
||||
#ifdef REDIS_TRACE
|
||||
fprintf(stdout, "Record ID: %s\n", id.c_str());
|
||||
fprintf(stdout, "attrs len: %lu\n", attrs.size());
|
||||
#endif
|
||||
for (auto a : attrs) {
|
||||
#ifdef ZT_TRACE
|
||||
#ifdef REDIS_TRACE
|
||||
fprintf(stdout, "key: %s\nvalue: %s\n", a.first.c_str(), a.second.c_str());
|
||||
#endif
|
||||
try {
|
||||
@@ -982,6 +983,7 @@ void PostgreSQL::_membersWatcher_Redis() {
|
||||
} else {
|
||||
_redis->xdel(key, id);
|
||||
}
|
||||
lastID = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1024,31 +1026,31 @@ void PostgreSQL::_networksWatcher_Postgres() {
|
||||
void PostgreSQL::_networksWatcher_Redis() {
|
||||
char buf[11] = {0};
|
||||
std::string key = "network-stream:{" + std::string(_myAddress.toString(buf)) + "}";
|
||||
|
||||
std::string lastID = "0";
|
||||
while (_run == 1) {
|
||||
try {
|
||||
json tmp;
|
||||
std::unordered_map<std::string, ItemStream> result;
|
||||
if (_rc->clusterMode) {
|
||||
_cluster->xread(key, "$", std::chrono::seconds(1), 0, std::inserter(result, result.end()));
|
||||
_cluster->xread(key, lastID, std::chrono::seconds(1), 0, std::inserter(result, result.end()));
|
||||
} else {
|
||||
_redis->xread(key, "$", std::chrono::seconds(1), 0, std::inserter(result, result.end()));
|
||||
_redis->xread(key, lastID, std::chrono::seconds(1), 0, std::inserter(result, result.end()));
|
||||
}
|
||||
|
||||
if (!result.empty()) {
|
||||
for (auto element : result) {
|
||||
#ifdef ZT_TRACE
|
||||
#ifdef REDIS_TRACE
|
||||
fprintf(stdout, "Received notification from: %s\n", element.first.c_str());
|
||||
#endif
|
||||
for (auto rec : element.second) {
|
||||
std::string id = rec.first;
|
||||
auto attrs = rec.second;
|
||||
#ifdef ZT_TRACE
|
||||
#ifdef REDIS_TRACE
|
||||
fprintf(stdout, "Record ID: %s\n", id.c_str());
|
||||
fprintf(stdout, "attrs len: %lu\n", attrs.size());
|
||||
#endif
|
||||
for (auto a : attrs) {
|
||||
#ifdef ZT_TRACE
|
||||
#ifdef REDIS_TRACE
|
||||
fprintf(stdout, "key: %s\nvalue: %s\n", a.first.c_str(), a.second.c_str());
|
||||
#endif
|
||||
try {
|
||||
@@ -1070,6 +1072,7 @@ void PostgreSQL::_networksWatcher_Redis() {
|
||||
} else {
|
||||
_redis->xdel(key, id);
|
||||
}
|
||||
lastID = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1512,7 +1515,7 @@ void PostgreSQL::onlineNotification_Redis()
|
||||
}
|
||||
}
|
||||
} catch (sw::redis::Error &e) {
|
||||
#ifdef ZT_TRACE
|
||||
#ifdef REDIS_TRACE
|
||||
fprintf(stderr, "Error in online notification thread (redis): %s\n", e.what());
|
||||
#endif
|
||||
}
|
||||
|
||||
Vendored
+6
@@ -1,3 +1,9 @@
|
||||
zerotier-one (1.8.10) unstable; urgency=medium
|
||||
|
||||
* See RELEASE-NOTES.md for release notes.
|
||||
|
||||
-- Adam Ierymenko <adam.ierymenko@zerotier.com> Tue, 10 May 2022 01:00:00 -0700
|
||||
|
||||
zerotier-one (1.8.9) unstable; urgency=medium
|
||||
|
||||
* See RELEASE-NOTES.md for release notes.
|
||||
|
||||
@@ -701,7 +701,7 @@
|
||||
<key>USE_HFS+_COMPRESSION</key>
|
||||
<false/>
|
||||
<key>VERSION</key>
|
||||
<string>1.8.9</string>
|
||||
<string>1.8.10</string>
|
||||
</dict>
|
||||
<key>TYPE</key>
|
||||
<integer>0</integer>
|
||||
|
||||
+106
-64
@@ -40,6 +40,9 @@ std::map<std::string, std::map<std::string, SharedPtr<Link> > > Bond::_interface
|
||||
|
||||
bool Bond::linkAllowed(std::string& policyAlias, SharedPtr<Link> link)
|
||||
{
|
||||
if (! link) {
|
||||
return false;
|
||||
}
|
||||
bool foundInDefinitions = false;
|
||||
if (_linkDefinitions.count(policyAlias)) {
|
||||
auto it = _linkDefinitions[policyAlias].begin();
|
||||
@@ -152,7 +155,7 @@ void Bond::destroyBond(uint64_t peerId)
|
||||
_bonds.erase(peerId);
|
||||
}
|
||||
|
||||
SharedPtr<Link> Bond::getLinkBySocket(const std::string& policyAlias, uint64_t localSocket)
|
||||
SharedPtr<Link> Bond::getLinkBySocket(const std::string& policyAlias, uint64_t localSocket, bool createIfNeeded = false)
|
||||
{
|
||||
Mutex::Lock _l(_links_m);
|
||||
char ifname[64] = { 0 };
|
||||
@@ -160,10 +163,14 @@ SharedPtr<Link> Bond::getLinkBySocket(const std::string& policyAlias, uint64_t l
|
||||
std::string ifnameStr(ifname);
|
||||
auto search = _interfaceToLinkMap[policyAlias].find(ifnameStr);
|
||||
if (search == _interfaceToLinkMap[policyAlias].end()) {
|
||||
// If the link wasn't already known, add a new entry
|
||||
SharedPtr<Link> s = new Link(ifnameStr, 0, 0, true, ZT_BOND_SLAVE_MODE_SPARE, "", 0.0);
|
||||
_interfaceToLinkMap[policyAlias].insert(std::pair<std::string, SharedPtr<Link> >(ifnameStr, s));
|
||||
return s;
|
||||
if (createIfNeeded) {
|
||||
SharedPtr<Link> s = new Link(ifnameStr, 0, 0, true, ZT_BOND_SLAVE_MODE_SPARE, "", 0.0);
|
||||
_interfaceToLinkMap[policyAlias].insert(std::pair<std::string, SharedPtr<Link> >(ifnameStr, s));
|
||||
return s;
|
||||
}
|
||||
else {
|
||||
return SharedPtr<Link>();
|
||||
}
|
||||
}
|
||||
else {
|
||||
return search->second;
|
||||
@@ -225,10 +232,12 @@ Bond::Bond(const RuntimeEnvironment* renv, SharedPtr<Bond> originalBond, const S
|
||||
void Bond::nominatePathToBond(const SharedPtr<Path>& path, int64_t now)
|
||||
{
|
||||
Mutex::Lock _l(_paths_m);
|
||||
debug("attempting to nominate link %s", pathToStr(path).c_str());
|
||||
/**
|
||||
* Ensure the link is allowed and the path is not already present
|
||||
*/
|
||||
if (! RR->bc->linkAllowed(_policyAlias, getLink(path))) {
|
||||
debug("link %s is not permitted according to user-specified rules", pathToStr(path).c_str());
|
||||
return;
|
||||
}
|
||||
bool alreadyPresent = false;
|
||||
@@ -236,6 +245,7 @@ void Bond::nominatePathToBond(const SharedPtr<Path>& path, int64_t now)
|
||||
// Sanity check
|
||||
if (path.ptr() == _paths[i].p.ptr()) {
|
||||
alreadyPresent = true;
|
||||
debug("link %s already exists", pathToStr(path).c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -254,20 +264,22 @@ void Bond::nominatePathToBond(const SharedPtr<Path>& path, int64_t now)
|
||||
// Determine if there are any other paths on this link
|
||||
bool bFoundCommonLink = false;
|
||||
SharedPtr<Link> commonLink = RR->bc->getLinkBySocket(_policyAlias, _paths[i].p->localSocket());
|
||||
for (unsigned int j = 0; j < ZT_MAX_PEER_NETWORK_PATHS; ++j) {
|
||||
if (_paths[j].p && _paths[j].p.ptr() != _paths[i].p.ptr()) {
|
||||
if (RR->bc->getLinkBySocket(_policyAlias, _paths[j].p->localSocket()) == commonLink) {
|
||||
bFoundCommonLink = true;
|
||||
_paths[j].onlyPathOnLink = false;
|
||||
if (commonLink) {
|
||||
for (unsigned int j = 0; j < ZT_MAX_PEER_NETWORK_PATHS; ++j) {
|
||||
if (_paths[j].p && _paths[j].p.ptr() != _paths[i].p.ptr()) {
|
||||
if (RR->bc->getLinkBySocket(_policyAlias, _paths[j].p->localSocket()) == commonLink, true) {
|
||||
bFoundCommonLink = true;
|
||||
_paths[j].onlyPathOnLink = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
_paths[i].ipvPref = sl->ipvPref();
|
||||
_paths[i].mode = sl->mode();
|
||||
_paths[i].enabled = sl->enabled();
|
||||
_paths[i].onlyPathOnLink = ! bFoundCommonLink;
|
||||
}
|
||||
_paths[i].ipvPref = sl->ipvPref();
|
||||
_paths[i].mode = sl->mode();
|
||||
_paths[i].enabled = sl->enabled();
|
||||
_paths[i].onlyPathOnLink = ! bFoundCommonLink;
|
||||
}
|
||||
log("nominate link %s", pathToStr(path).c_str());
|
||||
log("nominated link %s", pathToStr(path).c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -553,7 +565,6 @@ bool Bond::assignFlowToBondedPath(SharedPtr<Flow>& flow, int64_t now)
|
||||
}
|
||||
flow->assignPath(_abPathIdx, now);
|
||||
}
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[flow->assignedPath].p->localSocket());
|
||||
debug("assign out-flow %04x to link %s (%lu / %lu flows)", flow->id, pathToStr(_paths[flow->assignedPath].p).c_str(), _paths[flow->assignedPath].assignedFlowCount, (unsigned long)_flows.size());
|
||||
return true;
|
||||
}
|
||||
@@ -640,22 +651,24 @@ void Bond::processIncomingPathNegotiationRequest(uint64_t now, SharedPtr<Path>&
|
||||
return;
|
||||
}
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[pathIdx].p->localSocket());
|
||||
if (remoteUtility > _localUtility) {
|
||||
_paths[pathIdx].p->address().toString(pathStr);
|
||||
debug("peer suggests alternate link %s/%s, remote utility (%d) greater than local utility (%d), switching to suggested link\n", link->ifname().c_str(), pathStr, remoteUtility, _localUtility);
|
||||
_negotiatedPathIdx = pathIdx;
|
||||
}
|
||||
if (remoteUtility < _localUtility) {
|
||||
debug("peer suggests alternate link %s/%s, remote utility (%d) less than local utility (%d), not switching\n", link->ifname().c_str(), pathStr, remoteUtility, _localUtility);
|
||||
}
|
||||
if (remoteUtility == _localUtility) {
|
||||
debug("peer suggests alternate link %s/%s, remote utility (%d) equal to local utility (%d)\n", link->ifname().c_str(), pathStr, remoteUtility, _localUtility);
|
||||
if (_peer->_id.address().toInt() > RR->node->identity().address().toInt()) {
|
||||
debug("agree with peer to use alternate link %s/%s\n", link->ifname().c_str(), pathStr);
|
||||
if (link) {
|
||||
if (remoteUtility > _localUtility) {
|
||||
_paths[pathIdx].p->address().toString(pathStr);
|
||||
debug("peer suggests alternate link %s/%s, remote utility (%d) greater than local utility (%d), switching to suggested link\n", link->ifname().c_str(), pathStr, remoteUtility, _localUtility);
|
||||
_negotiatedPathIdx = pathIdx;
|
||||
}
|
||||
else {
|
||||
debug("ignore petition from peer to use alternate link %s/%s\n", link->ifname().c_str(), pathStr);
|
||||
if (remoteUtility < _localUtility) {
|
||||
debug("peer suggests alternate link %s/%s, remote utility (%d) less than local utility (%d), not switching\n", link->ifname().c_str(), pathStr, remoteUtility, _localUtility);
|
||||
}
|
||||
if (remoteUtility == _localUtility) {
|
||||
debug("peer suggests alternate link %s/%s, remote utility (%d) equal to local utility (%d)\n", link->ifname().c_str(), pathStr, remoteUtility, _localUtility);
|
||||
if (_peer->_id.address().toInt() > RR->node->identity().address().toInt()) {
|
||||
debug("agree with peer to use alternate link %s/%s\n", link->ifname().c_str(), pathStr);
|
||||
_negotiatedPathIdx = pathIdx;
|
||||
}
|
||||
else {
|
||||
debug("ignore petition from peer to use alternate link %s/%s\n", link->ifname().c_str(), pathStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -827,10 +840,17 @@ void Bond::curateBond(int64_t now, bool rebuildBond)
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove expired links from bond
|
||||
* Remove expired or invalid links from bond
|
||||
*/
|
||||
SharedPtr<Link> link = getLink(_paths[i].p);
|
||||
if (! link) {
|
||||
log("link is no longer valid, removing from bond");
|
||||
_paths[i] = NominatedPath();
|
||||
_paths[i].p = SharedPtr<Path>();
|
||||
continue;
|
||||
}
|
||||
if ((now - _paths[i].p->_lastIn) > (ZT_PEER_EXPIRED_PATH_TRIAL_PERIOD)) {
|
||||
log("link %s has expired, removing from bond", pathToStr(_paths[i].p).c_str());
|
||||
log("link (%s) has expired or is invalid, removing from bond", pathToStr(_paths[i].p).c_str());
|
||||
_paths[i] = NominatedPath();
|
||||
_paths[i].p = SharedPtr<Path>();
|
||||
continue;
|
||||
@@ -920,7 +940,9 @@ void Bond::curateBond(int64_t now, bool rebuildBond)
|
||||
for (int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
|
||||
if (_paths[i].p) {
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[i].p->localSocket());
|
||||
linkMap[link].push_back(i);
|
||||
if (link) {
|
||||
linkMap[link].push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Re-form bond from link<->path map
|
||||
@@ -1007,13 +1029,17 @@ void Bond::estimatePathQuality(int64_t now)
|
||||
for (unsigned int i = 0; i < _numBondedPaths; ++i) {
|
||||
if (_paths[i].p && _paths[i].allowed()) {
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[i].p->localSocket());
|
||||
totUserSpecifiedLinkSpeed += link->speed();
|
||||
if (link) {
|
||||
totUserSpecifiedLinkSpeed += link->speed();
|
||||
}
|
||||
}
|
||||
}
|
||||
for (unsigned int i = 0; i < _numBondedPaths; ++i) {
|
||||
if (_paths[i].p && _paths[i].allowed()) {
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[i].p->localSocket());
|
||||
link->setRelativeSpeed((uint8_t)round(((float)link->speed() / (float)totUserSpecifiedLinkSpeed) * 255));
|
||||
if (link) {
|
||||
link->setRelativeSpeed((uint8_t)round(((float)link->speed() / (float)totUserSpecifiedLinkSpeed) * 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1224,7 +1250,7 @@ bool Bond::abForciblyRotateLink()
|
||||
void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
|
||||
{
|
||||
int prevActiveBackupPathIdx = _abPathIdx;
|
||||
int nonPreferredPathIdx;
|
||||
int nonPreferredPathIdx = ZT_MAX_PEER_NETWORK_PATHS;
|
||||
bool bFoundPrimaryLink = false;
|
||||
|
||||
if (_abPathIdx != ZT_MAX_PEER_NETWORK_PATHS && ! _paths[_abPathIdx].p) {
|
||||
@@ -1247,7 +1273,6 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
|
||||
log("failover queue is empty, bond is no longer fault-tolerant");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select initial "active" active-backup link
|
||||
*/
|
||||
@@ -1272,6 +1297,7 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [Manual mode]
|
||||
* The user has specified links or failover rules that the bonding policy should adhere to.
|
||||
@@ -1283,36 +1309,38 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
|
||||
continue;
|
||||
}
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[i].p->localSocket());
|
||||
if (_paths[i].eligible && link->primary()) {
|
||||
if (! _paths[i].preferred()) {
|
||||
// Found path on primary link, take note in case we don't find a preferred path
|
||||
nonPreferredPathIdx = i;
|
||||
bFoundPrimaryLink = true;
|
||||
}
|
||||
if (_paths[i].preferred()) {
|
||||
_abPathIdx = i;
|
||||
bFoundPrimaryLink = true;
|
||||
if (_paths[_abPathIdx].p) {
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[_abPathIdx].p->localSocket());
|
||||
if (link) {
|
||||
log("found preferred primary link %s", pathToStr(_paths[_abPathIdx].p).c_str());
|
||||
if (link) {
|
||||
if (_paths[i].eligible && link->primary()) {
|
||||
if (! _paths[i].preferred()) {
|
||||
// Found path on primary link, take note in case we don't find a preferred path
|
||||
nonPreferredPathIdx = i;
|
||||
bFoundPrimaryLink = true;
|
||||
}
|
||||
if (_paths[i].preferred()) {
|
||||
_abPathIdx = i;
|
||||
bFoundPrimaryLink = true;
|
||||
if (_paths[_abPathIdx].p) {
|
||||
SharedPtr<Link> abLink = RR->bc->getLinkBySocket(_policyAlias, _paths[_abPathIdx].p->localSocket());
|
||||
if (abLink) {
|
||||
log("found preferred primary link %s", pathToStr(_paths[_abPathIdx].p).c_str());
|
||||
}
|
||||
break; // Found preferred path on primary link
|
||||
}
|
||||
break; // Found preferred path on primary link
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bFoundPrimaryLink && nonPreferredPathIdx) {
|
||||
if (bFoundPrimaryLink && (nonPreferredPathIdx != ZT_MAX_PEER_NETWORK_PATHS)) {
|
||||
log("found non-preferred primary link");
|
||||
_abPathIdx = nonPreferredPathIdx;
|
||||
}
|
||||
if (_abPathIdx == ZT_MAX_PEER_NETWORK_PATHS) {
|
||||
log("user-designated primary link is not yet ready");
|
||||
log("user-designated primary link is not available");
|
||||
// TODO: Should wait for some time (failover interval?) and then switch to spare link
|
||||
}
|
||||
}
|
||||
|
||||
else if (! userHasSpecifiedPrimaryLink()) {
|
||||
log("user did not specify a primary link, select first available link");
|
||||
for (int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
|
||||
if (_paths[i].p && _paths[i].eligible) {
|
||||
_abPathIdx = i;
|
||||
@@ -1368,7 +1396,9 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
|
||||
continue;
|
||||
}
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[i].p->localSocket());
|
||||
|
||||
if (! link) {
|
||||
continue;
|
||||
}
|
||||
int failoverScoreHandicap = _paths[i].failoverScore;
|
||||
if (_paths[i].preferred()) {
|
||||
failoverScoreHandicap += ZT_BOND_FAILOVER_HANDICAP_PREFERRED;
|
||||
@@ -1431,7 +1461,11 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
|
||||
if (! _paths[i].eligible) {
|
||||
failoverScoreHandicap = -10000;
|
||||
}
|
||||
if (getLink(_paths[i].p)->primary() && _abLinkSelectMethod != ZT_BOND_RESELECTION_POLICY_OPTIMIZE) {
|
||||
SharedPtr<Link> link = getLink(_paths[i].p);
|
||||
if (! link) {
|
||||
continue;
|
||||
}
|
||||
if (link->primary() && _abLinkSelectMethod != ZT_BOND_RESELECTION_POLICY_OPTIMIZE) {
|
||||
// If using "optimize" primary re-select mode, ignore user link designations
|
||||
failoverScoreHandicap = ZT_BOND_FAILOVER_HANDICAP_PRIMARY;
|
||||
}
|
||||
@@ -1500,15 +1534,19 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
|
||||
_lastActiveBackupPathChange = now;
|
||||
}
|
||||
if (_abLinkSelectMethod == ZT_BOND_RESELECTION_POLICY_ALWAYS) {
|
||||
if (! getLink(_paths[_abPathIdx].p)->primary() && _paths[_abFailoverQueue.front()].p && getLink(_paths[_abFailoverQueue.front()].p)->primary()) {
|
||||
SharedPtr<Link> abLink = getLink(_paths[_abPathIdx].p);
|
||||
SharedPtr<Link> abFailoverLink = getLink(_paths[_abFailoverQueue.front()].p);
|
||||
if (abLink && ! abLink->primary() && _paths[_abFailoverQueue.front()].p && abFailoverLink && abFailoverLink->primary()) {
|
||||
dequeueNextActiveBackupPath(now);
|
||||
log("switch back to available primary link %s (select mode: always)", pathToStr(_paths[_abPathIdx].p).c_str());
|
||||
}
|
||||
}
|
||||
if (_abLinkSelectMethod == ZT_BOND_RESELECTION_POLICY_BETTER) {
|
||||
if (! getLink(_paths[_abPathIdx].p)->primary()) {
|
||||
SharedPtr<Link> abLink = getLink(_paths[_abPathIdx].p);
|
||||
if (abLink && ! abLink->primary()) {
|
||||
// Active backup has switched to "better" primary link according to re-select policy.
|
||||
if (_paths[_abFailoverQueue.front()].p && getLink(_paths[_abFailoverQueue.front()].p)->primary() && (_paths[_abFailoverQueue.front()].failoverScore > _paths[_abPathIdx].failoverScore)) {
|
||||
SharedPtr<Link> abFailoverLink = getLink(_paths[_abFailoverQueue.front()].p);
|
||||
if (_paths[_abFailoverQueue.front()].p && abFailoverLink && abFailoverLink->primary() && (_paths[_abFailoverQueue.front()].failoverScore > _paths[_abPathIdx].failoverScore)) {
|
||||
dequeueNextActiveBackupPath(now);
|
||||
log("switch back to user-defined primary link %s (select mode: better)", pathToStr(_paths[_abPathIdx].p).c_str());
|
||||
}
|
||||
@@ -1708,8 +1746,12 @@ std::string Bond::pathToStr(const SharedPtr<Path>& path)
|
||||
char pathStr[64] = { 0 };
|
||||
char fullPathStr[384] = { 0 };
|
||||
path->address().toString(pathStr);
|
||||
snprintf(fullPathStr, 384, "%.16llx-%s/%s", (unsigned long long)(path->localSocket()), getLink(path)->ifname().c_str(), pathStr);
|
||||
return std::string(fullPathStr);
|
||||
SharedPtr<Link> link = getLink(path);
|
||||
if (link) {
|
||||
std::string ifnameStr = std::string(link->ifname());
|
||||
snprintf(fullPathStr, 384, "%.16llx-%s/%s", (unsigned long long)(path->localSocket()), ifnameStr.c_str(), pathStr);
|
||||
return std::string(fullPathStr);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
#else
|
||||
@@ -1723,11 +1765,11 @@ void Bond::dumpPathStatus(int64_t now, int pathIdx)
|
||||
std::string aliveOrDead = _paths[pathIdx].alive ? std::string("alive") : std::string("dead");
|
||||
std::string eligibleOrNot = _paths[pathIdx].eligible ? std::string("eligible") : std::string("ineligible");
|
||||
std::string bondedOrNot = _paths[pathIdx].bonded ? std::string("bonded") : std::string("unbonded");
|
||||
log("path[%2d] --- %5s (in %7d, out: %7d), %10s, %8s, flows=%-6d lat=%-8.3f pdv=%-7.3f err=%-6.4f loss=%-6.4f alloc=%-3d --- (%s)",
|
||||
log("path[%2u] --- %5s (in %7lld, out: %7lld), %10s, %8s, flows=%-6u lat=%-8.3f pdv=%-7.3f err=%-6.4f loss=%-6.4f alloc=%-3u --- (%s)",
|
||||
pathIdx,
|
||||
aliveOrDead.c_str(),
|
||||
_paths[pathIdx].p->age(now),
|
||||
(now - _paths[pathIdx].p->_lastOut),
|
||||
static_cast<long long int>(_paths[pathIdx].p->age(now)),
|
||||
static_cast<long long int>(_paths[pathIdx].p->_lastOut == 0 ? 0 : now - _paths[pathIdx].p->_lastOut),
|
||||
eligibleOrNot.c_str(),
|
||||
bondedOrNot.c_str(),
|
||||
_paths[pathIdx].assignedFlowCount,
|
||||
|
||||
+8
-1
@@ -458,9 +458,10 @@ class Bond {
|
||||
*
|
||||
* @param policyAlias Policy in use
|
||||
* @param localSocket Local source socket
|
||||
* @param createIfNeeded Whether a Link object is created if the name wasn't previously in the link map
|
||||
* @return Physical link definition
|
||||
*/
|
||||
static SharedPtr<Link> getLinkBySocket(const std::string& policyAlias, uint64_t localSocket);
|
||||
static SharedPtr<Link> getLinkBySocket(const std::string& policyAlias, uint64_t localSocket, bool createIfNeeded);
|
||||
|
||||
/**
|
||||
* Gets a reference to a physical link definition given its human-readable system name.
|
||||
@@ -1141,6 +1142,9 @@ class Bond {
|
||||
*
|
||||
*/
|
||||
void log(const char* fmt, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__((format(printf, 2, 3)))
|
||||
#endif
|
||||
{
|
||||
#ifdef ZT_TRACE
|
||||
time_t rawtime;
|
||||
@@ -1170,6 +1174,9 @@ class Bond {
|
||||
*
|
||||
*/
|
||||
void debug(const char* fmt, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__((format(printf, 2, 3)))
|
||||
#endif
|
||||
{
|
||||
#ifdef ZT_DEBUG
|
||||
time_t rawtime;
|
||||
|
||||
+30
-10
@@ -229,23 +229,33 @@ public:
|
||||
* @param s Socket object
|
||||
* @return Underlying OS-type (usually int or long) file descriptor associated with object
|
||||
*/
|
||||
static inline ZT_PHY_SOCKFD_TYPE getDescriptor(PhySocket *s) throw() { return reinterpret_cast<PhySocketImpl *>(s)->sock; }
|
||||
static inline ZT_PHY_SOCKFD_TYPE getDescriptor(PhySocket* s) throw()
|
||||
{
|
||||
return reinterpret_cast<PhySocketImpl*>(s)->sock;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param s Socket object
|
||||
* @return Pointer to user object
|
||||
*/
|
||||
static inline void** getuptr(PhySocket *s) throw() { return &(reinterpret_cast<PhySocketImpl *>(s)->uptr); }
|
||||
static inline void** getuptr(PhySocket* s) throw()
|
||||
{
|
||||
return &(reinterpret_cast<PhySocketImpl*>(s)->uptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param s Socket object
|
||||
* @param nameBuf Buffer to store name of interface which this Socket object is bound to
|
||||
* @param buflen Length of buffer to copy name into
|
||||
*/
|
||||
static inline void getIfName(PhySocket *s, char *nameBuf, int buflen)
|
||||
static inline void getIfName(PhySocket* s, char* nameBuf, int buflen)
|
||||
{
|
||||
PhySocketImpl& sws = *(reinterpret_cast<PhySocketImpl*>(s));
|
||||
if (sws.type == ZT_PHY_SOCKET_CLOSED) {
|
||||
return;
|
||||
}
|
||||
if (s) {
|
||||
memcpy(nameBuf, reinterpret_cast<PhySocketImpl *>(s)->ifname, buflen);
|
||||
memcpy(nameBuf, reinterpret_cast<PhySocketImpl*>(s)->ifname, buflen);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,10 +264,14 @@ public:
|
||||
* @param ifname Buffer containing name of interface that this Socket object is bound to
|
||||
* @param len Length of name of interface
|
||||
*/
|
||||
static inline void setIfName(PhySocket *s, char *ifname, int len)
|
||||
static inline void setIfName(PhySocket* s, char* ifname, int len)
|
||||
{
|
||||
PhySocketImpl& sws = *(reinterpret_cast<PhySocketImpl*>(s));
|
||||
if (sws.type == ZT_PHY_SOCKET_CLOSED) {
|
||||
return;
|
||||
}
|
||||
if (s) {
|
||||
memcpy(&(reinterpret_cast<PhySocketImpl *>(s)->ifname), ifname, len);
|
||||
memcpy(&(reinterpret_cast<PhySocketImpl*>(s)->ifname), ifname, len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,21 +284,27 @@ public:
|
||||
inline void whack()
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::send(_whackSendSocket,(const char *)this,1,0);
|
||||
::send(_whackSendSocket, (const char*)this, 1, 0);
|
||||
#else
|
||||
(void)(::write(_whackSendSocket,(PhySocket *)this,1));
|
||||
(void)(::write(_whackSendSocket, (PhySocket*)this, 1));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Number of open sockets
|
||||
*/
|
||||
inline unsigned long count() const throw() { return _socks.size(); }
|
||||
inline unsigned long count() const throw()
|
||||
{
|
||||
return _socks.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Maximum number of sockets allowed
|
||||
*/
|
||||
inline unsigned long maxCount() const throw() { return ZT_PHY_MAX_SOCKETS; }
|
||||
inline unsigned long maxCount() const throw()
|
||||
{
|
||||
return ZT_PHY_MAX_SOCKETS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a raw file descriptor in a PhySocket structure
|
||||
|
||||
@@ -568,6 +568,7 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer)
|
||||
j["active"] = (bool)(peer->paths[i].expired == 0);
|
||||
j["expired"] = (bool)(peer->paths[i].expired != 0);
|
||||
j["preferred"] = (bool)(peer->paths[i].preferred != 0);
|
||||
j["localSocket"] = peer->paths[i].localSocket;
|
||||
pa.push_back(j);
|
||||
}
|
||||
pj["paths"] = pa;
|
||||
@@ -787,6 +788,7 @@ public:
|
||||
// Time we last received a packet from a global address
|
||||
uint64_t _lastDirectReceiveFromGlobal;
|
||||
#ifdef ZT_TCP_FALLBACK_RELAY
|
||||
InetAddress _fallbackRelayAddress;
|
||||
uint64_t _lastSendToGlobalV4;
|
||||
#endif
|
||||
|
||||
@@ -850,6 +852,7 @@ public:
|
||||
,_udpPortPickerCounter(0)
|
||||
,_lastDirectReceiveFromGlobal(0)
|
||||
#ifdef ZT_TCP_FALLBACK_RELAY
|
||||
, _fallbackRelayAddress(ZT_TCP_FALLBACK_RELAY)
|
||||
,_lastSendToGlobalV4(0)
|
||||
#endif
|
||||
,_lastRestart(0)
|
||||
@@ -2146,7 +2149,10 @@ public:
|
||||
}
|
||||
|
||||
// bondingPolicy cannot be used with allowTcpFallbackRelay
|
||||
_allowTcpFallbackRelay = OSUtils::jsonBool(settings["allowTcpFallbackRelay"],true) && !(_node->bondController()->inUse());
|
||||
_allowTcpFallbackRelay = OSUtils::jsonBool(settings["allowTcpFallbackRelay"],true);
|
||||
#ifdef ZT_TCP_FALLBACK_RELAY
|
||||
_fallbackRelayAddress = InetAddress(OSUtils::jsonString("tcpFallbackRelay", ZT_TCP_FALLBACK_RELAY).c_str());
|
||||
#endif
|
||||
_primaryPort = (unsigned int)OSUtils::jsonInt(settings["primaryPort"],(uint64_t)_primaryPort) & 0xffff;
|
||||
_allowSecondaryPort = OSUtils::jsonBool(settings["allowSecondaryPort"],true);
|
||||
_secondaryPort = (unsigned int)OSUtils::jsonInt(settings["secondaryPort"],0);
|
||||
@@ -3154,7 +3160,7 @@ public:
|
||||
phyOnTcpWritable(_tcpFallbackTunnel->sock,&tmpptr);
|
||||
}
|
||||
} else if (((now - _lastSendToGlobalV4) < ZT_TCP_FALLBACK_AFTER)&&((now - _lastSendToGlobalV4) > (ZT_PING_CHECK_INVERVAL / 2))) {
|
||||
const InetAddress addr(ZT_TCP_FALLBACK_RELAY);
|
||||
const InetAddress addr(_fallbackRelayAddress);
|
||||
TcpConnection *tc = new TcpConnection();
|
||||
{
|
||||
Mutex::Lock _l(_tcpConnections_m);
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
/**
|
||||
* Revision
|
||||
*/
|
||||
#define ZEROTIER_ONE_VERSION_REVISION 9
|
||||
#define ZEROTIER_ONE_VERSION_REVISION 10
|
||||
|
||||
/**
|
||||
* Build version
|
||||
|
||||
@@ -411,7 +411,7 @@
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\..\zeroidc\target;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>ZT_EXPORT;FD_SETSIZE=1024;NOMINMAX;STATICLIB;WIN32;ZT_TRACE;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;ZT_SOFTWARE_UPDATE_DEFAULT="disable";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>ZT_SSO_ENABLED=1;ZT_EXPORT;FD_SETSIZE=1024;NOMINMAX;STATICLIB;WIN32;ZT_TRACE;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;ZT_SOFTWARE_UPDATE_DEFAULT="disable";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4996</DisableSpecificWarnings>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<LanguageStandard>stdcpp14</LanguageStandard>
|
||||
@@ -433,7 +433,7 @@
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\..\zeroidc\target;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>ZT_EXPORT;FD_SETSIZE=1024;NOMINMAX;STATICLIB;WIN32;ZT_TRACE;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;ZT_SOFTWARE_UPDATE_DEFAULT="disable";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>ZT_SSO_ENABLED=1;ZT_EXPORT;FD_SETSIZE=1024;NOMINMAX;STATICLIB;WIN32;ZT_TRACE;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;ZT_SOFTWARE_UPDATE_DEFAULT="disable";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4996</DisableSpecificWarnings>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<LanguageStandard>stdcpp14</LanguageStandard>
|
||||
@@ -454,7 +454,7 @@
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\..\zeroidc\target;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>ZT_EXPORT;FD_SETSIZE=1024;NOMINMAX;STATICLIB;WIN32;ZT_TRACE;ZT_RULES_ENGINE_DEBUGGING;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;ZT_SOFTWARE_UPDATE_DEFAULT="disable";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>ZT_SSO_ENABLED=1;ZT_EXPORT;FD_SETSIZE=1024;NOMINMAX;STATICLIB;WIN32;ZT_TRACE;ZT_RULES_ENGINE_DEBUGGING;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;ZT_SOFTWARE_UPDATE_DEFAULT="disable";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<DisableSpecificWarnings>4996</DisableSpecificWarnings>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
@@ -500,7 +500,7 @@
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\..\zeroidc\target;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>ZT_EXPORT;FD_SETSIZE=1024;NOMINMAX;STATICLIB;WIN32;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;ZT_SOFTWARE_UPDATE_DEFAULT="disable";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>ZT_SSO_ENABLED=1;ZT_EXPORT;FD_SETSIZE=1024;NOMINMAX;STATICLIB;WIN32;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;ZT_SOFTWARE_UPDATE_DEFAULT="disable";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<DisableSpecificWarnings>4996</DisableSpecificWarnings>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
@@ -546,7 +546,7 @@
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\..\zeroidc\target;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>ZT_EXPORT;FD_SETSIZE=1024;STATICLIB;ZT_SALSA20_SSE;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;WIN32;NOMINMAX;ZT_SOFTWARE_UPDATE_DEFAULT="apply";ZT_BUILD_PLATFORM=2;ZT_BUILD_ARCHITECTURE=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>ZT_SSO_ENABLED=1;ZT_EXPORT;FD_SETSIZE=1024;STATICLIB;ZT_SALSA20_SSE;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;WIN32;NOMINMAX;ZT_SOFTWARE_UPDATE_DEFAULT="apply";ZT_BUILD_PLATFORM=2;ZT_BUILD_ARCHITECTURE=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<StringPooling>true</StringPooling>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
@@ -582,7 +582,7 @@
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\..\zeroidc\target;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>ZT_EXPORT;FD_SETSIZE=1024;STATICLIB;ZT_SOFTWARE_UPDATE_DEFAULT="apply";ZT_SALSA20_SSE;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;WIN32;NOMINMAX;ZT_BUILD_PLATFORM=2;ZT_BUILD_ARCHITECTURE=2;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>ZT_SSO_ENABLED=1;ZT_EXPORT;FD_SETSIZE=1024;STATICLIB;ZT_SOFTWARE_UPDATE_DEFAULT="apply";ZT_SALSA20_SSE;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;WIN32;NOMINMAX;ZT_BUILD_PLATFORM=2;ZT_BUILD_ARCHITECTURE=2;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<StringPooling>true</StringPooling>
|
||||
|
||||
+4
-1
@@ -1,5 +1,5 @@
|
||||
Name: zerotier-one
|
||||
Version: 1.8.9
|
||||
Version: 1.8.10
|
||||
Release: 1%{?dist}
|
||||
Summary: ZeroTier network virtualization service
|
||||
|
||||
@@ -165,6 +165,9 @@ esac
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Tue May 10 2022 Adam Ierymenko <adam.ierymenko@zerotier.com> - 1.8.10
|
||||
- see https://github.com/zerotier/ZeroTierOne for release notes
|
||||
|
||||
* Fri Apr 25 2022 Adam Ierymenko <adam.ierymenko@zerotier.com> - 1.8.9
|
||||
- see https://github.com/zerotier/ZeroTierOne for release notes
|
||||
|
||||
|
||||
Reference in new issue
Block a user