한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

คู่มือเกมแลค › ต้นเหตุของการส่งซ้ำใน TCP

MTU black hole (เฉพาะแพ็กเก็ตใหญ่ที่หายซ้ำแล้วซ้ำอีก) PMTU black hole

ID สาเหตุ rt-mtu · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)

เปิดการ์ดในฉบับหลักที่มีภาพและการทดลอง →

เมื่อขนาดที่ช่วงกลางทางรับได้เล็กลง แต่ข้อความแจ้งว่า “ใหญ่เกินไป” (ICMP) ถูกบล็อก แพ็กเก็ตใหญ่จะหายไปทุกครั้งไม่ว่าจะส่งซ้ำกี่รอบ

ทำไม ขนาดสูงสุดลดลงในช่วงที่ผ่าน VPN หรืออุโมงค์ (tunnel) และข้อความแจ้งว่าเกินขนาดถูกไฟร์วอลล์บล็อก → ผลคือ ฝั่งส่งไม่รู้สาเหตุ จึงส่งแพ็กเก็ตใหญ่ตัวเดิมซ้ำไปเรื่อย ๆ และ RTO เพิ่มเป็นสองเท่าทุกครั้ง → บนหน้าจอ ปกติไม่มีอาการ แต่ในจังหวะที่มีข้อมูลใหญ่วิ่ง เช่น เปิดกระเป๋า, ไปที่ที่คนเยอะ หรือโหลดตอนเข้าแมพ แพ็กเก็ตเล็กที่ตามมาก็หยุดไปหมด สุดท้ายหลุดหรือโหลดไม่จบ

อาการ
ค้าง, หลุด, เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย
แพ็กเก็ตหาย
ใครเจอ
บางพื้นที่/บาง ISP, เราคนเดียว
เกิดเมื่อไร
ตอนทำแอ็กชันบางอย่าง, หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ
ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม
ถ้าจะลดขนาดจากฝั่งเซิร์ฟเวอร์เอง ให้ตั้งขนาด segment สูงสุดของซ็อกเก็ต (TCP_MAXSEG), แค่ซอยข้อความให้เล็กในโค้ดเกมไม่ช่วยป้องกัน (TCP จะรวมข้อมูลที่จะส่งเป็นก้อนขนาด MSS ใหม่)
งานฝั่งทีมอินฟรา
เครือข่าย: ปรับ MSS ที่อุปกรณ์ขอบเครือข่าย (clamping), อนุญาต ICMP แจ้งเกินขนาด (type 3 code 4, fragmentation needed) ที่ไฟร์วอลล์และ network ACL ของคลาวด์ เครื่องเซิร์ฟเวอร์/OS: ตั้งค่า path MTU, ตรวจว่าไฟร์วอลล์ของเซิร์ฟเวอร์และ security group ของคลาวด์ไม่บล็อก ICMP แจ้งเกินขนาด, ใช้ tcp_mtu_probing=1 ของ Linux เป็นตาข่ายรองรับชั้นสุดท้าย
ตัวเลขที่ควรรู้
ปกติ 1,500 ไบต์ ถ้าผ่านอุโมงค์จะเหลือราว 1,400 ถ้าแพ็กเก็ตเดิมถูกส่งซ้ำ 5–6 ครั้ง จะหยุดชะงักนานเกิน 10 วินาที
บนกราฟ
สูงเฉพาะบางกลุ่ม · RTO และ backoff ต่อการเชื่อมต่อ, จำนวนการหลุดแยกตามพื้นที่/ISP
จุดที่ต้องดู
การส่งซ้ำของการเชื่อมต่อที่มีปัญหาจาก packet capture ฝั่งเซิร์ฟเวอร์หรือ bcc tcpretrans -s (แสดง sequence number) และ mss, pmtu, backoff ของการเชื่อมต่อนั้นจาก ss -ti จากเซิร์ฟเวอร์ส่ง ping เล็กกับ ping 1,500 ไบต์ที่เปิด DF (ping -M do -s 1472) ไปยังที่อยู่ของผู้เล่นคนนั้นแล้วเทียบกัน
สัญญาณว่าใช่
แพ็กเก็ตที่เต็มขนาด MSS ถูกส่งซ้ำด้วย sequence number เดิมไปเรื่อย ๆ โดยช่วงห่างเพิ่มเป็นสองเท่าทุกครั้ง ส่วนแพ็กเก็ตที่เล็กกว่าผ่านได้ ไม่มี ICMP แจ้งเกินขนาด (ตัวกรอง Wireshark icmp.type == 3 and icmp.code == 4) เข้ามา ping เล็กได้คำตอบ แต่ ping ใหญ่ที่เปิด DF หายเงียบ
สัญญาณว่าไม่ใช่
แพ็กเก็ตเล็กก็หายด้วย: เป็นการหายที่ไม่เกี่ยวกับขนาด (“คิวคอขวดล้น”, “เส้นทางเปลี่ยน/เส้นทาง ECMP ที่เสีย”) ถ้า ICMP แจ้งเกินขนาดมาถึงและ pmtu ใน ss -ti ลดลง แปลว่า path MTU discovery ทำงานปกติ
วิธีตรวจ
ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม
tcp_mtu_probing=1 จะตัดสินว่าเป็น black hole แล้วลด MSS เหลือ 1,024 ไบต์ ก็ต่อเมื่อ RTO หมดเวลาต่อเนื่องไปหลายวินาที (เท่ากับ tcp_retries1=3) ระหว่างนั้นจะหยุดชะงัก จึงควรเก็บไว้เป็นตาข่ายรองรับชั้นสุดท้าย และทำ MSS clamping ที่ป้องกันไว้ล่วงหน้าเป็นอันดับแรก

