no-image

劣悪なネットワーク環境を再現する #スプラトゥーン2

Pingとは

簡単に言うとネットワークのレスポンスにかかる時間のこと。実はネットワーク対戦では通信速度はあまり重要ではない。
ここで通信速度を宅配業者に置き換えて考えてみる。ここでいうPingとは再配達を依頼してから実際に届くまでの時間に置き換えることができる。
一度に沢山の荷物を運んでくれたとしても、再配達を依頼してから実際に荷物が届くまでに一日かかっていたらちょー困りますよね。
これがネットワーク対戦に通信速度があまり重要ではないという理由です。どうせネットワーク対戦というのは入力されたキーのコマンドをやり取りしているだけなので大した情報量ではないので(多分)

Pingを測定する

某掲示板にやり方が書いてあったので調べてみる。

  1. 有線接続されたパソコンを用意します。
  2. Nintendo Switch のIPアドレスを調べます。
  3. ターミナルから”ping [Nintendo SwitchのローカルIP]”のコマンドを叩く。
  4. ずらーっとPINGを送ってくれるので100回くらい送ったところでCtrl+Cで止める。
  5. ターミナルから”ping  www.google.co.jp”。
  6. ずらーっとPINGを送ってくれるので100回くらい送ったところでCtrl+Cで止める。
64 bytes from 192.168.1.100: icmp_seq=165 ttl=64 time=1.58 ms
64 bytes from 192.168.1.100: icmp_seq=166 ttl=64 time=4.03 ms
64 bytes from 192.168.1.100: icmp_seq=167 ttl=64 time=5.63 ms
64 bytes from 192.168.1.100: icmp_seq=168 ttl=64 time=1.92 ms
64 bytes from 192.168.1.100: icmp_seq=169 ttl=64 time=4.19 ms
64 bytes from 192.168.1.100: icmp_seq=170 ttl=64 time=1.32 ms
64 bytes from 192.168.1.100: icmp_seq=171 ttl=64 time=1.26 ms
64 bytes from 192.168.1.100: icmp_seq=172 ttl=64 time=1.32 ms
64 bytes from 192.168.1.100: icmp_seq=173 ttl=64 time=1.28 ms
^C
--- 192.168.1.100 ping statistics ---
173 packets transmitted, 173 received, 0% packet loss, time 172238ms
rtt min/avg/max/mdev = 1.149/2.172/35.921/2.830 ms
64 bytes from nrt13s37-in-f227.1e100.net (216.58.220.227): icmp_seq=59 ttl=54 time=14.4 ms
64 bytes from nrt13s37-in-f227.1e100.net (216.58.220.227): icmp_seq=60 ttl=54 time=14.3 ms
64 bytes from nrt13s37-in-f227.1e100.net (216.58.220.227): icmp_seq=61 ttl=54 time=14.4 ms
64 bytes from nrt13s37-in-f227.1e100.net (216.58.220.227): icmp_seq=62 ttl=54 time=14.8 ms
64 bytes from nrt13s37-in-f227.1e100.net (216.58.220.227): icmp_seq=63 ttl=54 time=14.4 ms
64 bytes from nrt13s37-in-f227.1e100.net (216.58.220.227): icmp_seq=64 ttl=54 time=14.2 ms
64 bytes from nrt13s37-in-f227.1e100.net (216.58.220.227): icmp_seq=65 ttl=54 time=14.5 ms
64 bytes from nrt13s37-in-f227.1e100.net (216.58.220.227): icmp_seq=66 ttl=54 time=14.7 ms
^C
--- www.google.co.jp ping statistics ---
66 packets transmitted, 65 received, 1% packet loss, time 65104ms
rtt min/avg/max/mdev = 14.154/14.400/14.863/0.163 ms

これはローカルの遅延とグーグルのサーバとの遅延なのでそれを足してみる。
[table id=4 /]
あれ、うちの回線環境めっちゃいいやん?パケロス率が1%あるのが気になるところだけど、無線だからまあ仕方ないかって感じ。
15msということは0.015秒に相当するわけです。最も秒間発射数が高いスライド後のスパッタリーですら1秒に15発しか撃てないので1発撃つのに0.067秒かかります。となると0.015秒の遅延では0.25発くらいしか撃てないわけですね。
これでは2発しか当たってないのに3確ブキでやられた!みたいなことは起こらないわけです。

衝撃的な書き込みをみた

某掲示板で遅延について調べていたところこんな書き込みを見つけてしまいましたん。

481: イカ名無しに変わりましてイカ速がお送りします 2018/02/20(火) 16:01:19.38 ID:0DIKdwro0
いちおうネットワーク技術者やっとるものだが、前作のころ業務用ルータ使って実験したんだわ。
pingは1000msまで遅延させても回線落ちにはならない。パケロスは1%くらいであっさり回線エラーになる。ちなみに上りだけ遅延挿入するとアホみたいに撃ち勝てるようになるw

これマジで!?(あくまでスプラトゥーン1の話ですが)
業務用ルータっていうとコンシューマ向けのバッファローとかではなくて、ヤマハとかの高いやつだと思われ。遅延挿入っていうのはネットワーク環境をいろいろ再現するためのオプション機能だと思います。
ソフトウェア開発はいろいろな状況を想定しなければいけませんが、その一つとして当然ユーザのネットワーク状態が悪いということも考えられます。よってネットワーク状態が悪い状況でのテストも必要なのですが、そんな状態を再現できないと困るわけですね。

同じことを家庭用ルータで再現できないか?

当然普通のルータでは無理。
そこで家庭用ルータにDD-WRTを導入します。DD-WRTというのは簡単に言うとルータ用のカスタムファームウェア。バッファローのルータだとだいたい使えます。
[amazonjs asin=”B00GY0BXPG” locale=”JP” title=”BUFFALO 11n/a/g/b 300プラス300Mbps 無線LAN親機 WZR-600DHP3″]
ちょっと高いんだけど5GHzの電波も使えるのがいいところ。というか昨今のマンションだと2.4GHz帯の電波が飛びすぎていて干渉が酷いです。特にbluetoothなんか使い物にならなくなったりします。
[amazonjs asin=”B00D8QXSDO” locale=”JP” title=”BUFFALO QRsetup 11n/g/b 300Mbps 無線LAN親機 WHR-300HP2″]
こっちは2.4GHzしか対応していない。その代わりやすいというメリット。
どっちもDD-WRTを導入したことがあるのでまあ大丈夫。一応参考にしてください。

DD-WRTの設定

とここで問題が発生した。
DD-WRTは最小限の機能しかついていないのでtcコマンドが実装されていないのだ。

Ubuntuで再現

DD-WRTで再現しようとしたのだが、諦めてUbuntuで再現することにする。

Squid3を使う

Squid3がプロクシサーバとして機能するらしいのでそれをインストールします。3と無印があるらしいのだけれども、何が違うのかよくわかっていない。

sudo apt install squid3

で、設定を更新する。設定はconfファイルに書かれているので、中身全部消して以下の記述だけ行う。

acl localnet src 192.168.1.0/16 #me
http_access allow localnet
http_access allow localhost
http_port 8080

内容はわざわざ説明するまでもないと思うけれど、アクセス制限を設けて、ポートを8080に変更するっていうだけです。

sudo service squid status
● squid.service - LSB: Squid HTTP Proxy version 3.x
   Loaded: loaded (/etc/init.d/squid; bad; vendor preset: enabled)
   Active: active (running) since Sun 2018-03-18 08:07:48 JST; 1min 19s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 2147 ExecStop=/etc/init.d/squid stop (code=exited, status=0/SUCCESS)
  Process: 2177 ExecStart=/etc/init.d/squid start (code=exited, status=0/SUCCESS)
    Tasks: 4
   Memory: 18.2M
      CPU: 149ms
   CGroup: /system.slice/squid.service
           ├─2218 /usr/sbin/squid -YC -f /etc/squid/squid.conf
           ├─2220 (squid-1) -YC -f /etc/squid/squid.conf
           ├─2221 (logfile-daemon) /var/log/squid/access.log
           └─2222 (pinger)
