OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | #!/usr/bin/env bash |
2 | |||
3 | SELF="$0" |
||
4 | |||
5 | # Linux bridge for connecting lan and wan network of guest machines |
||
6 | BR_LAN="${BR_LAN:-br-lan}" |
||
7 | BR_WAN="${BR_WAN:-br-wan}" |
||
8 | |||
9 | # Host network interface providing internet access for guest machines |
||
10 | IF_INET="${IF_INET:-eth0}" |
||
11 | |||
12 | # qemu-bridge-helper does two things here |
||
13 | # |
||
14 | # - create tap interface |
||
15 | # - add the tap interface to bridge |
||
16 | # |
||
17 | # as such it requires CAP_NET_ADMIN to do its job. It will be convenient to |
||
18 | # have it as a root setuid program. Be aware of the security risks implied |
||
19 | # |
||
20 | # the helper has an acl list which defaults to deny all bridge. we need to add |
||
21 | # $BR_LAN and $BR_WAN to its allow list |
||
22 | # |
||
23 | # # sudo vim /etc/qemu/bridge.conf |
||
24 | # allow br-lan |
||
25 | # allow br-wan |
||
26 | # |
||
27 | # Other allowed directives can be 'allow all', 'deny all', 'include xxx', See |
||
28 | # qemu-bridge-helper.c of qemu source code for details. |
||
29 | # |
||
30 | # The helper can be provided by package qemu-system-common on debian, or |
||
31 | # qemu-kvm-common on rhel |
||
32 | # |
||
33 | HELPER="${HELPER:-/usr/libexec/qemu-bridge-helper}" |
||
34 | |||
35 | ### end of global settings |
||
36 | |||
37 | __errmsg() { |
||
38 | echo "$*" >&2 |
||
39 | } |
||
40 | |||
41 | do_setup() { |
||
42 | # setup bridge for LAN network |
||
43 | sudo ip link add dev "$BR_LAN" type bridge |
||
44 | sudo ip link set dev "$BR_LAN" up |
||
45 | sudo ip addr add 192.168.1.3/24 dev "$BR_LAN" |
||
46 | |||
47 | # setup bridge for WAN network |
||
48 | # |
||
49 | # minimal dnsmasq config for configuring guest wan network with dhcp |
||
50 | # |
||
51 | # # sudo apt-get install dnsmasq |
||
52 | # # sudo vi /etc/dnsmasq.conf |
||
53 | # interface=br-wan |
||
54 | # dhcp-range=192.168.7.50,192.168.7.150,255.255.255.0,30m |
||
55 | # |
||
56 | sudo ip link add dev "$BR_WAN" type bridge |
||
57 | sudo ip link set dev "$BR_WAN" up |
||
58 | sudo ip addr add 192.168.7.1/24 dev "$BR_WAN" |
||
59 | |||
60 | # guest internet access |
||
61 | sudo sysctl -w "net.ipv4.ip_forward=1" |
||
62 | sudo sysctl -w "net.ipv4.conf.$BR_WAN.proxy_arp=1" |
||
63 | while sudo iptables -t nat -D POSTROUTING -o "$IF_INET" -j MASQUERADE 2>/dev/null; do true; done |
||
64 | sudo iptables -t nat -A POSTROUTING -o "$IF_INET" -j MASQUERADE |
||
65 | } |
||
66 | |||
67 | check_setup_() { |
||
68 | ip link show "$BR_LAN" >/dev/null || return 1 |
||
69 | ip link show "$BR_WAN" >/dev/null || return 1 |
||
70 | [ -x "$HELPER" ] || { |
||
71 | __errmsg "helper $HELPER is not an executable" |
||
72 | return 1 |
||
73 | } |
||
74 | } |
||
75 | |||
76 | check_setup() { |
||
77 | check_setup_ || { |
||
78 | __errmsg "please check the script content to see the environment requirement" |
||
79 | return 1 |
||
80 | } |
||
81 | } |
||
82 | #do_setup; check_setup; exit $? |
||
83 | |||
84 | usage() { |
||
85 | cat >&2 <<EOF |
||
86 | Usage: $SELF [-h|--help] |
||
87 | $SELF <target> |
||
88 | [<subtarget> [<extra-qemu-options>]] |
||
89 | [--kernel <kernel>] |
||
90 | [--rootfs <rootfs>] |
||
91 | [--machine <machine>] |
||
92 | |||
93 | <subtarget> will default to "generic" and must be specified if |
||
94 | <extra-qemu-options> are present |
||
95 | |||
96 | e.g. <subtarget> for malta can be le, be, le64, be64, le-glibc, le64-glibc, etc |
||
97 | |||
98 | <kernel>, <rootfs> can be required or optional arguments to qemu depending on |
||
99 | the actual <target> in use. They will default to files under bin/targets/ |
||
100 | |||
101 | Examples |
||
102 | |||
103 | $SELF x86 64 |
||
104 | $SELF x86 64 --machine q35,accel=kvm -device virtio-balloon-pci |
||
105 | $SELF x86 64 -incoming tcp:0:4444 |
||
106 | $SELF x86 64-glibc |
||
107 | $SELF malta be -m 64 |
||
108 | $SELF malta le64 |
||
109 | $SELF malta be-glibc |
||
110 | $SELF armvirt 32 \\ |
||
111 | --machine virt,highmem=off \\ |
||
112 | --kernel bin/targets/armvirt/32/openwrt-armvirt-32-zImage \\ |
||
113 | --rootfs bin/targets/armvirt/32/openwrt-armvirt-32-root.ext4 |
||
114 | EOF |
||
115 | } |
||
116 | |||
117 | rand_mac() { |
||
118 | hexdump -n 3 -e '"52:54:00" 3/1 ":%02x"' /dev/urandom |
||
119 | } |
||
120 | |||
121 | parse_args() { |
||
122 | o_qemu_extra=() |
||
123 | while [ "$#" -gt 0 ]; do |
||
124 | case "$1" in |
||
125 | --kernel) o_kernel="$2"; shift 2 ;; |
||
126 | --rootfs) o_rootfs="$2"; shift 2 ;; |
||
127 | --machine|-machine|-M) o_mach="$2"; shift 2 ;; |
||
128 | --help|-h) |
||
129 | usage |
||
130 | exit 0 |
||
131 | ;; |
||
132 | *) |
||
133 | if [ -z "$o_target" ]; then |
||
134 | o_target="$1" |
||
135 | elif [ -z "$o_subtarget" ]; then |
||
136 | o_subtarget="$1" |
||
137 | else |
||
138 | o_qemu_extra+=("$1") |
||
139 | fi |
||
140 | shift |
||
141 | ;; |
||
142 | esac |
||
143 | done |
||
144 | |||
145 | MAC_LAN="$(rand_mac)" |
||
146 | MAC_WAN="$(rand_mac)" |
||
147 | [ -n "$o_target" ] || { |
||
148 | usage |
||
149 | return 1 |
||
150 | } |
||
151 | [ -n "$o_subtarget" ] || o_subtarget="generic" |
||
152 | o_bindir="bin/targets/$o_target/$o_subtarget" |
||
153 | } |
||
154 | |||
155 | start_qemu_armvirt() { |
||
156 | local kernel="$o_kernel" |
||
157 | local rootfs="$o_rootfs" |
||
158 | local mach="${o_mach:-virt}" |
||
159 | local cpu |
||
160 | local qemu_exe |
||
161 | |||
162 | case "${o_subtarget%-*}" in |
||
163 | 32) |
||
164 | qemu_exe="qemu-system-arm" |
||
165 | cpu="cortex-a15" |
||
166 | [ -n "$kernel" ] || kernel="$o_bindir/openwrt-$o_target-${o_subtarget%-*}-zImage-initramfs" |
||
167 | ;; |
||
168 | 64) |
||
169 | qemu_exe="qemu-system-aarch64" |
||
170 | cpu="cortex-a57" |
||
171 | [ -n "$kernel" ] || kernel="$o_bindir/openwrt-$o_target-${o_subtarget%-*}-Image-initramfs" |
||
172 | ;; |
||
173 | *) |
||
174 | __errmsg "target $o_target: unknown subtarget $o_subtarget" |
||
175 | return 1 |
||
176 | ;; |
||
177 | esac |
||
178 | [ -z "$rootfs" ] || { |
||
179 | if [ ! -f "$rootfs" -a -s "$rootfs.gz" ]; then |
||
180 | gunzip "$rootfs.gz" |
||
181 | fi |
||
182 | o_qemu_extra+=( \ |
||
183 | "-drive" "file=$rootfs,format=raw,if=virtio" \ |
||
184 | "-append" "root=/dev/vda rootwait" \ |
||
185 | ) |
||
186 | } |
||
187 | |||
188 | "$qemu_exe" -machine "$mach" -cpu "$cpu" -nographic \ |
||
189 | -netdev bridge,id=lan,br="$BR_LAN,helper=$HELPER" -device virtio-net-pci,id=devlan,netdev=lan,mac="$MAC_LAN" \ |
||
190 | -netdev bridge,id=wan,br="$BR_WAN,helper=$HELPER" -device virtio-net-pci,id=devwan,netdev=wan,mac="$MAC_WAN" \ |
||
191 | -kernel "$kernel" \ |
||
192 | "${o_qemu_extra[@]}" |
||
193 | } |
||
194 | |||
195 | start_qemu_malta() { |
||
196 | local is64 |
||
197 | local isel |
||
198 | local qemu_exe |
||
199 | local kernel="$o_kernel" |
||
200 | local mach="${o_mach:-malta}" |
||
201 | |||
202 | # o_subtarget can be le, be, le64, be64, le-glibc, le64-glibc, etc.. |
||
203 | is64="$(echo $o_subtarget | grep -o 64)" |
||
204 | [ "$(echo "$o_subtarget" | grep -o '^..')" = "le" ] && isel="el" |
||
205 | qemu_exe="qemu-system-mips$is64$isel" |
||
206 | |||
207 | [ -n "$kernel" ] || kernel="$o_bindir/openwrt-malta-${o_subtarget%-*}-vmlinux-initramfs.elf" |
||
208 | |||
209 | # NOTE: order of wan, lan -device arguments matters as it will affect which |
||
210 | # one will be actually used as the wan, lan network interface inside the |
||
211 | # guest machine |
||
212 | "$qemu_exe" -machine "$mach" -nographic \ |
||
213 | -netdev bridge,id=wan,br="$BR_WAN,helper=$HELPER" -device pcnet,netdev=wan,mac="$MAC_WAN" \ |
||
214 | -netdev bridge,id=lan,br="$BR_LAN,helper=$HELPER" -device pcnet,netdev=lan,mac="$MAC_LAN" \ |
||
215 | -kernel "$kernel" \ |
||
216 | "${o_qemu_extra[@]}" |
||
217 | } |
||
218 | |||
219 | start_qemu_x86() { |
||
220 | local rootfs="$o_rootfs" |
||
221 | local mach="${o_mach:-pc}" |
||
222 | local qemu_exe |
||
223 | |||
224 | [ -n "$rootfs" ] || { |
||
225 | rootfs="$o_bindir/openwrt-$o_target-${o_subtarget%-*}-combined-ext4.img" |
||
226 | if [ ! -f "$rootfs" -a -s "$rootfs.gz" ]; then |
||
227 | gunzip "$rootfs.gz" |
||
228 | fi |
||
229 | } |
||
230 | # |
||
231 | # generic: 32-bit, pentium4 (CONFIG_MPENTIUM4), kvm guest, virtio |
||
232 | # legacy: 32-bit, i486 (CONFIG_M486) |
||
233 | # 64: 64-bit, kvm guest, virtio |
||
234 | # |
||
235 | case "${o_subtarget%-*}" in |
||
236 | legacy) qemu_exe="qemu-system-i386" ;; |
||
237 | generic|64) qemu_exe="qemu-system-x86_64" ;; |
||
238 | *) |
||
239 | __errmsg "target $o_target: unknown subtarget $o_subtarget" |
||
240 | return 1 |
||
241 | ;; |
||
242 | esac |
||
243 | |||
244 | case "${o_subtarget%-*}" in |
||
245 | legacy) |
||
246 | # use IDE (PATA) disk instead of AHCI (SATA). Refer to link |
||
247 | # [1] for related discussions |
||
248 | # |
||
249 | # To use AHCI interface |
||
250 | # |
||
251 | # -device ich9-ahci,id=ahci \ |
||
252 | # -device ide-drive,drive=drv0,bus=ahci.0 \ |
||
253 | # -drive "file=$rootfs,format=raw,id=drv0,if=none" \ |
||
254 | # |
||
255 | # [1] https://dev.openwrt.org/ticket/17947 |
||
256 | "$qemu_exe" -machine "$mach" -nographic \ |
||
257 | -netdev bridge,id=lan,br="$BR_LAN,helper=$HELPER" -device e1000,id=devlan,netdev=lan,mac="$MAC_LAN" \ |
||
258 | -netdev bridge,id=wan,br="$BR_WAN,helper=$HELPER" -device e1000,id=devwan,netdev=wan,mac="$MAC_WAN" \ |
||
259 | -device ide-drive,drive=drv0 \ |
||
260 | -drive "file=$rootfs,format=raw,id=drv0,if=none" \ |
||
261 | "${o_qemu_extra[@]}" |
||
262 | ;; |
||
263 | generic|64) |
||
264 | "$qemu_exe" -machine "$mach" -nographic \ |
||
265 | -netdev bridge,id=lan,br="$BR_LAN,helper=$HELPER" -device virtio-net-pci,id=devlan,netdev=lan,mac="$MAC_LAN" \ |
||
266 | -netdev bridge,id=wan,br="$BR_WAN,helper=$HELPER" -device virtio-net-pci,id=devwan,netdev=wan,mac="$MAC_WAN" \ |
||
267 | -drive "file=$rootfs,format=raw,if=virtio" \ |
||
268 | "${o_qemu_extra[@]}" |
||
269 | ;; |
||
270 | esac |
||
271 | } |
||
272 | |||
273 | start_qemu() { |
||
274 | case "$o_target" in |
||
275 | armvirt) start_qemu_armvirt ;; |
||
276 | malta) start_qemu_malta ;; |
||
277 | x86) start_qemu_x86 ;; |
||
278 | *) |
||
279 | __errmsg "target $o_target is not supported yet" |
||
280 | return 1 |
||
281 | ;; |
||
282 | esac |
||
283 | } |
||
284 | |||
285 | check_setup \ |
||
286 | && parse_args "$@" \ |
||
287 | && start_qemu |