Почему дурачки то, вполне нормальное решение
Нормальное решение там и так было. Нормальный FreeBSD'шный сетевой стек, без особых излишеств. Было примерно так:
Драйвер железа -> BSD network stack -(вот тут переход в User space)-> User app -(переход обратно в ядро)-> BSD network stack -> Драйвер железа.
Для USB-устройств было чуть сложнее, драйвер железа превращался в Драйвер USB Host -> Драйвер собственно внешней железки -> и так далее. Драйвер собственно внешней железки - это, например, ECM, т.е. Ethernet over USB, грубо говоря.
Теперь что они сделали:
Драйвер USB Host в ядре -> Переход в User Space -> Драйвер собственно внешней железки в User Space -> Переход в Kernel -> BSD ... BSD ...-> Переход в User Space -> Драйвер внешней железки -> Переход в Kernel -> Драйвер USB Host в ядре.
И вот этот самый драйвер внешней железки в User Space вызывается только один раз в миллисекунду. Все пакеты, которые пришли за это время, просто ждут в очереди. Потом пачкой обрабатываются. Потому что очень накладно это, ходить туда-сюда из режима ядра в режим пользователя и назад.
Думаю, что то же самое ждет
все USB-устройства. Уже там все для этого есть.