BondController.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /*
  2. * Copyright (c)2013-2020 ZeroTier, Inc.
  3. *
  4. * Use of this software is governed by the Business Source License included
  5. * in the LICENSE.TXT file in the project's root directory.
  6. *
  7. * Change Date: 2025-01-01
  8. *
  9. * On the date above, in accordance with the Business Source License, use
  10. * of this software will be governed by version 2.0 of the Apache License.
  11. */
  12. /****/
  13. #include "../osdep/OSUtils.hpp"
  14. #include "Constants.hpp"
  15. #include "BondController.hpp"
  16. #include "Peer.hpp"
  17. namespace ZeroTier {
  18. int BondController::_minReqPathMonitorInterval;
  19. uint8_t BondController::_defaultBondingPolicy;
  20. BondController::BondController(const RuntimeEnvironment *renv) :
  21. RR(renv)
  22. {
  23. bondStartTime = RR->node->now();
  24. _defaultBondingPolicy = ZT_BONDING_POLICY_NONE;
  25. }
  26. bool BondController::linkAllowed(std::string &policyAlias, SharedPtr<Link> link)
  27. {
  28. bool foundInDefinitions = false;
  29. if (_linkDefinitions.count(policyAlias)) {
  30. auto it = _linkDefinitions[policyAlias].begin();
  31. while (it != _linkDefinitions[policyAlias].end()) {
  32. if (link->ifname() == (*it)->ifname()) {
  33. foundInDefinitions = true;
  34. break;
  35. }
  36. ++it;
  37. }
  38. }
  39. return _linkDefinitions[policyAlias].empty() || foundInDefinitions;
  40. }
  41. void BondController::addCustomLink(std::string& policyAlias, SharedPtr<Link> link)
  42. {
  43. Mutex::Lock _l(_links_m);
  44. _linkDefinitions[policyAlias].push_back(link);
  45. auto search = _interfaceToLinkMap[policyAlias].find(link->ifname());
  46. if (search == _interfaceToLinkMap[policyAlias].end()) {
  47. link->setAsUserSpecified(true);
  48. _interfaceToLinkMap[policyAlias].insert(std::pair<std::string, SharedPtr<Link>>(link->ifname(), link));
  49. }
  50. }
  51. bool BondController::addCustomPolicy(const SharedPtr<Bond>& newBond)
  52. {
  53. Mutex::Lock _l(_bonds_m);
  54. if (!_bondPolicyTemplates.count(newBond->policyAlias())) {
  55. _bondPolicyTemplates[newBond->policyAlias()] = newBond;
  56. return true;
  57. }
  58. return false;
  59. }
  60. bool BondController::assignBondingPolicyToPeer(int64_t identity, const std::string& policyAlias)
  61. {
  62. Mutex::Lock _l(_bonds_m);
  63. if (!_policyTemplateAssignments.count(identity)) {
  64. _policyTemplateAssignments[identity] = policyAlias;
  65. return true;
  66. }
  67. return false;
  68. }
  69. SharedPtr<Bond> BondController::getBondByPeerId(int64_t identity)
  70. {
  71. Mutex::Lock _l(_bonds_m);
  72. return _bonds.count(identity) ? _bonds[identity] : SharedPtr<Bond>();
  73. }
  74. SharedPtr<Bond> BondController::createTransportTriggeredBond(const RuntimeEnvironment *renv, const SharedPtr<Peer>& peer)
  75. {
  76. Mutex::Lock _l(_bonds_m);
  77. int64_t identity = peer->identity().address().toInt();
  78. Bond *bond = nullptr;
  79. char traceMsg[128];
  80. if (!_bonds.count(identity)) {
  81. std::string policyAlias;
  82. if (!_policyTemplateAssignments.count(identity)) {
  83. if (_defaultBondingPolicy) {
  84. sprintf(traceMsg, "%s (bond) Creating new default %s bond to peer %llx",
  85. OSUtils::humanReadableTimestamp().c_str(), getPolicyStrByCode(_defaultBondingPolicy).c_str(), identity); RR->t->bondStateMessage(NULL, traceMsg);
  86. bond = new Bond(renv, _defaultBondingPolicy, peer);
  87. }
  88. if (!_defaultBondingPolicy && _defaultBondingPolicyStr.length()) {
  89. sprintf(traceMsg, "%s (bond) Creating new default custom %s bond to peer %llx",
  90. OSUtils::humanReadableTimestamp().c_str(), _defaultBondingPolicyStr.c_str(), identity);
  91. RR->t->bondStateMessage(NULL, traceMsg);
  92. bond = new Bond(renv, _bondPolicyTemplates[_defaultBondingPolicyStr].ptr(), peer);
  93. }
  94. }
  95. else {
  96. if (!_bondPolicyTemplates[_policyTemplateAssignments[identity]]) {
  97. 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",
  98. OSUtils::humanReadableTimestamp().c_str(), identity, _policyTemplateAssignments[identity].c_str(), getPolicyStrByCode(_defaultBondingPolicy).c_str());
  99. RR->t->bondStateMessage(NULL, traceMsg);
  100. bond = new Bond(renv, _defaultBondingPolicy, peer);
  101. }
  102. else {
  103. sprintf(traceMsg, "%s (bond) Creating new default bond %s to peer %llx",
  104. OSUtils::humanReadableTimestamp().c_str(), _defaultBondingPolicyStr.c_str(), identity);
  105. RR->t->bondStateMessage(NULL, traceMsg);
  106. bond = new Bond(renv, _bondPolicyTemplates[_policyTemplateAssignments[identity]].ptr(), peer);
  107. }
  108. }
  109. }
  110. if (bond) {
  111. _bonds[identity] = bond;
  112. /**
  113. * Determine if user has specified anything that could affect the bonding policy's decisions
  114. */
  115. if (_interfaceToLinkMap.count(bond->policyAlias())) {
  116. std::map<std::string, SharedPtr<Link> >::iterator it = _interfaceToLinkMap[bond->policyAlias()].begin();
  117. while (it != _interfaceToLinkMap[bond->policyAlias()].end()) {
  118. if (it->second->isUserSpecified()) {
  119. bond->_userHasSpecifiedLinks = true;
  120. }
  121. if (it->second->isUserSpecified() && it->second->primary()) {
  122. bond->_userHasSpecifiedPrimaryLink = true;
  123. }
  124. if (it->second->isUserSpecified() && it->second->userHasSpecifiedFailoverInstructions()) {
  125. bond->_userHasSpecifiedFailoverInstructions = true;
  126. }
  127. if (it->second->isUserSpecified() && (it->second->speed() > 0)) {
  128. bond->_userHasSpecifiedLinkSpeeds = true;
  129. }
  130. ++it;
  131. }
  132. }
  133. return bond;
  134. }
  135. return SharedPtr<Bond>();
  136. }
  137. SharedPtr<Link> BondController::getLinkBySocket(const std::string& policyAlias, uint64_t localSocket)
  138. {
  139. Mutex::Lock _l(_links_m);
  140. char ifname[16];
  141. _phy->getIfName((PhySocket *) ((uintptr_t)localSocket), ifname, 16);
  142. std::string ifnameStr(ifname);
  143. auto search = _interfaceToLinkMap[policyAlias].find(ifnameStr);
  144. if (search == _interfaceToLinkMap[policyAlias].end()) {
  145. SharedPtr<Link> s = new Link(ifnameStr, 0, 0, 0, 0, 0, true, ZT_MULTIPATH_SLAVE_MODE_SPARE, "", 0.0);
  146. _interfaceToLinkMap[policyAlias].insert(std::pair<std::string,SharedPtr<Link> >(ifnameStr, s));
  147. return s;
  148. }
  149. else {
  150. return search->second;
  151. }
  152. }
  153. SharedPtr<Link> BondController::getLinkByName(const std::string& policyAlias, const std::string& ifname)
  154. {
  155. Mutex::Lock _l(_links_m);
  156. auto search = _interfaceToLinkMap[policyAlias].find(ifname);
  157. if (search != _interfaceToLinkMap[policyAlias].end()) {
  158. return search->second;
  159. }
  160. return SharedPtr<Link>();
  161. }
  162. bool BondController::allowedToBind(const std::string& ifname)
  163. {
  164. return true;
  165. /*
  166. if (!_defaultBondingPolicy) {
  167. return true; // no restrictions
  168. }
  169. Mutex::Lock _l(_links_m);
  170. if (_interfaceToLinkMap.empty()) {
  171. return true; // no restrictions
  172. }
  173. std::map<std::string, std::map<std::string, SharedPtr<Link> > >::iterator policyItr = _interfaceToLinkMap.begin();
  174. while (policyItr != _interfaceToLinkMap.end()) {
  175. std::map<std::string, SharedPtr<Link> >::iterator linkItr = policyItr->second.begin();
  176. while (linkItr != policyItr->second.end()) {
  177. if (linkItr->first == ifname) {
  178. return true;
  179. }
  180. ++linkItr;
  181. }
  182. ++policyItr;
  183. }
  184. return false;
  185. */
  186. }
  187. void BondController::processBackgroundTasks(void *tPtr, const int64_t now)
  188. {
  189. Mutex::Lock _l(_bonds_m);
  190. std::map<int64_t,SharedPtr<Bond> >::iterator bondItr = _bonds.begin();
  191. while (bondItr != _bonds.end()) {
  192. bondItr->second->processBackgroundTasks(tPtr, now);
  193. ++bondItr;
  194. }
  195. }
  196. } // namespace ZeroTier