概要
スマホなど無線ネットワークにつながる機器に向けて映像・音声などメディアを扱うアプリの開発を行うときに、ネットワーク上のパケットロスやジッターなどがある貧弱なネットワーク環境を作ってテストしたい場合があります。
そんなときには、スマホとLANの間にネットワークエミュレータと無線LANブリッジを挟めば、貧弱なネットワーク環境を意図的に作り出してテストすることができます。
+------------------+ +-------------+
LAN === | Network Emulator | === | WLAN Bridge | ... Smartphone
+------------------+ +-------------+
=== : Ether cable
... : Wifi connection
ネットワークエミュレータと無線LANブリッジはそれぞれ別の機器として用意するのが一般的と思いますが、Raspberry Piが1台あれば、この2つの役割をもたせたネットワークエミュレーション機能付きの無線LANブリッジを構成することができます。
+---------------------------+
LAN === | Raspbery pi WLAN Bridge | ... Smartphone
| with network emulator. |
+---------------------------+
用意するもの
Raspberry Pi3 または Pi4を用意します。ここでは、Raspberry Pi4を使って作成しましたが、Raspberry Pi3でも同じ方法で作成できると思います。
作成の手順
OSをインストールする
"Raspberry Pi Imager"を使ってRaspberry Pi OSがインストールされたSDカードを作成します。
ここでは、Raspberry piをヘッドレスでSSHでリモートから制御することを想定して、デスクトップ環境が無い「RASPBERRY PI OS LITE(32-BIT)」を選択します。
書き込みが終わったら一旦SDカードを抜いて再び書き込みをしたMac(or PC)に接続して認識させます。
SD-Cardの/boot
フォルダに"ssh"という名前で空のファイルを作成します。これによりRaspberry piが起動直後からSSHが有効化されSSHでパスワードでログインできるようになります。Macであれば以下のコマンドで/boot
フォルダにからファイルが作成できます。
touch /Volumes/boot/ssh
SDカードを"取り出し"てRaspberry piに差し込んで電源をつないで起動させます。このときに、有線LANも接続しておきます。
起動したらsshでユーザ名とRaspberry piのアドレス、パスワードを入れてログインします。初期のユーザ名は"pi"、パスワードは"raspberry"です。IPアドレスは、一旦、ディスプレイとキーボードを接続して取得する方法か、または、ルータのDHCPリース情報から取得する手段があります。
ssh pi@<IP Addres>
password:
ログインできたらパスワードを変更しておきましょう。.sshにリモートのパブリックキーを設定してパスワード入力なしでログインできるようにするのも良いでしょう。
ネットワークブリッジとして設定する
無線LANブリッジ化に必要なパッケージをインストールします。
sudo apt update
sudo apt install -y bridge-utils hostapd
/etc/netowork/interfaces
ファイルに以下を追加します。
auto br0
iface br0 inet dhcp
bridge_ports eth0 wlan0
/etc/hostapd/hostapd.conf
ファイルを以下のように記述します。一番下の2行はアクセスポイントとして動作するときの「SSID」と「WLAN」パスワードを記述します。
interface=wlan0
bridge=br0
driver=nl80211
hw_mode=b
channel=1
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
ieee80211ac=0
wmm_enabled=1
ieee80211d=1
country_code=JP
ieee80211h=1
local_pwr_constraint=3
spectrum_mgmt_required=1
wpa=3
wpa_key_mgmt=WPA-PSK
ssid=raspi_bridge
wpa_passphrase=********
/etc/default/hostapd
ファイルを編集して、「#DAEMON_CONF=""」の行を、以下のように変更します。。
DAEMON_CONF="/etc/hostapd/hostapd.conf"
hostapdサービスを自動起動するように設定します。
sudo systemctl unmask hostapd
sudo systemctl enable hostapd
sudo systemctl start hostapd
WLANがsoft blockされているので使えるようにします。
sudo rfkill unblock 0
Raspberry piを再起動します。
以上でRaspberry PiがWLANブリッジとして設定が完了して、動作を開始します。
試しに他のデバイスを/etc/hostapd/hostapd.conf
ファイルで設定したアクセスポイント名に接続して動作を確認しましょう。
ネットワークエミュレーション機能を設定する
遅延や、パケットロスなどのネットワークエミュレーション機能を使うには「tc コマンド」を使うのですが、標準で使えるようになっているので特に追加インストールの必要はありません。
使い方
tcコマンドには色々な機能と使用方法があるようですが、ここではパケットロスと遅延&ジッターをエミュレーションする方法のみを説明します。tcコマンドはsudo
を使ってルート権限で起動します。ネットワークエミュレーションは、無線LANから有線LANへのパケット送信、またはその逆に、有線LANから無線LANへの送信のそれぞれに設定することができます。
無線LANから有線LANへのパケットの送信にネットワークエミュレータを設定する
準備
初めに、wlan0 --> eth0の通信にネットワークエミュレータを追加します。devの後ろに有線LANのデバイス名'eth0'を指定していますが、これは'eth0'から出ていくパケットにネットワークエミュレーションを追加することを意味しています。
sudo tc qdisc add dev eth0 root netem
遅延の設定
ネットワークエミュレータの遅延を100msに設定変更します。
sudo tc qdisc change dev eth0 root netem delay 100ms
ジッターの設定
ネットワークエミュレータの遅延を100ms、ジッターを±50msに設定変更します。
sudo tc qdisc change dev eth0 root netem delay 100ms 50ms
パケットロスの設定
ネットワークエミュレータをパケットロス5%を発生するように設定変更します。
sudo tc qdisc change dev eth0 root netem loss 5%
削除
ネットワークエミュレータを削除します。
sudo tc qdisc del dev eth0 root
有線LANから無線LANへのパケットの送信にネットワークエミュレータを設定する
eth0 --> wlanの通信にネットワークエミュレータを追加設定するときは、devの後のeth0
をwlan0
に置き換えます。
# 準備(ネットワークエミュレーションの追加)
sudo tc qdisc add dev wlan0 root netem
# 遅延の設定
sudo tc qdisc change dev wlan0 root netem delay 100ms
# ジッターの設定
sudo tc qdisc change dev wlan0 root netem delay 100ms 50ms
# パケットロスの設定
sudo tc qdisc change dev wlan0 root netem loss 5%
# 削除
sudo tc qdisc del dev wlan0 root
検証
パケットロスとジッターの検証例
本当にパケットロスやジッターが狙ったとおり付加されているかを、ネットワークの品質測定ツールである"iPerf3"を使って実測して検証することができます。
iperf3のインストール
iperf3のubuntuへのインストール方法は、
sudo apt update
sudo apt install iperf3
iperf3のmacへインストール方法は、brewコマンドが使えるようになっていれば以下のとおりです。
brew update
brew install iperf3
検証環境
+---------------+ +---------------------+ +---------------+
| PC(Ubuntu) | ======= | Raspberry pi Bridge | ........ | Mac |
| iperf3 Server | LAN | network emulator | Wifi | iperf3 Client |
+---------------+ +---------------------+ +---------------+
Macをラズパイブリッジ経由でLANに接続しLAN上のUbuntu PCとの間の通信品質をiperf3で測定します。
PC(Ubuntu)側でiperf3をサーバーモードで動作させます
# Ubuntu
ubu$ iperf3 -s
Mac側でiPerf3をクライアントモードで立ち上げてUDPのパケットの品質を見てみます。
まずは、tcコマンドでネットワークをクライアントモードで起動します。-uオプションを付けてUDPのパケットロスとJitterを確認します。ここで接続先のホスト名としてubu
を指定します。ここには、iperf3 severが動作するホストのホスト名またはIPアドレスを指定します。
mac$ iperf3 -c ubu -u
Connecting to host ubu, port 5201
...
[ ID] Interval Transfer Bitrate Jitter Lost/Total Datagrams
[ 7] 0.00-10.00 sec 1.25 MBytes 1.05 Mbits/sec 0.000 ms 0/906 (0%) sender
[ 7] 0.00-10.00 sec 1.25 MBytes 1.04 Mbits/sec 0.437 ms 4/906 (0.44%) receiver
自宅環境では、なにも設定しないときにも0.44%のパケロスと 0.4ms程度のジッターが観測されました。
次にラズパイのコンソールでパケットロスを10%に指定します。
pi$ sudo tc qdisc add dev eth0 root netem
pi$ sudo tc qdisc change dev eth0 root netem loss 10%
Macから再度iperf3で測定します。
mac$ iperf3 -c ubu -u
Connecting to host ubu, port 5201
...
[ ID] Interval Transfer Bitrate Jitter Lost/Total Datagrams
[ 7] 0.00-10.00 sec 1.25 MBytes 1.05 Mbits/sec 0.000 ms 0/906 (0%) sender
[ 7] 0.00-10.00 sec 1.12 MBytes 942 Kbits/sec 6.712 ms 93/906 (10%) receiver
パケットロスが約10%になることが確認できました。
続いて、ラズパイのコンソールで遅延を100ms、ジッターを5msに指定します。
pi$ sudo tc qdisc change dev eth0 root netem delay 100ms 5ms
Macから再度iperf3で測定します。
mac$ iperf3 -c ubu -u
Connecting to host ubu, port 5201
...
[ ID] Interval Transfer Bitrate Jitter Lost/Total Datagrams
[ 7] 0.00-10.00 sec 1.25 MBytes 1.05 Mbits/sec 0.000 ms 0/906 (0%) sender
[ 7] 0.00-10.00 sec 1.25 MBytes 1.04 Mbits/sec 6.052 ms 93/904 (10%) receiver
6.0msのジッターが観測されました。
往復の遅延時間については、pingコマンドにより確認することができます。
iperf3 に'-R'オプションを付けて起動すると、server --> client方向の確認をすることができます。
まとめ
Raspberry Piを使って簡易的にネットワークエミュレーション機能付きのWLANブリッジを構築することができました。iperf3を使ってパケットロスとジッターが意図通りに付加されているか検証してみました。