delphij's Chaos

选择chaos这个词是因为~~实在很难找到一个更合适的词来形容这儿了……

12 Jun 2022

用 BHyVe 虚拟机解决 FreeBSD Wi-Fi 驱动的问题

BHyVe

https://www.FreeBSD.org/ 10.0-RELEASE 起,系统提供了一个最早由 NetApp 开发的使用处理器提供的虚拟化硬件支持 (目前是 Intel VT 和 AMD-V;针对 ARM 平台的支持也在 https://reviews.freebsd.org/D26976) 的虚拟化环境 https://wiki.freebsd.org/bhyve,这套虚拟化环境可以运行支持 VirtIO 规范的各种操作系统,并提供了 UEFI 支持。

这套环境提供了 PCI 直通(passthrough) 能力。通俗地说,PCI 直通是直接把某个或某些原本应该由宿主(host) 管理的 PCI 总线上的硬件交给虚拟机(guest), 而非以虚拟化的方式由宿主系统代为管理的方式。 这样做的本意是绕过一层抽象来获得更好的性能,但有时也可以用来实现一些其他的目的。

FreeBSD 的 Wi-Fi 支持

FreeBSD 的 802.11 支持是 2003 年左右由 Sam Leffler 在引入 Atheros (现已被高通收购) 无线网卡支持时实现的。此后基于这套支持和公开文档,人们开发了一系列 Wi-Fi 驱动。 由于无线网络设备厂商已经在 Linux 驱动开发上进行了大量投资,目前 Linux 的 Wi-Fi 驱动较 FreeBSD 来说更为丰富。由于大部分此类驱动采取了 GPL / BSD 双许可证的授权, 因此比较理想的做法是实现 Linux 内核接口从而直接利用这些驱动,而不是从头重新开发一遍。

wifibox

考虑到已经有了虚拟化环境的支持,另一种可行的做法便是直接运行一个精简版的 Linux,用它来管理 Wi-Fi 硬件,然后通过 virtnet 来把网络接到 FreeBSD 上面来用。这样一来这个 Linux 虚拟机便实际上承担了驱动的角色。目前这种做法已经加入了 port (net/wifibox) 并可通过 pkg 直接安装。

网络方面,配置好之后大致的状态如下:

**********************************************
*                  laptop                    *
* +---------+                    +---------+ *
* |         |10.2.0.2    10.2.0.1|         | *
* | FreeBSD |<------------------>| wifibox |<*------> AP/router <--------> Internet 
* |  (host) |       tap(4)       | (guest) | *
* +---------+                    +---------+ *
*                                            *
**********************************************

在 wifibox 中运行的是一套 Linux 系统,在其中启用了路由功能,其 IP 地址是 10.2.0.1。 它会通过 DHCP 给宿主系统分配一个 IP(10.2.0.2)。

目前版本的 wifibox 是通过 grub-bhyve 启动的,其内部是一个 Alpine Linux 环境,日志通过 9p 直接放到宿主机的 /var/run/wifibox/appliance/ 中便于观察其状态。

wifibox的配置

wifibox 基本上不需要做什么配置,主要需要做的配置是:

  1. 禁用 FreeBSD 自带的驱动,并改为使用 DHCP 获得 wifibox 提供的 IP。在 /etc/rc.conf 中加入:
        devmatch_blacklist="if_iwm if_iwlwifi"   # 根据实际情况自行调整
        ifconfig_wifibox0="DHCP"
        wifibox_enable="YES"
    并注释掉之前的 Wi-Fi 配置。
  1. 指定PCI直通设备。这个设备可以用下面的命令获得:
pciconf -lv | grep -iB2 wireless | head -n 1 | cut -f1-4 -d: | \
  sed -e 's,^.*@pci0:,,g' | tr : / | sed -e s,^,passthru=,g

上述命令会产生形似:

passthru=4/0/0

的输出(注意由于硬件的不同,4/0/0 可能是其他值),将其添加到 /usr/local/etc/wifibox/bhyve.conf

  1. /etc/wpa_supplicant.conf 的内容合并到 /usr/local/etc/wifibox/wpa_supplicant/wpa_supplicant.conf

总结

上述做法可以让 FreeBSD 直接连上 802.11ac 网络,目前未测试 IPv6 但大概率不行,不过还是希望 iwlwifi 尽早完工。