WiFi 与多播

最近折腾了一波 WiFi……

起因是老的 Netgear R6250 路由的无线好像有点问题。一开始是2.4G有问题,于是我拿出了一个 TP-Link 的小路由来对付2.4G。其实我家普通设备也不用2.4G,也就是那些破智能家居的东西,啥灯泡开关之类,还有啥打印机啦 Kindle啦,这些破烂没法用5G。症状是这些设备时不时就掉线,看看路由的设备列表也会发现大多数2.4G设备都消失了。ping 也不通,出问题的时候尝试手机连2.4G也连不上。

后来我刷了一波 dd-wrt(OpenWrt 没有 5G 支持),结果更糟糕了,有时候直接断网…… 虽然估计是dd-wrt的问题,但是也懒得再刷回去了,反正也有问题。

于是想想这个路由也用了5年了,干脆买个新的。毕竟快要 WiFi 6 (802.11 ax) 了嘛,要买就买支持AX的。等了一段时间的折扣,搞来一个 Netgear AX5200。

买来之后用了没几天,发现2.4G问题依旧…… 症状也差不多,反正就是设备会掉。根据经验么,我就开始折腾路由的各个设置,例如看看哪个频道空啦,改改无线信号频率宽度啦,改改各种WiFi设置啦…… 结果改完居然5G都出问题了,时不时会卡上个半分钟一分钟的,卡完之后ping能收到一堆延时了最多半分钟的包。于是只好恢复出厂设置,然后5G好歹恢复了,所以真的是改设置改出问题了……

所以回头看2.4G相关设置,实在是没啥搞头…… 频道么,公寓楼里每个频道都一堆信号,干扰总是免不了的。然而就算这样,应该也不至于就没法用……

没办法只能拉出来Wireshark抓包,看看有啥希望没有。在2.4G有问题的时候,抓包发现路由偶尔还是能吐出来几个包的,多数都是多播……

于是这个时候我意识到这个可能就是问题:2.4G应该没有设备要听这个多播啊……

说到这个多播吧,其实是远程音频的副产品。因为多个设备都需要播放音频,而我又不想把耳机来回拔插,于是在各个系统都搞了远程音频,各个系统都把音频发到一个机子上。Linux/BSD用的是PulseAudio rtp send/recv,而Windows用的Scream。

这俩底下其实貌似都是RTP,以及都是用的多播。多播这个东西有线网是挺合理的,无线网就比较堪忧了。有些路由器甚至有自动把多播转成单播的功能。一般来说普通用户也没这个需求,所以 Netgear 没在普通路由器做这个也很合理……

虽然吧,还是有些奇怪的。多播应该是要主动申请加入(通过IGMP)的,而那些2.4G的设备显然不会去加入。既然这样,那路由不该把这些多播包发给它们啊……

为了证实是多播的问题,我观察了一下ping的延时和远程音频的关系。结果发现,只要一开始播放音乐,延时就涨到几百,只要一停,过一会就掉回几十……

既然怀疑就是多播的问题,那干掉多播就完了。我把远程音频都改成了单播的,幸好这俩都可以改。改完之后到现在已经三天了,目前看来还没啥问题……

搞完之后回头想想,说不定本来的路由就没问题呢?……

关于在线音乐

某些在线音乐服务真是不行啊……
Amazon Music:音乐库特别小,很多歌找不到……
Youtube Music:这货感觉就没有音质的概念……

今天搜了个很常见的歌,Amazon Music干脆没有,Youtube Music 搜索结果第一位是个不知道谁传上去的视频,音质明显不行,感觉只有64K或者128K…… 这种东西你拿出来还不如说你没有呢…… 随便搜了个320K MP3的,音质天差地别啊……

反正这俩都不能用……

鼓包的后续

我已经发过俩关于鼓包的文了,鼓了至少三个平板一个手表了…… 之前也说过,上个设备鼓起来的时候,新平板貌似也开始鼓了。
现在过了若干个月,果然它鼓起来了,而且是我各个设备鼓得最厉害的一个,甚至把屏幕上的玻璃膜鼓裂了…… 中间断开来了。
另外看了眼换过的Surface Pro 4,果然又鼓起来了。虽然不厉害,但是屏幕左侧开始和背板分离了。放冰箱只能临时缩回去,拿出来过会又鼓起来了,看来也只是热胀冷缩而已。

为了避免重蹈覆辙,我去看了眼这个有什么办法。网上说法基本上就是锂电池长期没电/满电都不太行,时间长了会产生气体鼓起来。解决方法就是保持电量在中间位置。
然而谁有兴趣没事情去拔了再过会插回去呢…… 幸好微软是有解决方案的:Surface Pro 3之后的设备,BIOS里有个Kiosk Mode。开了之后会自动维持电量在50%,即使一直插着。
于是我就跑去把 Surface Pro 4,Surface Pro 6,以及老的 Surface 3 的这个选项都开了。说起来那个古老的 Surface 3 应该是15年的吧,居然还没事……
其他笔记本据说有的也有官方工具能够干类似的事情,虽然我暂时没别的……
对于其他设备,有个有趣的小东西可能可以解决问题:有个叫 Chargie 的设备,简单来说就是个蓝牙控制的开关,串联在供电接口上。手机/平板上要装对应的app,装了之后,电量到一定水平就自动控制那个开关关掉,低了再开回来。
看上去是不错,本来考虑搞一个。然而这货貌似不支持USB PD,如果用USB-C充电可能有点问题,所以还没下手。不过长期来说,应该就是给所有一直插着的带电池设备都配上这个,例如 Pixel Slate……

