Hyper-V编译并安装OpenWRT

由于一些众所周知的原因,国内访问很多海外网站会出现访问速度缓慢甚至打不开的问题,其中不乏一些日常经常使用的例如搜索、邮箱等应用,虽然目前有很多解决方案来解决电脑、手机上面的网络加速问题,但是每个终端都要单独适配非常麻烦,因此直接在路由器端进行配置,让所有连入路由器的设备都可以无感加速,成为了一个相对『完美』的解决方案,因此我在家里的Gen8上面,用Hyper-V虚拟了一个OpenWRT的软路由来提供此类服务。

Hyper-V由于本身不开源,因此OpenWRT的官方编译版本在很早的时候就移除了针对Hyper-V的支持,因此为了让OpenWRT可以完美的运行在Hyper-V上,我们需要自行编译相关驱动组件。当然网上也有很多大神已经编译好的固件,但是大都加入了一些我自己不太使用的功能,作为一个洁癖,当然是自己编译一个了。

参考了Chiphell大神tedaz的文章非官方编译,Hyper-V的Openwrt x86和x86-64版,Chaos Calmer正式版后,修改整理如下

准备工作

首先你需要准备一个Linux的编译环境,建议选择Ubuntu这类比较流行的Linux发行版本,并参考OpenWRT官方的OpenWRT编译系统-安装,安装好编译所需要的一些依赖包

以Ubuntu 64bit为例,需要执行下面的命令来安装相关的依赖

1
sudo apt-get install build-essential subversion libncurses5-dev zlib1g-dev gawk gcc-multilib flex git-core gettext libssl-dev

修改源码

首先从OpenWRT的官网Git下载OpenWRT的源码,建议下载15.05分支的,Trunk分支下的代码通常不是非常稳定。

1
git clone git://git.openwrt.org/15.05/openwrt.git

更新OpenWRT所有的feeds,以便你在后续可以提前把需要的ipk(例如luci、shadowsocks的一些依赖等)打包到固件中

1
2
3
cd openwrt
./scripts/feeds update -a
./scripts/feeds install -a

下载完成后,需要针对源码进行如下的修改。

修改/package/kernel/linux/modules/virtual.mk,在最后加入下面的内容,修改内核,添加让OpenWRT内核支持Hyper-V

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#
# Hyper-V Drives depends on x86 or x86_64.
#
define KernelPackage/hyperv-balloon
SUBMENU:=$(VIRTUAL_MENU)
DEPENDS:=@(TARGET_x86||TARGET_x86_64)
TITLE:=Microsoft Hyper-V Balloon Driver
KCONFIG:= \
CONFIG_HYPERV_BALLOON \
CONFIG_HYPERVISOR_GUEST=y \
CONFIG_PARAVIRT=n \
CONFIG_HYPERV=y
FILES:=$(LINUX_DIR)/drivers/hv/hv_balloon.ko
AUTOLOAD:=$(call AutoLoad,06,hv_balloon)
endef

define KernelPackage/hyperv-balloon/description
Microsofot Hyper-V balloon driver.
endef

$(eval $(call KernelPackage,hyperv-balloon))

define KernelPackage/hyperv-net-vsc
SUBMENU:=$(VIRTUAL_MENU)
DEPENDS:=@(TARGET_x86||TARGET_x86_64)
TITLE:=Microsoft Hyper-V Network Driver
KCONFIG:= \
CONFIG_HYPERV_NET \
CONFIG_HYPERVISOR_GUEST=y \
CONFIG_PARAVIRT=n \
CONFIG_HYPERV=y
FILES:=$(LINUX_DIR)/drivers/net/hyperv/hv_netvsc.ko
AUTOLOAD:=$(call AutoLoad,35,hv_netvsc)
endef

define KernelPackage/hyperv-net-vsc/description
Microsoft Hyper-V Network Driver
endef

$(eval $(call KernelPackage,hyperv-net-vsc))