แหล่งอ้างอิง

  1. RFC 1191: Path MTU discovery IETF
    path MTU discovery: แพ็กเก็ตที่ใหญ่เกินจะได้รับแจ้งด้วย ICMP “fragmentation needed and DF set” (type 3 code 4)
  2. RFC 2923: TCP Problems with Path MTU Discovery IETF
    ปัญหา PMTU black hole ที่ ICMP ถูกบล็อกจนแพ็กเก็ตใหญ่หายไปเรื่อย ๆ
  3. RFC 4821: Packetization Layer Path MTU Discovery IETF
    วิธีที่ชั้น transport ค้นหาขนาดแพ็กเก็ตเองโดยไม่ใช้ ICMP (พื้นฐานของ tcp_mtu_probing ใน Linux)
  4. IP Sysctl Linux kernel
    tcp_mtu_probing: 0 ปิด, 1 เฉพาะเมื่อตรวจพบ black hole, 2 ตลอดเวลา (MSS เริ่มต้นคือ tcp_base_mss) tcp_retries1 ค่าเริ่มต้น 3
  5. net/ipv4/tcp_timer.c Linux kernel
    เมื่อการส่งซ้ำจาก RTO ต่อเนื่องครบ tcp_retries1 ครั้ง จะถือว่าตรวจพบ black hole แล้วเปิด MTU probing เพื่อลด MSS
  6. include/net/tcp.h Linux kernel
    TCP_BASE_MSS = 1,024 ไบต์
  7. RFC 6298: Computing TCP's Retransmission Timer IETF
    เพิ่ม RTO เป็นสองเท่าทุกครั้งที่ตัวจับเวลาส่งซ้ำหมดเวลา
  8. iptables-extensions(8) — Linux manual page netfilter
    TCPMSS --clamp-mss-to-pmtu: เลี่ยงปัญหาแพ็กเก็ตใหญ่ไปไม่ถึงเพราะช่วงที่บล็อก ICMP ด้วยการปรับ MSS ใน SYN
  9. tcp(7) — Linux manual page Linux man-pages
    TCP_MAXSEG: ขนาด segment สูงสุดของแพ็กเก็ตขาออก ถ้าตั้งก่อนเชื่อมต่อ MSS ที่แจ้งให้อีกฝั่งทราบก็จะเปลี่ยนด้วย
  10. Network maximum transmission unit (MTU) for your EC2 instance AWS
    internet gateway และ VPN ใช้ MTU 1,500, PMTUD ต้องใช้ ICMP type 3 code 4 และถ้า security group หรือ network ACL บล็อกไว้จะรับไม่ได้
  11. MTU considerations | Cloud VPN Google Cloud
    MTU ของ Cloud VPN gateway คือ 1,460 ไบต์, payload MTU ของอุโมงค์ IPv4 คือ 1,406 ไบต์ (ผ่านอุโมงค์แล้วเหลือราว 1,400)
  12. Demonstrations of tcpretrans, the Linux eBPF/bcc version IO Visor
    แสดงหนึ่งบรรทัดต่อการส่งซ้ำแต่ละครั้ง และ -s แสดง sequence number ของแพ็กเก็ตที่ส่งซ้ำด้วย
  13. ss(8) — Linux manual page iproute2
    mss, pmtu (path MTU) และ backoff (จำนวนครั้งที่ RTO เพิ่มเป็นสองเท่า) ใน ss -i
  14. ping(8) — Linux manual page iputils
    -M do เปิด DF และไม่ส่งแพ็กเก็ตที่ใหญ่กว่า path MTU ที่เคอร์เนลรู้, -s คือขนาดข้อมูล (ไม่รวม ICMP header 8 ไบต์)
  15. Display Filter Reference: Internet Control Message Protocol Wireshark
    display filter icmp.type และ icmp.code

สาเหตุที่ควรดูประกอบ

ชั้นเดียวกัน: ต้นเหตุของการส่งซ้ำใน TCP

สาเหตุจากชั้นอื่นที่ทำให้เกิดอาการเดียวกัน (ค้าง)

ดูการ์ดในฉบับหลักที่มีภาพและการทดลอง