MTU คือ 65535 ใน UDP อย่างไร แต่อีเธอร์เน็ตไม่อนุญาตให้มีขนาดเฟรมมากกว่า 1500 ไบต์


11

ฉันใช้อีเธอร์เน็ตที่รวดเร็วขนาด 100 Mbps ซึ่งมีขนาดเฟรมน้อยกว่า 1500 ไบต์ (1472 ไบต์สำหรับเพย์โหลดตามตำราของฉัน) ในนั้นฉันสามารถส่งและรับแพ็คเก็ต UDP ที่มีขนาดข้อความ 65507 ไบต์ซึ่งหมายความว่าขนาดแพ็คเก็ตคือ 65507 + 20 (IP Header) + 8 (UDP Header) = 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 -1บนi > 65507และพิมพ์หรือได้รับแพ็คเก็ตของrecvmaximum of length 65507

คำตอบ:


11

UDP ดาต้าแกรมมีส่วนเกี่ยวข้องกับขนาด MTU เพียงเล็กน้อยคุณสามารถทำให้ใหญ่เท่าที่คุณต้องการมากถึง 64K สูงสุดที่กล่าวถึงข้างต้น คุณสามารถส่งหนึ่งของพวกเขาในแพ็คเก็ตทั้งหมดตราบเท่าที่คุณใช้เฟรมจัมโบ้ที่มีขนาดใหญ่กว่าดาตาแกรมขนาดใหญ่

อย่างไรก็ตามอุปกรณ์ทั้งหมดต้องรองรับเฟรมจัมโบ้เฟรมที่จะผ่านและเป็นปัญหา เพื่อประโยชน์ในทางปฏิบัติเฟรม Ethernet นั้นมีขนาด tranport ที่พบบ่อยที่สุด MTU สำหรับสิ่งเหล่านี้มีขนาดประมาณ 1500 ไบต์ฉันจะบอกว่า 1500 จะดำเนินต่อไป แต่ก็ไม่เสมอไป เมื่อคุณสร้างดาตาแกรม UDP ที่มีขนาดใหญ่กว่า MTU พื้นฐาน (ซึ่งตามที่ระบุบ่อยที่สุดคืออีเธอร์เน็ต) จากนั้นมันจะถูกแบ่งออกเป็นเงียบ ๆ เป็นจำนวนเฟรมขนาด 1500 ไบต์ หากคุณ tcpdump ทราฟฟิกนี้คุณจะเห็นจำนวนแพ็กเก็ตที่แตกที่ขอบเขต MTU ซึ่งจะมีการตั้งค่าแฟรกเมนต์เพิ่มเติมพร้อมกับหมายเลขแฟรกเมนต์ แพ็คเก็ตแรกจะมีหมายเลขแฟรกเมนต์เป็น 0 และชุดแฟรกเมนต์เพิ่มเติมและชุดสุดท้ายจะมีหมายเลขแฟรกเมนต์ที่ไม่เป็นศูนย์และไม่ได้ตั้งค่าแฟรกเมนต์เพิ่มเติม

ทำไมต้องแคร์ รายละเอียดการใช้งานจริงมีความสำคัญ การกระจายตัวของข้อมูลอาจส่งผลกระทบต่อประสิทธิภาพการทำงานในเครือข่ายไม่ใช่ปัญหาใหญ่อีกต่อไป แต่เป็นสิ่งที่ต้องระวัง หากมีขนาดดาตาแกรมขนาดใหญ่ที่ใช้ดังนั้นควรมีส่วนใดหายไปดาตาแกรมทั้งหมดจะต้องถูกส่งอีกครั้ง ในปริมาณที่สูงพอ ๆ กันและในวันนี้ปริมาณที่สามารถทำได้อย่างสมบูรณ์แบบนั้นการเชื่อมโยงเฟรมผิดพลาดที่การประกอบซ้ำนั้นเป็นไปได้ นอกจากนี้ยังอาจมีปัญหาในการรับแพ็คเก็ต UDP ที่แยกส่วนเพื่อกำหนดค่าไฟร์วอลล์ขององค์กรที่โหลดบาลานเซอร์กระจายแพ็คเก็ตออกหากชิ้นส่วนหนึ่งอยู่บนไฟร์วอลล์หนึ่งและอีกอันหนึ่งแตกต่างกันการรับส่งข้อมูลจะไม่สมบูรณ์

ดังนั้นอย่าสร้าง UDP ดาต้าแกรมที่ใหญ่กว่าการแตกแฟรกเมนต์ขนาด MTU ยกเว้นว่าคุณต้องทำและถ้าคุณต้องระบุว่าโครงสร้างพื้นฐานที่สื่อสารระหว่างกันนั้นใกล้กัน (subnet เดียวกันปิด) ซึ่งเฟรมจัมโบ้น่าจะเป็นตัวเลือกที่ดี


ข้อมูลที่ดีเกี่ยวกับ 'แฟรกเมนต์เพิ่มเติม' นั่นคือการตั้งค่าสถานะในส่วนหัวของ UDP หรือในส่วนหัวของ IP?
จอห์นพระเยซู

หมายเหตุ: ระบบปฏิบัติการบางระบบจะไม่ส่ง UDP หากข้อมูลมีการแยกส่วน IE Linux doc,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คุณควรเห็นว่าคอมพิวเตอร์ของคุณกำลังรับแพ็กเก็ต IP ที่ จำกัด เฉพาะ MTU


1

ปรากฎว่าการอนุญาตให้สแต็ก TCP / IP สามารถแบ่งแพ็คเก็ตได้ตามต้องการเป็นค่าใช้จ่ายที่ต่ำกว่าการส่งแต่ละแพ็คเก็ต


