TCP/UDP のパケット分割やMTUについて疑問があります。


1)
インターネット上でTCPを用いる場合、ハンドシェイクの時にMTUを交換してMSSの値を決めると思います。初めは、自分から相手に届くまでの全ての経路でフラグメント分割が発生しないMSSの値を決めているのかと思いましたが、良く考えるとパケットごとに異なる経路ごとを通る可能性がありますよね。ということは、ここで交換される値は途中の経路に関係なく、ただお互い(の内部ネットワーク)にとって都合のいいMSS値を交換しているのでしょうか?だとすると経路の途中のセグメントではフラグメント分割が行われる可能性があるため、経路上の適切なMSSの値を決めるという本来の目的を達成できていないように思うのですが、この理解で間違いないでしょうか?

2)
また、UDPの場合は(UDPレベルでの)サイズの限界値やMTUに相当する概念はあるのでしょうか?少し調べた限りですとOSごとに大きすぎるパケットを送信するとエラーが出て送信がキャンセルされることがあるようですが、具体的な値などあまり詳しいことはわかりませんでした。どのような仕組みになっているのでしょうか?

回答の条件
  • 1人5回まで
  • 13歳以上
  • 登録:2013/07/04 08:03:42
  • 終了:2013/07/08 01:03:44

ベストアンサー

id:JULY No.2

JULY回答回数966ベストアンサー獲得回数2472013/07/05 18:33:09

ポイント70pt

1) に関してですが、確かに経路上の MTU でより小さい物があれば、適切な MSS は、一番小さい MTU に合わせると効率が良くなります。で、経路上のパケットサイズを動的に探る方法としては、経路MTU探索(Path MTU Discovery)というのがあります。

Maximum Transmission Unit - Wikipedia

これは、フラグメント禁止フラグ(DF フラグ)を立てたパケットを送信し、ルータが転送先の回線の MTU サイズが小さくて、フラグメント無しには転送できない事を伝える ICMP パケットが送信元に返り、それを受け取って、より小さなサイズのパケットで再送する、という話です。

もし、経路 MTU 探索が有効に働いていれば、この結果から適切な MSS サイズが決まってくる、ということになります。

逆に言うと、途中にルータがある場合に、TCP の 3 way ハンドシェイクだけでは、適切な MSS サイズは分からないことになります。DF フラグを立っていなければ、経路上のルータが転送先の MTU に合わせてパケットを分割することになります。

あくまで MSS は、TCP の両端の話なので、本来は経路上の影響は考慮されていません。

ただ、ルータによっては、MSS の値を書き換える機能を持っている場合もあるようです。上記ページに下記のような記述があります。

MSSは本来、TCPコネクションの両端が設定する項目である。しかし最近のブロードバンドルーター等は、TCPセグメントの転送時にMSSオプションを書き換える機能を持っている。


2) ですが、MTU 自体は、IP よりも下位のレイア-で決まる値です。一方、IP パケット自体は、IP ヘッダにあるパケットサイズを表す部分が 16 bit であることから、原理的には 65,535 バイトまで許されることになります。

@IT:連載 基礎から学ぶWindowsネットワーク 第10回 IPパケットの構造とIPフラグメンテーション 1.IPパケットの構造

このサイズは IP ヘッダを含む、IP パケット全体のサイズになるので、UDP に載せられるデータの最大サイズは、IP ヘッダ(20 バイト)、UDP ヘッダ(8 バイト)のサイズを引いた 65,507 バイトが、一つの UDP パケットで送信可能な UDP の中身のサイズになります。

ただ、実際にこれを送信しようとすると当然、IP より下位のレイア-の制限を受けるので、PC の LAN のインタフェースから送信する場合には、イーサネットの MTU サイズ、1,500 バイトを最大とした IP パケットに分割されて送信することになります。

そのパケットが、経路上、より小さい MTU を持つ経路で転送される時には、DF フラグが立っていなければルータが再分割し、DF フラグが立っているパケットであれば、ICMP の Destination Unreachable が返ってくる、ということになります。

他1件のコメントを見る
id:JULY

> UDPのプログラムを実装する場合には、一般に下位レイヤーで
> 分割されないようなサイズに留めて利用すればよい

そうすれば、余計な負荷がかからず、効率的、というだけで、UDP を使うプログラムの方が、サイズを意識する必要は、あまりありません。アプリケーション側が、自分が送信するデータがイーサネット上で送られるのか、PPPoE のトンネルの中を通るのか、ダイアルアップ接続なのか、という事を意識するのは変ですよね。

