TCP ウィンドウ プローブ

TCP ウィンドウ プローブ

最初に Networking SE で質問したときに、このサイトを紹介されました。

TCP の rwnd アドバタイズメントについていくつか質問があります。RFC を読みましたが、答えが見つかりませんでした (または、何か見逃しているかもしれません)。回答の一部は実装に依存する可能性があります。この場合は、一般的なケースで何が起こるかを知りたいので、ご経験に基づいて回答してください。

TCP 標準では次のように規定されています。

送信 TCP は、送信ウィンドウがゼロの場合でも、ユーザーからの受信と少なくとも 1 オクテットの新しいデータの送信を準備する必要があります。

その理由は、ウィンドウ プローブ メッセージに 1 オクテットのデータが含まれているためだと推測します。しかし、次のようなことも考えさせられました。

  1. プローブ パケットには 1 オクテットの新しいデータが含まれていなければならないと標準で明記されているのを見たことはありません。ウィンドウ サイズをプローブする別の方法はありますか?

  2. それが唯一の方法であるならば、古いセグメント(古いシーケンス番号付き)を再送信するだけでは不十分なのはなぜでしょうか。受信側は、特定の瞬間にウィンドウ内にあるデータのみを確認する必要があります(つまり、古いデータは必ずしも確認されません)。つまり、プローブ パケットをそのルールの例外として扱う必要があるということですか。

  3. 一般的に言えば、受信側はウィンドウのサイズが大きくなったときに送信側に通知しますか? 通知は必ず行う必要がありますか (ack が失われる可能性があるため、送信側がとにかく調査する必要がある可能性があると理解しています)?

  4. プローブ パケットは必要な場合にのみ送信されますかwindow = 0、それともその前に送信される可能性がありますか?

答え1

その理由は、ウィンドウ プローブ メッセージに 1 オクテットのデータが含まれているためだと考えられます。

明確にしておくと、ウィンドウ プローブ パケットには特別なパケット形式、ヘッダー、またはその他の識別子はありません。TCP は、ウィンドウをプローブする必要があるときに、標準の TCP パケットを送信するだけです。その TCP パケット内のユーザー/アプリケーション データは、たまたま 1 つのオクテットに制限されます。

  1. プローブ パケットには 1 オクテットの新しいデータが含まれている必要があると標準で明記されているのを見たことはありません。

先ほど、プローブ パケットには少なくとも 1 オクテットの新しいデータが含まれていなければならないという標準の記述を引用しましたね。追加の記述が必要な場合は、RFC 793 および RFC 1122 に、新しいアプリケーション データのない ACK は確実に転送されない (つまり、新しいデータが転送されたかどうかを知るためには、何らかの新しいデータを送信する必要がある) ことを注意する記述があります。

ウィンドウのサイズを調べるにはさまざまな方法がありますか?

TCP 標準の作成者が他の方法を思いついた可能性もあると考えられますが、あなたが引用した方法は、標準で規定されている唯一の方法です。

  1. それが唯一の方法であるならば、古いセグメント(古いシーケンス番号付き)を再送信するだけではなぜ不十分なのか疑問に思います。

それは十分かどうかの問題ではなく、何が最善の方法かという問題です。送信するデータがない場合は、ウィンドウをプローブする必要はありません。するさらに送信するデータがある場合は、それ以前に送信された(そしておそらく確認応答された)データに帯域幅を浪費するのではなく、ウィンドウをプローブしますか?

受信側は、特定の瞬間にウィンドウ内にあるデータのみを確認する必要がありますか(つまり、古いデータは必ずしも確認されません)

受信側は、受信した最新のデータ、つまり最初から受信したすべてのデータと連続しているデータのみを確認する必要があります (連続しているというのは、1 つ以上のパケットを逃したためにホールが発生し、その後にパケットを受け取った場合、その後のパケットを確認できないということです。最初のホールの前の最後のシーケンス番号を確認し続ける必要があります)。

  1. 一般的に、受信側はウィンドウのサイズが大きくなったときに送信側に通知しますか?

はい、一般的に言えば、受信側は Ack ごとにウィンドウ サイズの更新を送信側に通知します。

また、RFC 793 の 43 ページの「ウィンドウ管理の提案」では、著者は TCP 受信側が「ウィンドウが大きくなったときに、新しいウィンドウ情報を含む別の確認応答を送信する」ことを提案しています。この RFC は、MAY/SHOULD/MUST の用語標準を定義した RFC 2119 より前のものですが、この提案は、RFC 2119 の要件レベル ガイダンスでは SHOULD と見なされるようです。

それを実行する必要がありますか (ack が失われる可能性があるため、送信者はとにかくプローブする必要がある可能性があることを理解しています)?

RFC 793 を更新してこの動作を必須にする RFC は知りません。

プローブ パケットは、ウィンドウ = 0 の場合にのみ送信されますか、それともその前に送信されることがありますか?

ウィンドウがゼロでない場合、単一データ バイトの TCP セグメントは実際にはプローブとは見なされません。たとえば、リモート ホストに個別のキーストロークを送信する Telnet 接続がある場合、各キーストロークは単一データ バイトの TCP セグメントとして送信される可能性があります。Telnet などのケースでは、ウィンドウが 0 または 1 より大きい場合でも、これらを送信しても問題ありませんが、プローブとは見なされません。

答え2

これはスピフの答え、しかしコメントに収まりきらないほど多くの追加事項があります。2022年8月にはRFC9293最終的に元の TCP 仕様を置き換え、すべての MUST/SHOULD/MAY 言語が含まれます。

Q1. プローブ パケットには 1 オクテットの新しいデータが含まれている必要があると標準で規定されているのを見たことはありません。

1オクテットに限定されない以下の要件は、元のTCP仕様にありました。RFC793そして、RFC9293 にそのままコピーされました:

When the receiving TCP peer has a zero window and a segment arrives, it must
still send an acknowledgment showing its next expected sequence number
and current window (zero).

Q2. 古いセグメントを再送信するだけでは不十分なのはなぜでしょうか

これは最も効率的な方法ではありません(ウィンドウが十分に大きくなると、オクテットは破棄されなければなりません)。しかし、TCP輻輳制御の仕様では常に次のように述べられているため、これは機能します。RFC5681今はこう言っています。

A TCP receiver SHOULD send an immediate duplicate ACK when an out-of-
order segment arrives.

Q3. 一般的に、受信側はウィンドウのサイズが大きくなったときに送信側に通知しますか?

受信側アプリケーションが受信バッファからデータを消費するため、受信側のウィンドウが拡大するということを意味しているのだと思います。そうすると、これを通知するために ACK を送信するという要件は仕様にはないと思います。したがって、ACK を引き出すためにウィンドウ プローブが必要になります。

Q4. プローブパケットはウィンドウ = 0 の場合にのみ送信されますか?

はい、定義上はそうです。なぜなら、window = 0 より前に 1 オクテットのパケットが送信された場合、それはたまたま 1 オクテットの大きさになった通常のパケットになるからです。

関連情報