define KernelPackage/hyperv-util
SUBMENU:=$(VIRTUAL_MENU)
DEPENDS:=@(TARGET_x86||TARGET_x86_64)
TITLE:=Microsoft Hyper-V Utility Driver
KCONFIG:= \
CONFIG_HYPERV_UTILS \
CONFIG_HYPERVISOR_GUEST=y \
CONFIG_PARAVIRT=n \
CONFIG_HYPERV=y
FILES:=$(LINUX_DIR)/drivers/hv/hv_util.ko
AUTOLOAD:=$(call AutoLoad,10,hv_util)
endef

define KernelPackage/hyperv-util/description
Microsoft Hyper-V Utility Driver
endef

$(eval $(call KernelPackage,hyperv-util))

#
# Hyper-V Storage Drive needs to be in kernel rather than module to load the root fs.
#
define KernelPackage/hyperv-storage
SUBMENU:=$(VIRTUAL_MENU)
DEPENDS:=@(TARGET_x86||TARGET_x86_64) +kmod-scsi-core
TITLE:=Microsoft Hyper-V Storage Driver
KCONFIG:= \
CONFIG_HYPERV_STORAGE=y \
CONFIG_HYPERVISOR_GUEST=y \
CONFIG_PARAVIRT=n \
CONFIG_HYPERV=y
FILES:=$(LINUX_DIR)/drivers/scsi/hv_storvsc.ko
AUTOLOAD:=$(call AutoLoad,40,hv_storvsc)
endef

define KernelPackage/hyperv-storage/description
Microsoft Hyper-V Storage Driver
endef

$(eval $(call KernelPackage,hyperv-storage))</code></pre>

修改/target/linux/x86/64/config-default和/target/linux/x86/config-3.18,均添加以下内容(这里后面如果内核有跟心,就修改对应的config-内核版本号即可)

1
2
3
4
5
6
7
8
# CONFIG_HYPERV is not set
# CONFIG_HYPERV_BALLOON is not set
# CONFIG_HYPERV_NET is not set
# CONFIG_HYPERV_STORAGE is not set
# CONFIG_HYPERV_UTILS is not set
# CONFIG_FB_HYPERV is not set
# CONFIG_HID_HYPERV_MOUSE is not set
# CONFIG_HYPERV_KEYBOARD is not set

至此,修改完成。网上还有很多人建议修改Build相关的部分,考虑到后面我们统一使用其他工具来把img转成vhd,因此这一步我们直接生成img即可,不用修改Build相关的内容。

配置编译参数

OpenWRT有GUI的配置工具,因此我们回到OpenWRT源码主目录,执行make menuconfig,选择Target System为x86,Subtarget有x86_64,以便支持多核心大内存的使用。但是如果你需要在OpenWRT上使用XWare这类只有32位的工具,那就只能编译32位的包了。

然后在Kernel modules里的Virtualization Support里勾选上4个Hyper-V相关的。


最后取消Kernel modules里的Network Devices中其他网卡即可。
当然,如果你希望提前编译类似于shadowsocks之类的工具,可以参考Shadowsocks OpenWRT上的说明,下载相应的package并在配置编译参数时选中这个包即可,相关依赖会自动选中。

开始编译

使用命令make可以进行编译,make V=s可以让它输出调试信息,带上-j1参数表示用1个核心编译。建议你选择一台4核心以上的机器来进行编译以免等待的时间太久,由于编译过程中需要下载很多内容,因此流畅的网络(能自动翻墙是最好的)会大大加快你的编译速度。

我之前使用了E3-1230V2的CPU,用了6个核心编译,首次编译大概花了接近1小时的事件才全部编译完成。

转换格式,大功告成

编译完成后,在BIN目录下,可以找到编译完成的img文件(一般是压缩包),解压后,我们使用下面的命令来转化为Hyper-V可用的vhd格式。

1
qemu-img convert -f raw -O vpc openwrt-x86-generic-combined-ext4.img openwrt-x86-generic-combined-ext4.vhd

然后直接在Hyper-V下面使用就一切OK啦。