Mar 18 08:07:48 TKG systemd[1]: Stopped LSB: Squid HTTP Proxy version 3.x.
Mar 18 08:07:48 TKG systemd[1]: Starting LSB: Squid HTTP Proxy version 3.x...
Mar 18 08:07:48 TKG squid[2177]:  * Starting Squid HTTP Proxy squid
Mar 18 08:07:48 TKG squid[2177]: 2018/03/18 08:07:48| aclIpParseIpData: WARNING: Netmask masks away part of the specified IP
Mar 18 08:07:48 TKG squid[2218]: Squid Parent: will start 1 kids
Mar 18 08:07:48 TKG squid[2177]:    ...done.
Mar 18 08:07:48 TKG systemd[1]: Started LSB: Squid HTTP Proxy version 3.x.
Mar 18 08:07:48 TKG squid[2218]: Squid Parent: (squid-1) process 2220 started

ということでSquidは正しく動いているらしい。

パスワードを設定する

認証のためのユーザー設定をします。
sudoをつけないと普通にファイルが作成できないとこで怒られてしまったのでちゃんとしましょう。

sudo htpasswd -c /etc/squid/passwd "username"

実際にやってみた感じがこれ。

sudo htpasswd -c /usr/lib/squid/passwd me
New password:
Re-type new password:
Adding password for user me

なんかうまく設定できたっぽい。

Nintendo Switchで設定する

Nintendo Switchのネットワーク設定からProxy Settingsで設定する。

  • Server 192.168.1.138 (UbuntuのIPアドレス)
  • Port 8080
  • Automatic Authentication
    • User me
    • Password “設定したパスワード”

こんな感じで設定。
接続テストをしたらうまくいきました。やった!!

遅延, パケロスを設定する

オンラインでやると仲間に迷惑がかかるのでプライベートマッチで実践する。

ネットワークアダプタを確認する

通常はeth0が使われていたりするのだが、場合によっては異なるので確認する。調べるのはifconfigコマンドを利用する。

ifconfig
enp8s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.106  netmask 255.255.255.0  broadcast 192.168.1.255
        inet6 fe80::428d:5cff:fe1e:46e7  prefixlen 64  scopeid 0x20<link>
        ether 40:8d:5c:1e:46:e7  txqueuelen 1000  (Ethernet)
        RX packets 2425173  bytes 1813019224 (1.8 GB)
        RX errors 0  dropped 33  overruns 0  frame 0
        TX packets 2249191  bytes 2874750823 (2.8 GB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 12630  bytes 989768 (989.7 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 12630  bytes 989768 (989.7 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0ではなくenp8s0という名前だったのでそれをどこかにメモしておく。

遅延を挿入する

enp8s0に対して遅延を挿入する。遅延を挿入するにはtcコマンドを利用する。

sudo tc qdisc add dev enp8s0 root netem delay 100ms

パケットロスを設定する

パケットロスを設定する。

sudo tc qdisc add dev enp8s0 root netem loss 10%

1%でエラーが発生するというので試しに10%で設定してみる。これで実際にやってみます。

検証(この辺は詳しくやりたい)

ナワバリバトルのプライベートマッチで実験してみた。
というか、プライベートマッチをやると毎回何故か通信切断されるんですよね(謎)

何もしない

ちょうど1分経ったら接続切れしました。
この何もしなくても接続切れするのは何なんでしょうねえ…

パケロスする機体がホスト

ちょうど1分経ったら接続切れしました。

パケロスする機体がクライアント

ちょうど1分経ったら接続切れしました。

本当に遅延できているのか

ここまで差がないと本当に遅延設定が効いているのか微妙になってくるので、スイッチのインターネット接続テストを利用してみることにしました。
[table id=5 /]
遅延があると実際に通信が行われるまでにラグが発生するので実質、通信速度が遅くなる。この結果からdelayを挿入するとそれに従って通信速度が遅くなっています。つまり、正しく反映されていることがわかります。
ちなみにこれは無線での結果なので、有線だともうちょっと良い結果がでる可能性があります。

結論

仮に500ms遅延したとしたらスパッタリーで7.5発も撃ててしまいます。これだけ遅延すれば確かにいくらでも打ち勝てそうですね。
もちろん、実際にラグで撃ち勝てるかは別にして、

良い子は真似しないようにしましょう!!!!!