Raspberry Pi で作るネットワークエミュレータ

Pocket

明けましておめでとうございます。

この記事は、 Raspberry Pi Advent Calendar 2020 24日目の記事だ。
…遅刻すぎるのもいいとこだわ。


さて、ネットワーク回りの仕事をしていると、意図的にネットワークの遅延やパケロスを発生させて、検証したくなる状況がままある。

対象のサーバーにネットワークを遅延させるようなモジュール入れるようなやり方も考えられるが、もっと手軽に、 LAN ケーブルの間に挟むだけで、そこを通る通信が全て遅延するみたいな、そんな機材が欲しくなる。

もちろん、そのような需要があれば、それに応える製品があるわけで、それらは一般的に「ネットワークエミュレータ」として売られている。
しかし、高いものでは数百万を軽く超え、安くても数万円はするものばかりだ。

なんか安く作れないかなぁ…
Raspberry Pi あたりで。

…ということで、 Raspberry Pi 4 を使って、遅延とパケロスを制御できる、お手軽ネットワークエミュレータを作ってみよう。

先駆者

そもそもなのだが、そのものズバリなことを実践している先駆者様がいらっしゃった。

この記事の Raspberry Pi には、小型ドットマトリックス LCD ディスプレイや、様々な物理キーが GPIO に繋がっていて、 THE IoT という仕上がりになっている。

かっこいいと思う。
でも、電子工作するのめんどくさいよね。

GUIで手っ取り早く作る

そんな複雑 (…というほど複雑でもないけど) な電子工作しなくても、 RasPi にタッチパネルディスプレイつけちゃえばいいじゃん。
…ということで、 Amazon で割と評判のよい、 OSOYOO の 2,980円 タッチスクリーン付き LCD を取り付けて、めっちゃ簡単な UI をつくってみよう。

