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}"
9 # Host network interface providing internet access for guest machines
10 IF_INET
="${IF_INET:-eth0}"
12 # qemu-bridge-helper does two things here
14 # - create tap interface
15 # - add the tap interface to bridge
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
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
23 # # sudo vim /etc/qemu/bridge.conf
27 # Other allowed directives can be 'allow all', 'deny all', 'include xxx', See
28 # qemu-bridge-helper.c of qemu source code for details.
30 # The helper can be provided by package qemu-system-common on debian, or
31 # qemu-kvm-common on rhel
33 HELPER
="${HELPER:-/usr/libexec/qemu-bridge-helper}"
35 ### end of global settings
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"
47 # setup bridge for WAN network
49 # minimal dnsmasq config for configuring guest wan network with dhcp
51 # # sudo apt-get install dnsmasq
52 # # sudo vi /etc/dnsmasq.conf
54 # dhcp-range=192.168.7.50,192.168.7.150,255.255.255.0,30m
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"
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
68 ip link show
"$BR_LAN" >/dev
/null ||
return 1
69 ip link show
"$BR_WAN" >/dev
/null ||
return 1
71 __errmsg
"helper $HELPER is not an executable"
77 [ -n "$o_network" ] ||
return 0
79 __errmsg
"please check the script content to see the environment requirement"
83 #do_setup; check_setup; exit $?
87 Usage: $SELF [-h|--help]
89 [<subtarget> [<extra-qemu-options>]]
95 <subtarget> will default to "generic" and must be specified if
96 <extra-qemu-options> are present
98 e.g. <subtarget> for malta can be le, be, le64, be64, le-glibc, le64-glibc, etc
100 <kernel>, <rootfs> can be required or optional arguments to qemu depending on
101 the actual <target> in use. They will default to files under bin/targets/
106 $SELF x86 64 --machine q35,accel=kvm -device virtio-balloon-pci
107 $SELF x86 64 -incoming tcp:0:4444
113 --machine virt,highmem=off \\
114 --kernel bin/targets/armsr/armv7/openwrt-armsr-armv7-generic-kernel.bin \\
115 --rootfs bin/targets/armsr/armv7/openwrt-armsr-armv7-generic-ext4-rootfs.img
120 hexdump -n 3 -e '"52:54:00" 3/1 ":%02x"' /dev
/urandom
126 while [ "$#" -gt 0 ]; do
127 # Cmdline options for the script itself SHOULD try to be
128 # prefixed with two dashes to distinguish them from those for
131 # Also note that qemu accepts both --opt and -opt
133 --kernel) o_kernel
="$2"; shift 2 ;;
134 --rootfs) o_rootfs
="$2"; shift 2 ;;
135 --machine|
-machine|
-M) o_mach
="$2"; shift 2 ;;
136 --network|
-n) o_network
=1; shift ;;
142 if [ -z "$o_target" ]; then
144 elif [ -z "$o_subtarget" ]; then
154 MAC_LAN
="$(rand_mac)"
155 MAC_WAN
="$(rand_mac)"
156 [ -n "$o_target" ] ||
{
160 [ -n "$o_subtarget" ] || o_subtarget
="generic"
161 eval "$(grep ^CONFIG_BINARY_FOLDER= .config 2>/dev/null)"
162 o_bindir
="${CONFIG_BINARY_FOLDER:-bin}/targets/$o_target/$o_subtarget"
166 local kernel
="$o_kernel"
167 local rootfs
="$o_rootfs"
168 local mach
="${o_mach:-virt}"
172 case "${o_subtarget%-*}" in
174 qemu_exe
="qemu-system-arm"
176 [ -n "$kernel" ] || kernel
="$o_bindir/openwrt-$o_target-${o_subtarget%-*}-generic-initramfs-kernel.bin"
179 qemu_exe
="qemu-system-aarch64"
181 [ -n "$kernel" ] || kernel
="$o_bindir/openwrt-$o_target-${o_subtarget%-*}-generic-initramfs-kernel.bin"
184 __errmsg
"target $o_target: unknown subtarget $o_subtarget"
188 [ -z "$rootfs" ] ||
{
189 if [ ! -f "$rootfs" -a -s "$rootfs.gz" ]; then
193 "-drive" "file=$rootfs,format=raw,if=virtio" \
194 "-append" "root=/dev/vda rootwait" \
198 [ -z "$o_network" ] ||
{
200 "-netdev" "bridge,id=lan,br=$BR_LAN,helper=$HELPER" \
201 "-device" "virtio-net-pci,id=devlan,netdev=lan,mac=$MAC_LAN" \
202 "-netdev" "bridge,id=wan,br=$BR_WAN,helper=$HELPER" "-device" \
203 "virtio-net-pci,id=devwan,netdev=wan,mac=$MAC_WAN" \
207 "$qemu_exe" -machine "$mach" -cpu "$cpu" -nographic \
217 local rootfs
="$o_rootfs"
218 local kernel
="$o_kernel"
219 local mach
="${o_mach:-malta}"
221 # o_subtarget can be le, be, le64, be64, le-glibc, le64-glibc, etc..
222 is64
="$(echo $o_subtarget | grep -o 64)"
223 [ "$(echo "$o_subtarget" | grep -o '^..')" = "le" ] && isel
="el"
224 qemu_exe
="qemu-system-mips$is64$isel"
225 [ -n "$is64" ] && cpu
="MIPS64R2-generic" || cpu
="24Kc"
227 [ -n "$kernel" ] || kernel
="$o_bindir/openwrt-malta-${o_subtarget%-*}-vmlinux-initramfs.elf"
229 [ -z "$rootfs" ] ||
{
230 if [ ! -f "$rootfs" -a -s "$rootfs.gz" ]; then
234 "-drive" "file=$rootfs,format=raw" \
235 "-append" "root=/dev/sda rootwait" \
239 # NOTE: order of wan, lan -device arguments matters as it will affect which
240 # one will be actually used as the wan, lan network interface inside the
242 [ -z "$o_network" ] ||
{
244 -netdev bridge
,id
=wan
,br
="$BR_WAN,helper=$HELPER" -device pcnet
,netdev
=wan
,mac
="$MAC_WAN"
245 -netdev bridge
,id
=lan
,br
="$BR_LAN,helper=$HELPER" -device pcnet
,netdev
=lan
,mac
="$MAC_LAN"
249 "$qemu_exe" -machine "$mach" -cpu "$cpu" -nographic \
256 local kernel
="$o_kernel"
257 local rootfs
="$o_rootfs"
258 local mach
="${o_mach:-pc}"
260 [ -n "$rootfs" ] ||
{
261 rootfs
="$o_bindir/openwrt-$o_target-${o_subtarget%-*}-generic-squashfs-combined.img"
262 if [ ! -f "$rootfs" -a -s "$rootfs.gz" ]; then
267 # generic: 32-bit, pentium4 (CONFIG_MPENTIUM4), kvm guest, virtio
268 # legacy: 32-bit, i486 (CONFIG_M486)
269 # 64: 64-bit, kvm guest, virtio
271 case "${o_subtarget%-*}" in
272 legacy
) qemu_exe
="qemu-system-i386" ;;
273 generic|
64) qemu_exe
="qemu-system-x86_64" ;;
275 __errmsg
"target $o_target: unknown subtarget $o_subtarget"
280 [ -n "$kernel" ] && {
282 "-kernel" "$kernel" \
283 "-append" "root=/dev/vda console=ttyS0 rootwait" \
287 [ -z "$o_network" ] ||
{
288 case "${o_subtarget%-*}" in
291 -netdev "bridge,id=lan,br=$BR_LAN,helper=$HELPER" -device "e1000,id=devlan,netdev=lan,mac=$MAC_LAN"
292 -netdev "bridge,id=wan,br=$BR_WAN,helper=$HELPER" -device "e1000,id=devwan,netdev=wan,mac=$MAC_WAN"
297 -netdev "bridge,id=lan,br=$BR_LAN,helper=$HELPER" -device "virtio-net-pci,id=devlan,netdev=lan,mac=$MAC_LAN"
298 -netdev "bridge,id=wan,br=$BR_WAN,helper=$HELPER" -device "virtio-net-pci,id=devwan,netdev=wan,mac=$MAC_WAN"
304 case "${o_subtarget%-*}" in
306 # use IDE (PATA) disk instead of AHCI (SATA). Refer to link
307 # [1] for related discussions
309 # To use AHCI interface
311 # -device ich9-ahci,id=ahci \
312 # -device ide-hd,drive=drv0,bus=ahci.0 \
313 # -drive "file=$rootfs,format=raw,id=drv0,if=none" \
315 # [1] https://dev.openwrt.org/ticket/17947
316 "$qemu_exe" -machine "$mach" -nographic \
317 -device ide-hd
,drive
=drv0 \
318 -drive "file=$rootfs,format=raw,id=drv0,if=none" \
322 "$qemu_exe" -machine "$mach" -nographic \
323 -drive "file=$rootfs,format=raw,if=virtio" \
331 armsr
) start_qemu_armsr
;;
332 malta
) start_qemu_malta
;;
333 x86
) start_qemu_x86
;;
335 __errmsg
"target $o_target is not supported yet"