読者です 読者をやめる 読者になる 読者になる

エンジニアですよ!

頑張れ俺くん、巨匠と呼ばれるその日まで

TCPのTail Loss Probeと再送周りについて少し

linux tcp

仕様は RFC にはないっぽくて(?) 2013年にgoogleの方々が出してるinternet draft で定義されている模様。

Tail Loss Probe は、一連の送信パケットの最後のパケットがロスした場合に、送信側が再送タイムアウトを待たずにロスを検知して回復することを目的としている。

パケットがロスした時、後続のパケットが次々と送られている場合はduplicate ackが返されるため、fast retransmitによってリカバリすることができる。

しかし、末尾のパケットや途中から末尾までウィンドウいっぱいのパケットがロスしてしまった場合などは、dup ackが届かないためfast retransmitはトリガーされないため再送タイムアウトまでリカバリできない。

再送タイムアウトを待つと時間がかかりすぎるし、タイムアウトが発生すると輻輳ウィンドウが小さくなってスロースタートからやり直しになってしまう。

そのためなんとか末尾のパケットのロスもタイムアウトより先に検知してリカバリしたいというのが動機。

それをどうやって実現しているかというと、簡単には次のような感じ。

再送タイムアウト(RTO)とは別に、probe timeout (PTO) を定義する。PTOの初期値は先述のdraftで max(2 * SRTT, 10ms) となっており、linuxのRTOの初期値の1秒と比べると短め。

で、データを送信するたびにPTOをスケジュールして、タイムアウトを迎えたらプローブを送信するというもの。

プローブとしては、まだ送っていないセグメントがある場合は新しいセグメントを送り、ない場合は最後に送信したセグメントを再送する。

プローブを送ることで、

  1. 最後のセグメントだけがロスしている場合、最後のセグメントを再送することによってリカバリできる。
  2. 複数のセグメントがロスしている場合、プローブによって他のリカバリの仕組みがトリガーされてリカバリできる。

他のリカバリの仕組みというのは、early retransmit[RFC5827]FACK fast recoveryなど。

early retransmitは、ネットワークに送出されているセグメントが4つ未満である場合、fast retransmitをトリガーするduplicate ackの回数を減らすというもの。

SACKオプションが有効な場合は、(送出中のセグメント-1)回のdup ackを受け取り、かつ最後のセグメントがSACKされている場合は再送する。

例えば最後の2つのセグメントがロスした場合、duplicate ackを受け取ることはないので、TLPがない場合はタイムアウトまで再送されることはない。

TLPがある場合は、PTO後に最後のセグメントを再送するので、それがちゃんと届けば送信側は最後のセグメントがSACKされたdup ackを受け取り、early retransmitにより(dup ackのthreasholdが低くなっているのでfast retransmitがトリガーし)ロスしたセグメントが再送される。

最後の3つのセグメントがロスした場合については1つのプローブを再送しただけではRFC5827のearly retransmitの範囲では再送するには足りないので、最後のセグメントがSACKされたら再送し始めるアルゴリズムを提案している。(proportional rate reduction algorithm。http://conferences.sigcomm.org/imc/2011/docs/p155.pdf

FACK fast recoveryも、同じくduplicate ackの数が少なくても再送しようというもの。

再送する時duplicate ackを3つ以上受け取ったら、となっているのはパケットの順序が入れ替わっただけの場合でもduplicate ackを受け取る可能性はあるからだが、FACK fast recoveryでは順序の入れ替わりであっても抜けが多かったら再送してしまおうというもの。(超ざっくり)

SACKされている最大のack番号と、送信済みでackされていない最小のシーケンス番号の差が3(fast retransmitをトリガーするdup ackの閾値)以上なら再送する。

最後のセグメントを含む4つ以上のセグメントがロスしている場合、再送されたプローブが届いたらこれで再送が始まり、リカバリできる。

ちなみに上記の通り色々な箇所でSACKが使われているので受信者側がSACKオプションを使えることは必須。

ということでTLPでロスをリカバリできるようになる、ということでした。

(主に参照したdraftが古いので、既に古いところはありそう)