こういったパケットのフラグメント処理は、TCP や UDP の層ではなく、その下の IP の層で行われます。私の回答で紹介しているページの2つめの方で IP ヘッダを見るとフラグメント・オフセットというフィールドがあるのが分かると思います。あくまで分割は「IP」の層で行われるので、IP の中身が TCP だろうが UDP だろうが関係なく、「IP」の判断として分割されます。下記のページも参考にしてみて下さい。

http://www.atmarkit.co.jp/fwin2k/network/baswinlan010/baswinlan010_03.html

余談ですが、IPv6 では、基本的に経路MTU探索が有効である事を前提にしています。で、ファイアウォールで過大に「ICMP を全部ドロップ」という事をしていると、経路MTU探索ができなくなります。IPv6 に対応する ICMP は ICMPv6 と別に定義されているので、IPv4 での ICMP のフィルタがそのまま影響する訳ではないですが、同じ調子で ICMPv6 を丸ごとドロップすると、IPv6 では通信できない状況が発生します。

その絡みなのか分かりませんが、CentOS Ver.6 系が、IPv4 でも DF フラグが立っていて、通信が不安定になるケースを見たことがあります。どこかのルータかファイアウォールが ICMP をドロップしているらしく、ある大きさを超えたパケットを送信すると、相手から届くはずの応答パケットが来ない、という現象があって、よくよく見たら、送信パケットで DF フラグが立っている状態だった、という事がありました。DF フラグを立てないように設定したら、正常に通信できるようになりました。

2013/07/06 07:49:35
id:quesit

さらに詳しい回答ありがとうございます。こちらの返答としては、UDP利用時にIPレベルで分割が起きないように「しなければならない」と理解したという意味ではなくて、UDPでパケットサイズをどうするかに対してIPレベルでの分割が起きないあたりのサイズを狙うのが「現実解」というつもりでの発言でした。こちらの書き方が悪かったです、すみません。IPレベルでのフラグメントについてはほぼ理解していましたが、TCPのMTUに対応するUDPの概念があるのかが質問での疑問点で、それがないということがわかったので、実装時にUDPパケットサイズをどうするべきかという問題に対して、MTUのような指標がないので、一般的にIPレベルでフラグメントがおきないあたりのサイズを狙っていくべきですね、という結論に落ち着いた次第です。
あと、余談に関しては非常に参考になる情報ありがとうございます。このような話は特に現場の方からしか聞けませんので(笑)世の中がまだまだIPv4を使い続けているので自分の環境でIPv6が利用されているのを見る例は少ないですが、IPv6へ移行したらまた別の問題が発生したりするわけですね。もちろん高機能になっている分、楽もできるのでしょうけど。

2013/07/06 08:35:50

その他の回答(1件)

id:tea_cup No.1

tea_cup回答回数1047ベストアンサー獲得回数1902013/07/05 14:36:29

ポイント30pt

1)について
 途中に複数経路があった場合の考慮はされていませんので、途中でMSSが小さい経路を通るようになると、通信効率は下がります。
 他にありがちな問題は、Windows および Sun のシステムでの IP MTU、TCP MSS、および PMTUD の調整 - 他のプロトコルおよび旧来のプロトコル : MS Windows ネットワーキング - Cisco Systems
が参考になるかと思います。

id:quesit

やっぱり途中は考慮されていないということですね。回答ありがとうございます。参考リンクも参考にさせていただきますね。

2013/07/05 23:07:58
id:JULY No.2

JULY回答回数966ベストアンサー獲得回数2472013/07/05 18:33:09ここでベストアンサー

ポイント70pt

1) に関してですが、確かに経路上の MTU でより小さい物があれば、適切な MSS は、一番小さい MTU に合わせると効率が良くなります。で、経路上のパケットサイズを動的に探る方法としては、経路MTU探索(Path MTU Discovery)というのがあります。

Maximum Transmission Unit - Wikipedia

これは、フラグメント禁止フラグ(DF フラグ)を立てたパケットを送信し、ルータが転送先の回線の MTU サイズが小さくて、フラグメント無しには転送できない事を伝える ICMP パケットが送信元に返り、それを受け取って、より小さなサイズのパケットで再送する、という話です。

もし、経路 MTU 探索が有効に働いていれば、この結果から適切な MSS サイズが決まってくる、ということになります。

逆に言うと、途中にルータがある場合に、TCP の 3 way ハンドシェイクだけでは、適切な MSS サイズは分からないことになります。DF フラグを立っていなければ、経路上のルータが転送先の MTU に合わせてパケットを分割することになります。

あくまで MSS は、TCP の両端の話なので、本来は経路上の影響は考慮されていません。

ただ、ルータによっては、MSS の値を書き換える機能を持っている場合もあるようです。上記ページに下記のような記述があります。

