Operation Jumbo Drop: How sending large packets broke our AWS network
medium.com
medium.com
Eventually we figured out that Open Broadcaster Software has a compiled configuration of a max MTU of 1392 for the UDP packets we're sending. Generally this is fine because most routers have a default MTU of 1500, however when coupled with some of the VPN technologies, it ends up pushing the MTU over the limit and the video packets get dropped.
Overall MTUs seem to be slightly a not well understood thing, because answers on the internet wildly vary for appropriate ways of handling it. The consensus from some Google/WebRTC folks seems to be that 1200 is a safe and fast default.
> Anyway, 1200 bytes is 1280 bytes minus the RTP headers minus some bytes for RTP header extensions minus a few "let's play it safe" bytes. It'll usually work.
- https://groups.google.com/g/discuss-webrtc/c/gH5ysR3SoZI?pli...
- https://stackoverflow.com/questions/47635545/why-webrtc-chos...
// tunMTU is the MTU we set on tailscale's TUN interface. wireguard-go
// defaults to 1420 bytes, which only works if the "outer" MTU is 1500
// bytes. This breaks on DSL connections (typically 1492 MTU) and on
// GCE (1460 MTU?!).
//
// 1280 is the smallest MTU allowed for IPv6, which is a sensible
// "probably works everywhere" setting until we develop proper PMTU
// discovery.
And: https://datatracker.ietf.org/doc/rfc9000/ (sec 14) The maximum datagram size is defined as the largest size of UDP
payload that can be sent across a network path using a single UDP
datagram. QUIC MUST NOT be used if the network path cannot support a
maximum datagram size of at least 1200 bytes.
QUIC assumes a minimum IP packet size of at least 1280 bytes. This
is the IPv6 minimum size [IPv6] and is also supported by most modern
IPv4 networks. Assuming the minimum IP header size of 40 bytes for
IPv6 and 20 bytes for IPv4 and a UDP header size of 8 bytes, this
results in a maximum datagram size of 1232 bytes for IPv6 and 1252
bytes for IPv4. Thus, modern IPv4 and all IPv6 network paths are
expected to be able to support QUIC.
| Note: This requirement to support a UDP payload of 1200 bytes
| limits the space available for IPv6 extension headers to 32
| bytes or IPv4 options to 52 bytes if the path only supports the
| IPv6 minimum MTU of 1280 bytes. This affects Initial packets
| and path validation.
Any maximum datagram size larger than 1200 bytes can be discovered
using Path Maximum Transmission Unit Discovery (PMTUD) (see
Section 14.2.1) or Datagram Packetization Layer PMTU Discovery
(DPLPMTUD) (see Section 14.3).But, I don’t like the presumption in IPv6 that everything supports 1280. What if there is a VPN running over a 1280-MTU link, what is the MTU of the encrypted IPv6 payload? Now add in a couple more layers of VPNs for good measure.
For example, in the bad old days, when there was still a lot of ATM, packets would routinely get transmitted in 48 byte pieces (with a 5 byte header). Nobody wondered whether this kind of fragmentation should honor the DF bit.
If I recall correctly, multi-link PPP could also split a packet in smaller pieces to transmit it over multiple links at the same time.
So for IPv6, anything that is 1280 octets or smaller needs to forwarded without triggering a packet too big ICMP. Otherwise the link violates the IPv6 standard.
I’m leaning towards satire but in case you are serious, IPv6 built-in encryption is IPsec using opportunistic encryption (which then relies on dnsec…), and it’s not built into all IPv6 endpoints. Nor easy to configure, debug or support.
WireGuard, OpenVPN, etc are easier for users to configure and set up than IPsec, and less chances of mismatched configs, unsupported cipher suites, etc.
As for NAT, that’s irrelevant to the reason for using a VPN. IPv6 has Unique Local Addresses (ULA), which can be routable across and organisation but not from the internet, and so you may want a VPN for access to those. You may also simply want to extend your IPv6 network to a remote location that doesn’t have native IPv4, or whose ISP doesn’t provide sufficient delegated subnet ranges for your requirements. The VPN could also be to provide access to an IPv4 network behind the IPv6 router. The list goes on…
Quite the footgun you've got there, AWS.
This whole process is thwarted by overeager network administrators blocking ICMP traffic, or, apparently, by devices like this "transit gateway" that don't generate the ICMP packet at all.
Edit: Sorry, I think I may have fallen into the trap of explaining something that you already knew and not answering your question. I realized this after jsnell's comment elsewhere that the kernel may not want to split packets with the PSH bit set. I wasn't able to find an answer to your question in linux/net/ipv4/tcp_output.c, hopefully someone more familiar with Linux's TCP can chime in.
Linux doesn't actually need ICMP-based path MTU discovery to figure out the safe MSS to use. It implements RFC 4821-style MTU probing, where after repeated retransmissions the sender will try to retransmit smaller prefixes of the segment and see if that makes it through. If it does, it can be deduced that the safe MSS is lower than advertised, and the MSS for the connection is (permanently) dropped to the newly discovered limit. So even if the ICMP return path isn't working, the connection should just have a hickup for a few seconds but then resume working.
Why isn't MTU probing triggering here? I haven't checked the code, but would guess that it's refusing to split a segment with the PSH flag set.
Is it different here for mss-based discovery? You say permanently?
It would make sense to keep it permanently if the justification is purely based on the risk of icmp spoofing. But TCP connections can be very long-lived and the network might change under your feet, even worst if you're doing some bonding/teaming or container-/connection-migration, it might be a good idea to probe the path mtu again. It's just a pain from a latency perspective. I wish I could skip a bit of a stream without re-establishing the full connection.
https://m.youtube.com/watch?v=19JXZcmMJx0
(From a time when Disney made Vietnam War comedies with ensemble casts, instead of superhero movies)
A required max of 64 kB with a default segment size of 16 kB would improve performance and allow any amount of headers to be added.
From a hardware perspective, supporting jumbo frames makes everything harder. You need to have larger buffers. Especially when dealing with ethernet flow control. And latencies increase, because most NICs do store-and-forward, and need to hold onto the packet until the end arrives so they can calculate the CRC.
The solution to ethernet flow control is to disable it, of course.
I was doing 10GbE line rate with 1500b frames in 2006 or so on consumer-grade CPUs using software LRO (implemented in the driver).
I worked for a NIC vendor (Myricom) that shipped our NIC drivers with a default 9000b MTU. That was fine when we just did HPC & everything reachable via layer 2 was another one of our NICs with a 9k MTU. But it was a mess when we started selling 10GbE NICs. I got pretty good at diagnosing MTU mis-matches..
https://www.spokesman.com/stories/1995/jul/31/elephant-airli...
Aws uses A LOT of different overlay technologies which are implemented through encapsulation(aka overhead).
To enable cross region vpc connectivity, additional encryption and encapsulation can be layered on top of the existing encapsulation.
9001 bytes was the absolute max they could give to customers and still be able to do packet shenanigans.
I wouldn't mix VPC peering and transit gateway if you avoid it.
Seems to be a crappy migration path (execute these updates quickly and hopefully you don't drop too many packets before they apply)
This is a colossal pain if you run your home lan at 9000 for the aforementioned storage/NAS reason.