GitHub issue #191 - kill intra-network multicast rate limits (which were not well supported or easily configurable anyway) -- this is really left over from the old collaborative multicast propagation algorithm. New algorithm (in for a while) has been sender-side replication in which sender "pays" all bandwidth, which intrinsically limits multicast.

This commit is contained in:
Adam Ierymenko 2015-06-26 12:36:45 -07:00
parent c287ae4d1d
commit 57c7992c78
10 changed files with 4 additions and 140 deletions

View File

@ -155,7 +155,6 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) :
||(sqlite3_prepare_v2(_db,"UPDATE Node SET lastAt = ?,lastSeen = ? WHERE id = ?",-1,&_sUpdateNode,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"UPDATE Node SET lastAt = ?,lastSeen = ? WHERE id = ?",-1,&_sUpdateNode,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"UPDATE Node SET lastSeen = ? WHERE id = ?",-1,&_sUpdateNode2,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"UPDATE Node SET lastSeen = ? WHERE id = ?",-1,&_sUpdateNode2,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"SELECT etherType FROM Rule WHERE networkId = ? AND \"action\" = 'accept'",-1,&_sGetEtherTypesFromRuleTable,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT etherType FROM Rule WHERE networkId = ? AND \"action\" = 'accept'",-1,&_sGetEtherTypesFromRuleTable,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"SELECT mgMac,mgAdi,preload,maxBalance,accrual FROM MulticastRate WHERE networkId = ?",-1,&_sGetMulticastRates,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"SELECT nodeId FROM Member WHERE networkId = ? AND activeBridge > 0 AND authorized > 0",-1,&_sGetActiveBridges,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT nodeId FROM Member WHERE networkId = ? AND activeBridge > 0 AND authorized > 0",-1,&_sGetActiveBridges,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"SELECT ip,ipNetmaskBits FROM IpAssignment WHERE networkId = ? AND nodeId = ? AND ipVersion = ?",-1,&_sGetIpAssignmentsForNode,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT ip,ipNetmaskBits FROM IpAssignment WHERE networkId = ? AND nodeId = ? AND ipVersion = ?",-1,&_sGetIpAssignmentsForNode,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"SELECT ipNetwork,ipNetmaskBits FROM IpAssignmentPool WHERE networkId = ? AND ipVersion = ?",-1,&_sGetIpAssignmentPools,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT ipNetwork,ipNetmaskBits FROM IpAssignmentPool WHERE networkId = ? AND ipVersion = ?",-1,&_sGetIpAssignmentPools,(const char **)0) != SQLITE_OK)
@ -204,7 +203,6 @@ SqliteNetworkController::~SqliteNetworkController()
sqlite3_finalize(_sUpdateNode); sqlite3_finalize(_sUpdateNode);
sqlite3_finalize(_sUpdateNode2); sqlite3_finalize(_sUpdateNode2);
sqlite3_finalize(_sGetEtherTypesFromRuleTable); sqlite3_finalize(_sGetEtherTypesFromRuleTable);
sqlite3_finalize(_sGetMulticastRates);
sqlite3_finalize(_sGetActiveBridges); sqlite3_finalize(_sGetActiveBridges);
sqlite3_finalize(_sGetIpAssignmentsForNode); sqlite3_finalize(_sGetIpAssignmentsForNode);
sqlite3_finalize(_sGetIpAssignmentPools); sqlite3_finalize(_sGetIpAssignmentPools);
@ -403,26 +401,10 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co
netconf[ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES] = allowedEtherTypesCsv; netconf[ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES] = allowedEtherTypesCsv;
} }
{ if (network.multicastLimit > 0) {
std::string multicastRates; char ml[16];
sqlite3_reset(_sGetMulticastRates); Utils::snprintf(ml,sizeof(ml),"%lx",(unsigned long)network.multicastLimit);
sqlite3_bind_text(_sGetMulticastRates,1,network.id,16,SQLITE_STATIC); netconf[ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT] = ml;
while (sqlite3_step(_sGetMulticastRates) == SQLITE_ROW) {
const char *mac = (const char *)sqlite3_column_text(_sGetMulticastRates,0);
if ((mac)&&(strlen(mac) == 12)) {
unsigned long adi = ((unsigned long)sqlite3_column_int64(_sGetMulticastRates,1)) & 0xffffffff;
char tmp[256];
Utils::snprintf(tmp,sizeof(tmp),"%s/%.4lx=%x,%x,%x\n",mac,adi,sqlite3_column_int(_sGetMulticastRates,2),sqlite3_column_int(_sGetMulticastRates,3),sqlite3_column_int(_sGetMulticastRates,4));
multicastRates.append(tmp);
}
}
if (multicastRates.length() > 0)
netconf[ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES] = multicastRates;
if (network.multicastLimit > 0) {
char ml[16];
Utils::snprintf(ml,sizeof(ml),"%lx",(unsigned long)network.multicastLimit);
netconf[ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT] = ml;
}
} }
{ {

View File

@ -99,7 +99,6 @@ private:
sqlite3_stmt *_sUpdateNode; sqlite3_stmt *_sUpdateNode;
sqlite3_stmt *_sUpdateNode2; sqlite3_stmt *_sUpdateNode2;
sqlite3_stmt *_sGetEtherTypesFromRuleTable; sqlite3_stmt *_sGetEtherTypesFromRuleTable;
sqlite3_stmt *_sGetMulticastRates;
sqlite3_stmt *_sGetActiveBridges; sqlite3_stmt *_sGetActiveBridges;
sqlite3_stmt *_sGetIpAssignmentsForNode; sqlite3_stmt *_sGetIpAssignmentsForNode;
sqlite3_stmt *_sGetIpAssignmentPools; sqlite3_stmt *_sGetIpAssignmentPools;

View File

@ -64,17 +64,6 @@ CREATE TABLE Member (
CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge); CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);
CREATE TABLE MulticastRate (
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
mgMac char(12) NOT NULL,
mgAdi integer NOT NULL DEFAULT(0),
preload integer NOT NULL,
maxBalance integer NOT NULL,
accrual integer NOT NULL
);
CREATE INDEX MulticastRate_networkId ON MulticastRate (networkId);
CREATE TABLE Relay ( CREATE TABLE Relay (
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE, nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,

View File

@ -65,17 +65,6 @@
"\n"\ "\n"\
"CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);\n"\ "CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);\n"\
"\n"\ "\n"\
"CREATE TABLE MulticastRate (\n"\
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
" mgMac char(12) NOT NULL,\n"\
" mgAdi integer NOT NULL DEFAULT(0),\n"\
" preload integer NOT NULL,\n"\
" maxBalance integer NOT NULL,\n"\
" accrual integer NOT NULL\n"\
");\n"\
"\n"\
"CREATE INDEX MulticastRate_networkId ON MulticastRate (networkId);\n"\
"\n"\
"CREATE TABLE Relay (\n"\ "CREATE TABLE Relay (\n"\
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ " networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
" nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\ " nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\

View File

@ -357,20 +357,6 @@ void Network::clean()
} }
} }
bool Network::updateAndCheckMulticastBalance(const MulticastGroup &mg,unsigned int bytes)
{
const uint64_t now = RR->node->now();
Mutex::Lock _l(_lock);
if (!_config)
return false;
std::map< MulticastGroup,BandwidthAccount >::iterator bal(_multicastRateAccounts.find(mg));
if (bal == _multicastRateAccounts.end()) {
NetworkConfig::MulticastRate r(_config->multicastRate(mg));
bal = _multicastRateAccounts.insert(std::pair< MulticastGroup,BandwidthAccount >(mg,BandwidthAccount(r.preload,r.maxBalance,r.accrual,now))).first;
}
return bal->second.deduct(bytes,now);
}
void Network::learnBridgeRoute(const MAC &mac,const Address &addr) void Network::learnBridgeRoute(const MAC &mac,const Address &addr)
{ {
Mutex::Lock _l(_lock); Mutex::Lock _l(_lock);

View File

@ -47,7 +47,6 @@
#include "MulticastGroup.hpp" #include "MulticastGroup.hpp"
#include "MAC.hpp" #include "MAC.hpp"
#include "Dictionary.hpp" #include "Dictionary.hpp"
#include "BandwidthAccount.hpp"
#include "Multicaster.hpp" #include "Multicaster.hpp"
#include "NetworkConfig.hpp" #include "NetworkConfig.hpp"
#include "CertificateOfMembership.hpp" #include "CertificateOfMembership.hpp"
@ -237,15 +236,6 @@ public:
_externalConfig(ec); _externalConfig(ec);
} }
/**
* Update and check multicast rate balance for a multicast group
*
* @param mg Multicast group
* @param bytes Size of packet
* @return True if packet is within budget
*/
bool updateAndCheckMulticastBalance(const MulticastGroup &mg,unsigned int bytes);
/** /**
* Get current network config or throw exception * Get current network config or throw exception
* *
@ -370,7 +360,6 @@ private:
std::vector< MulticastGroup > _myMulticastGroups; // multicast groups that we belong to including those behind us (updated periodically) std::vector< MulticastGroup > _myMulticastGroups; // multicast groups that we belong to including those behind us (updated periodically)
std::map< MulticastGroup,uint64_t > _multicastGroupsBehindMe; // multicast groups bridged to us and when we last saw activity on each std::map< MulticastGroup,uint64_t > _multicastGroupsBehindMe; // multicast groups bridged to us and when we last saw activity on each
std::map< MulticastGroup,BandwidthAccount > _multicastRateAccounts;
std::map<MAC,Address> _remoteBridgeRoutes; // remote addresses where given MACs are reachable std::map<MAC,Address> _remoteBridgeRoutes; // remote addresses where given MACs are reachable

View File

@ -32,10 +32,6 @@
namespace ZeroTier { namespace ZeroTier {
// This is fast enough for things like Apple's mDNS spam, so it should serve
// as a good default for your average network.
const NetworkConfig::MulticastRate NetworkConfig::DEFAULT_MULTICAST_RATE(40000,60000,80);
SharedPtr<NetworkConfig> NetworkConfig::createTestNetworkConfig(const Address &self) SharedPtr<NetworkConfig> NetworkConfig::createTestNetworkConfig(const Address &self)
{ {
SharedPtr<NetworkConfig> nc(new NetworkConfig()); SharedPtr<NetworkConfig> nc(new NetworkConfig());
@ -85,18 +81,6 @@ std::vector<unsigned int> NetworkConfig::allowedEtherTypes() const
return ets; return ets;
} }
const NetworkConfig::MulticastRate &NetworkConfig::multicastRate(const MulticastGroup &mg) const
throw()
{
std::map<MulticastGroup,MulticastRate>::const_iterator r(_multicastRates.find(mg));
if (r == _multicastRates.end()) {
r = _multicastRates.find(MulticastGroup()); // zero MG signifies network's default rate
if (r == _multicastRates.end())
return DEFAULT_MULTICAST_RATE; // neither specific nor default found in network config
}
return r->second;
}
void NetworkConfig::_fromDictionary(const Dictionary &d) void NetworkConfig::_fromDictionary(const Dictionary &d)
{ {
static const std::string zero("0"); static const std::string zero("0");
@ -181,13 +165,6 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
std::sort(_activeBridges.begin(),_activeBridges.end()); std::sort(_activeBridges.begin(),_activeBridges.end());
std::unique(_activeBridges.begin(),_activeBridges.end()); std::unique(_activeBridges.begin(),_activeBridges.end());
Dictionary multicastRateEntries(d.get(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES,std::string()));
for(Dictionary::const_iterator i(multicastRateEntries.begin());i!=multicastRateEntries.end();++i) {
std::vector<std::string> params(Utils::split(i->second.c_str(),",","",""));
if (params.size() >= 3)
_multicastRates[MulticastGroup(i->first)] = MulticastRate(Utils::hexStrToUInt(params[0].c_str()),Utils::hexStrToUInt(params[1].c_str()),Utils::hexStrToUInt(params[2].c_str()));
}
std::vector<std::string> relaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_RELAYS,"").c_str(),",","","")); std::vector<std::string> relaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_RELAYS,"").c_str(),",","",""));
for(std::vector<std::string>::const_iterator r(relaysSplit.begin());r!=relaysSplit.end();++r) { for(std::vector<std::string>::const_iterator r(relaysSplit.begin());r!=relaysSplit.end();++r) {
std::size_t semi(r->find(';')); // address;ip/port,... std::size_t semi(r->find(';')); // address;ip/port,...
@ -221,14 +198,6 @@ bool NetworkConfig::operator==(const NetworkConfig &nc) const
if (_gateways != nc._gateways) return false; if (_gateways != nc._gateways) return false;
if (_activeBridges != nc._activeBridges) return false; if (_activeBridges != nc._activeBridges) return false;
if (_relays != nc._relays) return false; if (_relays != nc._relays) return false;
if (_multicastRates.size() == nc._multicastRates.size()) {
// uclibc++ doesn't seem to implement map<> != map<> correctly, so do
// it ourselves. Note that this depends on the maps being sorted.
for(std::map<MulticastGroup,MulticastRate>::const_iterator a(_multicastRates.begin()),b(nc._multicastRates.begin());a!=_multicastRates.end();++a,++b) {
if ((a->first != b->first)||(a->second != b->second))
return false;
}
} else return false;
if (_com != nc._com) return false; if (_com != nc._com) return false;
return true; return true;
} }

View File

@ -68,9 +68,6 @@ namespace ZeroTier {
// integer(hex) // integer(hex)
#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT "ml" #define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT "ml"
// dictionary of one or more of: MAC/ADI=preload,maxbalance,accrual
#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES "mr"
// 0/1 // 0/1
#define ZT_NETWORKCONFIG_DICT_KEY_PRIVATE "p" #define ZT_NETWORKCONFIG_DICT_KEY_PRIVATE "p"
@ -114,27 +111,6 @@ class NetworkConfig
friend class SharedPtr<NetworkConfig>; friend class SharedPtr<NetworkConfig>;
public: public:
/**
* Tuple of multicast rate parameters
*/
struct MulticastRate
{
MulticastRate() throw() {}
MulticastRate(uint32_t pl,uint32_t maxb,uint32_t acc) throw() : preload(pl),maxBalance(maxb),accrual(acc) {}
uint32_t preload;
uint32_t maxBalance;
uint32_t accrual;
inline bool operator==(const MulticastRate &mr) const { return ((preload == mr.preload)&&(maxBalance == mr.maxBalance)&&(accrual == mr.accrual)); }
inline bool operator!=(const MulticastRate &mr) const { return (!(*this == mr)); }
};
/**
* A hard-coded default multicast rate for networks that don't specify
*/
static const MulticastRate DEFAULT_MULTICAST_RATE;
/** /**
* Create an instance of a NetworkConfig for the test network ID * Create an instance of a NetworkConfig for the test network ID
* *
@ -176,7 +152,6 @@ public:
inline uint64_t revision() const throw() { return _revision; } inline uint64_t revision() const throw() { return _revision; }
inline const Address &issuedTo() const throw() { return _issuedTo; } inline const Address &issuedTo() const throw() { return _issuedTo; }
inline unsigned int multicastLimit() const throw() { return _multicastLimit; } inline unsigned int multicastLimit() const throw() { return _multicastLimit; }
inline const std::map<MulticastGroup,MulticastRate> &multicastRates() const throw() { return _multicastRates; }
inline bool allowPassiveBridging() const throw() { return _allowPassiveBridging; } inline bool allowPassiveBridging() const throw() { return _allowPassiveBridging; }
inline bool isPublic() const throw() { return (!_private); } inline bool isPublic() const throw() { return (!_private); }
inline bool isPrivate() const throw() { return _private; } inline bool isPrivate() const throw() { return _private; }
@ -198,13 +173,6 @@ public:
return ( (_allowPassiveBridging) || (std::find(_activeBridges.begin(),_activeBridges.end(),fromPeer) != _activeBridges.end()) ); return ( (_allowPassiveBridging) || (std::find(_activeBridges.begin(),_activeBridges.end(),fromPeer) != _activeBridges.end()) );
} }
/**
* @param mg Multicast group
* @return Multicast rate or DEFAULT_MULTICAST_RATE if not set
*/
const MulticastRate &multicastRate(const MulticastGroup &mg) const
throw();
bool operator==(const NetworkConfig &nc) const; bool operator==(const NetworkConfig &nc) const;
inline bool operator!=(const NetworkConfig &nc) const { return (!(*this == nc)); } inline bool operator!=(const NetworkConfig &nc) const { return (!(*this == nc)); }
@ -229,7 +197,6 @@ private:
std::vector<InetAddress> _gateways; std::vector<InetAddress> _gateways;
std::vector<Address> _activeBridges; std::vector<Address> _activeBridges;
std::vector< std::pair<Address,InetAddress> > _relays; std::vector< std::pair<Address,InetAddress> > _relays;
std::map<MulticastGroup,MulticastRate> _multicastRates;
CertificateOfMembership _com; CertificateOfMembership _com;
AtomicCounter __refCount; AtomicCounter __refCount;

View File

@ -145,12 +145,6 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
if (fromBridged) if (fromBridged)
network->learnBridgedMulticastGroup(mg,RR->node->now()); network->learnBridgedMulticastGroup(mg,RR->node->now());
// Check multicast/broadcast bandwidth quotas and reject if quota exceeded
if (!network->updateAndCheckMulticastBalance(mg,len)) {
TRACE("%.16llx: didn't multicast %u bytes, quota exceeded for multicast group %s",network->id(),len,mg.toString().c_str());
return;
}
//TRACE("%.16llx: MULTICAST %s -> %s %s %u",network->id(),from.toString().c_str(),mg.toString().c_str(),etherTypeName(etherType),len); //TRACE("%.16llx: MULTICAST %s -> %s %s %u",network->id(),from.toString().c_str(),mg.toString().c_str(),etherTypeName(etherType),len);
RR->mc->send( RR->mc->send(