As a quick summary, first of all the host at each end of the connection knows it's MTU and advertises this as MSS in the TCP connection so that in theory the connection is established at the right MTU but this is never tested until a large packet is sent (which may or may not arrive). (the MSS is actually smaller than the MTU since its the data size without headers and even on a given link can change e.g. if IP options are in use.. but in any case it's derived from the MTU.. RTFM for the gory details).

Most consumer routers having an MTU of 1492 due to PPPoE will modify the MSS in-flight of the TCP connection to the MSS it knows for the next hop. This is not a standard feature in other routers though, and obviously wouldn't really work on the internet at large where paths can change mid connection. So it's best used at endpoint routers only.

Ideally such routers might advertise the MTU using DHCP or similar, and it is possible to do this now (and this is commonly used e.g. openstack clouds) however it does unnecessarily then limit the MTU of the local network unnecessarily. In theory I guess it could send a mtu for the default route and local subnet separately but basically in practice no one does this afaik.

Originally, a router along the path would know the MTU was smaller on the subsequent link, and would fragment the packet. For various reasons this is an expensive operation for all involved so we decided to instead take advantage of the "DF" (Don't Fragment) flag to instead generate an ICMP message back to the source asking them to please adjust their MTU/MSS and re-transmit. This flag specifically prevents the router fragmenting the message (that will never happen now) and is the default behavior at least on Linux and I assume most OS now.

This can go wrong in two ways, firstly ICMP may be blocked somewhere so it never arrives even at the end host or by some over zealous firewall. Secondly, the MTU may be misconfigured somewhere at layer 2 so the packet is silently dropped rather than having an ICMP message generated. The ICMP message requires that a router knows* the MTU of the complete l2 path to the next hop. If it get's that wrong, it will just send the packet and assume it is OK, when in reality it is dropped silently. (This same problem can be seen on just a local network, if you configure e.g. 9000 MTU on two hosts but an MTU of 1500 on your switch, your connections will break. It's not purely a routing issue).

There is a second protocol designed to detect PMTU "passively" to solve this problem called TCP PLPMD (Packetization Layer Path MTU Discovery). This basically uses heuristics to detect that packets are being dropped and then start probing the real path MTU by doing something like a binary search between some base MTU (e.g. 512) and the known max MTU (e.g. 1500). It tries various values until it settles on the actual MTU. The problem with this of course, is that packets may be dropped by packet loss rather than MTU issues and so there is a bit of luck and strategy to getting this right - and it also introduces some extra latency while some packets are being dropped.

For whatever reason this option is currently off by default in Linux (e.g. Ubuntu) and if it was on, it would silently fix the MTU on a lot of connections that are currently not fixed. The option is sysctl net.ipv4.tcp_mtu_probing. This has been enabled by default since Windows Vista, which explains why we still see people with their MSS misconfigured since Windows Vista onwards will just fix it. In linux at least it also has two modes, one where it waits to detect an ICMP blackhole and another where it always uses the protocol from the start. The former results in a 1-2s delay before it kicks in to fix a connection, so not ideal if it's happening on every connection but OK for the odd broken connection.

There is of course, like all topics, more to it than this.. but hopefully that helps.