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 will end up blocked.
Fix the problem by removing the zero-copy scheme in the FreeBSD port.
Emulated mode is not intended to provide the highest possible
performance, so this is acceptable. Meanwhile, this change allows
netmap to attach to software interfaces without running into the
deadlock described above. In the future it should be possible to
reintroduce zero-copy transmits for hardware interfaces running in
emulated mode, and the transmit path still attempts to recycle mbufs
without an extra trip into UMA per transmit.