OpenWrt – Blame information for rev 4
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
4 | 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 | |||
92 | <subtarget> will default to "generic" and must be specified if |
||
93 | <extra-qemu-options> are present |
||
94 | |||
95 | e.g. <subtarget> for malta can be le, be, le64, be64, le-glibc, le64-glibc, etc |
||
96 | |||
97 | <kernel>, <rootfs> can be required or optional arguments to qemu depending on |
||
98 | the actual <target> in use. They will default to files under bin/targets/ |
||
99 | |||
100 | Examples |
||
101 | |||
102 | $SELF x86 64 |
||
103 | $SELF x86 64 -enable-kvm -device virtio-balloon-pci |
||
104 | $SELF x86 64 -incoming tcp:0:4444 |
||
105 | $SELF x86 64-glibc |
||
106 | $SELF malta be -m 64 |
||
107 | $SELF malta le64 |
||
108 | $SELF malta be-glibc |
||
109 | $SELF armvirt 32 \\ |
||
110 | --kernel bin/targets/armvirt/32/openwrt-armvirt-32-zImage \\ |
||
111 | --rootfs bin/targets/armvirt/32/openwrt-armvirt-32-root.ext4 |
||
112 | EOF |
||
113 | } |
||
114 | |||
115 | rand_mac() { |
||
116 | hexdump -n 3 -e '"52:54:00:" 2/1 "%02x:" 1/1 "%02x"' /dev/urandom |
||
117 | } |
||
118 | |||
119 | parse_args() { |
||
120 | o_qemu_extra=() |
||
121 | while [ "$#" -gt 0 ]; do |
||
122 | case "$1" in |
||
123 | --kernel) o_kernel="$2"; shift 2 ;; |
||
124 | --rootfs) o_rootfs="$2"; shift 2 ;; |
||
125 | --help|-h) |
||
126 | usage |
||
127 | exit 0 |
||
128 | ;; |
||
129 | *) |
||
130 | if [ -z "$o_target" ]; then |
||
131 | o_target="$1" |
||
132 | elif [ -z "$o_subtarget" ]; then |
||
133 | o_subtarget="$1" |
||
134 | else |
||
135 | o_qemu_extra+=("$1") |
||
136 | fi |
||
137 | shift |
||
138 | ;; |
||
139 | esac |
||
140 | done |
||
141 | |||
142 | MAC_LAN="$(rand_mac)" |
||
143 | MAC_WAN="$(rand_mac)" |
||
144 | [ -n "$o_target" ] || { |
||
145 | usage |
||
146 | return 1 |
||
147 | } |
||
148 | [ -n "$o_subtarget" ] || o_subtarget="generic" |
||
149 | o_bindir="bin/targets/$o_target/$o_subtarget" |
||
150 | } |
||
151 | |||
152 | start_qemu_armvirt() { |
||
153 | local kernel="$o_kernel" |
||
154 | local rootfs="$o_rootfs" |
||
155 | local cpu |
||
156 | local qemu_exe |
||
157 | |||
158 | case "${o_subtarget%-*}" in |
||
159 | 32) |
||
160 | qemu_exe="qemu-system-arm" |
||
161 | cpu="cortex-a15" |
||
162 | [ -n "$kernel" ] || kernel="$o_bindir/openwrt-$o_target-${o_subtarget%-*}-zImage-initramfs" |
||
163 | ;; |
||
164 | 64) |
||
165 | qemu_exe="qemu-system-aarch64" |
||
166 | cpu="cortex-a57" |
||
167 | [ -n "$kernel" ] || kernel="$o_bindir/openwrt-$o_target-${o_subtarget%-*}-Image-initramfs" |
||
168 | ;; |
||
169 | *) |
||
170 | __errmsg "target $o_target: unknown subtarget $o_subtarget" |
||
171 | return 1 |
||
172 | ;; |
||
173 | esac |
||
174 | [ -z "$rootfs" ] || { |
||
175 | if [ ! -f "$rootfs" -a -s "$rootfs.gz" ]; then |
||
176 | gunzip "$rootfs.gz" |
||
177 | fi |
||
178 | o_qemu_extra+=( \ |
||
179 | "-drive" "file=$rootfs,format=raw,if=virtio" \ |
||
180 | "-append" "root=/dev/vda rootwait" \ |
||
181 | ) |
||
182 | } |
||
183 | |||
184 | "$qemu_exe" -machine virt -cpu "$cpu" -nographic \ |
||
185 | -netdev bridge,id=lan,br="$BR_LAN,helper=$HELPER" -device virtio-net-pci,id=devlan,netdev=lan,mac="$MAC_LAN" \ |
||
186 | -netdev bridge,id=wan,br="$BR_WAN,helper=$HELPER" -device virtio-net-pci,id=devwan,netdev=wan,mac="$MAC_WAN" \ |
||
187 | -kernel "$kernel" \ |
||
188 | "${o_qemu_extra[@]}" |
||
189 | } |
||
190 | |||
191 | start_qemu_malta() { |
||
192 | local is64 |
||
193 | local isel |
||
194 | local qemu_exe |
||
195 | local kernel="$o_kernel" |
||
196 | |||
197 | # o_subtarget can be le, be, le64, be64, le-glibc, le64-glibc, etc.. |
||
198 | is64="$(echo $o_subtarget | grep -o 64)" |
||
199 | [ "$(echo "$o_subtarget" | grep -o '^..')" = "le" ] && isel="el" |
||
200 | qemu_exe="qemu-system-mips$is64$isel" |
||
201 | |||
202 | [ -n "$kernel" ] || kernel="$o_bindir/openwrt-malta-${o_subtarget%-*}-vmlinux-initramfs.elf" |
||
203 | |||
204 | # NOTE: order of wan, lan -device arguments matters as it will affect which |
||
205 | # one will be actually used as the wan, lan network interface inside the |
||
206 | # guest machine |
||
207 | "$qemu_exe" -machine malta -nographic \ |
||
208 | -netdev bridge,id=wan,br="$BR_WAN,helper=$HELPER" -device pcnet,netdev=wan,mac="$MAC_WAN" \ |
||
209 | -netdev bridge,id=lan,br="$BR_LAN,helper=$HELPER" -device pcnet,netdev=lan,mac="$MAC_LAN" \ |
||
210 | -kernel "$kernel" \ |
||
211 | "${o_qemu_extra[@]}" |
||
212 | } |
||
213 | |||
214 | start_qemu_x86() { |
||
215 | local rootfs="$o_rootfs" |
||
216 | local qemu_exe |
||
217 | |||
218 | [ -n "$rootfs" ] || { |
||
219 | rootfs="$o_bindir/openwrt-$o_target-${o_subtarget%-*}-combined-ext4.img" |
||
220 | if [ ! -f "$rootfs" -a -s "$rootfs.gz" ]; then |
||
221 | gunzip "$rootfs.gz" |
||
222 | fi |
||
223 | } |
||
224 | # |
||
225 | # generic: 32-bit, pentium4 (CONFIG_MPENTIUM4), kvm guest, virtio |
||
226 | # legacy: 32-bit, i486 (CONFIG_M486) |
||
227 | # 64: 64-bit, kvm guest, virtio |
||
228 | # |
||
229 | case "${o_subtarget%-*}" in |
||
230 | legacy) qemu_exe="qemu-system-i386" ;; |
||
231 | generic|64) qemu_exe="qemu-system-x86_64" ;; |
||
232 | *) |
||
233 | __errmsg "target $o_target: unknown subtarget $o_subtarget" |
||
234 | return 1 |
||
235 | ;; |
||
236 | esac |
||
237 | |||
238 | case "${o_subtarget%-*}" in |
||
239 | legacy) |
||
240 | # use IDE (PATA) disk instead of AHCI (SATA). Refer to link |
||
241 | # [1] for related discussions |
||
242 | # |
||
243 | # To use AHCI interface |
||
244 | # |
||
245 | # -device ich9-ahci,id=ahci \ |
||
246 | # -device ide-drive,drive=drv0,bus=ahci.0 \ |
||
247 | # -drive "file=$rootfs,format=raw,id=drv0,if=none" \ |
||
248 | # |
||
249 | # [1] https://dev.openwrt.org/ticket/17947 |
||
250 | "$qemu_exe" -nographic \ |
||
251 | -netdev bridge,id=lan,br="$BR_LAN,helper=$HELPER" -device e1000,id=devlan,netdev=lan,mac="$MAC_LAN" \ |
||
252 | -netdev bridge,id=wan,br="$BR_WAN,helper=$HELPER" -device e1000,id=devwan,netdev=wan,mac="$MAC_WAN" \ |
||
253 | -device ide-drive,drive=drv0 \ |
||
254 | -drive "file=$rootfs,format=raw,id=drv0,if=none" \ |
||
255 | "${o_qemu_extra[@]}" |
||
256 | ;; |
||
257 | generic|64) |
||
258 | "$qemu_exe" -nographic \ |
||
259 | -netdev bridge,id=lan,br="$BR_LAN,helper=$HELPER" -device virtio-net-pci,id=devlan,netdev=lan,mac="$MAC_LAN" \ |
||
260 | -netdev bridge,id=wan,br="$BR_WAN,helper=$HELPER" -device virtio-net-pci,id=devwan,netdev=wan,mac="$MAC_WAN" \ |
||
261 | -drive "file=$rootfs,format=raw,if=virtio" \ |
||
262 | "${o_qemu_extra[@]}" |
||
263 | ;; |
||
264 | esac |
||
265 | } |
||
266 | |||
267 | start_qemu() { |
||
268 | case "$o_target" in |
||
269 | armvirt) start_qemu_armvirt ;; |
||
270 | malta) start_qemu_malta ;; |
||
271 | x86) start_qemu_x86 ;; |
||
272 | *) |
||
273 | __errmsg "target $o_target is not supported yet" |
||
274 | return 1 |
||
275 | ;; |
||
276 | esac |
||
277 | } |
||
278 | |||
279 | check_setup \ |
||
280 | && parse_args "$@" \ |
||
281 | && start_qemu |