咩咩有一个J4125的软路由,曾经使用Pve直通网卡运行Openwrt做路由器,但发现即使在较低的网络负载下cpu的使用率还是比较高,排查下来是网卡直通带来的性能损耗,因此就换成了单Openwrt,其余软件均跑在Docker中,并在编译的Openwrt固件中编译了声卡显卡驱动,这样在Docker中依然能使用硬件加速的视频流转码(比如用路由器接采集卡推流直播),以上功能实现都比较容易,下面说说用Openwrt做虚拟化母机跑QEMU虚拟机,代替Pve跑Windows的事。

安装QEMU

首先,固件在编译时必须带kmod-tun,或者有能力安装,kmod-开头的包是内核模块,是不通用的,强制忽略也装不上的,建议在编译时将用不到的kmod-开头的包全选成<M>编译了保存起来以备不时之需,uname -a可以看到当前的内核版本,咩咩的是5.10.89

下载这个文件,里面有需要的包,上传到路由器任意目录(比如/tmp)
openwrt-qemu_x86_64-ipk.tgz

cd /tmp
tar -xzvf openwrt-qemu_x86_64-ipk.tgz
cd openwrt-qemu_x86_64-ipk
# 首先确保 kmod-tun 已安装,没装可以试试 opkg install kmod-tun
opkg install ./lib*.ipk ./glib2_2.58.3-5_x86_64.ipk ./pixman_0.38.4-1_x86_64.ipk ./uclibcxx_0.2.5-3_x86_64.ipk
opkg install ./qemu-firmware*.ipk ./qemu-keymaps_4.2.0-1_x86_64.ipk
opkg install ./qemu-keymaps_4.2.0-1_x86_64.ipk
opkg install ./qemu-img_4.2.0-1_x86_64.ipk ./qemu-ga_4.2.0-1_x86_64.ipk ./qemu-bridge-helper_4.2.0-1_x86_64.ipk ./virtio-console-helper_4.2.0-1_x86_64.ipk
# 最后这个能装上就装装不上就算,目前这样也用不到,需要 kmod-nbd 
opkg install ./qemu-nbd_4.2.0-1_x86_64.ipk

这样就装完了

启动虚拟机

首先如果你需要后台运行,建议装个opkg install screen

首先可以先启动一个3核心,4G,并且挂了一个iso的winpe来试试,调好了再建虚拟硬盘装系统

qemu-system-x86_64 -enable-kvm -nodefaults -monitor stdio \
  -machine q35,accel=kvm -vga virtio \
  -cpu host -smp 4,cores=4,threads=1 -m 4G \
  -cdrom /opt/Sparkle-PE.iso \
  -device e1000e,mac=EE:FF:00:01:02:03,netdev=br0 -netdev bridge,br=br-lan,id=br0 \
  -usb -device usb-kbd -device usb-tablet \
  -vnc :0,password -k en-us

运行了之后,就可以使用vnc连接了,:0就是5900的意思(最后一位),比如macOS可以访问vnc://192.168.1.1连接桌面,Windows则需要自行下载VNC客户端
需要在显示(qemu)的情况下输入change vnc password回车来设置vnc密码,输完密码回车就设置好了

解释一下配置内容:

  • 虚拟cpu总数 -smp 4,核心 cores=4,核心的线程 threads=1,他们的关系是cores * threads = smp,如果你是双核四线程的超线程cpu,那建议配置为-cpu host -smp 4,cores=2,threads=2
  • 内存大小4G -m 4G 分多少启动的时候就占多少
  • 网卡支持e1000e ,vmxnet3,virtio-net-pci,性能最好的是virtio那个(win不带驱动),兼容性最好是e1000e,接到br-lan上,也就是Op的lan口,可以设置多个虚拟网卡,注意id要唯一
  • vnc用的usb鼠标键盘usb-tabletusb-kbd
  • vnc就算设置password=off也是没有效果的依然需要密码,:0就是5900,:1就是5901,以此类推,或是可以配置监听指定ip,比如-vnc 192.168.1.1:5900,password=yes -k en-us,另外还支持网页版的noVNC,只要将配置改为-vnc :0,websocket -k en-us就可以用noVNC v1.1.0来进行连接了
  • 不可以直通(重定向)物理usb设备,先插上,lsusb查看id,然后添加配置
    比如lsusb得到的是这样的Bus 001 Device 009: ID 058f:6387 Sparkle 32G Sandisk
    对应lsusb -tPort 5: Dev 9, If 0, Class=, Driver=usb-storage, 480M
    那就配置 -device usb-host,vendorid=0x058f,productid=0x6387
    或者-device usb-host,hostbus=1,hostport=5 上面的针对设备,下面的针对接口
  • 添加-drive file=镜像文件,cache=none,format=raw,if=virtio 指定虚拟硬盘镜像,if=virtio需要驱动支持,但可以大幅提升磁盘性能,format根据镜像来定义,可以是raw也可以是qcow2,我btrfs开压缩,用的raw,file也可以直接指向物理硬盘设备
  • 如果一定要sata硬盘,那就这样配置(那个反斜杠\是告诉shell命令还没结束,可以把一行很长的命令拆成几行)

    -device ich9-intel-hda -device hda-duplex \
    -device ich9-ahci,id=sata \
    -drive id=dri1,if=none,format=raw,file=镜像文件 \
    -device ide-hd,bus=sata.0,drive=dri1

其他更多参数可以看 Arch的Wiki

最后启动Win10,我也不知道为什么打了驱动virtio的硬盘启动还是蓝屏,可能安装时应该勾选win to go

qemu-system-x86_64 -enable-kvm -nodefaults -monitor stdio \
  -machine q35,accel=kvm -vga virtio \
  -cpu host -smp 3,sockets=0,cores=3,threads=1 -m 4G \
  -drive file=/opt/win10.img,cache=none,format=raw \          
  -device virtio-net-pci,mac=EE:FF:00:01:02:03,netdev=br0 -netdev bridge,br=br-lan,id=br0 \
  -usb -device usb-kbd -device usb-tablet \
  -vnc :0,password -k en-us

QEMU控制台命令

设置vnc密码 change vnc password
软关机 system_powerdown
复位键 system_reset
USB设备信息 info usb
连接USB usb_add host:058f:6387