2020-05-12 08:35:48 +00:00
/*
* Copyright ( c ) 2013 - 2020 ZeroTier , Inc .
*
* Use of this software is governed by the Business Source License included
* in the LICENSE . TXT file in the project ' s root directory .
*
* Change Date : 2024 - 01 - 01
*
* On the date above , in accordance with the Business Source License , use
* of this software will be governed by version 2.0 of the Apache License .
*/
/****/
2020-06-16 19:30:21 +00:00
# include "Constants.hpp"
2020-05-12 08:35:48 +00:00
# include "BondController.hpp"
# include "Peer.hpp"
namespace ZeroTier {
int BondController : : _minReqPathMonitorInterval ;
uint8_t BondController : : _defaultBondingPolicy ;
BondController : : BondController ( const RuntimeEnvironment * renv ) :
RR ( renv )
{
bondStartTime = RR - > node - > now ( ) ;
2020-06-16 19:30:21 +00:00
_defaultBondingPolicy = ZT_BONDING_POLICY_NONE ;
2020-05-12 08:35:48 +00:00
}
2020-06-17 21:54:13 +00:00
bool BondController : : linkAllowed ( std : : string & policyAlias , SharedPtr < Link > link )
2020-05-12 08:35:48 +00:00
{
bool foundInDefinitions = false ;
2020-06-17 21:54:13 +00:00
if ( _linkDefinitions . count ( policyAlias ) ) {
auto it = _linkDefinitions [ policyAlias ] . begin ( ) ;
while ( it ! = _linkDefinitions [ policyAlias ] . end ( ) ) {
if ( link - > ifname ( ) = = ( * it ) - > ifname ( ) ) {
2020-05-12 08:35:48 +00:00
foundInDefinitions = true ;
break ;
}
+ + it ;
}
}
2020-06-17 21:54:13 +00:00
return _linkDefinitions [ policyAlias ] . empty ( ) | | foundInDefinitions ;
2020-05-12 08:35:48 +00:00
}
2020-06-17 21:54:13 +00:00
void BondController : : addCustomLink ( std : : string & policyAlias , SharedPtr < Link > link )
2020-05-12 08:35:48 +00:00
{
2020-06-17 21:54:13 +00:00
Mutex : : Lock _l ( _links_m ) ;
_linkDefinitions [ policyAlias ] . push_back ( link ) ;
auto search = _interfaceToLinkMap [ policyAlias ] . find ( link - > ifname ( ) ) ;
if ( search = = _interfaceToLinkMap [ policyAlias ] . end ( ) ) {
link - > setAsUserSpecified ( true ) ;
_interfaceToLinkMap [ policyAlias ] . insert ( std : : pair < std : : string , SharedPtr < Link > > ( link - > ifname ( ) , link ) ) ;
2020-05-12 08:35:48 +00:00
} else {
2020-06-17 21:54:13 +00:00
fprintf ( stderr , " link already exists=%s \n " , link - > ifname ( ) . c_str ( ) ) ;
// Link is already defined, overlay user settings
2020-05-12 08:35:48 +00:00
}
}
bool BondController : : addCustomPolicy ( const SharedPtr < Bond > & newBond )
{
Mutex : : Lock _l ( _bonds_m ) ;
if ( ! _bondPolicyTemplates . count ( newBond - > policyAlias ( ) ) ) {
_bondPolicyTemplates [ newBond - > policyAlias ( ) ] = newBond ;
return true ;
}
return false ;
}
bool BondController : : assignBondingPolicyToPeer ( int64_t identity , const std : : string & policyAlias )
{
Mutex : : Lock _l ( _bonds_m ) ;
if ( ! _policyTemplateAssignments . count ( identity ) ) {
_policyTemplateAssignments [ identity ] = policyAlias ;
return true ;
}
return false ;
}
SharedPtr < Bond > BondController : : createTransportTriggeredBond ( const RuntimeEnvironment * renv , const SharedPtr < Peer > & peer )
{
fprintf ( stderr , " createTransportTriggeredBond \n " ) ;
Mutex : : Lock _l ( _bonds_m ) ;
int64_t identity = peer - > identity ( ) . address ( ) . toInt ( ) ;
Bond * bond = nullptr ;
if ( ! _bonds . count ( identity ) ) {
std : : string policyAlias ;
fprintf ( stderr , " new bond, registering for %llx \n " , identity ) ;
if ( ! _policyTemplateAssignments . count ( identity ) ) {
2020-06-16 19:30:21 +00:00
if ( _defaultBondingPolicy ) {
2020-05-12 08:35:48 +00:00
fprintf ( stderr , " no assignment, using default (%d) \n " , _defaultBondingPolicy ) ;
bond = new Bond ( renv , _defaultBondingPolicy , peer ) ;
}
if ( ! _defaultBondingPolicy & & _defaultBondingPolicyStr . length ( ) ) {
fprintf ( stderr , " no assignment, using default custom (%s) \n " , _defaultBondingPolicyStr . c_str ( ) ) ;
2020-06-02 05:58:58 +00:00
bond = new Bond ( renv , _bondPolicyTemplates [ _defaultBondingPolicyStr ] . ptr ( ) , peer ) ;
2020-05-12 08:35:48 +00:00
}
}
else {
fprintf ( stderr , " assignment found for %llx, using it as a template (%s) \n " , identity , _policyTemplateAssignments [ identity ] . c_str ( ) ) ;
if ( ! _bondPolicyTemplates [ _policyTemplateAssignments [ identity ] ] ) {
fprintf ( stderr , " unable to locate template (%s), ignoring assignment for (%llx), using defaults \n " , _policyTemplateAssignments [ identity ] . c_str ( ) , identity ) ;
bond = new Bond ( renv , _defaultBondingPolicy , peer ) ;
}
else {
2020-06-02 05:58:58 +00:00
bond = new Bond ( renv , _bondPolicyTemplates [ _policyTemplateAssignments [ identity ] ] . ptr ( ) , peer ) ;
2020-05-12 08:35:48 +00:00
}
}
}
else {
2020-06-01 00:30:41 +00:00
fprintf ( stderr , " bond already exists for %llx. \n " , identity ) ;
2020-05-12 08:35:48 +00:00
}
if ( bond ) {
_bonds [ identity ] = bond ;
/**
* Determine if user has specified anything that could affect the bonding policy ' s decisions
*/
2020-06-17 21:54:13 +00:00
if ( _interfaceToLinkMap . count ( bond - > policyAlias ( ) ) ) {
std : : map < std : : string , SharedPtr < Link > > : : iterator it = _interfaceToLinkMap [ bond - > policyAlias ( ) ] . begin ( ) ;
while ( it ! = _interfaceToLinkMap [ bond - > policyAlias ( ) ] . end ( ) ) {
2020-05-12 08:35:48 +00:00
if ( it - > second - > isUserSpecified ( ) ) {
2020-06-17 21:54:13 +00:00
bond - > _userHasSpecifiedLinks = true ;
2020-05-12 08:35:48 +00:00
}
if ( it - > second - > isUserSpecified ( ) & & it - > second - > primary ( ) ) {
2020-06-17 21:54:13 +00:00
bond - > _userHasSpecifiedPrimaryLink = true ;
2020-05-12 08:35:48 +00:00
}
if ( it - > second - > isUserSpecified ( ) & & it - > second - > userHasSpecifiedFailoverInstructions ( ) ) {
bond - > _userHasSpecifiedFailoverInstructions = true ;
}
if ( it - > second - > isUserSpecified ( ) & & ( it - > second - > speed ( ) > 0 ) ) {
2020-06-17 21:54:13 +00:00
bond - > _userHasSpecifiedLinkSpeeds = true ;
2020-05-12 08:35:48 +00:00
}
+ + it ;
}
}
return bond ;
}
return SharedPtr < Bond > ( ) ;
}
2020-06-17 21:54:13 +00:00
SharedPtr < Link > BondController : : getLinkBySocket ( const std : : string & policyAlias , uint64_t localSocket )
2020-05-12 08:35:48 +00:00
{
2020-06-17 21:54:13 +00:00
Mutex : : Lock _l ( _links_m ) ;
2020-05-12 08:35:48 +00:00
char ifname [ 16 ] ;
_phy - > getIfName ( ( PhySocket * ) ( ( uintptr_t ) localSocket ) , ifname , 16 ) ;
std : : string ifnameStr ( ifname ) ;
2020-06-17 21:54:13 +00:00
auto search = _interfaceToLinkMap [ policyAlias ] . find ( ifnameStr ) ;
if ( search = = _interfaceToLinkMap [ policyAlias ] . end ( ) ) {
SharedPtr < Link > s = new Link ( ifnameStr , 0 , 0 , 0 , 0 , 0 , true , ZT_MULTIPATH_SLAVE_MODE_SPARE , " " , 0.0 ) ;
_interfaceToLinkMap [ policyAlias ] . insert ( std : : pair < std : : string , SharedPtr < Link > > ( ifnameStr , s ) ) ;
2020-05-12 08:35:48 +00:00
return s ;
}
else {
return search - > second ;
}
}
2020-06-17 21:54:13 +00:00
SharedPtr < Link > BondController : : getLinkByName ( const std : : string & policyAlias , const std : : string & ifname )
2020-05-12 08:35:48 +00:00
{
2020-06-17 21:54:13 +00:00
Mutex : : Lock _l ( _links_m ) ;
auto search = _interfaceToLinkMap [ policyAlias ] . find ( ifname ) ;
if ( search ! = _interfaceToLinkMap [ policyAlias ] . end ( ) ) {
2020-05-12 08:35:48 +00:00
return search - > second ;
}
2020-06-17 21:54:13 +00:00
return SharedPtr < Link > ( ) ;
2020-05-12 08:35:48 +00:00
}
bool BondController : : allowedToBind ( const std : : string & ifname )
{
return true ;
/*
if ( ! _defaultBondingPolicy ) {
return true ; // no restrictions
}
2020-06-17 21:54:13 +00:00
Mutex : : Lock _l ( _links_m ) ;
if ( _interfaceToLinkMap . empty ( ) ) {
2020-05-12 08:35:48 +00:00
return true ; // no restrictions
}
2020-06-17 21:54:13 +00:00
std : : map < std : : string , std : : map < std : : string , SharedPtr < Link > > > : : iterator policyItr = _interfaceToLinkMap . begin ( ) ;
while ( policyItr ! = _interfaceToLinkMap . end ( ) ) {
std : : map < std : : string , SharedPtr < Link > > : : iterator linkItr = policyItr - > second . begin ( ) ;
while ( linkItr ! = policyItr - > second . end ( ) ) {
if ( linkItr - > first = = ifname ) {
2020-05-12 08:35:48 +00:00
return true ;
}
2020-06-17 21:54:13 +00:00
+ + linkItr ;
2020-05-12 08:35:48 +00:00
}
+ + policyItr ;
}
return false ;
*/
}
void BondController : : processBackgroundTasks ( void * tPtr , const int64_t now )
{
Mutex : : Lock _l ( _bonds_m ) ;
std : : map < int64_t , SharedPtr < Bond > > : : iterator bondItr = _bonds . begin ( ) ;
while ( bondItr ! = _bonds . end ( ) ) {
bondItr - > second - > processBackgroundTasks ( tPtr , now ) ;
+ + bondItr ;
}
}
} // namespace ZeroTier