GPU Passthrough in Bhyve (2)

接着昨天继续折腾,目前并没有什么进展……

Windows 这边还是错误43。经常看某些视频的可能知道普通情况是显卡坏了,然而我这个显卡直接用是没问题的,所以还是 passthrough 有啥问题。

首先,说 NVidia 从某个版本开始,在驱动里面做了限制。如果检测到 VM,那就报43。围绕这个有很多办法,比如 KVM 那边可以设置一个 kvm=off (或者 libvirt 里面 hidden=on),隐藏 hypervisor 的存在。我看了眼那个 patch,照着改了几次 bhyve 里面的 CPUID 处理,另外还改了系统的 vendor 之类,然而依然没用。后来看见还有另一个办法:直接 patch 掉驱动里面的检测代码。我 patch 了一波,结果还是 43,那看来根本就不是这个检测的问题了……

那看来应该还是某种硬件上的问题。鉴于 Nouveau 跑得好好的,看来是某些不是那么关键的东西没有模拟对。Linux 虚拟机里面一开始有一堆错误,主要是 PCI BAR 分配的问题。

Bhyve 的 PCI BAR 分配很基础,就是从 0xC0000000 开始一路往上填。对于64位的 BAR,从64位的基础地址开始填。然而 Bhyve 的64位基础地址太高,所以其实搞下来一点就行。我为了尽可能模拟真实环境(我看我真机上64位 BAR 也是在32位地址空间里),hack 了一波分配逻辑,把显卡最大的那个64位 BAR 给塞到了 0xC0000000 – 0xD0000000,然后其他的直接从0xD0000000开始填。这么搞完之后,这部分错误就没有了。另一部分错误是因为 Bhyve 不关心 PCI ROM 那块的空间,所以 PCI Bridge 上面的资源窗口不包括 ROM 那块。因为 ROM 默认在 0xDF000000 – 0xDF00FFFF,我直接把窗口开到了 0xE0000000,那么这个错误也解决了。

所以现在就很尴尬,Linux 那边没啥错误,Nouveau 跑得挺好,官方驱动起不来,报RmInitAdapter Failed (0x31:0xffff:834),Windows下面错误43,也不清楚到底是哪里有问题……

剩下的疑点有几个:

  1. Linux那边的guide一般提到需要 VBIOS 支持 EFI。我看我 Windows 里面 VBIOS 访问并没有问题(GPU-Z还可以dump,结果和真机一样),所以VBIOS访问应该正常。然而是不是需要真的去跑这个VBIOS呢?比如说在OVMF固件里面?我也不知道……
  2. 中断可能有点问题,Linux有个错误说无法找到中断路径啥的,然而理论上不用MSI应该也能跑?比较奇怪……
  3. 貌似有些 PCI capability 没有传进去,两边的 lspci 结果有区别。

只能接着折腾了……

GPU Passthrough in Bhyve

所谓 GPU Passthrough 其实就是把一个 GPU 扔给虚拟机用。众所周知,虚拟机没法打游戏的主要问题就是显示性能不行,因为基本上没有 3D 加速。如果能够把整个显卡直接扔进去,那当然性能应该和原生的差不多,就可以打游戏了……

所以因为懒得重启到 win 下面打游戏,就想尝试在 Bhyve 搞这个。Linux 下面这套东西其实很成熟,大家都用 KVM 搞个 windows 虚拟机然后传个显卡进去,然而 FreeBSD 底下这个 Bhyve 么…… 问题还不少。

首先是设置一些设备为 passthrough 设备,这样 host 就管不着它们了。这个是在 /boot/loader.conf 里面加上

pptdevs="1/0/0 1/0/1"

至于为啥是这俩,是因为这俩是我显卡搞出来的俩 PCI 设备。装了 vm-bhyve 之后,直接 vm passthru 就能看见对应的 Bhyve ID 了。

弄完之后,直接在 VM 的配置文件(vm configure <vm name>)里面加上

passthru0="1/0/0=10:0"
passthru1="1/0/1=10:1"

就可以让这俩设备传给 VM 了。

当然,以上只是最基本的…… 接着跑个 windows 就会发现显卡错误43,跑个 Linux 会和你说啥 PCI BAR 地址不对之类。

根据某些网上的帖子,这个原因是 bhyve 没检查 CPU 能支持的最大地址,于是分了个巨高的地址给某个 BAR,结果高过头了…… 这个可以通过篡改 bhyve 解决:

#define PCI_EMUL_MEMBASE64  0xD0000000UL
#define PCI_EMUL_MEMLIMIT64 0xFD000000UL

改完这个之后,跑个 Linux,里面用上 nouveau 驱动,就可以在 VM 里跑加速桌面了……

然而官方驱动还是不行。根据 Linux 各种帖子的说法,是因为 NV 会检测虚拟机,检测到就不让跑…… KVM 为此有个选项能隐藏 hypervisor 信息。然而我照着那个在 bhyve 抄了一份,依旧没法跑…… 不知道是不是抄得不对…… 官方驱动现在 Linux 里会说 RmInitAdapter Failed …… 还需要研究研究……

因为 nouveau 不支持 cuda,搞个 Linux 桌面最多也就能跑几个 Linux 游戏而已,最终目标还是要搞出来 windows 桌面……