Hi, In tcp_mtudisc() we resend a TCP packet by calling tcp_output() if the TCP maximum segment size changes. At least that is what the code and commit message pretend.
---------------------------- revision 1.78 date: 2004/04/26 18:12:25; author: frantzen; state: Exp; lines: +10 -8; - allow the user to force the TCP mss below the fail-safe 216 with a low interface MTU. - break a tcp_output() -> tcp_mtudisc() -> tcp_output() infinite recursion when the TCP mss ends up larger than the interface MTU (when the if_mtu is smaller than the tcp header). connections will still stall feedback from itojun@, claudio@ and provos and testing from beck@ ---------------------------- But the functions in_rtchange() and in_pcbrtentry() do not touch t_maxseg. So orig_maxseg is always equal to tp->t_maxseg and tcp_output() is not called after changes in t_maxseg. The function tcp_mss() changes the maximum segment size t_maxseg, a different value can only be detected after calling it. Note that my diff checks whether orig_maxseg is greater than t_maxseg. For path MTU discovery it makes only sense to resend a packet immediately if it becomes smaller and is more likely to fit. While tobhe@ and I were debugging the endless tcp_mtudisc() recursion with TCP over UDP encap IPsec, we found the issue in tcp_mtudisc(). PMTU did not always work. The recursion bug is somewhere else and the current check does not prevent it. But let's get a correct PMTU discovery first. ok? bluhm Index: netinet/tcp_subr.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_subr.c,v retrieving revision 1.176 diff -u -p -U4 -r1.176 tcp_subr.c --- netinet/tcp_subr.c 25 Feb 2021 02:48:21 -0000 1.176 +++ netinet/tcp_subr.c 29 Jun 2021 12:20:46 -0000 @@ -836,30 +836,30 @@ void tcp_mtudisc(struct inpcb *inp, int errno) { struct tcpcb *tp = intotcpcb(inp); struct rtentry *rt; - int change = 0; + int orig_maxseg, change = 0; if (tp == NULL) return; + orig_maxseg = tp->t_maxseg; rt = in_pcbrtentry(inp); if (rt != NULL) { - int orig_maxseg = tp->t_maxseg; - /* * If this was not a host route, remove and realloc. */ if ((rt->rt_flags & RTF_HOST) == 0) { in_rtchange(inp, errno); if ((rt = in_pcbrtentry(inp)) == NULL) return; } - if (orig_maxseg != tp->t_maxseg || - (rt->rt_locks & RTV_MTU)) + if (rt->rt_locks & RTV_MTU) change = 1; } tcp_mss(tp, -1); + if (orig_maxseg > tp->t_maxseg) + change = 1; /* * Resend unacknowledged packets */