mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 03:53:44 +02:00
Improved multipath link monitoring
This commit is contained in:
parent
0797adf223
commit
bc521504ca
9 changed files with 232 additions and 255 deletions
|
@ -86,6 +86,11 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
#define ZT_MIN_PHYSMTU 1400
|
#define ZT_MIN_PHYSMTU 1400
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum physical interface name length. This number is gigantic because of Windows.
|
||||||
|
*/
|
||||||
|
#define ZT_MAX_PHYSIFNAME 256
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default UDP payload size (physical path MTU) not including UDP and IP overhead
|
* Default UDP payload size (physical path MTU) not including UDP and IP overhead
|
||||||
*
|
*
|
||||||
|
@ -1317,35 +1322,20 @@ typedef struct
|
||||||
*/
|
*/
|
||||||
float packetErrorRatio;
|
float packetErrorRatio;
|
||||||
|
|
||||||
/**
|
|
||||||
* Mean throughput
|
|
||||||
*/
|
|
||||||
uint64_t throughputMean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum observed throughput
|
|
||||||
*/
|
|
||||||
float throughputMax;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Throughput variance
|
|
||||||
*/
|
|
||||||
float throughputVariance;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Address scope
|
* Address scope
|
||||||
*/
|
*/
|
||||||
uint8_t scope;
|
uint8_t scope;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Percentage of traffic allocated to this path
|
* Percentage of traffic allocated to this path (0-255)
|
||||||
*/
|
*/
|
||||||
float allocation;
|
uint8_t allocation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of physical interface (for monitoring)
|
* Name of physical interface this path resides on
|
||||||
*/
|
*/
|
||||||
char ifname[32];
|
char ifname[ZT_MAX_PHYSIFNAME];
|
||||||
|
|
||||||
uint64_t localSocket;
|
uint64_t localSocket;
|
||||||
|
|
||||||
|
@ -1354,6 +1344,21 @@ typedef struct
|
||||||
*/
|
*/
|
||||||
int expired;
|
int expired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this path is currently included in the bond
|
||||||
|
*/
|
||||||
|
uint8_t bonded;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this path is currently eligible to be used in a bond
|
||||||
|
*/
|
||||||
|
uint8_t eligible;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The speed of this link (as given to bonding layer)
|
||||||
|
*/
|
||||||
|
uint32_t linkSpeed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is path preferred?
|
* Is path preferred?
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -28,6 +28,8 @@ uint8_t Bond::_defaultPolicy = ZT_BOND_POLICY_NONE;
|
||||||
|
|
||||||
Phy<Bond*>* Bond::_phy;
|
Phy<Bond*>* Bond::_phy;
|
||||||
|
|
||||||
|
Binder* Bond::_binder;
|
||||||
|
|
||||||
Mutex Bond::_bonds_m;
|
Mutex Bond::_bonds_m;
|
||||||
Mutex Bond::_links_m;
|
Mutex Bond::_links_m;
|
||||||
|
|
||||||
|
@ -158,13 +160,13 @@ void Bond::destroyBond(uint64_t peerId)
|
||||||
SharedPtr<Link> Bond::getLinkBySocket(const std::string& policyAlias, uint64_t localSocket, bool createIfNeeded = false)
|
SharedPtr<Link> Bond::getLinkBySocket(const std::string& policyAlias, uint64_t localSocket, bool createIfNeeded = false)
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_links_m);
|
Mutex::Lock _l(_links_m);
|
||||||
char ifname[64] = { 0 };
|
char ifname[ZT_MAX_PHYSIFNAME] = {};
|
||||||
_phy->getIfName((PhySocket*)((uintptr_t)localSocket), ifname, sizeof(ifname) - 1);
|
_binder->getIfName((PhySocket*)((uintptr_t)localSocket), ifname, sizeof(ifname) - 1);
|
||||||
std::string ifnameStr(ifname);
|
std::string ifnameStr(ifname);
|
||||||
auto search = _interfaceToLinkMap[policyAlias].find(ifnameStr);
|
auto search = _interfaceToLinkMap[policyAlias].find(ifnameStr);
|
||||||
if (search == _interfaceToLinkMap[policyAlias].end()) {
|
if (search == _interfaceToLinkMap[policyAlias].end()) {
|
||||||
if (createIfNeeded) {
|
if (createIfNeeded) {
|
||||||
SharedPtr<Link> s = new Link(ifnameStr, 0, 0, true, ZT_BOND_SLAVE_MODE_PRIMARY, "", 0.0);
|
SharedPtr<Link> s = new Link(ifnameStr, 0, 0, true, ZT_BOND_SLAVE_MODE_PRIMARY, "");
|
||||||
_interfaceToLinkMap[policyAlias].insert(std::pair<std::string, SharedPtr<Link> >(ifnameStr, s));
|
_interfaceToLinkMap[policyAlias].insert(std::pair<std::string, SharedPtr<Link> >(ifnameStr, s));
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
@ -250,6 +252,12 @@ void Bond::nominatePathToBond(const SharedPtr<Path>& path, int64_t now)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (! alreadyPresent) {
|
if (! alreadyPresent) {
|
||||||
|
SharedPtr<Link> link = getLink(path);
|
||||||
|
if (link) {
|
||||||
|
std::string ifnameStr = std::string(link->ifname());
|
||||||
|
memset(path->_ifname, 0x0, ZT_MAX_PHYSIFNAME);
|
||||||
|
memcpy(path->_ifname, ifnameStr.c_str(), std::min((int)ifnameStr.length(), ZT_MAX_PHYSIFNAME));
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Find somewhere to stick it
|
* Find somewhere to stick it
|
||||||
*/
|
*/
|
||||||
|
@ -523,6 +531,7 @@ int32_t Bond::generateQoSPacket(int pathIdx, int64_t now, char* qosBuffer)
|
||||||
std::map<uint64_t, uint64_t>::iterator it = _paths[pathIdx].qosStatsIn.begin();
|
std::map<uint64_t, uint64_t>::iterator it = _paths[pathIdx].qosStatsIn.begin();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int numRecords = std::min(_paths[pathIdx].packetsReceivedSinceLastQoS, ZT_QOS_TABLE_SIZE);
|
int numRecords = std::min(_paths[pathIdx].packetsReceivedSinceLastQoS, ZT_QOS_TABLE_SIZE);
|
||||||
|
debug("numRecords=%3d, packetsReceivedSinceLastQoS=%3d, _paths[pathIdx].qosStatsIn.size()=%3lu", numRecords, _paths[pathIdx].packetsReceivedSinceLastQoS, _paths[pathIdx].qosStatsIn.size());
|
||||||
while (i < numRecords && it != _paths[pathIdx].qosStatsIn.end()) {
|
while (i < numRecords && it != _paths[pathIdx].qosStatsIn.end()) {
|
||||||
uint64_t id = it->first;
|
uint64_t id = it->first;
|
||||||
memcpy(qosBuffer, &id, sizeof(uint64_t));
|
memcpy(qosBuffer, &id, sizeof(uint64_t));
|
||||||
|
@ -800,8 +809,8 @@ void Bond::sendQOS_MEASUREMENT(void* tPtr, int pathIdx, int64_t localSocket, con
|
||||||
Packet outp(_peer->_id.address(), RR->identity.address(), Packet::VERB_QOS_MEASUREMENT);
|
Packet outp(_peer->_id.address(), RR->identity.address(), Packet::VERB_QOS_MEASUREMENT);
|
||||||
char qosData[ZT_QOS_MAX_PACKET_SIZE];
|
char qosData[ZT_QOS_MAX_PACKET_SIZE];
|
||||||
int16_t len = generateQoSPacket(pathIdx, _now, qosData);
|
int16_t len = generateQoSPacket(pathIdx, _now, qosData);
|
||||||
debug("sending QOS via link %s (len=%d)", pathToStr(_paths[pathIdx].p).c_str(), len);
|
|
||||||
if (len) {
|
if (len) {
|
||||||
|
debug("sending QOS via link %s (len=%d)", pathToStr(_paths[pathIdx].p).c_str(), len);
|
||||||
outp.append(qosData, len);
|
outp.append(qosData, len);
|
||||||
if (atAddress) {
|
if (atAddress) {
|
||||||
outp.armor(_peer->key(), false, _peer->aesKeysIfSupported());
|
outp.armor(_peer->key(), false, _peer->aesKeysIfSupported());
|
||||||
|
@ -905,6 +914,7 @@ void Bond::curateBond(int64_t now, bool rebuildBond)
|
||||||
SharedPtr<Link> link = getLink(_paths[i].p);
|
SharedPtr<Link> link = getLink(_paths[i].p);
|
||||||
if (! link) {
|
if (! link) {
|
||||||
log("link is no longer valid, removing from bond");
|
log("link is no longer valid, removing from bond");
|
||||||
|
_paths[i].p->_valid = false;
|
||||||
_paths[i] = NominatedPath();
|
_paths[i] = NominatedPath();
|
||||||
_paths[i].p = SharedPtr<Path>();
|
_paths[i].p = SharedPtr<Path>();
|
||||||
continue;
|
continue;
|
||||||
|
@ -1109,6 +1119,7 @@ void Bond::curateBond(int64_t now, bool rebuildBond)
|
||||||
if (_policy == ZT_BOND_POLICY_BALANCE_RR) {
|
if (_policy == ZT_BOND_POLICY_BALANCE_RR) {
|
||||||
// Cause a RR reset since the current index might no longer be valid
|
// Cause a RR reset since the current index might no longer be valid
|
||||||
_rrPacketsSentOnCurrLink = _packetsPerLink;
|
_rrPacketsSentOnCurrLink = _packetsPerLink;
|
||||||
|
_rrIdx = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1166,9 +1177,13 @@ void Bond::estimatePathQuality(int64_t now)
|
||||||
_paths[i].p->_packetLossRatio = _paths[i].packetLossRatio;
|
_paths[i].p->_packetLossRatio = _paths[i].packetLossRatio;
|
||||||
_paths[i].p->_packetErrorRatio = _paths[i].packetErrorRatio;
|
_paths[i].p->_packetErrorRatio = _paths[i].packetErrorRatio;
|
||||||
_paths[i].p->_bonded = _paths[i].bonded;
|
_paths[i].p->_bonded = _paths[i].bonded;
|
||||||
_paths[i].p->_givenLinkSpeed = 0;//_paths[i].givenLinkSpeed;
|
_paths[i].p->_eligible = _paths[i].eligible;
|
||||||
|
// _valid is written elsewhere
|
||||||
_paths[i].p->_allocation = _paths[i].allocation;
|
_paths[i].p->_allocation = _paths[i].allocation;
|
||||||
|
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[i].p->localSocket());
|
||||||
|
if (link) {
|
||||||
|
_paths[i].p->_givenLinkSpeed = link->speed();
|
||||||
|
}
|
||||||
//_paths[i].packetErrorRatio = 1.0 - (_paths[i].packetValiditySamples.count() ? _paths[i].packetValiditySamples.mean() : 1.0);
|
//_paths[i].packetErrorRatio = 1.0 - (_paths[i].packetValiditySamples.count() ? _paths[i].packetValiditySamples.mean() : 1.0);
|
||||||
|
|
||||||
// Drain unacknowledged QoS records
|
// Drain unacknowledged QoS records
|
||||||
|
@ -1725,10 +1740,11 @@ void Bond::setBondParameters(int policy, SharedPtr<Bond> templateBond, bool useT
|
||||||
_policy = (policy <= ZT_BOND_POLICY_NONE || policy > ZT_BOND_POLICY_BALANCE_AWARE) ? _defaultPolicy : policy;
|
_policy = (policy <= ZT_BOND_POLICY_NONE || policy > ZT_BOND_POLICY_BALANCE_AWARE) ? _defaultPolicy : policy;
|
||||||
|
|
||||||
// Check if non-leaf to prevent spamming infrastructure
|
// Check if non-leaf to prevent spamming infrastructure
|
||||||
|
ZT_PeerRole role;
|
||||||
if (_peer) {
|
if (_peer) {
|
||||||
ZT_PeerRole role = RR->topology->role(_peer->address());
|
role = RR->topology->role(_peer->address());
|
||||||
_isLeaf = (role != ZT_PEER_ROLE_PLANET && role != ZT_PEER_ROLE_MOON);
|
|
||||||
}
|
}
|
||||||
|
_isLeaf = _peer ? (role != ZT_PEER_ROLE_PLANET && role != ZT_PEER_ROLE_MOON) : false;
|
||||||
|
|
||||||
// Flows
|
// Flows
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#ifndef ZT_BOND_HPP
|
#ifndef ZT_BOND_HPP
|
||||||
#define ZT_BOND_HPP
|
#define ZT_BOND_HPP
|
||||||
|
|
||||||
|
#include "../osdep/Binder.hpp"
|
||||||
#include "../osdep/Phy.hpp"
|
#include "../osdep/Phy.hpp"
|
||||||
#include "Packet.hpp"
|
#include "Packet.hpp"
|
||||||
#include "Path.hpp"
|
#include "Path.hpp"
|
||||||
|
@ -122,7 +123,7 @@ class Link {
|
||||||
* @param failoverToLinkStr
|
* @param failoverToLinkStr
|
||||||
* @param userSpecifiedAlloc
|
* @param userSpecifiedAlloc
|
||||||
*/
|
*/
|
||||||
Link(std::string ifnameStr, uint8_t ipvPref, uint32_t speed, bool enabled, uint8_t mode, std::string failoverToLinkStr, float userSpecifiedAlloc)
|
Link(std::string ifnameStr, uint8_t ipvPref, uint32_t speed, bool enabled, uint8_t mode, std::string failoverToLinkStr)
|
||||||
: _ifnameStr(ifnameStr)
|
: _ifnameStr(ifnameStr)
|
||||||
, _ipvPref(ipvPref)
|
, _ipvPref(ipvPref)
|
||||||
, _speed(speed)
|
, _speed(speed)
|
||||||
|
@ -130,7 +131,6 @@ class Link {
|
||||||
, _enabled(enabled)
|
, _enabled(enabled)
|
||||||
, _mode(mode)
|
, _mode(mode)
|
||||||
, _failoverToLinkStr(failoverToLinkStr)
|
, _failoverToLinkStr(failoverToLinkStr)
|
||||||
, _userSpecifiedAlloc(userSpecifiedAlloc)
|
|
||||||
, _isUserSpecified(false)
|
, _isUserSpecified(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -287,11 +287,6 @@ class Link {
|
||||||
*/
|
*/
|
||||||
std::string _failoverToLinkStr;
|
std::string _failoverToLinkStr;
|
||||||
|
|
||||||
/**
|
|
||||||
* User-specified allocation
|
|
||||||
*/
|
|
||||||
float _userSpecifiedAlloc;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not this link was created as a result of manual user specification. This is
|
* Whether or not this link was created as a result of manual user specification. This is
|
||||||
* important to know because certain policy decisions are dependent on whether the user
|
* important to know because certain policy decisions are dependent on whether the user
|
||||||
|
@ -328,6 +323,14 @@ class Bond {
|
||||||
return ! _bondPolicyTemplates.empty() || _defaultPolicy;
|
return ! _bondPolicyTemplates.empty() || _defaultPolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a pointer to an instance of _binder used by the Bond to get interface data
|
||||||
|
*/
|
||||||
|
static void setBinder(Binder* b)
|
||||||
|
{
|
||||||
|
_binder = b;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param basePolicyName Bonding policy name (See ZeroTierOne.h)
|
* @param basePolicyName Bonding policy name (See ZeroTierOne.h)
|
||||||
* @return The bonding policy code for a given human-readable bonding policy name
|
* @return The bonding policy code for a given human-readable bonding policy name
|
||||||
|
@ -461,7 +464,7 @@ class Bond {
|
||||||
* @param createIfNeeded Whether a Link object is created if the name wasn't previously in the link map
|
* @param createIfNeeded Whether a Link object is created if the name wasn't previously in the link map
|
||||||
* @return Physical link definition
|
* @return Physical link definition
|
||||||
*/
|
*/
|
||||||
static SharedPtr<Link> getLinkBySocket(const std::string& policyAlias, uint64_t localSocket, bool createIfNeeded);
|
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.
|
* Gets a reference to a physical link definition given its human-readable system name.
|
||||||
|
@ -840,14 +843,6 @@ class Bond {
|
||||||
_maxAcceptablePacketErrorRatio = errorRatio;
|
_maxAcceptablePacketErrorRatio = errorRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param errorRatio Maximum acceptable packet error ratio (PER).
|
|
||||||
*/
|
|
||||||
void setMinAcceptableAllocation(float minAlloc)
|
|
||||||
{
|
|
||||||
_minAcceptableAllocation = (uint8_t)(minAlloc * 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Whether the user has defined links for use on this bond
|
* @return Whether the user has defined links for use on this bond
|
||||||
*/
|
*/
|
||||||
|
@ -970,14 +965,6 @@ class Bond {
|
||||||
return _failoverInterval;
|
return _failoverInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param strategy Strategy that the bond uses to re-assign protocol flows.
|
|
||||||
*/
|
|
||||||
inline void setFlowRebalanceStrategy(uint32_t strategy)
|
|
||||||
{
|
|
||||||
_flowRebalanceStrategy = strategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param strategy Strategy that the bond uses to prob for path aliveness and quality
|
* @param strategy Strategy that the bond uses to prob for path aliveness and quality
|
||||||
*/
|
*/
|
||||||
|
@ -1150,26 +1137,8 @@ class Bond {
|
||||||
*/
|
*/
|
||||||
bool abForciblyRotateLink();
|
bool abForciblyRotateLink();
|
||||||
|
|
||||||
/**
|
|
||||||
* @param now Current time
|
|
||||||
* @return All known paths to this peer
|
|
||||||
*/
|
|
||||||
inline std::vector<SharedPtr<Path> > paths(const int64_t now) const
|
|
||||||
{
|
|
||||||
std::vector<SharedPtr<Path> > pp;
|
|
||||||
Mutex::Lock _l(_paths_m);
|
|
||||||
for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
|
|
||||||
if (! _paths[i].p) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pp.push_back(_paths[i].p);
|
|
||||||
}
|
|
||||||
return pp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emit message to tracing system but with added timestamp and subsystem info
|
* Emit message to tracing system but with added timestamp and subsystem info
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
void log(const char* fmt, ...)
|
void log(const char* fmt, ...)
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
@ -1201,7 +1170,6 @@ class Bond {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emit message to tracing system but with added timestamp and subsystem info
|
* Emit message to tracing system but with added timestamp and subsystem info
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
void debug(const char* fmt, ...)
|
void debug(const char* fmt, ...)
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
@ -1412,7 +1380,6 @@ class Bond {
|
||||||
{
|
{
|
||||||
p = path;
|
p = path;
|
||||||
whenNominated = now;
|
whenNominated = now;
|
||||||
p->_bondingMetricPtr = (void*)this;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1487,6 +1454,8 @@ class Bond {
|
||||||
|
|
||||||
std::string _policyAlias; // Custom name given by the user to this bond type.
|
std::string _policyAlias; // Custom name given by the user to this bond type.
|
||||||
|
|
||||||
|
static Binder* _binder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set of indices corresponding to paths currently included in the bond proper. This
|
* Set of indices corresponding to paths currently included in the bond proper. This
|
||||||
* may only be updated during a call to curateBond(). The reason for this is so that
|
* may only be updated during a call to curateBond(). The reason for this is so that
|
||||||
|
@ -1518,7 +1487,6 @@ class Bond {
|
||||||
|
|
||||||
// balance-aware
|
// balance-aware
|
||||||
uint64_t _totalBondUnderload;
|
uint64_t _totalBondUnderload;
|
||||||
uint8_t _flowRebalanceStrategy;
|
|
||||||
|
|
||||||
// dynamic link monitoring
|
// dynamic link monitoring
|
||||||
uint8_t _linkMonitorStrategy;
|
uint8_t _linkMonitorStrategy;
|
||||||
|
@ -1546,7 +1514,6 @@ class Bond {
|
||||||
uint16_t _maxAcceptableLatency;
|
uint16_t _maxAcceptableLatency;
|
||||||
uint16_t _maxAcceptableMeanLatency;
|
uint16_t _maxAcceptableMeanLatency;
|
||||||
uint16_t _maxAcceptablePacketDelayVariance;
|
uint16_t _maxAcceptablePacketDelayVariance;
|
||||||
uint8_t _minAcceptableAllocation;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Link state reporting
|
* Link state reporting
|
||||||
|
|
|
@ -496,15 +496,30 @@ ZT_PeerList *Node::peers() const
|
||||||
SharedPtr<Path> bestp(pi->second->getAppropriatePath(_now,false));
|
SharedPtr<Path> bestp(pi->second->getAppropriatePath(_now,false));
|
||||||
p->pathCount = 0;
|
p->pathCount = 0;
|
||||||
for(std::vector< SharedPtr<Path> >::iterator path(paths.begin());path!=paths.end();++path) {
|
for(std::vector< SharedPtr<Path> >::iterator path(paths.begin());path!=paths.end();++path) {
|
||||||
memcpy(&(p->paths[p->pathCount].address),&((*path)->address()),sizeof(struct sockaddr_storage));
|
if((*path)->valid()) {
|
||||||
p->paths[p->pathCount].localSocket = (*path)->localSocket();
|
memcpy(&(p->paths[p->pathCount].address),&((*path)->address()),sizeof(struct sockaddr_storage));
|
||||||
p->paths[p->pathCount].lastSend = (*path)->lastOut();
|
p->paths[p->pathCount].localSocket = (*path)->localSocket();
|
||||||
p->paths[p->pathCount].lastReceive = (*path)->lastIn();
|
p->paths[p->pathCount].lastSend = (*path)->lastOut();
|
||||||
p->paths[p->pathCount].trustedPathId = RR->topology->getOutboundPathTrust((*path)->address());
|
p->paths[p->pathCount].lastReceive = (*path)->lastIn();
|
||||||
p->paths[p->pathCount].expired = 0;
|
p->paths[p->pathCount].trustedPathId = RR->topology->getOutboundPathTrust((*path)->address());
|
||||||
p->paths[p->pathCount].preferred = ((*path) == bestp) ? 1 : 0;
|
p->paths[p->pathCount].expired = 0;
|
||||||
p->paths[p->pathCount].scope = (*path)->ipScope();
|
p->paths[p->pathCount].preferred = ((*path) == bestp) ? 1 : 0;
|
||||||
++p->pathCount;
|
p->paths[p->pathCount].scope = (*path)->ipScope();
|
||||||
|
if (pi->second->bond()) {
|
||||||
|
p->paths[p->pathCount].latencyMean = (*path)->latencyMean();
|
||||||
|
p->paths[p->pathCount].latencyVariance = (*path)->latencyVariance();
|
||||||
|
p->paths[p->pathCount].packetLossRatio = (*path)->packetLossRatio();
|
||||||
|
p->paths[p->pathCount].packetErrorRatio = (*path)->packetErrorRatio();
|
||||||
|
p->paths[p->pathCount].allocation = (*path)->allocation();
|
||||||
|
p->paths[p->pathCount].linkSpeed = (*path)->givenLinkSpeed();
|
||||||
|
p->paths[p->pathCount].bonded = (*path)->bonded();
|
||||||
|
p->paths[p->pathCount].eligible = (*path)->eligible();
|
||||||
|
std::string ifname = std::string((*path)->ifname());
|
||||||
|
memset(p->paths[p->pathCount].ifname, 0x0, std::min((int)ifname.length() + 1, ZT_MAX_PHYSIFNAME));
|
||||||
|
memcpy(p->paths[p->pathCount].ifname, ifname.c_str(), std::min((int)ifname.length(), ZT_MAX_PHYSIFNAME));
|
||||||
|
}
|
||||||
|
++p->pathCount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (pi->second->bond()) {
|
if (pi->second->bond()) {
|
||||||
p->isBonded = pi->second->bond();
|
p->isBonded = pi->second->bond();
|
||||||
|
|
|
@ -85,6 +85,15 @@ public:
|
||||||
_lastTrustEstablishedPacketReceived(0),
|
_lastTrustEstablishedPacketReceived(0),
|
||||||
_lastEchoRequestReceived(0),
|
_lastEchoRequestReceived(0),
|
||||||
_localSocket(-1),
|
_localSocket(-1),
|
||||||
|
_latencyMean(0.0),
|
||||||
|
_latencyVariance(0.0),
|
||||||
|
_packetLossRatio(0.0),
|
||||||
|
_packetErrorRatio(0.0),
|
||||||
|
_valid(true),
|
||||||
|
_eligible(false),
|
||||||
|
_bonded(false),
|
||||||
|
_givenLinkSpeed(0),
|
||||||
|
_allocation(0),
|
||||||
_latency(0xffff),
|
_latency(0xffff),
|
||||||
_addr(),
|
_addr(),
|
||||||
_ipScope(InetAddress::IP_SCOPE_NONE)
|
_ipScope(InetAddress::IP_SCOPE_NONE)
|
||||||
|
@ -96,6 +105,15 @@ public:
|
||||||
_lastTrustEstablishedPacketReceived(0),
|
_lastTrustEstablishedPacketReceived(0),
|
||||||
_lastEchoRequestReceived(0),
|
_lastEchoRequestReceived(0),
|
||||||
_localSocket(localSocket),
|
_localSocket(localSocket),
|
||||||
|
_latencyMean(0.0),
|
||||||
|
_latencyVariance(0.0),
|
||||||
|
_packetLossRatio(0.0),
|
||||||
|
_packetErrorRatio(0.0),
|
||||||
|
_valid(true),
|
||||||
|
_eligible(false),
|
||||||
|
_bonded(false),
|
||||||
|
_givenLinkSpeed(0),
|
||||||
|
_allocation(0),
|
||||||
_latency(0xffff),
|
_latency(0xffff),
|
||||||
_addr(addr),
|
_addr(addr),
|
||||||
_ipScope(addr.ipScope())
|
_ipScope(addr.ipScope())
|
||||||
|
@ -300,6 +318,17 @@ public:
|
||||||
*/
|
*/
|
||||||
inline unsigned int packetErrorRatio() const { return _packetErrorRatio; }
|
inline unsigned int packetErrorRatio() const { return _packetErrorRatio; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Whether this path is valid as reported by the bonding layer. The bonding layer
|
||||||
|
* actually checks with Phy to see if the interface is still up
|
||||||
|
*/
|
||||||
|
inline unsigned int valid() const { return _valid; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Whether this path is eligible for use in a bond as reported by the bonding layer
|
||||||
|
*/
|
||||||
|
inline unsigned int eligible() const { return _eligible; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Whether this path is bonded as reported by the bonding layer
|
* @return Whether this path is bonded as reported by the bonding layer
|
||||||
*/
|
*/
|
||||||
|
@ -313,27 +342,36 @@ public:
|
||||||
/**
|
/**
|
||||||
* @return Traffic allocation as reported by the bonding layer
|
* @return Traffic allocation as reported by the bonding layer
|
||||||
*/
|
*/
|
||||||
inline unsigned int allocation() const { return _allocation; }
|
inline unsigned char allocation() const { return _allocation; }
|
||||||
|
|
||||||
void *_bondingMetricPtr;
|
/**
|
||||||
|
* @return Physical interface name that this path lives on
|
||||||
|
*/
|
||||||
|
char *ifname() {
|
||||||
|
return _ifname;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
char _ifname[ZT_MAX_PHYSIFNAME] = { };
|
||||||
|
|
||||||
volatile int64_t _lastOut;
|
volatile int64_t _lastOut;
|
||||||
volatile int64_t _lastIn;
|
volatile int64_t _lastIn;
|
||||||
volatile int64_t _lastTrustEstablishedPacketReceived;
|
volatile int64_t _lastTrustEstablishedPacketReceived;
|
||||||
|
|
||||||
|
int64_t _lastEchoRequestReceived;
|
||||||
|
|
||||||
|
int64_t _localSocket;
|
||||||
|
|
||||||
volatile float _latencyMean;
|
volatile float _latencyMean;
|
||||||
volatile float _latencyVariance;
|
volatile float _latencyVariance;
|
||||||
volatile float _packetLossRatio;
|
volatile float _packetLossRatio;
|
||||||
volatile float _packetErrorRatio;
|
volatile float _packetErrorRatio;
|
||||||
|
volatile bool _valid;
|
||||||
|
volatile bool _eligible;
|
||||||
volatile bool _bonded;
|
volatile bool _bonded;
|
||||||
volatile int64_t _givenLinkSpeed;
|
volatile uint32_t _givenLinkSpeed;
|
||||||
volatile int8_t _allocation;
|
volatile uint8_t _allocation;
|
||||||
|
|
||||||
int64_t _lastEchoRequestReceived;
|
|
||||||
|
|
||||||
int64_t _localSocket;
|
|
||||||
|
|
||||||
volatile unsigned int _latency;
|
volatile unsigned int _latency;
|
||||||
InetAddress _addr;
|
InetAddress _addr;
|
||||||
|
|
44
one.cpp
44
one.cpp
|
@ -611,41 +611,49 @@ static int cli(int argc,char **argv)
|
||||||
} else {
|
} else {
|
||||||
int numAliveLinks = OSUtils::jsonInt(j["numAliveLinks"],0);
|
int numAliveLinks = OSUtils::jsonInt(j["numAliveLinks"],0);
|
||||||
int numTotalLinks = OSUtils::jsonInt(j["numTotalLinks"],0);
|
int numTotalLinks = OSUtils::jsonInt(j["numTotalLinks"],0);
|
||||||
printf("Peer : %s\n", arg1.c_str());
|
printf("Peer : %s\n", arg1.c_str());
|
||||||
printf("Bond : %s\n", OSUtils::jsonString(j["bondingPolicy"],"-").c_str());
|
printf("Bond : %s\n", OSUtils::jsonString(j["bondingPolicyStr"],"-").c_str());
|
||||||
printf("Link Select Method : %d\n", (int)OSUtils::jsonInt(j["linkSelectMethod"],0));
|
printf("Link Select Method : %d\n", (int)OSUtils::jsonInt(j["linkSelectMethod"],0));
|
||||||
printf("Links : %d/%d\n", numAliveLinks, numTotalLinks);
|
printf("Links : %d/%d\n", numAliveLinks, numTotalLinks);
|
||||||
printf("Failover Interval : %d (ms)\n", (int)OSUtils::jsonInt(j["failoverInterval"],0));
|
printf("Failover Interval (ms) : %d\n", (int)OSUtils::jsonInt(j["failoverInterval"],0));
|
||||||
printf("Up Delay : %d (ms)\n", (int)OSUtils::jsonInt(j["upDelay"],0));
|
printf("Up Delay (ms) : %d\n", (int)OSUtils::jsonInt(j["upDelay"],0));
|
||||||
printf("Down Delay : %d (ms)\n", (int)OSUtils::jsonInt(j["downDelay"],0));
|
printf("Down Delay (ms) : %d\n", (int)OSUtils::jsonInt(j["downDelay"],0));
|
||||||
printf("Packets Per Link : %d (ms)\n", (int)OSUtils::jsonInt(j["packetsPerLink"],0));
|
printf("Packets Per Link : %d\n", (int)OSUtils::jsonInt(j["packetsPerLink"],0));
|
||||||
nlohmann::json &p = j["links"];
|
nlohmann::json &p = j["paths"];
|
||||||
if (p.is_array()) {
|
if (p.is_array()) {
|
||||||
printf("\n interface\t\t\t\t\t path\n");
|
printf("\nidx"
|
||||||
for(int i=0; i<80; i++) { printf("-"); }
|
" interface"
|
||||||
|
" "
|
||||||
|
"path socket\n");
|
||||||
|
for(int i=0; i<100; i++) { printf("-"); }
|
||||||
printf("\n");
|
printf("\n");
|
||||||
for (int i=0; i<p.size(); i++)
|
for (int i=0; i<p.size(); i++)
|
||||||
{
|
{
|
||||||
printf("[%3d] %21s %50s\n",
|
printf("%2d: %26s %51s %.16llx\n",
|
||||||
i,
|
i,
|
||||||
OSUtils::jsonString(p[i]["ifname"],"-").c_str(),
|
OSUtils::jsonString(p[i]["ifname"],"-").c_str(),
|
||||||
OSUtils::jsonString(p[i]["path"],"-").c_str()
|
OSUtils::jsonString(p[i]["address"],"-").c_str(),
|
||||||
|
(unsigned long long)OSUtils::jsonInt(p[i]["localSocket"],0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
printf("\n lat pdv plr per speed alloc alive bonded\n");
|
printf("\nidx lat pdv "
|
||||||
for(int i=0; i<80; i++) { printf("-"); }
|
"plr per speed alloc "
|
||||||
|
"rx_age tx_age eligible bonded\n");
|
||||||
|
for(int i=0; i<100; i++) { printf("-"); }
|
||||||
printf("\n");
|
printf("\n");
|
||||||
for (int i=0; i<p.size(); i++)
|
for (int i=0; i<p.size(); i++)
|
||||||
{
|
{
|
||||||
printf("[%3d] %7.2f %7.2f %6.2f %6.2f %8d %9d %8d %8d\n",
|
printf("%2d: %8.2f %8.2f %7.4f %7.4f %7d %6.2f %11d %11d %9d %7d\n",
|
||||||
i,
|
i,
|
||||||
OSUtils::jsonDouble(p[i]["latencyMean"], 0),
|
OSUtils::jsonDouble(p[i]["latencyMean"], 0),
|
||||||
OSUtils::jsonDouble(p[i]["latencyVariance"], 0),
|
OSUtils::jsonDouble(p[i]["latencyVariance"], 0),
|
||||||
OSUtils::jsonDouble(p[i]["packetLossRatio"], 0),
|
OSUtils::jsonDouble(p[i]["packetLossRatio"], 0),
|
||||||
OSUtils::jsonDouble(p[i]["packetErrorRatio"], 0),
|
OSUtils::jsonDouble(p[i]["packetErrorRatio"], 0),
|
||||||
(int)OSUtils::jsonInt(p[i]["givenLinkSpeed"], 0),
|
(int)OSUtils::jsonInt(p[i]["givenLinkSpeed"], 0),
|
||||||
(int)OSUtils::jsonInt(p[i]["allocation"], 0),
|
OSUtils::jsonDouble(p[i]["allocation"], 0),
|
||||||
(int)OSUtils::jsonInt(p[i]["alive"],0),
|
(int)OSUtils::jsonInt(p[i]["lastInAge"], 0),
|
||||||
|
(int)OSUtils::jsonInt(p[i]["lastOutAge"], 0),
|
||||||
|
(int)OSUtils::jsonInt(p[i]["eligible"],0),
|
||||||
(int)OSUtils::jsonInt(p[i]["bonded"],0));
|
(int)OSUtils::jsonInt(p[i]["bonded"],0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,9 @@
|
||||||
// Max number of bindings
|
// Max number of bindings
|
||||||
#define ZT_BINDER_MAX_BINDINGS 256
|
#define ZT_BINDER_MAX_BINDINGS 256
|
||||||
|
|
||||||
|
// Maximum physical interface name length. This number is gigantic because of Windows.
|
||||||
|
#define ZT_MAX_PHYSIFNAME 256
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,6 +91,7 @@ class Binder {
|
||||||
PhySocket* udpSock;
|
PhySocket* udpSock;
|
||||||
PhySocket* tcpListenSock;
|
PhySocket* tcpListenSock;
|
||||||
InetAddress address;
|
InetAddress address;
|
||||||
|
char ifname[256] = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -443,7 +447,7 @@ class Binder {
|
||||||
_bindings[_bindingCount].udpSock = udps;
|
_bindings[_bindingCount].udpSock = udps;
|
||||||
_bindings[_bindingCount].tcpListenSock = tcps;
|
_bindings[_bindingCount].tcpListenSock = tcps;
|
||||||
_bindings[_bindingCount].address = ii->first;
|
_bindings[_bindingCount].address = ii->first;
|
||||||
phy.setIfName(udps, (char*)ii->second.c_str(), (int)ii->second.length());
|
memcpy(_bindings[_bindingCount].ifname, (char*)ii->second.c_str(), (int)ii->second.length());
|
||||||
++_bindingCount;
|
++_bindingCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -514,6 +518,22 @@ class Binder {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
void getIfName(PhySocket* s, char* nameBuf, int buflen) const
|
||||||
|
{
|
||||||
|
Mutex::Lock _l(_lock);
|
||||||
|
for (unsigned int b = 0, c = _bindingCount; b < c; ++b) {
|
||||||
|
if (_bindings[b].udpSock == s) {
|
||||||
|
memcpy(nameBuf, _bindings[b].ifname, buflen);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
_Binding _bindings[ZT_BINDER_MAX_BINDINGS];
|
_Binding _bindings[ZT_BINDER_MAX_BINDINGS];
|
||||||
std::atomic<unsigned int> _bindingCount;
|
std::atomic<unsigned int> _bindingCount;
|
||||||
|
|
|
@ -140,12 +140,11 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PhySocketImpl {
|
struct PhySocketImpl {
|
||||||
PhySocketImpl() { memset(ifname, 0, sizeof(ifname)); }
|
PhySocketImpl() {}
|
||||||
PhySocketType type;
|
PhySocketType type;
|
||||||
ZT_PHY_SOCKFD_TYPE sock;
|
ZT_PHY_SOCKFD_TYPE sock;
|
||||||
void *uptr; // user-settable pointer
|
void *uptr; // user-settable pointer
|
||||||
ZT_PHY_SOCKADDR_STORAGE_TYPE saddr; // remote for TCP_OUT and TCP_IN, local for TCP_LISTEN, RAW, and UDP
|
ZT_PHY_SOCKADDR_STORAGE_TYPE saddr; // remote for TCP_OUT and TCP_IN, local for TCP_LISTEN, RAW, and UDP
|
||||||
char ifname[256 + 4];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::list<PhySocketImpl> _socks;
|
std::list<PhySocketImpl> _socks;
|
||||||
|
@ -243,38 +242,6 @@ public:
|
||||||
return &(reinterpret_cast<PhySocketImpl*>(s)->uptr);
|
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)
|
|
||||||
{
|
|
||||||
PhySocketImpl& sws = *(reinterpret_cast<PhySocketImpl*>(s));
|
|
||||||
if (sws.type == ZT_PHY_SOCKET_CLOSED) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (s) {
|
|
||||||
memcpy(nameBuf, reinterpret_cast<PhySocketImpl*>(s)->ifname, buflen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param s Socket object
|
|
||||||
* @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)
|
|
||||||
{
|
|
||||||
PhySocketImpl& sws = *(reinterpret_cast<PhySocketImpl*>(s));
|
|
||||||
if (sws.type == ZT_PHY_SOCKET_CLOSED) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (s) {
|
|
||||||
memcpy(&(reinterpret_cast<PhySocketImpl*>(s)->ifname), ifname, len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cause poll() to stop waiting immediately
|
* Cause poll() to stop waiting immediately
|
||||||
*
|
*
|
||||||
|
|
|
@ -520,7 +520,7 @@ static void _networkToJson(nlohmann::json &nj,NetworkState &ns)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer)
|
static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer, SharedPtr<Bond> &bond)
|
||||||
{
|
{
|
||||||
char tmp[256];
|
char tmp[256];
|
||||||
|
|
||||||
|
@ -541,10 +541,15 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer)
|
||||||
pj["latency"] = peer->latency;
|
pj["latency"] = peer->latency;
|
||||||
pj["role"] = prole;
|
pj["role"] = prole;
|
||||||
pj["isBonded"] = peer->isBonded;
|
pj["isBonded"] = peer->isBonded;
|
||||||
if (peer->isBonded) {
|
if (bond && peer->isBonded) {
|
||||||
pj["bondingPolicy"] = peer->bondingPolicy;
|
pj["bondingPolicyCode"] = peer->bondingPolicy;
|
||||||
|
pj["bondingPolicyStr"] = Bond::getPolicyStrByCode(peer->bondingPolicy);
|
||||||
pj["numAliveLinks"] = peer->numAliveLinks;
|
pj["numAliveLinks"] = peer->numAliveLinks;
|
||||||
pj["numTotalLinks"] = peer->numTotalLinks;
|
pj["numTotalLinks"] = peer->numTotalLinks;
|
||||||
|
pj["failoverInterval"] = bond->getFailoverInterval();
|
||||||
|
pj["downDelay"] = bond->getDownDelay();
|
||||||
|
pj["upDelay"] = bond->getUpDelay();
|
||||||
|
pj["packetsPerLink"] = bond->getPacketsPerLink();
|
||||||
}
|
}
|
||||||
|
|
||||||
nlohmann::json pa = nlohmann::json::array();
|
nlohmann::json pa = nlohmann::json::array();
|
||||||
|
@ -560,56 +565,25 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer)
|
||||||
j["expired"] = (bool)(peer->paths[i].expired != 0);
|
j["expired"] = (bool)(peer->paths[i].expired != 0);
|
||||||
j["preferred"] = (bool)(peer->paths[i].preferred != 0);
|
j["preferred"] = (bool)(peer->paths[i].preferred != 0);
|
||||||
j["localSocket"] = peer->paths[i].localSocket;
|
j["localSocket"] = peer->paths[i].localSocket;
|
||||||
|
if (bond && peer->isBonded) {
|
||||||
|
uint64_t now = OSUtils::now();
|
||||||
|
j["ifname"] = std::string(peer->paths[i].ifname);
|
||||||
|
j["latencyMean"] = peer->paths[i].latencyMean;
|
||||||
|
j["latencyVariance"] = peer->paths[i].latencyVariance;
|
||||||
|
j["packetLossRatio"] = peer->paths[i].packetLossRatio;
|
||||||
|
j["packetErrorRatio"] = peer->paths[i].packetErrorRatio;
|
||||||
|
j["lastInAge"] = (now - lastReceive);
|
||||||
|
j["lastOutAge"] = (now - lastSend);
|
||||||
|
j["bonded"] = peer->paths[i].bonded;
|
||||||
|
j["eligible"] = peer->paths[i].eligible;
|
||||||
|
j["givenLinkSpeed"] = peer->paths[i].linkSpeed;
|
||||||
|
j["allocation"] = std::round(((float)(peer->paths[i].allocation) / 255.0) * 1000.0) / 1000.0;
|
||||||
|
}
|
||||||
pa.push_back(j);
|
pa.push_back(j);
|
||||||
}
|
}
|
||||||
pj["paths"] = pa;
|
pj["paths"] = pa;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _bondToJson(nlohmann::json &pj, SharedPtr<Bond> &bond)
|
|
||||||
{
|
|
||||||
uint64_t now = OSUtils::now();
|
|
||||||
|
|
||||||
int bondingPolicy = bond->policy();
|
|
||||||
pj["bondingPolicy"] = Bond::getPolicyStrByCode(bondingPolicy);
|
|
||||||
if (bondingPolicy == ZT_BOND_POLICY_NONE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pj["numAliveLinks"] = bond->getNumAliveLinks();
|
|
||||||
pj["numTotalLinks"] = bond->getNumTotalLinks();
|
|
||||||
pj["failoverInterval"] = bond->getFailoverInterval();
|
|
||||||
pj["downDelay"] = bond->getDownDelay();
|
|
||||||
pj["upDelay"] = bond->getUpDelay();
|
|
||||||
if (bondingPolicy == ZT_BOND_POLICY_BALANCE_RR) {
|
|
||||||
pj["packetsPerLink"] = bond->getPacketsPerLink();
|
|
||||||
}
|
|
||||||
if (bondingPolicy == ZT_BOND_POLICY_ACTIVE_BACKUP) {
|
|
||||||
pj["linkSelectMethod"] = bond->getLinkSelectMethod();
|
|
||||||
}
|
|
||||||
|
|
||||||
nlohmann::json pa = nlohmann::json::array();
|
|
||||||
std::vector< SharedPtr<Path> > paths = bond->paths(now);
|
|
||||||
|
|
||||||
for(unsigned int i=0;i<paths.size();++i) {
|
|
||||||
char pathStr[128];
|
|
||||||
paths[i]->address().toString(pathStr);
|
|
||||||
|
|
||||||
nlohmann::json j;
|
|
||||||
j["ifname"] = bond->getLink(paths[i])->ifname();
|
|
||||||
j["path"] = pathStr;
|
|
||||||
j["latencyMean"] = paths[i]->latencyMean();
|
|
||||||
j["latencyVariance"] = paths[i]->latencyVariance();
|
|
||||||
j["packetLossRatio"] = paths[i]->packetLossRatio();
|
|
||||||
j["packetErrorRatio"] = paths[i]->packetErrorRatio();
|
|
||||||
j["alive"] = paths[i]->alive(now);
|
|
||||||
j["bonded"] = paths[i]->bonded();
|
|
||||||
j["givenLinkSpeed"] = paths[i]->givenLinkSpeed();
|
|
||||||
j["allocation"] = paths[i]->allocation();
|
|
||||||
pa.push_back(j);
|
|
||||||
}
|
|
||||||
pj["links"] = pa;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _moonToJson(nlohmann::json &mj,const World &world)
|
static void _moonToJson(nlohmann::json &mj,const World &world)
|
||||||
{
|
{
|
||||||
char tmp[4096];
|
char tmp[4096];
|
||||||
|
@ -1496,23 +1470,28 @@ public:
|
||||||
if (ps[0] == "bond") {
|
if (ps[0] == "bond") {
|
||||||
if (_node->bondController()->inUse()) {
|
if (_node->bondController()->inUse()) {
|
||||||
if (ps.size() == 3) {
|
if (ps.size() == 3) {
|
||||||
//fprintf(stderr, "ps[0]=%s\nps[1]=%s\nps[2]=%s\n", ps[0].c_str(), ps[1].c_str(), ps[2].c_str());
|
|
||||||
if (ps[2].length() == 10) {
|
if (ps[2].length() == 10) {
|
||||||
// check if hex string
|
// check if hex string
|
||||||
const uint64_t id = Utils::hexStrToU64(ps[2].c_str());
|
|
||||||
if (ps[1] == "show") {
|
ZT_PeerList *pl = _node->peers();
|
||||||
SharedPtr<Bond> bond = _node->bondController()->getBondByPeerId(id);
|
if (pl) {
|
||||||
if (bond) {
|
uint64_t wantp = Utils::hexStrToU64(ps[2].c_str());
|
||||||
_bondToJson(res,bond);
|
for(unsigned long i=0;i<pl->peerCount;++i) {
|
||||||
scode = 200;
|
if (pl->peers[i].address == wantp) {
|
||||||
} else {
|
if (ps[1] == "show") {
|
||||||
fprintf(stderr, "unable to find bond to peer %llx\n", (unsigned long long)id);
|
SharedPtr<Bond> bond = _node->bondController()->getBondByPeerId(wantp);
|
||||||
scode = 400;
|
if (bond) {
|
||||||
|
_peerToJson(res,&(pl->peers[i]),bond);
|
||||||
|
scode = 200;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "unable to find bond to peer %llx\n", (unsigned long long)wantp);
|
||||||
|
scode = 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ps[1] == "flows") {
|
_node->freeQueryResult((void *)pl);
|
||||||
fprintf(stderr, "displaying flows\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1635,36 +1614,12 @@ public:
|
||||||
res = nlohmann::json::array();
|
res = nlohmann::json::array();
|
||||||
for(unsigned long i=0;i<pl->peerCount;++i) {
|
for(unsigned long i=0;i<pl->peerCount;++i) {
|
||||||
nlohmann::json pj;
|
nlohmann::json pj;
|
||||||
_peerToJson(pj,&(pl->peers[i]));
|
SharedPtr<Bond> bond = SharedPtr<Bond>();
|
||||||
res.push_back(pj);
|
if (pl->peers[i].isBonded) {
|
||||||
}
|
const uint64_t id = pl->peers[i].address;
|
||||||
|
bond = _node->bondController()->getBondByPeerId(id);
|
||||||
scode = 200;
|
|
||||||
} else if (ps.size() == 2) {
|
|
||||||
// Return a single peer by ID or 404 if not found
|
|
||||||
|
|
||||||
uint64_t wantp = Utils::hexStrToU64(ps[1].c_str());
|
|
||||||
for(unsigned long i=0;i<pl->peerCount;++i) {
|
|
||||||
if (pl->peers[i].address == wantp) {
|
|
||||||
_peerToJson(res,&(pl->peers[i]));
|
|
||||||
scode = 200;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
_peerToJson(pj,&(pl->peers[i]),bond);
|
||||||
|
|
||||||
} else scode = 404;
|
|
||||||
_node->freeQueryResult((void *)pl);
|
|
||||||
} else scode = 500;
|
|
||||||
} else if (ps[0] == "bonds") {
|
|
||||||
ZT_PeerList *pl = _node->peers();
|
|
||||||
if (pl) {
|
|
||||||
if (ps.size() == 1) {
|
|
||||||
// Return [array] of all peers
|
|
||||||
|
|
||||||
res = nlohmann::json::array();
|
|
||||||
for(unsigned long i=0;i<pl->peerCount;++i) {
|
|
||||||
nlohmann::json pj;
|
|
||||||
_peerToJson(pj,&(pl->peers[i]));
|
|
||||||
res.push_back(pj);
|
res.push_back(pj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1675,7 +1630,11 @@ public:
|
||||||
uint64_t wantp = Utils::hexStrToU64(ps[1].c_str());
|
uint64_t wantp = Utils::hexStrToU64(ps[1].c_str());
|
||||||
for(unsigned long i=0;i<pl->peerCount;++i) {
|
for(unsigned long i=0;i<pl->peerCount;++i) {
|
||||||
if (pl->peers[i].address == wantp) {
|
if (pl->peers[i].address == wantp) {
|
||||||
_peerToJson(res,&(pl->peers[i]));
|
SharedPtr<Bond> bond = SharedPtr<Bond>();
|
||||||
|
if (pl->peers[i].isBonded) {
|
||||||
|
bond = _node->bondController()->getBondByPeerId(wantp);
|
||||||
|
}
|
||||||
|
_peerToJson(res,&(pl->peers[i]),bond);
|
||||||
scode = 200;
|
scode = 200;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1769,11 +1728,11 @@ public:
|
||||||
if (ps[0] == "bond") {
|
if (ps[0] == "bond") {
|
||||||
if (_node->bondController()->inUse()) {
|
if (_node->bondController()->inUse()) {
|
||||||
if (ps.size() == 3) {
|
if (ps.size() == 3) {
|
||||||
//fprintf(stderr, "ps[0]=%s\nps[1]=%s\nps[2]=%s\n", ps[0].c_str(), ps[1].c_str(), ps[2].c_str());
|
|
||||||
if (ps[2].length() == 10) {
|
if (ps[2].length() == 10) {
|
||||||
// check if hex string
|
// check if hex string
|
||||||
const uint64_t id = Utils::hexStrToU64(ps[2].c_str());
|
const uint64_t id = Utils::hexStrToU64(ps[2].c_str());
|
||||||
if (ps[1] == "rotate") {
|
if (ps[1] == "rotate") {
|
||||||
|
exit(0);
|
||||||
SharedPtr<Bond> bond = _node->bondController()->getBondByPeerId(id);
|
SharedPtr<Bond> bond = _node->bondController()->getBondByPeerId(id);
|
||||||
if (bond) {
|
if (bond) {
|
||||||
scode = bond->abForciblyRotateLink() ? 200 : 400;
|
scode = bond->abForciblyRotateLink() ? 200 : 400;
|
||||||
|
@ -1782,9 +1741,6 @@ public:
|
||||||
scode = 400;
|
scode = 400;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ps[1] == "enable") {
|
|
||||||
fprintf(stderr, "enabling bond\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2039,6 +1995,7 @@ public:
|
||||||
json &settings = lc["settings"];
|
json &settings = lc["settings"];
|
||||||
|
|
||||||
if (!_node->bondController()->inUse()) {
|
if (!_node->bondController()->inUse()) {
|
||||||
|
_node->bondController()->setBinder(&_binder);
|
||||||
// defaultBondingPolicy
|
// defaultBondingPolicy
|
||||||
std::string defaultBondingPolicyStr(OSUtils::jsonString(settings["defaultBondingPolicy"],""));
|
std::string defaultBondingPolicyStr(OSUtils::jsonString(settings["defaultBondingPolicy"],""));
|
||||||
int defaultBondingPolicy = _node->bondController()->getPolicyCodeByStr(defaultBondingPolicyStr);
|
int defaultBondingPolicy = _node->bondController()->getPolicyCodeByStr(defaultBondingPolicyStr);
|
||||||
|
@ -2073,7 +2030,6 @@ public:
|
||||||
newTemplateBond->setMaxAcceptablePacketDelayVariance(OSUtils::jsonInt(customPolicy["maxAcceptablePacketDelayVariance"],-1));
|
newTemplateBond->setMaxAcceptablePacketDelayVariance(OSUtils::jsonInt(customPolicy["maxAcceptablePacketDelayVariance"],-1));
|
||||||
newTemplateBond->setMaxAcceptablePacketLossRatio((float)OSUtils::jsonDouble(customPolicy["maxAcceptablePacketLossRatio"],-1));
|
newTemplateBond->setMaxAcceptablePacketLossRatio((float)OSUtils::jsonDouble(customPolicy["maxAcceptablePacketLossRatio"],-1));
|
||||||
newTemplateBond->setMaxAcceptablePacketErrorRatio((float)OSUtils::jsonDouble(customPolicy["maxAcceptablePacketErrorRatio"],-1));
|
newTemplateBond->setMaxAcceptablePacketErrorRatio((float)OSUtils::jsonDouble(customPolicy["maxAcceptablePacketErrorRatio"],-1));
|
||||||
newTemplateBond->setMinAcceptableAllocation((float)OSUtils::jsonDouble(customPolicy["minAcceptableAllocation"],0));
|
|
||||||
// Quality weights
|
// Quality weights
|
||||||
json &qualityWeights = customPolicy["qualityWeights"];
|
json &qualityWeights = customPolicy["qualityWeights"];
|
||||||
if (qualityWeights.size() == ZT_QOS_WEIGHT_SIZE) {
|
if (qualityWeights.size() == ZT_QOS_WEIGHT_SIZE) {
|
||||||
|
@ -2088,7 +2044,6 @@ public:
|
||||||
// Bond-specific properties
|
// Bond-specific properties
|
||||||
newTemplateBond->setUpDelay(OSUtils::jsonInt(customPolicy["upDelay"],-1));
|
newTemplateBond->setUpDelay(OSUtils::jsonInt(customPolicy["upDelay"],-1));
|
||||||
newTemplateBond->setDownDelay(OSUtils::jsonInt(customPolicy["downDelay"],-1));
|
newTemplateBond->setDownDelay(OSUtils::jsonInt(customPolicy["downDelay"],-1));
|
||||||
newTemplateBond->setFlowRebalanceStrategy(OSUtils::jsonInt(customPolicy["flowRebalanceStrategy"],(uint64_t)0));
|
|
||||||
newTemplateBond->setFailoverInterval(OSUtils::jsonInt(customPolicy["failoverInterval"],ZT_BOND_FAILOVER_DEFAULT_INTERVAL));
|
newTemplateBond->setFailoverInterval(OSUtils::jsonInt(customPolicy["failoverInterval"],ZT_BOND_FAILOVER_DEFAULT_INTERVAL));
|
||||||
newTemplateBond->setPacketsPerLink(OSUtils::jsonInt(customPolicy["packetsPerLink"],-1));
|
newTemplateBond->setPacketsPerLink(OSUtils::jsonInt(customPolicy["packetsPerLink"],-1));
|
||||||
|
|
||||||
|
@ -2097,16 +2052,8 @@ public:
|
||||||
for (json::iterator linkItr = links.begin(); linkItr != links.end();++linkItr) {
|
for (json::iterator linkItr = links.begin(); linkItr != links.end();++linkItr) {
|
||||||
std::string linkNameStr(linkItr.key());
|
std::string linkNameStr(linkItr.key());
|
||||||
json &link = linkItr.value();
|
json &link = linkItr.value();
|
||||||
|
|
||||||
bool enabled = OSUtils::jsonInt(link["enabled"],true);
|
bool enabled = OSUtils::jsonInt(link["enabled"],true);
|
||||||
uint32_t speed = OSUtils::jsonInt(link["speed"],0);
|
uint32_t speed = OSUtils::jsonInt(link["speed"],0);
|
||||||
float alloc = (float)OSUtils::jsonDouble(link["alloc"],0);
|
|
||||||
|
|
||||||
if (speed && alloc) {
|
|
||||||
fprintf(stderr, "error: cannot specify both speed (%d) and alloc (%f) for link (%s), pick one, link disabled.\n",
|
|
||||||
speed, alloc, linkNameStr.c_str());
|
|
||||||
enabled = false;
|
|
||||||
}
|
|
||||||
uint8_t ipvPref = OSUtils::jsonInt(link["ipvPref"],0);
|
uint8_t ipvPref = OSUtils::jsonInt(link["ipvPref"],0);
|
||||||
std::string failoverToStr(OSUtils::jsonString(link["failoverTo"],""));
|
std::string failoverToStr(OSUtils::jsonString(link["failoverTo"],""));
|
||||||
// Mode
|
// Mode
|
||||||
|
@ -2124,7 +2071,7 @@ public:
|
||||||
failoverToStr = "";
|
failoverToStr = "";
|
||||||
enabled = false;
|
enabled = false;
|
||||||
}
|
}
|
||||||
_node->bondController()->addCustomLink(customPolicyStr, new Link(linkNameStr,ipvPref,speed,enabled,linkMode,failoverToStr,alloc));
|
_node->bondController()->addCustomLink(customPolicyStr, new Link(linkNameStr,ipvPref,speed,enabled,linkMode,failoverToStr));
|
||||||
}
|
}
|
||||||
std::string linkSelectMethodStr(OSUtils::jsonString(customPolicy["activeReselect"],"optimize"));
|
std::string linkSelectMethodStr(OSUtils::jsonString(customPolicy["activeReselect"],"optimize"));
|
||||||
if (linkSelectMethodStr == "always") {
|
if (linkSelectMethodStr == "always") {
|
||||||
|
@ -2142,12 +2089,6 @@ public:
|
||||||
if (newTemplateBond->getLinkSelectMethod() < 0 || newTemplateBond->getLinkSelectMethod() > 3) {
|
if (newTemplateBond->getLinkSelectMethod() < 0 || newTemplateBond->getLinkSelectMethod() > 3) {
|
||||||
fprintf(stderr, "warning: invalid value (%s) for linkSelectMethod, assuming mode: always\n", linkSelectMethodStr.c_str());
|
fprintf(stderr, "warning: invalid value (%s) for linkSelectMethod, assuming mode: always\n", linkSelectMethodStr.c_str());
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
newBond->setPolicy(_node->bondController()->getPolicyCodeByStr(basePolicyStr));
|
|
||||||
newBond->setFlowHashing((bool)OSUtils::jsonInt(userSpecifiedBondingPolicies[i]["allowFlowHashing"],(bool)allowFlowHashing));
|
|
||||||
newBond->setBondMonitorInterval((unsigned int)OSUtils::jsonInt(userSpecifiedBondingPolicies[i]["monitorInterval"],(uint64_t)0));
|
|
||||||
newBond->setAllowPathNegotiation((bool)OSUtils::jsonInt(userSpecifiedBondingPolicies[i]["allowPathNegotiation"],(bool)false));
|
|
||||||
*/
|
|
||||||
if (!_node->bondController()->addCustomPolicy(newTemplateBond)) {
|
if (!_node->bondController()->addCustomPolicy(newTemplateBond)) {
|
||||||
fprintf(stderr, "error: a custom policy of this name (%s) already exists.\n", customPolicyStr.c_str());
|
fprintf(stderr, "error: a custom policy of this name (%s) already exists.\n", customPolicyStr.c_str());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue