Below is outdated. Please see: https://docs.zerotier.com/zerotier/multipath

Multipath link aggregation (e.g. bonding) allows the simultaneous use of multiple physical links to enable increased throughput, load balancing, redundancy, and fault tolerance. There are a variety of standard policies available that can be used right out of the box with no configuration. These policies are directly inspired by the policies offered by the Linux kernel but are now offered in user-space and hence available on all platforms that ZeroTier supports (including Windows!).

Standard policies


Policy name

Fault tolerance

Min. failover (sec.)

Default Failover (sec.)

Balancing

Aggregation efficiency

Redundancy

Sequence Reordering

none

None

60+

60+

none

none

1

No

active-backup

Brief interruption

0.25

10

none

low

1

Only during failover

broadcast

Fully tolerant

N/A

N/A

none

very low

N

Often

balance-rr

Self-healing

0.25

10

packet-based

high

1

Often

balance-xor

Self-healing

0.25

10

flow-based

very high

1

Only during failover

balance-aware

Self-healing

0.25

10

adaptive flow-based

very high

1

Only during failover and re-balance

A policy can be used easily without specifying any additional parameters:

{
  "settings":
  {
    "defaultBondingPolicy": "active-backup"
  }
}

Custom policies


To customize a bonding policy for your use-case simply specify a basePolicy and override chosen parameters. For example, to create a more aggressive active-backup policy with low monitoring overhead that will failover 0.250 seconds after it detects a link failure, one could do the following:

{
  "settings":
  {
    "defaultBondingPolicy": "aggressive-active-backup",
    "policies":
    {
      "aggressive-active-backup":
      {
        "failoverInterval": 250,
        "pathMonitorStrategy": "dynamic",
        "basePolicy": "active-backup"
      }
    }
  }
}

Manually-specifying links


Bonds are composed of multiple links. Different sets of links can be constructed for different bonding policies and used simultaneously. One can specify the links that ZeroTier should use in any given bonding policy simply by providing an array of links with names corresponding to interface names. If a user doesn't specify a set of interfaces to use, ZeroTier will assume every system interface is available for use. However, if the user does specify a set of interfaces, ZeroTier will only use what is specified. The same applies to failover rules, if none are specified, ZeroTier will failover to any operational link. On the other hand, if the user does specify failover rules and there is ever a situation where a link is available for usage but does not fit within the rules specified by the user, it will go unused.

To specify that ZeroTier should only use eth0 and eth1 as primary links, and eth2 as a backup spare and that it should prefer IPv4 over IPv6 except on eth2 where only IPv6 is allowed:

{
  "settings":
  {
    "defaultBondingPolicy": "aggressive-active-backup",
    "policies": {
      "aggressive-active-backup":
      {
        "links": {
          "eth0": {
            "ipvPref": 46,
            "failoverTo": "eth2",
            "mode": "primary"
          },
          "eth1": {
            "ipvPref": 46,
            "failoverTo": "eth2",
            "mode": "primary"
            },
          "eth2": {
            "ipvPref": 6,
            "mode": "spare"
          }
        }
      }
    }
  }
}

Additional link-specific parameters:

"links":
{
  "interfaceName": /* System-name of the network interface. */
  {
    "failoverInterval": 0-65535, /* (optional) How quickly a path on this link should failover after a detected failure. */
    "ipvPref": [0,4,6,46,64], /* (optional) IP version preference for detected paths on a link. */
    "speed": 0-1000000, /* (optional) How fast this link is (in arbitrary units). This is a useful way to manually allocate a bond. */
    "alloc": 0-255, /* (optional) A relative value representing a desired allocation. */
    "upDelay": 0-65535, /* (optional) How long after a path becomes alive before it is added to the bond. */
    "downDelay": 0-65535, /* (optional) How long after a path fails before it is removed from the bond. */
    "failoverTo": "spareInterfaceName", /* (optional) Which link should be used next after a failure of this link. */
    "enabled": true|false, /* (optional) Whether any paths on this link are allowed to be used this bond. */
    "mode": "primary"|"spare" /* (optional) Whether this link is used by default or only after failover events. */
  }
}

Peer-specific bonds


It is possible to direct ZeroTier to form a certain type of bond with specific peers of your choice:

{
  "settings":
  {
    "defaultBondingPolicy": "active-backup",
    "peerSpecificBonds":
    {
      "f6203a2db3":"active-backup",
      "45b0301da2":"balance-xor",
      "a92cb526fa":"broadcast"
    }
  }
}

Active backup (active-backup)


Traffic is sent on only one path at any given time. A different path becomes active if the current path fails. This mode provides fault tolerance with a nearly immediate fail-over. This mode does not increase total throughput.

The zerotier-cli bond <peerId> rotate command will forcibly switch to the next link available from the failover queue in an active-backup bond.

{
  "settings":
  {
    "defaultBondingPolicy": "active-backup",
    "active-backup":
    {
      "linkSelectMethod": "always",
      "links":
      {
        "eth0": { "failoverTo": "eth1", "mode": "primary" },
        "eth1": { "mode": "spare" },
        "eth2": { "mode": "spare" },
        "eth3": { "mode": "spare" }
      }
    }
  }
}

Broadcast (broadcast)


Traffic is sent on (all) available paths simultaneously. This mode provides fault tolerance and effectively immediate failover due to transmission redundancy. This mode is a poor utilization of throughput resources and will not increase throughput but can prevent packet loss during a link failure. The only option available is dedup which will de-duplicate all packets on the receiving end if set to true.

Balance round robin (balance-rr)


Traffic is striped across multiple paths. Offers partial fault tolerance immediately, full fault tolerance eventually. This policy is unaware of protocols and is primarily intended for use with protocols that are not sensitive to reordering delays. The only option available for this policy is packetsPerLink which specifies the number of packets to transmit via a path before moving to the next in the RR sequence. When set to 0 a path is chosen at random for each outgoing packet. The default value is 8, low values can begin to add overhead to packet processing.

