BondController.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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 "BondController.hpp"
  14. #include "../osdep/OSUtils.hpp"
  15. #include "Bond.hpp"
  16. #include "Node.hpp"
  17. #include "RuntimeEnvironment.hpp"
  18. namespace ZeroTier {
  19. int BondController::_minReqPathMonitorInterval;
  20. uint8_t BondController::_defaultBondingPolicy;
  21. BondController::BondController(const RuntimeEnvironment* renv) : 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", OSUtils::humanReadableTimestamp().c_str(), getPolicyStrByCode(_defaultBondingPolicy).c_str(), (unsigned long long)identity);
  85. 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", OSUtils::humanReadableTimestamp().c_str(), _defaultBondingPolicyStr.c_str(), (unsigned long long)identity);
  90. RR->t->bondStateMessage(NULL, traceMsg);
  91. bond = new Bond(renv, _bondPolicyTemplates[_defaultBondingPolicyStr].ptr(), peer);
  92. }
  93. }
  94. else {
  95. if (! _bondPolicyTemplates[_policyTemplateAssignments[identity]]) {
  96. sprintf(
  97. traceMsg,
  98. "%s (bond) Creating new bond. Assignment for peer %llx was specified as %s but the bond definition was not found. Using default %s",
  99. OSUtils::humanReadableTimestamp().c_str(),
  100. (unsigned long long)identity,
  101. _policyTemplateAssignments[identity].c_str(),
  102. getPolicyStrByCode(_defaultBondingPolicy).c_str());
  103. RR->t->bondStateMessage(NULL, traceMsg);
  104. bond = new Bond(renv, _defaultBondingPolicy, peer);
  105. }
  106. else {
  107. sprintf(traceMsg, "%s (bond) Creating new default bond %s to peer %llx", OSUtils::humanReadableTimestamp().c_str(), _defaultBondingPolicyStr.c_str(), (unsigned long long)identity);
  108. RR->t->bondStateMessage(NULL, traceMsg);
  109. bond = new Bond(renv, _bondPolicyTemplates[_policyTemplateAssignments[identity]].ptr(), peer);
  110. }
  111. }
  112. }
  113. if (bond) {
  114. _bonds[identity] = bond;
  115. /**
  116. * Determine if user has specified anything that could affect the bonding policy's decisions
  117. */
  118. if (_interfaceToLinkMap.count(bond->policyAlias())) {
  119. std::map<std::string, SharedPtr<Link> >::iterator it = _interfaceToLinkMap[bond->policyAlias()].begin();
  120. while (it != _interfaceToLinkMap[bond->policyAlias()].end()) {
  121. if (it->second->isUserSpecified()) {
  122. bond->_userHasSpecifiedLinks = true;
  123. }
  124. if (it->second->isUserSpecified() && it->second->primary()) {
  125. bond->_userHasSpecifiedPrimaryLink = true;
  126. }
  127. if (it->second->isUserSpecified() && it->second->userHasSpecifiedFailoverInstructions()) {
  128. bond->_userHasSpecifiedFailoverInstructions = true;
  129. }
  130. if (it->second->isUserSpecified() && (it->second->speed() > 0)) {
  131. bond->_userHasSpecifiedLinkSpeeds = true;
  132. }
  133. ++it;
  134. }
  135. }
  136. return bond;
  137. }
  138. return SharedPtr<Bond>();
  139. }
  140. SharedPtr<Link> BondController::getLinkBySocket(const std::string& policyAlias, uint64_t localSocket)
  141. {
  142. Mutex::Lock _l(_links_m);
  143. char ifname[16];
  144. _phy->getIfName((PhySocket*)((uintptr_t)localSocket), ifname, 16);
  145. std::string ifnameStr(ifname);
  146. auto search = _interfaceToLinkMap[policyAlias].find(ifnameStr);
  147. if (search == _interfaceToLinkMap[policyAlias].end()) {
  148. SharedPtr<Link> s = new Link(ifnameStr, 0, 0, 0, 0, 0, true, ZT_MULTIPATH_SLAVE_MODE_SPARE, "", 0.0);
  149. _interfaceToLinkMap[policyAlias].insert(std::pair<std::string, SharedPtr<Link> >(ifnameStr, s));
  150. return s;
  151. }
  152. else {
  153. return search->second;
  154. }
  155. }
  156. SharedPtr<Link> BondController::getLinkByName(const std::string& policyAlias, const std::string& ifname)
  157. {
  158. Mutex::Lock _l(_links_m);
  159. auto search = _interfaceToLinkMap[policyAlias].find(ifname);
  160. if (search != _interfaceToLinkMap[policyAlias].end()) {
  161. return search->second;
  162. }
  163. return SharedPtr<Link>();
  164. }
  165. bool BondController::allowedToBind(const std::string& ifname)
  166. {
  167. return true;
  168. /*
  169. if (!_defaultBondingPolicy) {
  170. return true; // no restrictions
  171. }
  172. Mutex::Lock _l(_links_m);
  173. if (_interfaceToLinkMap.empty()) {
  174. return true; // no restrictions
  175. }
  176. std::map<std::string, std::map<std::string, SharedPtr<Link> > >::iterator policyItr = _interfaceToLinkMap.begin();
  177. while (policyItr != _interfaceToLinkMap.end()) {
  178. std::map<std::string, SharedPtr<Link> >::iterator linkItr = policyItr->second.begin();
  179. while (linkItr != policyItr->second.end()) {
  180. if (linkItr->first == ifname) {
  181. return true;
  182. }
  183. ++linkItr;
  184. }
  185. ++policyItr;
  186. }
  187. return false;
  188. */
  189. }
  190. void BondController::processBackgroundTasks(void* tPtr, const int64_t now)
  191. {
  192. Mutex::Lock _l(_bonds_m);
  193. std::map<int64_t, SharedPtr<Bond> >::iterator bondItr = _bonds.begin();
  194. while (bondItr != _bonds.end()) {
  195. bondItr->second->processBackgroundTasks(tPtr, now);
  196. ++bondItr;
  197. }
  198. }
  199. } // namespace ZeroTier