UDPのMTUは65535ですが、イーサネットでは1500バイトを超えるフレームサイズは許可されていません


11

私は100 Mbpsの高速イーサネットを使用しています。そのフレームサイズは1500バイト未満です(私の教科書によると、ペイロード用に1472バイトです)。その中で、メッセージサイズ65507バイトのUDPパケットを送受信できました。つまり、パケットサイズは65507 + 20(IPヘッダー)+ 8(UDPヘッダー)= 65535でした。

フレームのペイロードサイズ自体が最大1472バイト(私の教科書によると)である場合、IPのパケットサイズを65535のサイズよりも大きくするにはどうすればよいですか。

私は送信者コードを次のように使用しました

char buffer[100000];
for (int i = 1; i < 100000; i++)
{
    int len = send (socket_id, buffer, i);
    printf("%d\n", len);
}

受信者コードとして

while (len = recv (socket_id, buffer, 100000))
{
     printf("%d\n". len);
}

私はそれを観察しsend returns -1i > 65507し、recv印刷物やのパケットを受信しますmaximum of length 65507

回答:


11

UDPデータグラムはMTUサイズとはほとんど関係がなく、最大64Kまでは好きなだけ大きくすることができます。大きなデータグラムより大きなサイズのジャンボフレームを使用している限り、パケットの1つをパケット全体で送信することもできます。

ただし、ジャンボフレームは、フレームが通過するすべての機器でサポートされる必要があり、これが問題となります。実際には、イーサネットフレームが最も一般的なトランスポートサイズであり、これらのMTUは約1500バイトです。今後は1500バイトと言いますが、常にそうとは限りません。基礎となるMTU(示されているように、ほとんどの場合イーサネット)より大きいUDPデータグラムを作成すると、静かにいくつかの1500バイトフレームに分割されます。このトラフィックをtcpdumpすると、MTU境界で壊れたパケットの数が表示され、フラグメント数とともにフラグメントフラグが設定されます。最初のパケットにはフラグメント番号0とより多くのフラグメントが設定され、最後のパケットにはゼロ以外のフラグメント番号とより多くのフラグメントが設定されていません。

では、なぜ気にするのでしょうか?実装の詳細は実際に重要です。フラグメンテーションは、ネットワークのパフォーマンスを損なう可能性がありますが、大きな問題ではありませんが、注意が必要です。巨大なデータグラムサイズを使用した場合、フラグメントが失われた場合は、データグラム全体を再送信する必要があります。同様に大量生産で、今日ではこれらは完全に達成可能な量であるため、再組み立て時にフレームの誤関連付けが発生する可能性があります。また、フラグメント化されたUDPパケットを取得して、ロードバランサーがパケットを分散させるエンタープライズファイアウォール構成を通過する際に問題が発生する可能性があります。

したがって、MTUサイズの断片化よりも大きなUDPデータグラムを作成しないでください。ただし、通信するインフラストラクチャが近接している(同じサブネットが近接している)場合は、ジャンボフレームを使用することをお勧めします。


「もっと断片フラグ」についての良い情報。それはUDPヘッダーまたはIPヘッダーのフラグですか?
ジョンジーザス

注:データが断片化される場合、一部のOSはUDPを送信しません。IE Linuxドキュメント、By default, Linux UDP does path MTU (Maximum Transmission Unit) discovery. This means the kernel will keep track of the MTU to a specific target IP address and return EMSGSIZE when a UDP packet write exceeds it.
Rahly

2

IP層は、送信側でパケットをフラグメント化し、UDPに渡す前に受信側で再構成します。UDP層からは、パケットがフラグメント化されていることを実際に確認することはできません。Wiresharkなどのパケットキャプチャツールを使用すると、コンピュータがMTUに制限されたIPパケットを受信して​​いることがわかります。


1

TCP / IPスタックが必要に応じてパケットをフラグメント化できるようにすると、個々のパケットを送信するよりもオーバーヘッドが大幅に低くなることがわかりました。


1
TCP / IPが断片化し、それ自体を再構成しているということですか?もしそうなら、なぜ人々はいつもあなたのコードがレシーバー側での再構成を処理するべきであるといつも言うのですか?私は今のところ断片化を観察していませんが、これを言っている多くのフォーラムとそれを受け入れている人々さえ見ました。

OSIモデルに挑戦している私たちにとって、あなたの答えにもう少し詳細を追加してもらえますか?
Robert Harvey

これが宿題かどうかわからないので、少し気が動転していました。これはトレードオフです。UDPは配信を保証しないため、パケットフラグメントがドロップされると、パケット全体が失われます。UDP上で信頼できるトランスポートが必要な場合は、これをすべて自分で処理する必要があります。ただし、(たとえば)ストリーミングプロトコル(またはストリーミングのようなパスをとるNFS over UDP)を実行している場合、必要に応じて、これらのパケットを単にドロップするか、長い遅延の後に大きなパケットを再送信する方がオーバーヘッドは低くなります。プロトコルの機能とプロトコルのオーバーヘッドに対してニーズのバランスをとる必要があります。
ギーコサウルス

1

