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 .
*
2020-08-20 19:51:39 +00:00
* Change Date : 2025 - 01 - 01
2020-05-12 08:35:48 +00:00
*
* 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 .
*/
/****/
# include "BondController.hpp"
2021-05-04 00:59:31 +00:00
# include "../osdep/OSUtils.hpp"
# include "Bond.hpp"
# include "Node.hpp"
# include "RuntimeEnvironment.hpp"
2020-05-12 08:35:48 +00:00
namespace ZeroTier {
int BondController : : _minReqPathMonitorInterval ;
uint8_t BondController : : _defaultBondingPolicy ;
2021-05-04 00:59:31 +00:00
BondController : : BondController ( const RuntimeEnvironment * renv ) : RR ( renv )
2020-05-12 08:35:48 +00:00
{
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
}
2021-05-04 00:59:31 +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 ) ;
2021-05-04 00:59:31 +00:00
_interfaceToLinkMap [ policyAlias ] . insert ( std : : pair < std : : string , SharedPtr < Link > > ( link - > ifname ( ) , link ) ) ;
2020-05-12 08:35:48 +00:00
}
}
bool BondController : : addCustomPolicy ( const SharedPtr < Bond > & newBond )
{
Mutex : : Lock _l ( _bonds_m ) ;
2021-05-04 00:59:31 +00:00
if ( ! _bondPolicyTemplates . count ( newBond - > policyAlias ( ) ) ) {
2020-05-12 08:35:48 +00:00
_bondPolicyTemplates [ newBond - > policyAlias ( ) ] = newBond ;
return true ;
}
return false ;
}
bool BondController : : assignBondingPolicyToPeer ( int64_t identity , const std : : string & policyAlias )
{
Mutex : : Lock _l ( _bonds_m ) ;
2021-05-04 00:59:31 +00:00
if ( ! _policyTemplateAssignments . count ( identity ) ) {
2020-05-12 08:35:48 +00:00
_policyTemplateAssignments [ identity ] = policyAlias ;
return true ;
}
return false ;
}
2020-11-23 17:59:28 +00:00
SharedPtr < Bond > BondController : : getBondByPeerId ( int64_t identity )
{
Mutex : : Lock _l ( _bonds_m ) ;
return _bonds . count ( identity ) ? _bonds [ identity ] : SharedPtr < Bond > ( ) ;
}
2021-05-04 00:59:31 +00:00
SharedPtr < Bond > BondController : : createTransportTriggeredBond ( const RuntimeEnvironment * renv , const SharedPtr < Peer > & peer )
2020-05-12 08:35:48 +00:00
{
Mutex : : Lock _l ( _bonds_m ) ;
int64_t identity = peer - > identity ( ) . address ( ) . toInt ( ) ;
2021-05-04 00:59:31 +00:00
Bond * bond = nullptr ;
2020-08-07 01:10:40 +00:00
char traceMsg [ 128 ] ;
2021-05-04 00:59:31 +00:00
if ( ! _bonds . count ( identity ) ) {
2020-05-12 08:35:48 +00:00
std : : string policyAlias ;
2021-05-04 00:59:31 +00:00
if ( ! _policyTemplateAssignments . count ( identity ) ) {
2020-06-16 19:30:21 +00:00
if ( _defaultBondingPolicy ) {
2021-05-04 00:59:31 +00:00
sprintf ( traceMsg , " %s (bond) Creating new default %s bond to peer %llx " , OSUtils : : humanReadableTimestamp ( ) . c_str ( ) , getPolicyStrByCode ( _defaultBondingPolicy ) . c_str ( ) , ( unsigned long long ) identity ) ;
RR - > t - > bondStateMessage ( NULL , traceMsg ) ;
2020-05-12 08:35:48 +00:00
bond = new Bond ( renv , _defaultBondingPolicy , peer ) ;
}
2021-05-04 00:59:31 +00:00
if ( ! _defaultBondingPolicy & & _defaultBondingPolicyStr . length ( ) ) {
sprintf ( traceMsg , " %s (bond) Creating new default custom %s bond to peer %llx " , OSUtils : : humanReadableTimestamp ( ) . c_str ( ) , _defaultBondingPolicyStr . c_str ( ) , ( unsigned long long ) identity ) ;
2020-08-07 01:10:40 +00:00
RR - > t - > bondStateMessage ( NULL , traceMsg ) ;
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 {
2021-05-04 00:59:31 +00:00
if ( ! _bondPolicyTemplates [ _policyTemplateAssignments [ identity ] ] ) {
sprintf (
traceMsg ,
" %s (bond) Creating new bond. Assignment for peer %llx was specified as %s but the bond definition was not found. Using default %s " ,
OSUtils : : humanReadableTimestamp ( ) . c_str ( ) ,
( unsigned long long ) identity ,
_policyTemplateAssignments [ identity ] . c_str ( ) ,
getPolicyStrByCode ( _defaultBondingPolicy ) . c_str ( ) ) ;
2020-08-07 01:10:40 +00:00
RR - > t - > bondStateMessage ( NULL , traceMsg ) ;
2020-05-12 08:35:48 +00:00
bond = new Bond ( renv , _defaultBondingPolicy , peer ) ;
}
else {
2021-05-04 00:59:31 +00:00
sprintf ( traceMsg , " %s (bond) Creating new default bond %s to peer %llx " , OSUtils : : humanReadableTimestamp ( ) . c_str ( ) , _defaultBondingPolicyStr . c_str ( ) , ( unsigned long long ) identity ) ;
2020-08-07 01:10:40 +00:00
RR - > t - > bondStateMessage ( NULL , traceMsg ) ;
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
}
}
}
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 ] ;
2021-05-04 00:59:31 +00:00
_phy - > getIfName ( ( PhySocket * ) ( ( uintptr_t ) localSocket ) , ifname , 16 ) ;
2020-05-12 08:35:48 +00:00
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 ) ;
2021-05-04 00:59:31 +00:00
_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 ;
*/
}
2021-05-04 00:59:31 +00:00
void BondController : : processBackgroundTasks ( void * tPtr , const int64_t now )
2020-05-12 08:35:48 +00:00
{
Mutex : : Lock _l ( _bonds_m ) ;
2021-05-04 00:59:31 +00:00
std : : map < int64_t , SharedPtr < Bond > > : : iterator bondItr = _bonds . begin ( ) ;
2020-05-12 08:35:48 +00:00
while ( bondItr ! = _bonds . end ( ) ) {
bondItr - > second - > processBackgroundTasks ( tPtr , now ) ;
+ + bondItr ;
}
}
2021-05-04 00:59:31 +00:00
} // namespace ZeroTier