In-kernel NAT [ipfw] dropping large UDP return packets

Jeff Kletsky jmk at wagsky.com
Wed Jun 13 23:44:56 UTC 2018



On 6/13/18 1:28 PM, Andrey V. Elsukov wrote:
> On 13.06.2018 23:04, Jeff Kletsky wrote:
>>> 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.
>>>
>> Thanks!!
>>
>> Mystery solved...
>>
>> /usr/src/sys/netinet/libalias/alias.c
>>
>> #ifdef _KERNEL
>> /*
>>   * m_megapullup() - this function is a big hack.
>>   * Thankfully, it's only used in ng_nat and ipfw+nat.
>>
>> suggests that the "old school" approach of natd might resolve this. I'll
>> give it a try when I'm close enough to the box to resolve it when I make
>> a configuration error.
> I didn't look at the rest of libalias, but you, probably, can improve
> this hack to use 9k or 16k mbufs. You can replace m_get2() call in
> m_megapullup() with the following code:
>
> 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);
> else
> 	goto bad;
>

Tested and "works for me" on 11.1-RELEASE-p10 with GENERIC kernconf

8<
--- 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))
          return (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);
+    else
+        goto bad;
      if (mcl == NULL)
          goto bad;
      m_align(mcl, len);
 >8

Thanks again!

Jeff



More information about the freebsd-ipfw mailing list