OSOYOO(オソヨー) HDMI 3.5 インチ LCD ディスプレイ IPS モニター IPSタッチスクリーン 1920x1280ハイビジョン Raspberry Pi 4 3 2 Model B に対応 (3.5" HDMI LCD+クリアケース)

もはや、 IoT 感を感じるのが難しくなってしまっているな……

構成は、以下の図のように有線 LAN 2つ をブリッジ接続させる。

これなら、 Raspberry Pi OS の標準の機能だけで実現できそうだ。

なお設計的には、 Raspberry Pi が 2, 3, 4 どれでも機能するとは思うが、 1000BASE-T や USB 3.0 のポートを持っている Raspberry Pi 4B がオススメ。

RasPi 4B には 1つ しか 有線LAN ポートがないので、適当にもう一つ USB 有線LAN アダプタをつける必要がある。
Gigabit 対応のアダプタが良いだろう。

Raspberry Pi のセットアップ

まず、 Raspberry Pi OS with desktop イメージを SD カードに焼く。
"and recommended software" ではない ほうでかまわない。

今回は、 2020-12-02-raspios-buster-armhf.img のバージョンのイメージで試した。

OS イメージを焼くツールは何でも良いが、 balenaEtcher あたりが良いだろう。

Raspberry Pi OS が起動したら、以下の手順に従って、タッチスクリーンのドライバーが動くようにしておく。
http://osoyoo.com/ja/?p=4244

Raspberry Pi の2つの有線NICでブリッジ

まず接続されている、 NIC のインターフェイス名を確認する。

$ ip address show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
4: eth1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN group default qlen 1000

Raspberry Pi の 有線LAN インターフェイスの場合は、 eth0, eth1... と名前がついていくため、 ここでは eth0, eth1 がブリッジ接続させる対象だとわかる。

続いて、 ip コマンドを使って、ブリッジの作成する。

$ sudo ip link add br0 type bridge
$ sudo ip link set dev br0 up
$ sudo ip link set dev eth0 promisc on
$ sudo ip link set dev eth0 up
$ sudo ip link set dev eth0 master br0
$ sudo ip link set dev eth1 promisc on
$ sudo ip link set dev eth1 up
$ sudo ip link set dev eth1 master br0

※: ip link コマンドで設定したブリッジ設定は、 Raspberry Pi を再起動するとリセットされる。 起動時に自動設定させたければ Raspberry Pi OS であれば /etc/network/interfaces.d/ 以下に、 Ubuntu であれば /etc/netplan/ 以下に、 設定を書いておけば良いはず。

この状態でブリッジが意図したとおり機能しているか、 PC1, PC2 を接続して iperf で速度を測ってみる。

> .\iperf3.exe -c PC2
Connecting to host 192.168.1.222, port 5201
[  4] local 192.168.1.111 port 59582 connected to 192.168.1.222 port 5201
[ ID] Interval           Transfer     Bandwidth
[  4]   0.00-1.00   sec  53.6 MBytes   449 Mbits/sec
[  4]   1.00-2.00   sec  56.9 MBytes   478 Mbits/sec
[  4]   2.00-3.00   sec  58.0 MBytes   486 Mbits/sec
[  4]   3.00-4.00   sec  57.1 MBytes   479 Mbits/sec
[  4]   4.00-5.00   sec  57.9 MBytes   487 Mbits/sec
[  4]   5.00-6.00   sec  58.6 MBytes   491 Mbits/sec
[  4]   6.00-7.00   sec  57.6 MBytes   483 Mbits/sec
[  4]   7.00-8.00   sec  55.0 MBytes   462 Mbits/sec
[  4]   8.00-9.00   sec  56.5 MBytes   474 Mbits/sec
[  4]   9.00-10.00  sec  58.9 MBytes   492 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth
[  4]   0.00-10.00  sec   570 MBytes   478 Mbits/sec                  sender
[  4]   0.00-10.00  sec   570 MBytes   478 Mbits/sec                  receiver

iperf Done.

1Gbps 出てないが、まぁこんなもんだろう。

qdisc 制御 GUI コード

Raspberry Pi 上のブリッジを通過して通信が通るようになったので、お次は通過するパケット2021-01-01 11:26:57 Friday

に遅延やパケロスを発生させるための UI を作る。

UI 上でポチポチした値を基に、 tc qdisc コマンドを実行するような、単純な仕組みで良いだろう。
Python と tkinter で適当に仕上げてみる。

https://gist.github.com/advanceboy/b2bb75b1b1b95d7cd2af15c199c4a5b5

試しに動かしてみた動画がこちら。

UI上で設定した値に応じて、 ping の遅延とパケロスが発生しているのが、一目瞭然だろう。

遅延を 100ms (RTT 200ms) としたときに、先ほどと同じ組み合わせで iperf を動かしたところ、以下のようになった。

> .\iperf3.exe -c PC2
Connecting to host 192.168.1.222, port 5201
[  4] local 192.168.1.111 port 59582 connected to 192.168.1.222 port 5201
[ ID] Interval           Transfer     Bandwidth
[  4]   0.00-1.03   sec   256 KBytes  2.04 Mbits/sec
[  4]   1.03-2.03   sec  0.00 Bytes  0.00 bits/sec
[  4]   2.03-3.00   sec   512 KBytes  4.30 Mbits/sec
[  4]   3.00-4.00   sec   384 KBytes  3.14 Mbits/sec
[  4]   4.00-5.01   sec   640 KBytes  5.23 Mbits/sec
[  4]   5.01-6.01   sec   384 KBytes  3.14 Mbits/sec
[  4]   6.01-7.01   sec   512 KBytes  4.18 Mbits/sec
[  4]   7.01-8.01   sec   384 KBytes  3.14 Mbits/sec
[  4]   8.01-9.00   sec   640 KBytes  5.31 Mbits/sec
[  4]   9.00-10.00  sec   384 KBytes  3.14 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth
[  4]   0.00-10.00  sec  4.00 MBytes  3.35 Mbits/sec                  sender
[  4]   0.00-10.00  sec  3.95 MBytes  3.31 Mbits/sec                  receiver

iperf Done.

輻輳制御が働いて 3.35Mbps しか速度が出なくなっていることがわかる。

…とまぁ、こんな感じで目的を達成することができた。

余談

Raspberry Pi に Raspberry Pi OS 以外の OS を入れる場合

Raspberry Pi OS では、標準だと sudo コマンドにパスワードが不要な設定が visudo にされている。
一方、 Ubuntu など他の多くのディストリビューションではそうなっていない。

他の OS で動かしたい場合、 visudo で /usr/sbin/tc コマンドをパスワードなしで実行できるように設定しておこう。

OSOYOO のタッチスクリーン付き LCD について

先ほど挙げた OSOYOO のタッチスクリーン付き LCD は、 この価格帯のものなので過度な期待は禁物ではあるものの、 少なくともこの用途にはコスパ抜群だった。

クリアケース付きのもののケースは、正直このクオリティだと +1,000円 分に達していないレベルのものだが、 LCD ディスプレイにちょうど合うサイズだったので、払ってしまっても損はないと思う。
ただし、 Raspberry Pi 4B には端子の穴の位置が合わないため、サイドのアクリルが取り付けられなかった。

また、同梱されていた紙のマニュアルに書かれていたリンクでダウンロードしたドライバーが古かったらしく、 最新の Raspberry Pi OS に入れたら、 タッチ位置が 90° 回転して認識されるトラブルに遭遇した。
以下のオンラインマニュアルのリンク先の、最新(?) のドライバーを使うようにしたら、上記のタッチ位置の問題は解消されたので、参考まで。
http://osoyoo.com/ja/?p=4244

同梱されていた Raspberry Pi 4B 用の HDMI - microHDMI コネクターが壊れていたのだが、 サポートにメールしたら即返事が来て代替品送ってくれたので、好印象。
代替品が届くまでは、家にあった変換ケーブルで我慢。

一方で、タッチパネルの「ドライバー」とやらが、インストールスクリプトの中身をよく見ると、 何故かカーネルごとゴッソリ置き換える仕組みになっている。
HW のドライバーという時点で、提供元を信頼しないとどうしようもないのだが、カーネルごと置き換えられるのにはちょっとモニョる。

2020年末現在、 Raspberry Pi OS の Linux カーネルは 5.4系 なのだが、 このドライバーでカーネルが置き換えられると、 Linux カーネルが 4.19系 に落ちる点は注意。
とりあえず、 2020-12-02-raspios-buster-armhf にインストールした限りは、問題なく動いていそうではあるが。

マニュアルにも書いてあるが、 Kernel を更新すると正常に動作しなくなる可能性があるので、 apt の更新大将から Kernel を除外すると良いようだ。
このため、常用するマシンにはオススメしない。

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください