はじめに
過去にトラブルシューティングでTCPについて深く学習する必要がありまして
その際に学んだ情報で、ネットで調べてもすぐ出てこない情報を記事にしたいと思います。
2:送信バッファについて
3:受信ウインドウについて
4:輻輳ウインドウについて
前提となる知識や要点
この記事でお伝えしたいことをまとめると
・TCPの送信ウインドウサイズの大きさがスループットを決める(前提知識)。
・送信ウインドウサイズを決める要素として、受信ウインドウ(rwnd)と輻輳ウインドウ(cwnd)が存在する(ブログで解説)。
・受信ウインドウ(rwnd)と輻輳ウインドウ(cwnd)の大きさを比較して、小さい方が送信ウインドウサイズとして採用される(ブログで解説)。
・その結果、輻輳が原因でスループットが上がらない場合が多いと思われる(管理人の初見)。
これを踏まえながら解説を見ていただくと理解しやすいと思われます。
1:受信バッファについて
以下の2つで構成されています。
A:確認応答を返したものの、まだアプリケーションにデータを渡せていない領域
A’:空き領域
図1:受信バッファ
この中でA’:空き領域が所謂受信ウインドウで通知するサイズとなります。TCPヘッダのウインドウ・サイズで16bitで定義されている箇所です(余談となりますがオプション部で更に拡張可能となります)。これをACKで返答する際に送信側に通知することで、送信側は確認応答(Ack)無しで受信側が受け取ることができるバッファサイズを知ることが出来ます。
2:送信バッファについて
以下の2つで構成されています。
B:既に送信済みではあるものの、確認応答(Ack)が帰ってきていない領域。
B’:送信準備は完了したものの、まだ送信していない領域。
図2:送信バッファ
3:受信ウインドウについて
前述したとおり、受信ウインドウ(rwnd)のサイズをAckで送信元に通知することで、
送信側は受信側バッファで受け取ることができるデータサイズを知ることができます。
可能な限り一度にデータを送った方が効率が良いので、このサイズを目途にAckを待たずにパケットを送ります。この場合、送信ウインドウサイズ = 受信ウインドウサイズ(rwnd)です。
しかし、実際には帯域の太さや混雑具合のためrwndまで送ることが難しい場合があります。そのような場合は輻輳ウインドウ(cwnd)の出番です。
4:輻輳ウインドウについて
輻輳ウインドウ(cwnd)は輻輳制御[送信側が行う流量調整]で用いられるもので、
送信するTCPセグメントの個数をこれで制御しています。
輻輳ウインドウズサイズの初期値は、送信するTCPセグメントの数がwindows10などでは
デフォルト値で10と定義されているため、cwnd = 1460 × 10 = 14600(byte)となります。
少し話が脱線しますが、cwndについて理解するために以下の概念について説明します。
①スロースタートアルゴリズム
初期の輻輳ウインドウズサイズを指数関数的に上げていくフェーズです。
巨大なファイルを転送する試験などで、wiresharkでパケットを取得するとわかるのですが
0.1マイクロ秒以下の時間単位でサイズが増えていくものと思われます。
予め定められている閾値(ssthresh)を超えるか、使用している輻輳制御アルゴリズムによって輻輳を検知したらcwndを半分まで下げます。
図3:スロースタートアルゴリズム及び輻輳回避フェーズ時の輻輳ウインドウ(cwnd)の関係
出典:https://gihyo.jp/admin/serial/01/tcp-cc/0001
②輻輳回避フェーズ
前述したとおり、閾値を超えたり輻輳を検知した場合はcwndは半分まで下がります。
その後は指数関数的に増えていくのとは異なり、少しずつゆっくりとcwndを増やしていきます。これが輻輳回避フェーズであり、輻輳を再度検知するとcwndが更に半分になります。
※実際は採用している輻輳制御アルゴリズムによって仕様が異なります。
①ロスベース②遅延ベース③ハイブリッドベースの3種類があるのですが
基本的には③が使用されています。CUBICやCTCP(windows10で採用)などが該当します。
図4:輻輳制御アルゴリズムの種類
出典:https://gihyo.jp/admin/serial/01/tcp-cc/0002
話を元に戻します。ここで大事なのは
輻輳ウインドウサイズ(cwnd)が送信ウインドウサイズに成り得ることです。
以下の場合に送信ウインドウサイズ= 輻輳ウインドウサイズ(cwnd)となります。
輻輳ウインドウサイズ(cwnd) < 受信ウインドウサイズ(rwnd)
cwndとrwndの関係性を図にしてみた
図5:cwndとrwndの関係性
①受信側は自分が処理できるデータ量(=受信バッファサイズ)を
②送信元への確認応答(Ack)に含めて通知する。
③送信側は輻輳ウインドウサイズ(cwnd) と受信ウインドウサイズ(rwnd)を比較。
小さい方を送信ウインドウサイズとして採用する。
④送信ウインドウサイズに応じたTCPセグメントが送信側から受信側へ送られる。
つまり、受信側でデータを大量に受け取ることができる余力がいくらあっても
図のように、1Gbpsの回線で既に800Mbps使われているなど、大量にデータを送ると渋滞する状況であれば輻輳ウインドウサイズ(cwnd)に従った方がよいよね!という判断を送信元でするわけです。
そのため、受信バッファに余力がある場合でも、途中の通信経路の帯域が狭い場合や輻輳・パケットロスが多発している場合は送信元にて確認応答(Ack)無しで一度に送ることができるデータ量が小さくなり、送信レートが低くなります。
コメント
It’s going to be finish of mine day, but before finish I am reading this fantastic
post to increase my experience.
Having read this I thought it was extremely informative.
I appreciate you taking the time and effort to put
this information together. I once again find myself spending
a significant amount of time both reading and leaving comments.
But so what, it was still worthwhile!