The IPv4 packet parsing logic in iflib is incredibly complex, prematurely optimized, and believes all the world is TCP. This causes it to pullup part of the UDP payload into the packet header, causing unneeded memory copies. This impacts a project I'm working on, and it also impacts NFS. Eg, NFS over UDP will result in pullups for every datagram sent over an iflib NIC in this path:
m_pullup
kernel`iflib_encap+0x980
kernel`iflib_txq_drain+0x246
kernel`drain_ring_lockless+0x5e
kernel`ifmp_ring_enqueue+0x274
kernel`iflib_if_transmit+0x247
kernel`ether_output_frame+0xab
kernel`ether_output+0x6b0
kernel`ip_output_send+0xd6
kernel`ip_output+0x124d
kernel`udp_send+0x98c
kernel`sosend_dgram+0x2fc
kernel`svc_dg_reply+0xa2
kernel`svc_sendreply_common+0x97
kernel`svc_sendreply_mbuf+0x51
kernel`nfssvc_program+0x93f
kernel`svc_run_internal+0xbd0
kernel`svc_thread_start+0xb
kernel`fork_exit+0x7b
kernel`0xffffffff8104152eThis patch:
- adds parsing for UDP to iflib
- attempts to pull up the correct header size, based on UDP or TCP protocol type.
- simplifies packet parsing in iflib by
- no longer special casing having an ethernet header in a packet by itself
- no longer checking that we're trying to pullup something beyond the end of the packet. Since we're no longer trying to pull up a larger TCP header, attempting to pullup something larger than the packet should no longer happen. If it does, the packet is malformed and m_pullup will return an error when it runs out of data in the mbuf chain