Linuxにおける Equal Cost Multipath (ECMP) の設定方法と挙動に関するメモ

Linuxのネットワークスタックでmultipathを使用する場合の設定方法と挙動に関するメモ。

設定方法

設定自体は ip route add コマンドで nexthop を複数指定するだけ。src の指定は必要に応じて。

# ip route add 10.1.1.0/24 src 10.0.0.3 \
    nexthop via 192.168.11.1 weight 1 \
    nexthop via 192.168.12.1 weight 1
$ ip route
(snip)
10.1.1.0/24  src 10.0.0.3 
        nexthop via 192.168.11.1  dev eth1 weight 1
        nexthop via 192.168.12.1  dev eth2 weight 1

なお、カーネルCONFIG_IP_ROUTE_MULTIPATH=yコンパイルされていることが必要。

カーネルバージョンごとの挙動の差異

カーネルバージョン毎にトラフィックバランシング方法が異なるため、注意が必要*1

  • ~ 3.5: レイヤ3情報 (src/dst IP address) に基づく per-flow ECMP
  • 3.6 ~ 4.3: per-packet ECMP
  • 4.4 ~ 4.11: レイヤ3情報に基づく per-flow ECMP
  • 4.12 ~: レイヤ3情報 or 5-tuple (src/dst IP addr, src/dst port, L4 proto) に基づく per-flow ECMP

カーネル3.6から4.4の間の状況の概要はredditのこのスレッドに纏まっている:

www.reddit.com

カーネル3.6で一旦消滅した per-flow ECMP は、カーネル4.4で復活した:

github.com

ちなみに RHEL 7 (CentOS 7) のカーネルは3.10ベースであるため、当初の挙動は per-packet ECMP だった。ただし、3.10.0-514 (=7.3の初期カーネルパッケージ) で上記パッチがバックポートされたため、これ以降は動作が per-flow ECMP に変わっている。

https://git.centos.org/blob/rpms!kernel.git/f91430943f84931525936ea22f3cb2f24577f23a/SPECS!kernel.spec#L17805

レイヤ4情報も含めた per-flow ECMP はカーネル4.12でマージされた。net.ipv4.fib_multipath_hash_policy で 1 を指定すれば使用可能。(デフォルトは0 = L3のみ)

github.com

*1:IPv4の場合。IPv6に関しては未調査