Linux に mpls 対応コードが入ってきていた。ぶっちゃけ openvswitch
kernel module で使いたいから入ったんだと思うけど mpls_router
というmodule もある。
使い方を調べてみたので、そのメモ。
iproute2
ip
コマンドは新しいものが必要なので、iproute2 を手元でビルドしておく。
pacman -S gcc make pkgconfig flex bison
git clone git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git
cd iproute2 && make
使いかた
モジュールは modprobe で読み込む。
modprobe mpls_router
読み込むと /proc/sys/net/mpls
以下ができる。platform_labels
は MPLS のラベルで扱う数字の最大値を決める。…これ制限する必要性はよくわからないけれど、一般的なMPLS ハードウェアルータでは設定するものが多い様子。とりあえず 64 あたりにしてみた。いずれにせよ mpls の最大値は 20bit を超えられない。それから 0--15 は予約されているものとして、使うことができない。
echo 64 > /proc/sys/net/mpls/platform_labels
mpls_router の基本的な流れはこうなる。openflow の MPLS と同じで、ether header と ether payload の間に mpls shim header が入っていく形式。
[IN] -- mpls(@label=n, payload) --> [routing table] -- payload --> [OUT]
上記の IN に使う netdev で mpls routing を有効にする。
echo 1 > /proc/sys/net/mpls/conf/eth2/input
mpls routing table の表示は ip -M route
でできる。経路情報の追加は 3 種類使える。いずれのパターンも出力 netdev は必須。20, 21, 22, 23 と書いているところが MPLS 入力ラベル。残りは出力パラメータ。
ip -M route add 20 dev eth1
ip -M route add 21 dev eth1 via link 00:11:22:33:44:55
ip -M route add 22 dev eth1 via inet 192.168.0.2
ip -M route add 23 dev eth1 via inet6 fe80::2345
via 省略時は inet の loopback が割当たっている様子。ただ ip -M route
の出力には inet 0.0.8.0
と表示されるのだけど、127.0.0.1
のバイトオーダーどこかで間違えてる感じか…?
MPLS 出力時にも同じように MPLS パケットを出したければ、次のようにできる。
ip -M route add 24 dev eth1 via link 00:11:22:33:44:55 as 24
ip -M route add 25 dev eth1 via link 00:11:22:33:44:55 as 26/27
上の行は、ラベル変更なしで次のリンクに送り出し、下の行は stack させて次のリンクに送り出します。もっとたくさん stack させたい気分になったりもしますが、#define MAX_NEW_LABELS 2
とハードコードされているので 2 段まで。
送信テスト
マシンの外側から python scapy を使って送り込むと簡単。scapy の interactive shell を使う。
load_contrib("mpls")
sendp(Ether(dst="00:11:22:33:44:55")/MPLS(label=20, ttl=5), iface="eth1")
ポイントは TTL に 1 より大きい数を指定するところ。普通にやると TTL=0 になっていて即破棄される。