MTU 1500 và 1492 nó khác biệt nhiều không bác, em thử thì không thấy khác biệt lắm
Nếu chỉ tính về hiệu năng thì khi dùng PPPoE, không có VLAN, IPv4 và TCP, với MTU 1492 gửi 1 packet tối đa được 1452 bytes dữ liệu thực sự, thì cần tốn 1538 bytes trên đường truyền ethernet (gồm 20 bytes overhead ở layer 1, 18 ở layer 2, 8 bytes header PPPoE, 20 bytes header IPv4, và 20 bytes header TCP). Như vậy hiệu quả đạt được 1452 / 1538 tầm 94.41% (đây là lý do các bác speedtest với đường 1Gbps ra được tầm 94xMbps).
Khi dùng MTU 1500 thì payload đạt được là 1460 bytes, tốn tổng cộng 1546 bytes trên đường ethernet, hiệu năng 94.44%. Khác biệt giữa 2 con số này chẳng là cái gì đáng kể hết. Ngay cả nếu so khi dùng IPv6, overhead thêm 20 bytes so với IPv4, thì có 1432/1538 so với 1440/1546, vẫn chỉ là 93.11% so với 93.14% mà thôi. Lợi ích thực sự của việc dùng được MTU 1500 nó ở chỗ khác.
Các giá trị MTU mà bác thấy ghi trên interface PPPoE hay các interface ethernet hay bridge hay vlan, là kích thước tối đa của packet ở layer 3, layer IP có thể truyền qua được. Tức là không tính các overhead của các layer với protocol bên dưới (không tính overhead PPPoE, Ethernet, v.v...) mặc dù có là chữ T (Transmission) cho chiều gửi đi nhưng thường nó cũng áp dụng cho cả chiều nhận vì nó thường bằng luôn giá trị MRU. Khi truyền dữ liệu từ 1 đầu A đến 1 đầu B qua giao thức IP (có thể là IPv4 hoặc IPv6 không quan trong, vẫn là packet IP) thì một packet sẽ được truyền lần lượt qua nhiều node/hop khác nhau, thường là các router. Mỗi node sẽ có giới hạn MTU của nó, cho phép packet IP có kích thước tối đa bao nhiêu được đi qua. Khi đến 1 node mà packet nhỏ hơn MTU thì sẽ được chuyển đi tiếp. Hầu hết các node trung chuyển trên internet, cũng như trong mạng LAN dùng ethernet đều hỗ trợ MTU 1500 chuẩn của payload của ethernet.
Điều gì xảy ra khi trên đường truyền 1 packet lớn đến một node/hop/router và kích thước của packet đó to hơn giá trị MTU mà node đó chấp thuận được? Cái này phụ thuộc vào protocol đang là IPv4 hay IPv6, và thuộc tính của packet đó.
* Nếu là IPv4, và nếu packet đó không bật cờ (flag) DF (do not fragment), thông thường là như vậy, thì node có MTU nhỏ hơn kích thước packet này sẽ tiến hành phân mảnh packet thành nhiều packet nhỏ hơn MTU. Các packet này sẽ được bật flag MF (more fragments), trừ packet cuối, và được gán giá trị ở trường fragment offset của packet để biết vị trí của mảnh này trong packet gốc. Các packets/mảnh này sẽ được chuyển tiếp, và khi đến đích sẽ được ghép lại thành packet gốc, đúng thứ tự và vị trí, nhờ các thông tin flag và offset kia. Tất nhiên là với điều kiện phải đợi nhận được đủ tất cả các packet mảnh. Nếu có packet loss thì chỉ cần mất 1 trong các mảnh là coi như mất cả packet gốc. Như vậy với cùng tỉ lệ packet loss, do thay vì chỉ có 1 packet thành ra có nhiều packet, nên nguy cơ bị mất packet sẽ tăng lên so với trường hợp không cần phân mảnh packet. Ngoài ra việc phải phân mảnh packet tốn tài nguyên xử lý và bộ nhớ của các node trên đường truyền, do phải xử lý nhiều packet hơn, node phải thực hiện phân mảnh và node đích phải thực hiện ghép mảnh còn phải tốn nhiều tài nguyên hơn nữa. Ngoài ra overhead của các tầng protocol do có nhiều packet cũng tăng lên, so với kích thước payload vẫn như ban đầu, nên hiệu năng bị giảm. Delay cũng sẽ cao lên.
* Nếu là IPv4 và packet có bật cờ DF thì node sẽ không tự phân mảnh packet mà sẽ drop nó và gửi 1 packet ICMP về nguồn gửi của packet với type 3 code 4 (Fragmentation required, and DF flag set). Packet này cũng mang thông tin MTU ở vị trí node bị drop packet. Nếu trên đường truyền về này không bị cái nào chặn ICMP thì phía gửi ban đầu sẽ nhận được thông tin này. Có thể nó sẽ biết xử lý đúng đắn và giảm kích thước packet xuống (với thông tin MTU trong packet ICMP này), gửi lại, cũng có thể nó sẽ thông báo lỗi, do việc giảm kích thước không tương thích với ứng dụng, hoặc tệ hơn hơn là nó không biết phải làm gì. Tệ hơn nữa là có tường lửa nào đó trên đường chặn ICMP (vì admin đọc được cái guide cũ rích từ mấy chục năm trước bảo nên chặn ICMP để block ping
), và thế là phía gửi không biết packet bị drop do to quá, đợi một hồi thì tưởng là bị packet loss, và thử gửi lại với kích thước y như cũ, và lại bị từ chối, kết quả là người dùng thấy mọi thứ như bị treo đơ đơ.
* Nếu là IPv6 thì do IPv6 quy định rõ là các router trên đường truyền không được phép tự ý phân mảnh packet, nên với IPv6 thì sẽ giống như tình huống IPv4 mà có bật cờ DF. Chỉ khác biệt là ở chỗ là khi drop packet do to quá thì node bên IPv6 sẽ gửi packet ICMPv6 type 2 code 0 (packet too big) trả lại về cho sender mà thôi (còn thông tin MTU thì cũng có như bên IPv4). Và ở đây sẽ cũng có các vấn đề như bên IPv4 nếu các tường lửa chặn ICMPv6.
Như vậy vấn đề gặp phải khi lỡ gửi packet to hơn MTU đâu đó trên đường truyền không nhỏ. Nhẹ thì như bên IPv4 sẽ bị giảm hiệu năng do phải phân mảnh packet, nặng hơn như bên IPv6 thì phải truyền lại, hoặc nếu ICMPv6 bị chặn thì treo đơ luôn. Tối ưu sẽ là phía bên gửi đi chỉ gửi các packet không lớn hơn MTU trên khắp đường truyền.
Một giải pháp là khi A truyền dữ liệu đến B, trước khi bắt đầu truyền A sẽ thử tìm giá trị MTU nhỏ nhất trên toàn bộ đường truyền. Cái này là Path MTU Discovery (PMTUD), phía gửi ban đầu coi như MTU là MTU trên adapter mạng của nó và gửi packet với kích thước này đến B. Với IPv4 nó sẽ bật cờ DF. Như viết ở trên, nếu trên đường truyền gặp node nào đó có MTU nhỏ hơn thì packet sẽ bị drop và trả về packet ICMP/ICMPv6 chứa thông tin MTU nhỏ hơn đó. Phía gửi sẽ dùng thông tin này, giảm kích thước packet xuống và gửi lại. Cứ thế lặp lại cho đến khi đến đích. Khi đến đích được thì packet đã đủ nhỏ để không bị chỗ nào drop và kích thước đó có thể được sử dụng như MTU của toàn bộ đường truyền (Path MTU). Từ đó A chỉ dùng kích thước tối đa này khi gửi packet cho B.
Tuy nhiên như ở trên đã đề cập, cái này fail toàn tập nếu đâu đó trên đường truyền có tường lửa chặn ICMP/ICMPv6, khi này kết nối sẽ bị treo 1 hồi đến khi timeout. Ngoài ra, ngay cả khi không bị chặn thì quá trình dò PMTUD cũng tạo ra delay trước khi dữ liệu được truyền.
Một giải pháp nữa, nhưng mà chỉ áp dụng được cho TCP, đó là node trên đường truyền có MTU nhỏ hơn sẽ chỉnh sửa giá trị của field MSS (Maximum Segment Size) trên packet TCP SYN được gửi đi qua nó khi khởi tạo kết nối. Thí dụ với IPv4 TCP khi packet SYN đi qua node có MTU 1492, và node này có hỗ trợ tính năng điều chỉnh MSS tự động, và nó thấy field MSS của packet không có giá trị hoặc to hơn 1452 (1492-40 bytes header IPv4 TCP, với IPv6 thì là 1432 = 1492-60), thì nó sẽ sửa giá trị này của packet xuống 1452. Điều này cũng sẽ được nó làm với packet đi từ hướng kia trở lại của quá trình khởi tạo kết nối TCP. Kết quả là sau bước này ở hai đầu kết nối TCP vừa được tạo đều có thông tin MSS=1452 (1432 với IPv6) và cả 2 đầu sau đó sẽ không tạo packet TCP nào to hơn 1492 cho kết nối này.
Nhiều HĐH router, trong đó có RouterOS tự động làm điều này. Trong RouterOS thì nó là setting "Change TCP MSS" bật mặc định trong cái profile PPP mà các interface pppoe-out sử dụng. Nhờ đó, với các kết nối thông thường dùng TCP, hầu như các bác sẽ không cảm nhận thấy các vấn đề gây ra bởi việc packet quá khổ so với MTU. Nếu cái này không hoạt động tự động thì có thể thêm rule mangle vào RouterOS như bác
@ppptran viết ở trên, để nó "clamp MSS to path-mtu".
Nhưng cái này chỉ áp dụng cho TCP, không sử dụng được cho UDP hay các protocol khác. Trong khi, thí dụ, mặc định DNS dùng UDP trước tiên, và nhiều domain trả về rất nhiều địa chỉ khiến packet trả lời chạm đến giới hạn MTU (trả lời query to qua sẽ bị cụt trong packet này, và sau đó client sẽ chuyển sang query bằng TCP, nhưng chỉ làm điều đó nếu nó nhận được cái packet UDP trước cái đã), hay với HTTP/3 và QUIC, cả duyệt web bình thường cũng chuyển qua dùng UDP, và sẽ bị ảnh hưởng bởi MTU sai. Một lần nữa nhắc lại thì thông thường IPv4 sẽ không bật cờ DF và router sẽ tự phân mảnh packet quá khổ hộ nên các bác sẽ không cảm nhận được nhiều (nhưng sẽ có thêm delay và tốn thêm tài nguyên). Nhưng với IPv6, nếu PMTUD không hoạt động được đúng thì các vấn đề gặp phải sẽ lớn hơn nhiều. Em nghĩ chắc phần lớn các vấn đề các bác trên này hay gặp phải khi bật IPv6, kiểu lag giật, timeout, trắng xóa, đại khái là không "mượt" như bác
@ppptran viết ở trên, là do MTU gây ra.
Quay lại vấn đề MTU của PPPoE mặc định bị hạ xuống <= 1492. Ở phần Introduction của RFC4638 (
RFC 4638: Accommodating a Maximum Transit Unit/Maximum Receive Unit (MTU/MRU) Greater Than 1492 in the Point-to-Point Protocol over Ethernet (PPPoE) (https://datatracker.ietf.org/doc/rfc4638/)) họ có đề cập đến lý do tại sao ngày nay cái RFC này, cái đề xuất giải pháp cho MTU PPPoE lên được 1500 hoặc cao hơn, lại cần thiết hơn so với trước:
* Thời hai mươi mấy năm trước, lúc PPPoE mới ra, thì khi vào internet bằng PPPoE thường sẽ là có 1 thiết bị PC cắm trực tiếp vào thiết bị chuyển đổi (CPE), và chính cái PC đó (đa số là Windows) thực hiện việc quay PPPoE. Do tự quay nên cái interface này trên hệ điều hành (Windows) chạy trên cái PC này biết rõ MTU tối đa chỉ có 1492 (hoặc nhỏ hơn). Từ đó các ứng dụng chạy trên PC này cũng biết chỉ nên gửi packet to tối đa này mà thôi. Và như vậy coi như không gây ra vấn đề gì ít ra là cho chiều gửi đi cả. Và do tự biết MTU bị hạ, các ứng dụng cũng có thể tự bảo đầu bên kia không gửi packet to quá (thí du bằng cách set TCP MSS).
* Ngày nay (từ cả chục năm nay) hầu hết những nơi sử dụng PPPoE đều đã chuyển sang mô hình có 1 router đứng sau đường PPPoE, và sau router là một lô thiết bị, máy tính, điện thoại, tablet, IoT này nọ. Các cổng quay về hướng LAN của router, gồm cả các giao diện WiFi, đều có MTU đặt mặc định 1500 (hoặc cao hơn nếu bật jumbo frames). Tương tự, adapter mạng ethernet hay WiFi trên các thiết bị client cũng đều có MTU mặc định 1500. Nếu dùng Windows các bác có thể chạy lệnh
Code:
netsh interface ipv4 show subinterfaces
Nếu Linux thì
Code:
ip addr
(hoặc lệnh cũ)
ifconfig
MacOS thì
Code:
ifconfig
(hoặc)
netstat -i
Và thấy MTU 1500 ở các adapter ethernet và WiFi (trừ phi bật jumbo frames). Thông thường chỉ có các interface VPN mới có MTU < 1500 trên các thiết bị. Tóm lại các ứng dụng trên các thiết bị đều sẽ bắt đầu với assumption là gửi packet to đến 1500 bytes sẽ ok, và sẽ có nhiều ứng dụng tận dụng điều này, gửi packet to tối đa. Lúc này hoặc cần router can thiệp, phân mảnh hộ hoặc set hộ TCP MSS, hoặc các ứng dụng trên các thiết bị dùng PMTUD và phát hiện ra trên đường truyền có MTU < 1500, hoặc xui hơn thì gặp các kịch bản lỗi treo đơ đơ.
Cái này cũng áp dụng với chiều từ ngoài internet gửi dữ liệu về mạng của bác. MTU 1500 gần như là chuẩn được mọi node ngoài internet (không kể PPPoE) chấp nhận. Nếu không bị can thiệp bởi MSS, sẽ có rất nhiều server gửi packet to 1500 bytes cho bác, để rồi đến router sẽ bị phân mảnh (với IPv6 thì thường họ không dám làm điều này, thí dụ Cloudflare chỉ dám gửi packet to 1400 bytes nếu dùng IPv6
Fixing an old hack - why we are bumping the IPv6 MTU (https://blog.cloudflare.com/increasing-ipv6-mtu/) do lo sợ PMTUD không hoạt động).
Như vậy giải pháp đỡ đau đầu nhất là làm cho cái đường PPPoE của bác nó dùng được MTU 1500. Từ đầu đến cuối sẽ chỉ có MTU 1500, không sợ bị dính các cái quái gở như ở trên kia. Chính vì thế cái RFC4638 nó mới ra đời và giờ được càng nhiều ISP hỗ trợ (và RouterOS hỗ trợ từ 6.33).