MSSは本来、TCPコネクションの両端が設定する項目である。しかし最近のブロードバンドルーター等は、TCPセグメントの転送時にMSSオプションを書き換える機能を持っている。


2) ですが、MTU 自体は、IP よりも下位のレイア-で決まる値です。一方、IP パケット自体は、IP ヘッダにあるパケットサイズを表す部分が 16 bit であることから、原理的には 65,535 バイトまで許されることになります。

@IT:連載 基礎から学ぶWindowsネットワーク 第10回 IPパケットの構造とIPフラグメンテーション 1.IPパケットの構造

このサイズは IP ヘッダを含む、IP パケット全体のサイズになるので、UDP に載せられるデータの最大サイズは、IP ヘッダ(20 バイト)、UDP ヘッダ(8 バイト)のサイズを引いた 65,507 バイトが、一つの UDP パケットで送信可能な UDP の中身のサイズになります。

ただ、実際にこれを送信しようとすると当然、IP より下位のレイア-の制限を受けるので、PC の LAN のインタフェースから送信する場合には、イーサネットの MTU サイズ、1,500 バイトを最大とした IP パケットに分割されて送信することになります。

そのパケットが、経路上、より小さい MTU を持つ経路で転送される時には、DF フラグが立っていなければルータが再分割し、DF フラグが立っているパケットであれば、ICMP の Destination Unreachable が返ってくる、ということになります。

他1件のコメントを見る
id:JULY

> UDPのプログラムを実装する場合には、一般に下位レイヤーで
> 分割されないようなサイズに留めて利用すればよい

そうすれば、余計な負荷がかからず、効率的、というだけで、UDP を使うプログラムの方が、サイズを意識する必要は、あまりありません。アプリケーション側が、自分が送信するデータがイーサネット上で送られるのか、PPPoE のトンネルの中を通るのか、ダイアルアップ接続なのか、という事を意識するのは変ですよね。

こういったパケットのフラグメント処理は、TCP や UDP の層ではなく、その下の IP の層で行われます。私の回答で紹介しているページの2つめの方で IP ヘッダを見るとフラグメント・オフセットというフィールドがあるのが分かると思います。あくまで分割は「IP」の層で行われるので、IP の中身が TCP だろうが UDP だろうが関係なく、「IP」の判断として分割されます。下記のページも参考にしてみて下さい。

http://www.atmarkit.co.jp/fwin2k/network/baswinlan010/baswinlan010_03.html

余談ですが、IPv6 では、基本的に経路MTU探索が有効である事を前提にしています。で、ファイアウォールで過大に「ICMP を全部ドロップ」という事をしていると、経路MTU探索ができなくなります。IPv6 に対応する ICMP は ICMPv6 と別に定義されているので、IPv4 での ICMP のフィルタがそのまま影響する訳ではないですが、同じ調子で ICMPv6 を丸ごとドロップすると、IPv6 では通信できない状況が発生します。

その絡みなのか分かりませんが、CentOS Ver.6 系が、IPv4 でも DF フラグが立っていて、通信が不安定になるケースを見たことがあります。どこかのルータかファイアウォールが ICMP をドロップしているらしく、ある大きさを超えたパケットを送信すると、相手から届くはずの応答パケットが来ない、という現象があって、よくよく見たら、送信パケットで DF フラグが立っている状態だった、という事がありました。DF フラグを立てないように設定したら、正常に通信できるようになりました。

2013/07/06 07:49:35
id:quesit

さらに詳しい回答ありがとうございます。こちらの返答としては、UDP利用時にIPレベルで分割が起きないように「しなければならない」と理解したという意味ではなくて、UDPでパケットサイズをどうするかに対してIPレベルでの分割が起きないあたりのサイズを狙うのが「現実解」というつもりでの発言でした。こちらの書き方が悪かったです、すみません。IPレベルでのフラグメントについてはほぼ理解していましたが、TCPのMTUに対応するUDPの概念があるのかが質問での疑問点で、それがないということがわかったので、実装時にUDPパケットサイズをどうするべきかという問題に対して、MTUのような指標がないので、一般的にIPレベルでフラグメントがおきないあたりのサイズを狙っていくべきですね、という結論に落ち着いた次第です。
あと、余談に関しては非常に参考になる情報ありがとうございます。このような話は特に現場の方からしか聞けませんので(笑)世の中がまだまだIPv4を使い続けているので自分の環境でIPv6が利用されているのを見る例は少ないですが、IPv6へ移行したらまた別の問題が発生したりするわけですね。もちろん高機能になっている分、楽もできるのでしょうけど。

2013/07/06 08:35:50

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません