پروژهٔ tokio-tun برای کار asynchronous با TUN/TAP در Rust و با استفاده از Tokio، پشتیبانی از FreeBSD، macOS، iOS و Android را در کنار Linux معرفی کرده است. در همهٔ platformهای پشتیبانیشده، packet I/O از طریق AsyncFd به Tokio متصل میشود؛ این crate از polling loop اختصاصی یا blocking fallback استفاده نمیکند.
دامنهٔ پشتیبانی در هر سیستم متفاوت است. Linux از TUN، TAP، multi-queue و offload پشتیبانی میکند. FreeBSD هر دو نوع TUN و TAP را دارد، اما multi-queue و offload در آن در دسترس نیست. macOS از driver داخلی utun استفاده میکند و فقط TUN در layer 3 را ارائه میدهد؛ ساخت utun نیز به دسترسی root نیاز دارد. تنظیم MAC address برای TAP در Linux و FreeBSD ممکن است، اما TUN اساساً MAC address ندارد.
پشتیبانی Android و iOS فقط به I/O محدود است. برنامه باید یک file descriptor آماده را از بیرون به TunQueue بدهد؛ tokio-tun در این دو سیستم device نمیسازد و مستقیماً با VpnService یا NEPacketTunnelFlow یکپارچه نمیشود. در Android، file descriptor از VpnService میآید و در iOS به یک NetworkExtension bridge نیاز است. در هر دو حالت، bridge باید packet خام IP فراهم کند.
در Linux، فراخوانی TunBuilder::offload() قابلیتهای checksum، TSO4، TSO6 و GRO مبتنی بر NAPI را همراه با virtio-net header فعال میکند. هر packet دریافتی با یک header دهبایتی شروع میشود و packet ارسالی هم باید آن را داشته باشد. این حالت با packet_info() قابل ترکیب نیست. نکتهٔ مهم این است که GRO فقط برای packetهای نوشتهشده از userspace به kernel اعمال میشود، نه packetهای تحویلی به userspace؛ مسئولیت منطق segmentation و coalescing همچنان با برنامه است. همچنین receive buffer باید دستکم VIRTIO_NET_HDR_LEN + 65_536 بایت باشد، چون packetهای GSO میتوانند از MTU بزرگتر باشند.
برای انتقال queue میان processها، میتوان Tun را به TunQueue و سپس به OwnedFd تبدیل کرد. این تبدیل دسترسی به accessorهای interface را حذف میکند؛ بنابراین اطلاعاتی مثل نام interface باید پیش از آن نگه داشته شوند. TunQueue::new نیز file descriptor را non-blocking میکند؛ تغییری که بهدلیل اشتراک open file description، در process فرستنده هم اثر دارد.