1
คุณหมายความว่า TCP / IP กำลังแยกส่วนและรวมตัวใหม่อีกครั้งหรือไม่ ถ้าใช่แล้วทำไมผู้คนถึงพูดตลอดเวลาที่รหัสของคุณควรดูแลการประกอบซ้ำในตอนท้ายผู้รับ ฉันไม่ได้สังเกตการแตกแฟรกเมนต์ ณ ตอนนี้ แต่เคยเห็นฟอรัมมากมายที่พูดถึงเรื่องนี้และแม้กระทั่งคนที่ยอมรับมัน

สำหรับพวกเราที่เป็นแบบจำลอง OSI คุณสามารถเพิ่มรายละเอียดเพิ่มเติมในคำตอบของคุณได้ไหม?
Robert Harvey

ฉันเป็นคนขี้เหร่นิดหน่อยเพราะฉันไม่สามารถบอกได้ว่านี่เป็นการบ้านหรือไม่ เป็นการแลกเปลี่ยน: เนื่องจาก UDP ไม่รับประกันการส่งมอบหากส่วนของแพ็คเก็ตใด ๆ ถูกทิ้งแพ็กเก็ตทั้งหมดจะหายไป ถ้าคุณต้องการการขนส่งที่เชื่อถือได้บนยอด UDP คุณต้องจัดการทั้งหมดนี้ด้วยตัวเอง แต่ถ้าคุณกำลังทำ (พูด) โพรโทคอลการสตรีม (หรือ NFS บน UDP ซึ่งใช้เส้นทางแบบสตรีม) มันเป็นโอเวอร์เฮดที่ต่ำกว่าเพียงแค่วางแพ็กเก็ตเหล่านั้นหรือส่งแพ็กเก็ตที่มีขนาดใหญ่ขึ้นอีกครั้ง คุณต้องสมดุลความต้องการของคุณกับคุณสมบัติโปรโตคอลและค่าใช้จ่ายโปรโตคอล
geekosaur

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 โดยไม่มีการกระจายตัวดังนั้นแม้แพ็คเก็ต IP 576 ไบต์อาจได้รับการแยกส่วนระหว่างสองโฮสต์

ขนาดแพ็คเก็ตเท่านั้นที่คุณเชื่อถือได้ที่สามารถขนส่งได้โดยไม่มีการแตกแฟรกเมนต์คือ 24 ไบต์สำหรับ IPv4 และ 56 ไบต์ IPv6 เป็นส่วนหัว IP ที่เล็กที่สุดสำหรับส่วนคือ 20/48 ไบต์ (v4 / v6) และชิ้นส่วนต้องมีอย่างน้อย 4/8 ข้อมูลส่วนของข้อมูลไบต์ (v4 / v6) ดังนั้นระบบการขนส่งที่อยู่ต่ำกว่าชั้น IP ที่ไม่สามารถส่งอย่างน้อยหนึ่งซองที่มีขนาดเหล่านี้ไม่สามารถใช้เพื่อการรับส่งข้อมูล IP

และก่อนที่ทุกคนจะแสดงความคิดเห็นว่าส่วนหัว IPv6 มีเพียง 40 ไบต์: ถูกต้อง แต่ไม่เหมือนกับส่วนหัวของ IPv4 ส่วนหัว IPv6 มาตรฐานจะไม่มีฟิลด์ส่วนหัวสำหรับการกระจายตัว หากแพ็คเก็ตจะต้องมีการแยกส่วนแล้วส่วนหัวของการกระจายตัวของการกระจายตัวจะต้องเพิ่มด้านล่างส่วนหัวฐาน IPv6 และส่วนหัวของส่วนขยายนี้มีความยาว 8 ไบต์ แตกต่างจาก IPv4 เช่นการแตกแฟรกเมนต์ใน IPv6 นับเป็น 8 ไบต์และไม่ใช่ 4 ไบต์ดังนั้นแฟรกเมนต์สามารถขนย้ายข้อมูลที่มีหลาย 8 ไบต์ในกรณีของ IPv6 เท่านั้น


0

เพื่อตอบคำถามของคุณ "ถ้าขนาดของเฟรมของตัวเองมีขนาดสูงสุด 1472 ไบต์ (ตามตำราของฉัน) ขนาดแพ็กเก็ตของ IP จะใหญ่กว่าขนาดของที่นี่คือ 65535 อย่างไร"

มันเป็นเพราะคุณสมบัติการขนถ่ายที่เรียกว่ายูเอฟโอ (UDP Fragmentation Offload) โปรดดูที่นี้การเชื่อมโยง

คุณสามารถตรวจสอบและสลับการถ่ายคุณสมบัติได้ผ่าน ethtool -k ethX และ ethtool -K ethX ตามลำดับ


0

หากคุณกำลังตรวจสอบเฟรมที่ส่งออกอาจเป็นไปได้ว่าอะแดปเตอร์เครือข่ายของคุณรองรับการแบ่งส่วนการถ่ายโอนข้อมูลและเปิดใช้งาน เมื่อเปิดใช้งานการแบ่งส่วนการเปิดใช้งานการ์ดเครือข่ายจะจัดการการแบ่งกลุ่มแพ็คเก็ต / เฟรมให้มีขนาดที่เหมาะสมแทนที่จะใช้สแต็กเครือข่าย สิ่งนี้จะทำให้ CPU ในคอมพิวเตอร์ทำงานได้อย่างอิสระเพิ่มประสิทธิภาพ บน linux "ethtool -k [อุปกรณ์]" จะแสดงแฟล็กการโหลด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.