On Fri 07/08/2026 07:17, Zixu Wu wrote:
> Zero padding shouldn't cause the packet size to go beyond MTU.
> 
> diff --git a/sys/net/if_wg.c b/sys/net/if_wg.c
> index 0641c4b5ba9..90ef5b808a0 100644
> --- a/sys/net/if_wg.c
> +++ b/sys/net/if_wg.c
> @@ -1592,6 +1592,9 @@ wg_encap(struct wg_softc *sc, struct mbuf *m)
>         peer = t->t_peer;
> 
>         plaintext_len = WG_PKT_WITH_PADDING(m->m_pkthdr.len);
> +       if (m->m_pkthdr.len <= t->t_mtu && plaintext_len > t->t_mtu) {
> +               plaintext_len = t->t_mtu;
> +       }
>         padding_len = plaintext_len - m->m_pkthdr.len;
>         out_len = sizeof(struct wg_pkt_data) + plaintext_len +
>             NOISE_AUTHTAG_LEN;

I think the premise of Zixu's patch is valid: with t_mtu = if_mtu = 1420
(default, not a multiple of 16), inner packets of 1409–1420 round up to
1424 via WG_PKT_WITH_PADDING. Adding the 80-byte wg envelope pushes
total volume to 1504 bytes, exceeding the standard transport capacity
and forcing the network to split single packages into fragments.

Zixu's proposed change:

        if (m->m_pkthdr.len <= t->t_mtu && plaintext_len > t->t_mtu) {
                plaintext_len = t->t_mtu;
        }

However:
- If an incoming package already exceeds the limit (m->m_pkthdr.len >
  t->t_mtu), the guard condition evaluates to false. The restriction is
  bypassed completely, allowing padding to inflate the payload even
  further. The MTU ceiling must apply unconditionally.
- System keepalives initialize with zeroed values (t_mtu = 0, len = 0).
  Applying padding to zero yields 16 bytes, triggering the clamp back to
  0 only by coincidence. Explicitly checking (t->t_mtu != 0) makes the
  logic transparent: keepalives carry no MTU constraint, whereas data
  payloads must strictly observe it.

Using MIN() provides an explicit, elegant safeguard while maintaining
clean code conventions:

diff --git sys/net/if_wg.c sys/net/if_wg.c
index 0641c4b5ba9..1a00af9dc1d 100644
--- sys/net/if_wg.c
+++ sys/net/if_wg.c
@@ -1592,6 +1592,8 @@ wg_encap(struct wg_softc *sc, struct mbuf *m)
        peer = t->t_peer;
 
        plaintext_len = WG_PKT_WITH_PADDING(m->m_pkthdr.len);
+       if (t->t_mtu != 0)
+               plaintext_len = MIN(plaintext_len, t->t_mtu);
        padding_len = plaintext_len - m->m_pkthdr.len;
        out_len = sizeof(struct wg_pkt_data) + plaintext_len +
            NOISE_AUTHTAG_LEN;

Reply via email to