mirror of
https://github.com/opnsense/src.git
synced 2026-02-03 20:49:35 -05:00
In emulated mode, the FreeBSD netmap port attempts to perform zero-copy transmission. This works as follows: the kernel ring is populated with mbuf headers to which netmap buffers are attached. When transmitting, the mbuf refcount is initialized to 2, and when the counter value has been decremented to 1 netmap infers that the driver has freed the mbuf and thus transmission is complete. This scheme does not generalize to the situation where netmap is attaching to a software interface which may transmit packets among multiple "queues", as is the case with bridge or lagg interfaces. In that case, we would be relying on backing hardware drivers to free transmitted mbufs promptly, but this isn't guaranteed; a driver may reasonably defer freeing a small number of transmitted buffers indefinitely. If such a buffer ends up at the tail of a netmap transmit ring, further transmits can end up blocked indefinitely. Fix the problem by removing the zero-copy scheme (which is also not implemented in the Linux port of netmap). Instead, the kernel ring is populated with regular mbuf clusters into which netmap buffers are copied by nm_os_generic_xmit_frame(). The refcounting scheme is preserved, and this lets us avoid allocating a fresh cluster per transmitted packet in the common case. If the transmit ring is full, a callout is used to free the "stuck" mbuf, avoiding the queue deadlock described above. Furthermore, when recycling mbuf clusters, be sure to fully reinitialize the mbuf header instead of simply re-setting M_PKTHDR. Some software interfaces, like if_vlan, may set fields in the header which should be reset before the mbuf is reused. Reviewed by: vmaffione MFC after: 1 month Sponsored by: Zenarmor Sponsored by: OPNsense Sponsored by: Klara, Inc. Differential Revision: https://reviews.freebsd.org/D38065 |
||
|---|---|---|
| .. | ||
| if_ptnet.c | ||
| if_re_netmap.h | ||
| if_vtnet_netmap.h | ||
| netmap.c | ||
| netmap_bdg.c | ||
| netmap_bdg.h | ||
| netmap_freebsd.c | ||
| netmap_generic.c | ||
| netmap_kern.h | ||
| netmap_kloop.c | ||
| netmap_legacy.c | ||
| netmap_mbq.c | ||
| netmap_mbq.h | ||
| netmap_mem2.c | ||
| netmap_mem2.h | ||
| netmap_monitor.c | ||
| netmap_null.c | ||
| netmap_offloadings.c | ||
| netmap_pipe.c | ||
| netmap_vale.c | ||