UDPはMTUについて何も知りません。UDPパケットのサイズは8〜65535バイトです。UDPの下のプロトコル層は、特定のサイズのパケットを送信できるか、大きすぎる場合はエラーでそのパケットの送信を拒否します。

UDPの下の層は通常、IPであり、IPv4またはIPv6です。また、IPパケットのサイズは、20(IPv4)/ 40(IPv6)から65535バイトまで、UDPと同じ最大サイズです。ただし、IPはフラグメンテーションと呼ばれるメカニズムをサポートしています。IPパケットのサイズが下の層が転送できるサイズより大きい場合、IPは単一のパケットをフラグメントと呼ばれる複数のパケットに分割できます。すべてのフラグメントは、実際には独自のIPパケットであり(独自のIPヘッダーがあります)、独自に宛先に送信されます。次に、すべてのフラグメントを収集し、次の上位層(UDPなど)で受信データを渡す前にそれらから完全なパケットを再構築することが宛先のタスクです。

イーサネットプロトコルは、46〜1500バイトのペイロードを持つフレームのみを転送できます(例外はありますが、この応答の範囲を超えています)。ペイロードデータが46バイト未満の場合は、46バイトになるようにパディングされます。ペイロードデータが1500バイトを超える場合、インターフェイスはそれを受け入れることを拒否します。この場合、パケットをフラグメント化するかどうかを決定するのはIPレイヤーです。そのため、1500バイトを超えるフラグメントはありません。また、この特定の接続でフラグメンテーションが無効化または禁止されている場合は、次の上位レイヤーにエラーを報告します。

断片化は一般に避けられるべきです、

  • 送信側でリソースを浪費しています。
  • 受信側でリソースを浪費します。
  • 同じ量のペイロードデータに対してプロトコルのオーバーヘッドが増加します。
  • 単一のフラグメントが失われると、パケット全体が失われます。
  • 単一のフラグメントが破損している場合は、パケット全体が破損しています。
  • 再送信の場合、すべてのフラグメントを再送信する必要があります。

そのため、TCPはインテリジェントにフレームサイズを採用しているため、パケットを断片化するためにIPが必要になることはありません。これは、IPを禁止してパケットをフラグメント化することで実行できます。IPでパケットが大きすぎて送信できないと報告された場合、TCPはフレームサイズを縮小し、エラーが報告されなくなるまで再試行します。

ただし、UDPの場合、これはアプリケーション自体のタスクです。UDPは「ダム」プロトコルであるため、独自の管理ロジックがないため、非常に柔軟、高速、かつ単純になります。

常に転送可能であると信頼できる唯一のUDPサイズは、576マイナス8バイトのUDPヘッダーとマイナス20(v4)/ 40(v6)バイトのIPヘッダーです。IP標準では、すべてのIPホストがIPパケットを受信できる必要があるためです合計サイズは576バイトです。プロトコルの実装は、少なくともそのサイズのパケットを受け入れることができない場合、標準に準拠しません。ただし、標準ではフラグメンテーションなしの576は規定されていないため、576バイトのIPパケットでも2つのホスト間でフラグメント化される可能性があります。

フラグメントの最小IPヘッダーは20/48バイト(v4 / v6)であり、フラグメントには少なくとも4/8が必要であるため、フラグメント化なしで転送可能であると信頼できる唯一のパケットサイズは、IPv4で24バイト、56バイトIPv6です。バイト(v4 / v6)ペイロードデータ。したがって、少なくともこれらのサイズのパケットを転送できないIP層の下の転送システムは、IPトラフィックの転送には使用できません。

そして、誰かがIPv6ヘッダーは40バイトしかないとコメントする前に:それは正しいですが、IPv4ヘッダーとは異なり、標準のIPv6ヘッダーにはフラグメンテーション用のヘッダーフィールドがありません。パケットをフラグメント化する必要がある場合は、IPv6ベースヘッダーの下にフラグメンテーション拡張ヘッダーを追加する必要があります。この拡張ヘッダーは8バイトの長さです。また、IPv4とは異なり、IPv6のフラグメンテーションオフセットは4バイト単位ではなく8バイトでカウントされるため、IPv6の場合、フラグメントは8バイトの倍数のペイロードしか運ぶことができません。


0

あなたの質問に答えるために、「フレームのペイロードサイズ自体が最大1472バイト(私の教科書によると)である場合、IPのパケットサイズは、ここで65535であるものよりもどのように大きくなりますか?」

これは、UFO(UDP Fragmentation Offload)と呼ばれるオフロード機能が原因です。このリンクを参照しください。

オフロード機能は、それぞれethtool -k ethXおよびethtool -K ethXを使用して確認および切り替えることができます。


0

送信フレームを監視している場合、ネットワークアダプターがセグメンテーションオフロードをサポートしていて、有効になっている可能性があります。セグメンテーションオフロードを有効にすると、ネットワークカード自体が、ネットワークスタックではなく、パケット/フレームを適切なサイズにセグメント化します。これにより、コンピューターのCPUが解放され、他のタスクを実行できるようになり、パフォーマンスが向上します。Linuxでは、「ethtool -k [device]」でオフロードフラグが表示されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.