User-configurable physical MTU for individual links

This patch allows users to specify the physical layer MTU for individual links
when in multipath mode. For example:

{
  "settings":
  {
    "defaultBondingPolicy": "custom-balance-xor",
    "policies":
    {
      "custom-balance-xor":
      {
        "basePolicy": "balance-xor",
        "failoverInterval": 5000,
        "links": {
          "weird_5g_link": { "mtu": 1300 },
          "enp5s0": { "mtu": 1400  }
        }
      }
    }
  }
}
This commit is contained in:
Joseph Henry 2023-01-11 20:12:15 -08:00 committed by Sean OMeara
parent eccc31a4b9
commit 39f3f5b2d9
6 changed files with 36 additions and 7 deletions

View File

@ -184,7 +184,7 @@ SharedPtr<Link> Bond::getLinkBySocket(const std::string& policyAlias, uint64_t l
auto search = _interfaceToLinkMap[policyAlias].find(ifnameStr); auto search = _interfaceToLinkMap[policyAlias].find(ifnameStr);
if (search == _interfaceToLinkMap[policyAlias].end()) { if (search == _interfaceToLinkMap[policyAlias].end()) {
if (createIfNeeded) { if (createIfNeeded) {
SharedPtr<Link> s = new Link(ifnameStr, 0, 0, true, ZT_BOND_SLAVE_MODE_PRIMARY, ""); SharedPtr<Link> s = new Link(ifnameStr, 0, 0, 0, true, ZT_BOND_SLAVE_MODE_PRIMARY, "");
_interfaceToLinkMap[policyAlias].insert(std::pair<std::string, SharedPtr<Link> >(ifnameStr, s)); _interfaceToLinkMap[policyAlias].insert(std::pair<std::string, SharedPtr<Link> >(ifnameStr, s));
return s; return s;
} }
@ -1253,6 +1253,7 @@ void Bond::estimatePathQuality(int64_t now)
if (link) { if (link) {
int linkSpeed = link->capacity(); int linkSpeed = link->capacity();
_paths[i].p->_givenLinkSpeed = linkSpeed; _paths[i].p->_givenLinkSpeed = linkSpeed;
_paths[i].p->_mtu = link->mtu();
maxObservedLinkCap = linkSpeed > maxObservedLinkCap ? linkSpeed : maxObservedLinkCap; maxObservedLinkCap = linkSpeed > maxObservedLinkCap ? linkSpeed : maxObservedLinkCap;
} }
} }

View File

@ -122,9 +122,10 @@ class Link {
* @param mode * @param mode
* @param failoverToLinkStr * @param failoverToLinkStr
*/ */
Link(std::string ifnameStr, uint8_t ipvPref, uint32_t capacity, bool enabled, uint8_t mode, std::string failoverToLinkStr) Link(std::string ifnameStr, uint8_t ipvPref, uint16_t mtu, uint32_t capacity, bool enabled, uint8_t mode, std::string failoverToLinkStr)
: _ifnameStr(ifnameStr) : _ifnameStr(ifnameStr)
, _ipvPref(ipvPref) , _ipvPref(ipvPref)
, _mtu(mtu)
, _capacity(capacity) , _capacity(capacity)
, _relativeCapacity(0.0) , _relativeCapacity(0.0)
, _enabled(enabled) , _enabled(enabled)
@ -226,6 +227,14 @@ class Link {
return _ipvPref; return _ipvPref;
} }
/**
* @return The MTU for this link (as specified by the user.)
*/
inline uint16_t mtu()
{
return _mtu;
}
/** /**
* @return The mode (e.g. primary/spare) for this link (as specified by the user.) * @return The mode (e.g. primary/spare) for this link (as specified by the user.)
*/ */
@ -260,6 +269,11 @@ class Link {
*/ */
uint8_t _ipvPref; uint8_t _ipvPref;
/**
* The physical-layer MTU for this link
*/
uint16_t _mtu;
/** /**
* User-specified capacity of this link * User-specified capacity of this link
*/ */

View File

@ -92,6 +92,7 @@ public:
_valid(true), _valid(true),
_eligible(false), _eligible(false),
_bonded(false), _bonded(false),
_mtu(0),
_givenLinkSpeed(0), _givenLinkSpeed(0),
_relativeQuality(0), _relativeQuality(0),
_latency(0xffff), _latency(0xffff),
@ -112,6 +113,7 @@ public:
_valid(true), _valid(true),
_eligible(false), _eligible(false),
_bonded(false), _bonded(false),
_mtu(0),
_givenLinkSpeed(0), _givenLinkSpeed(0),
_relativeQuality(0), _relativeQuality(0),
_latency(0xffff), _latency(0xffff),
@ -334,6 +336,11 @@ public:
*/ */
inline unsigned int bonded() const { return _bonded; } inline unsigned int bonded() const { return _bonded; }
/**
* @return Whether the user-specified MTU for this path (determined by MTU for parent link)
*/
inline unsigned int mtu() const { return _mtu; }
/** /**
* @return Given link capacity as reported by the bonding layer * @return Given link capacity as reported by the bonding layer
*/ */
@ -370,6 +377,7 @@ private:
volatile bool _valid; volatile bool _valid;
volatile bool _eligible; volatile bool _eligible;
volatile bool _bonded; volatile bool _bonded;
volatile uint16_t _mtu;
volatile uint32_t _givenLinkSpeed; volatile uint32_t _givenLinkSpeed;
volatile float _relativeQuality; volatile float _relativeQuality;

View File

@ -1009,7 +1009,8 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt,int32_t flowId)
Mutex::Lock _l(peer->_paths_m); Mutex::Lock _l(peer->_paths_m);
for(int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) { for(int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
if (peer->_paths[i].p && peer->_paths[i].p->alive(now)) { if (peer->_paths[i].p && peer->_paths[i].p->alive(now)) {
_sendViaSpecificPath(tPtr,peer,peer->_paths[i].p,now,packet,encrypt,flowId); uint16_t userSpecifiedMtu = peer->_paths[i].p->mtu();
_sendViaSpecificPath(tPtr,peer,peer->_paths[i].p, userSpecifiedMtu,now,packet,encrypt,flowId);
} }
} }
return true; return true;
@ -1025,7 +1026,8 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt,int32_t flowId)
} }
} }
if (viaPath) { if (viaPath) {
_sendViaSpecificPath(tPtr,peer,viaPath,now,packet,encrypt,flowId); uint16_t userSpecifiedMtu = viaPath->mtu();
_sendViaSpecificPath(tPtr,peer,viaPath,userSpecifiedMtu,now,packet,encrypt,flowId);
return true; return true;
} }
} }
@ -1033,12 +1035,15 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt,int32_t flowId)
return false; return false;
} }
void Switch::_sendViaSpecificPath(void *tPtr,SharedPtr<Peer> peer,SharedPtr<Path> viaPath,int64_t now,Packet &packet,bool encrypt,int32_t flowId) void Switch::_sendViaSpecificPath(void *tPtr,SharedPtr<Peer> peer,SharedPtr<Path> viaPath,uint16_t userSpecifiedMtu, int64_t now,Packet &packet,bool encrypt,int32_t flowId)
{ {
unsigned int mtu = ZT_DEFAULT_PHYSMTU; unsigned int mtu = ZT_DEFAULT_PHYSMTU;
uint64_t trustedPathId = 0; uint64_t trustedPathId = 0;
RR->topology->getOutboundPathInfo(viaPath->address(),mtu,trustedPathId); RR->topology->getOutboundPathInfo(viaPath->address(),mtu,trustedPathId);
if (userSpecifiedMtu > 0) {
mtu = userSpecifiedMtu;
}
unsigned int chunkSize = std::min(packet.size(),mtu); unsigned int chunkSize = std::min(packet.size(),mtu);
packet.setFragmented(chunkSize < packet.size()); packet.setFragmented(chunkSize < packet.size());

View File

@ -207,7 +207,7 @@ public:
private: private:
bool _shouldUnite(const int64_t now,const Address &source,const Address &destination); bool _shouldUnite(const int64_t now,const Address &source,const Address &destination);
bool _trySend(void *tPtr,Packet &packet,bool encrypt,int32_t flowId = ZT_QOS_NO_FLOW); // packet is modified if return is true bool _trySend(void *tPtr,Packet &packet,bool encrypt,int32_t flowId = ZT_QOS_NO_FLOW); // packet is modified if return is true
void _sendViaSpecificPath(void *tPtr,SharedPtr<Peer> peer,SharedPtr<Path> viaPath,int64_t now,Packet &packet,bool encrypt,int32_t flowId); void _sendViaSpecificPath(void *tPtr,SharedPtr<Peer> peer,SharedPtr<Path> viaPath,uint16_t userSpecifiedMtu, int64_t now,Packet &packet,bool encrypt,int32_t flowId);
const RuntimeEnvironment *const RR; const RuntimeEnvironment *const RR;
int64_t _lastBeaconResponse; int64_t _lastBeaconResponse;

View File

@ -2075,6 +2075,7 @@ public:
bool enabled = OSUtils::jsonInt(link["enabled"],true); bool enabled = OSUtils::jsonInt(link["enabled"],true);
uint32_t capacity = OSUtils::jsonInt(link["capacity"],0); uint32_t capacity = OSUtils::jsonInt(link["capacity"],0);
uint8_t ipvPref = OSUtils::jsonInt(link["ipvPref"],0); uint8_t ipvPref = OSUtils::jsonInt(link["ipvPref"],0);
uint16_t mtu = OSUtils::jsonInt(link["mtu"],0);
std::string failoverToStr(OSUtils::jsonString(link["failoverTo"],"")); std::string failoverToStr(OSUtils::jsonString(link["failoverTo"],""));
// Mode // Mode
std::string linkModeStr(OSUtils::jsonString(link["mode"],"spare")); std::string linkModeStr(OSUtils::jsonString(link["mode"],"spare"));
@ -2091,7 +2092,7 @@ public:
failoverToStr = ""; failoverToStr = "";
enabled = false; enabled = false;
} }
_node->bondController()->addCustomLink(customPolicyStr, new Link(linkNameStr,ipvPref,capacity,enabled,linkMode,failoverToStr)); _node->bondController()->addCustomLink(customPolicyStr, new Link(linkNameStr,ipvPref,mtu,capacity,enabled,linkMode,failoverToStr));
} }
std::string linkSelectMethodStr(OSUtils::jsonString(customPolicy["activeReselect"],"optimize")); std::string linkSelectMethodStr(OSUtils::jsonString(customPolicy["activeReselect"],"optimize"));
if (linkSelectMethodStr == "always") { if (linkSelectMethodStr == "always") {