前回記事に対して、「ICMP(ping)のパケットの優先度を落としているだけでは」という意見も幾つかあったようだ。
本文でも書いているとおり、僕自身はパケットロス率に注目したのではなく、それに伴うラウンドトリップタイム(RTT)の時間帯での差異から(ICMP/TCPあるいはUDP関わらず)バックボーンを守るための何らかのパケット制限がかけられているのではないか、という見解だ。
ただ70-90%という値があまりにセンセーショナルだったため数字が一人歩きしたか、エントリー全文が読まれていないということかと思うのだが、せっかくなので、ではTCPではどうなのか確かめてみた。以下、その結果。
テスト概要
前回と同じJailBreakしたiPhone3GSにてソフトバンク iPhone通常回線(smile.world)とドコモ データ定額(mopera.flat.foma.ne.jp)でSafariから3ページ表示させ、その間にパケットロスなどがどのように発生しているか計測する。
テスト方法
SSHでiPhoneへログイン、tcpdumpを実行した後Safariで同一サーバー3ページを順次表示、その後netstat -sにて統計値も取得する。テスト前にはiPhoneは再起動しておく(つまりnetstat統計値をクリア)。
テストサーバー
前回のテストサーバー2(さくらインターネットのVPS、国内設置。つまりはこのサーバーである)
netstat計測値については起動直後にテストを開始しているとは言えsshアクセスなども含まれるので絶対値ではないことに注意して欲しい。各テスト間での相対値に注目したい。
以上だが、まずはリファレンスとしてWi-Fi(フレッツ光)アクセス時のnetstat値を示す。つまり基本的には回線上何のストレスもかかっていない場合と理解することが出来るだろう。
以下、テスト時間帯はPM10時台である。
なおこの時点でSB回線でのpingテストではロス率54%程度を示していたが、Wi-Fi環境では0%である。
実施時間: PM10時台
iPhone3GS:/var/mobile root# netstat -s tcp: 937 packets sent 210 data packets (60643 bytes) 1 data packet (80 bytes) retransmitted 0 resends initiated by MTU discovery 485 ack-only packets (7 delayed) 0 URG only packets 0 window probe packets 123 window update packets 118 control packets 1112 packets received 329 acks (for 60701 bytes) 77 duplicate acks 0 acks for unsent data 722 packets (694013 bytes) received in-sequence 4 completely duplicate packets (192 bytes) 0 old duplicate packets 0 packets with some dup. data (0 bytes duped) 58 out-of-order packets (79106 bytes) 0 packets (0 bytes) of data after window 0 window probes 0 window update packets 0 packets received after close 0 bad resets 0 discarded for bad checksums 0 discarded for bad header offset fields 0 discarded because packet too short 61 connection requests 1 connection accept 0 bad connection attempts 0 listen queue overflows 62 connections established (including accepts) 37 connections closed (including 3 drops) 0 connections updated cached RTT on close 0 connections updated cached RTT variance on close 0 connections updated cached ssthresh on close 0 embryonic connections dropped 325 segments updated rtt (of 324 attempts) 1 retransmit timeout 0 connections dropped by rexmit timeout 0 persist timeouts 0 connections dropped by persist timeout 0 keepalive timeouts 0 keepalive probes sent 0 connections dropped by keepalive 0 correct ACK header predictions 530 correct data packet header predictions 0 SACK recovery episodes 0 segment rexmits in SACK recovery episodes 0 byte rexmits in SACK recovery episodes 0 SACK options (SACK blocks) received 48 SACK options (SACK blocks) sent 0 SACK scoreboard overflow
今回ポイントになりそうなところは強調しておいた。
まず送信210パケットに対して同再送によるパケット送信は1に止まっている。また61セッションに対する再送回数は1回だ。
再送というのは一般的には途中回線品質などにより送信パケットがロスし、受信側が送信側へパケットが欠けていることを通知し再び欠けているところから送信が再度行われたことを意味している。影響は欠けた1パケットに止まるのではなく、セッション中欠けたところから全て再送されなければならないので、受信バッファが大きいとそれだけコストの高い再処理となる。
Wi-Fi環境でも起き得る一般的な現象であることはここから分かるだろう。しかしそれは全体に対して大したインパクトでも無さそうだ。
また以下はtcpdumpから該当箇所を抜き出した例だ。
ソフトバンク回線の場合
次にソフトバンク回線で試した。以下は同様にnetstat値である。
iPhone3GS:/var/mobile root# netstat -s tcp: 1697 packets sent 192 data packets (88115 bytes) 28 data packets (20512 bytes) retransmitted 0 resends initiated by MTU discovery 1043 ack-only packets (24 delayed) 0 URG only packets 0 window probe packets 212 window update packets 222 control packets 1566 packets received 412 acks (for 88176 bytes) 241 duplicate acks 0 acks for unsent data 1032 packets (1050871 bytes) received in-sequence 110 completely duplicate packets (77865 bytes) 0 old duplicate packets 0 packets with some dup. data (0 bytes duped) 0 out-of-order packets (0 bytes) 0 packets (0 bytes) of data after window 0 window probes 0 window update packets 1 packet received after close 0 bad resets 0 discarded for bad checksums 0 discarded for bad header offset fields 0 discarded because packet too short 112 connection requests 1 connection accept 0 bad connection attempts 0 listen queue overflows 113 connections established (including accepts) 101 connections closed (including 2 drops) 0 connections updated cached RTT on close 0 connections updated cached RTT variance on close 0 connections updated cached ssthresh on close 0 embryonic connections dropped 408 segments updated rtt (of 400 attempts) 174 retransmit timeouts 0 connections dropped by rexmit timeout 0 persist timeouts 0 connections dropped by persist timeout 0 keepalive timeouts 0 keepalive probes sent 0 connections dropped by keepalive 0 correct ACK header predictions 789 correct data packet header predictions 11 SACK recovery episodes 0 segment rexmits in SACK recovery episodes 0 byte rexmits in SACK recovery episodes 0 SACK options (SACK blocks) received 0 SACK options (SACK blocks) sent 0 SACK scoreboard overflow
違いに気付いてもらえるだろうか。再送率が格段に上がっている。
112回のセッションに対して再送は174回起きている。つまり1セッション当たり1-2回は送信がやり直されている計算になる。
以下はtcpdumpから一部のセッションを抜き出したものだ。
ドコモ回線ではどうか
同様にnetstat値を示す。
iPhone3GS:/var/mobile root# netstat -s tcp: 1262 packets sent 211 data packets (114082 bytes) 15 data packets (9984 bytes) retransmitted 0 resends initiated by MTU discovery 645 ack-only packets (15 delayed) 0 URG only packets 0 window probe packets 175 window update packets 216 control packets 1336 packets received 425 acks (for 113728 bytes) 138 duplicate acks 0 acks for unsent data 764 packets (765746 bytes) received in-sequence 17 completely duplicate packets (15598 bytes) 0 old duplicate packets 0 packets with some dup. data (0 bytes duped) 129 out-of-order packets (118511 bytes) 0 packets (0 bytes) of data after window 0 window probes 0 window update packets 0 packets received after close 0 bad resets 0 discarded for bad checksums 0 discarded for bad header offset fields 0 discarded because packet too short 108 connection requests 1 connection accept 0 bad connection attempts 0 listen queue overflows 109 connections established (including accepts) 75 connections closed (including 0 drops) 0 connections updated cached RTT on close 0 connections updated cached RTT variance on close 0 connections updated cached ssthresh on close 0 embryonic connections dropped 417 segments updated rtt (of 417 attempts) 35 retransmit timeouts 0 connections dropped by rexmit timeout 0 persist timeouts 0 connections dropped by persist timeout 0 keepalive timeouts 0 keepalive probes sent 0 connections dropped by keepalive 2 correct ACK header predictions 598 correct data packet header predictions 1 SACK recovery episode 0 segment rexmits in SACK recovery episodes 0 byte rexmits in SACK recovery episodes 10 SACK options (SACK blocks) received 49 SACK options (SACK blocks) sent 0 SACK scoreboard overflow
ドコモ回線とてWi-Fi並みの品質ではないと言えるだろう。しかしその再送回数は108セッション中35回であるので単純に考えると75%程度のセッションでは再送は行われず綺麗に完了している計算だ。
AM3時台のソフトバンク回線
次にAM3時台のソフトバンク回線の例も示そう。この時点でpingパケットロス率は0%になっている。
iPhone3GS:/var/mobile root# netstat -s tcp: 948 packets sent 156 data packets (60612 bytes) 13 data packets (9747 bytes) retransmitted 0 resends initiated by MTU discovery 530 ack-only packets (14 delayed) 0 URG only packets 0 window probe packets 114 window update packets 135 control packets 960 packets received 291 acks (for 60613 bytes) 87 duplicate acks 0 acks for unsent data 649 packets (626454 bytes) received in-sequence 16 completely duplicate packets (11814 bytes) 0 old duplicate packets 0 packets with some dup. data (0 bytes duped) 44 out-of-order packets (62216 bytes) 0 packets (0 bytes) of data after window 0 window probes 3 window update packets 0 packets received after close 0 bad resets 0 discarded for bad checksums 0 discarded for bad header offset fields 0 discarded because packet too short 67 connection requests 3 connection accepts 0 bad connection attempts 0 listen queue overflows 70 connections established (including accepts) 46 connections closed (including 0 drops) 0 connections updated cached RTT on close 0 connections updated cached RTT variance on close 0 connections updated cached ssthresh on close 0 embryonic connections dropped 281 segments updated rtt (of 273 attempts) 25 retransmit timeouts 0 connections dropped by rexmit timeout 0 persist timeouts 0 connections dropped by persist timeout 0 keepalive timeouts 0 keepalive probes sent 0 connections dropped by keepalive 0 correct ACK header predictions 479 correct data packet header predictions 0 SACK recovery episodes 0 segment rexmits in SACK recovery episodes 0 byte rexmits in SACK recovery episodes 0 SACK options (SACK blocks) received 38 SACK options (SACK blocks) sent 0 SACK scoreboard overflow
ドコモに比べれば率は悪いものの、PM11時時点に比べればかなり改善されていることが分かる。
つまり時間帯により何らかの外的要因により(要するに回線品質)変動が起きていると言えるだろう。
ICMPとTCPが異なったポリシーで優先度が変えられているかも知れないという意見については同意だ。
しかしそれは外部から判別できるものではなく(予想は大いにされているようだが)正直なところ中の人にでも聞かなければ分かるはずもない。
ただ繰り返しになるが、これは憶測でしかないがTCPでも同様の傾向がある以上、何らかの運用ポリシーがあるのは間違いなさそうだし、そもそもRTT変動からすれば繁忙期にバックボーンを守るための何らかの施策が関わっている可能性は高いのではないかと思う。
なおエビデンスとして、こちらにtcpdump結果を公開しておく。参考にして欲しい。
前回も書いたとおり、筆者は専門家でも詳しいわけでもないのであまり応答することはないと思うが、意見や見解・議論などは大いに拝見できればと思っている。
なお、僕自身は仮に内部的に問題抱えていようと、「いいじゃん、普通に使えるなら。他社より安いし」という立場です。
tcpdumpの結果を拝見しましたが、上りのトラフィックで再送が起こっているのは、全てHTTP GETリクエストのパケットのようですね。
下りの再送も、上りで再送が起こったセッションと同一のセッションで発生していることが多いようです。
特定のHTTPリクエストでレスポンスが返ってくるのが想定より遅かった(それまでの通信のRTTから計算したRTOの時間内にレスポンスが返って来なかった)ために、再送タイムアウトが発生したのかも知れません。
1秒前後でリクエストを再送している例が多くありました。
回線の太さや混雑具合が引き金になっていると思いますが、最終的にはエンドホストの問題のように見えました。
時間帯で変わるみたいですね。
こちらでも、iPhone4使って試してみましたが、この時間帯は、
20MByteのファイルのUPLoad/DownLoadを試しても、
どちらも大きな再送などは発生しませんでした。@東京都北部
#データのダウンロードでは上位のスイッチ-iPhone間での、
#再送が発生したとしても、netstat上ではカウントされない
#気がするので、正確な再送率を調べるのは難しいようですが。