Balance XOR (balance-xor, similar to the Linux kernel's balance-xor with xmit_hash_policy=layer3+4)


Traffic is categorized into flows based on source portdestination port, and protocol type these flows are then hashed onto available links. Each flow will persist on its assigned link interface for its entire life-cycle. Traffic that does not have an assigned port (such as ICMP pings) will be randomly distributed across links. The hash function is simply: src_port ^ dst_port ^ proto.

Balance aware (balance-aware, similar to Linux kernel's balance-*lb modes)


Traffic is dynamically allocated and balanced across multiple links simultaneously according to the target allocation. Options allow for packet or flow-based processing, and active-flow reassignment. Flows mediated over a recently failed links will be reassigned in a manner that respects the target allocation of the bond. An optional balancePolicy can be specified with the following effects: flow-dynamic(default) will hash flows onto links according to target allocation and may perform periodic re-assignments in order to preserve balance. flow-static, will hash flows onto links according to target allocation but will not re-assign flows unless a failure occurs or the link is no longer operating within acceptable parameters. And lastly packet which simply load balances packets across links according to target allocation but with no concern for sequence reordering.

{
    "settings":
    {
        "defaultBondingPolicy": "balance-aware",
        "balance-aware": {
            "allowFlowHashing": true|false,
            "rebalanceStrategy": "passive"|"opportunistic"|"aggressive"
        }
    }
}

Available commands


The zerotier-cli bond list or listbonds command will show the current type and health status of bonds between all peers:

$ zerotier-cli listbonds

    <peer>                        <bondtype>    <status>    <links>
16a03a3d03                     active-backup     Healthy        4/4
a92cb526fa                       balance-xor    Degraded        2/3
45b0301da2                       balance-xor     Healthy        6/6
f6203a2db3                        balance-rr     Healthy        3/3

The zerotier-cli bond <peerId> show command prints the parameters of a bond and real-time quality metrics of its constituent links:

$ zerotier-cli show bond a92cb526fa

PEER          BOND TYPE                         STATUS    LINKS 

  4ac8a21e06  balance-xor                       Degraded  4/7    

BOND PARAMETERS

  Failover Interval    Up Delay    Down Delay    Packets Per Link    Link Selection Method
  500                  40000       0             N/A                 N/A              

LINK QUALITY
                         STATUS   LAT   PDV     PLR      PER     SPD   ALLOC
  1.2.3.4/40000          Dead      46    11   1.000    0.000     100    0.00
  34.65.23.78/3000       Alive      3    11   0.000    0.000      10    0.25
  5.23.21.100/9000       Dead      17    11   0.970    0.220    1000    0.00
  12.165.23.199/10000    Alive      7    11   0.000    0.000      10    0.25
  88.11.22.78/8000       Alive      1    11   0.001    0.000     100    0.25
  6.123.91.100/9000      Dead      22    11   1.000    0.000     100    0.00
  188.11.22.78/8000      Alive     11    11   0.000    0.000    1000    0.25

The zerotier-cli bond <peerId> link <action> command will provides a facility to add and remove links in real time and nominate them for usage for particular bonds:

$ zerotier-cli bond a92cb526fa link add ppp0
$ zerotier-cli bond a92cb526fa link nominate ppp0
$ zerotier-cli bond a92cb526fa link remove ppp0

The zerotier-cli bond <peerId> enable will forcibly enable bonding on

Logging


If you compile with ZT_TRACE=1 ZeroTier will output important bond events to stderr allowing you to see the decisions being made by the bonding layer in real-time. For instance, below is a fairly straightforward case of the creation of an active-backup bond and the subsequent failure of its primary link and instantaneous recovery on a backup link:

2020-09-10 20:09:58 (bond) Creating new default active-backup bond to peer 16a03a3d03
2020-09-10 20:09:58 (bond) Bond to peer 16a03a3d03 is configured as (monStrat=3, fi= 500, bmi= 166, qos= 664, ack= 500, estimateInt= 1000, refractory= 8000, ud= 0, dd= 0)
2020-09-10 20:09:58 (bond) Nominating link v0aa/10.200.2.2/9997 to peer 16a03a3d03. It has now entered its trial period
2020-09-10 20:09:58 (bond) Nominating link v1ab/11.100.1.21/9997 to peer 16a03a3d03. It has now entered its trial period
2020-09-10 20:09:58 (bond) Bond to peer 16a03a3d03 is in a HEALTHY state (2/2 links)
2020-09-10 20:09:58 (bond) Eligibility of link v0aa/10.200.2.2/9997 to peer 16a03a3d03 has changed from 0 to 1
2020-09-10 20:09:58 (bond) Eligibility of link v1ab/11.100.1.21/9997 to peer 16a03a3d03 has changed from 0 to 1

...

2020-09-10 20:10:28 (active-backup) Active link to peer 16a03a3d03 is v0aa/10.200.2.2/9997, failover queue size is 2

...

2020-09-10 21:29:06 (bond) Eligibility of link v0aa/10.200.2.2/9997 to peer 16a03a3d03 has changed from 1 to 0
2020-09-10 21:29:06 (active-backup) Link v0aa/10.200.2.2/9997 to peer 16a03a3d03 has failed. Selecting new link from failover queue, there are 2 links in the queue
2020-09-10 21:29:06 (active-backup) Active link to peer 16a03a3d03 has been switched to v1ab/11.100.1.21/9997
2020-09-10 21:29:10 (active-backup) Active link to peer 16a03a3d03 is v1ab/11.100.1.21/9997, failover queue size is 1

Link quality


ZeroTier measures various properties of a link (such as latency, throughput, jitter, packet loss ratio, etc) in order to arrive at a quality estimate. This estimate is used by bonding policies to make allocation and failover decisions:

Policy name

Role

active-backup

Determines the order of the failover queue. And if activeReselect=optimize whether a new active link is selected.

broadcast

Does not use quality measurements.

balance-rr

May trigger removal of link from bond.

balance-xor

May trigger removal of link from bond.

balance-aware

Informs flow assignments and (re-)assignments. May trigger removal of link from bond.

A link's eligibility for being included in a bond is dependent on more than perceived quality. If a path on a link begins to exhibit disruptive behavior such as extremely high packet loss, corruption, or periodic inability to process traffic it will be removed from the bond, its traffic will be appropriately reallocated and it will be punished. Punishments gradually fade and a link can be readmitted to the bond over time. However, punishments increase exponentially if applied more than once within a given window of time.

Asymmetric links


In cases where it is necessary to bond physical links that vary radically in terms of cost, throughput, latency, and or reliability, there are a couple of ways to automatically (or manually) allocate traffic among them. Traffic distribution and balancing can be either packet or flowbased. Where packet-based is suitable for protocols not susceptible to reordering penalties and flow-based is suitable for protocols such as TCP where it is desirable to keep a conversation on a single link unless we can't avoid having to re-assign it. Additionally, a target allocation of traffic used by the bonding policy can be derived/specified in the following ways:

"balance-aware": {
    "quality": {
        "lat": 0.3, /* Moving average of latency in milliseconds */
        "ltm": 0.2, /* Maximum observed latency in milliseconds */
        "pdv": 0.3, /* Packet delay variance in milliseconds. Similar to jitter */
        "plr": 0.1, /* Packet loss ratio */
        "per": 0.1, /* Packet error ratio */
        "avl": 0.0, /* Availability */
    }
}

In the absence of user guidance ZeroTier will attempt to form an understanding of each link's speed and capacity but this value can be inaccurate if the links are not routinely saturated. Therefore we provide a way to explicitly signal the capacity of each link in terms of arbitrary but relative values:

"links": {
  "eth0": { "speed": 10000 },
  "eth1": { "speed": 1000 },
  "eth2": { "speed": 100 }
}

The user specifies allocation percentages (totaling 1.0). In this case quality measurements will only be used to determine a link's eligibility to be a member of a bond, now how much traffic it will carry:

"links": {
  "eth0": { "alloc": 0.50 },
  "eth1": { "alloc": 0.25 },
  "eth2": { "alloc": 0.25 }
}

Performance and overhead considerations