As discovered on 11.1-RELEASE-p9 and present on -p10, reassembled packets over 4k are silently dropped by in-kernel NAT.
Patch based on suggestion of Andrey V. Elsukov supplied.
Cause identified by Andrey V. Elsukov on the freebsd-net and freebsd-ipfw lists on 2018-06-13 as being due to buffer allocation limits in the in-kernel implementation of libalias.
"The kernel version of libalias uses m_megapullup() function to make
single contiguous buffer. m_megapullup() uses m_get2() function to
allocate mbuf of appropriate size. If size of packet greater than 4k it
will fail. So, if you use MTU greater than 4k or if after fragments
reassembly you get a packet with length greater than 4k, ipfw_nat()
function will drop this packet."
Additional communication on those lists by Andrey suggested a patch might resolve this issue. The following is his code, I take no credit for it. Tested and "works for me" on kernel sources from 11.1-RELEASE-p10 and GENERIC kernconf.
/usr/src/sys/netinet/libalias]$ diff -u alias.c.orig alias.c
--- alias.c.orig 2017-07-20 16:42:02.000000000 -0700
+++ alias.c 2018-06-13 15:41:46.862121000 -0700
@@ -1758,7 +1758,14 @@
if (m->m_next == NULL && M_WRITABLE(m))
- mcl = m_get2(len, M_NOWAIT, MT_DATA, M_PKTHDR);
+ if (len <= MJUMPAGESIZE)
+ mcl = m_get2(len, M_NOWAIT, MT_DATA, M_PKTHDR);
+ else if (len <= MJUM9BYTES)
+ mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES);
+ else if (len <= MJUM16BYTES)
+ mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM16BYTES);
+ goto bad;
if (mcl == NULL)
Additional details on the situation that highlighted this can be found at
Relates to documentation issue #229003
Created attachment 194242 [details]
Possible patch from suggestion of Andrey V. Elsukov
A commit references this bug:
Date: Thu Jun 14 11:15:40 UTC 2018
New revision: 335133
In m_megapullup() use m_getjcl() to allocate 9k or 16k mbuf when requested.
It is better to try allocate a big mbuf, than just silently drop a big
packet. A better solution could be reworking of libalias modules to be
able use m_copydata()/m_copyback() instead of requiring the single
MFC after: 1 week
Some historical context:
Due to discussion thread after this commit: