1b002434f0
The qemustart script currently picks the ext4 filesystem rather than squashfs, while the latter is default for nearly all OpenWrt targets. Change the default behaviour of qemustart to be in line with the rest. Signed-off-by: Paul Spooren <mail@aparcar.org>
343 lines
8.8 KiB
Bash
Executable File
343 lines
8.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
SELF="$0"
|
|
|
|
# Linux bridge for connecting lan and wan network of guest machines
|
|
BR_LAN="${BR_LAN:-br-lan}"
|
|
BR_WAN="${BR_WAN:-br-wan}"
|
|
|
|
# Host network interface providing internet access for guest machines
|
|
IF_INET="${IF_INET:-eth0}"
|
|
|
|
# qemu-bridge-helper does two things here
|
|
#
|
|
# - create tap interface
|
|
# - add the tap interface to bridge
|
|
#
|
|
# as such it requires CAP_NET_ADMIN to do its job. It will be convenient to
|
|
# have it as a root setuid program. Be aware of the security risks implied
|
|
#
|
|
# the helper has an acl list which defaults to deny all bridge. we need to add
|
|
# $BR_LAN and $BR_WAN to its allow list
|
|
#
|
|
# # sudo vim /etc/qemu/bridge.conf
|
|
# allow br-lan
|
|
# allow br-wan
|
|
#
|
|
# Other allowed directives can be 'allow all', 'deny all', 'include xxx', See
|
|
# qemu-bridge-helper.c of qemu source code for details.
|
|
#
|
|
# The helper can be provided by package qemu-system-common on debian, or
|
|
# qemu-kvm-common on rhel
|
|
#
|
|
HELPER="${HELPER:-/usr/libexec/qemu-bridge-helper}"
|
|
|
|
### end of global settings
|
|
|
|
__errmsg() {
|
|
echo "$*" >&2
|
|
}
|
|
|
|
do_setup() {
|
|
# setup bridge for LAN network
|
|
sudo ip link add dev "$BR_LAN" type bridge
|
|
sudo ip link set dev "$BR_LAN" up
|
|
sudo ip addr add 192.168.1.3/24 dev "$BR_LAN"
|
|
|
|
# setup bridge for WAN network
|
|
#
|
|
# minimal dnsmasq config for configuring guest wan network with dhcp
|
|
#
|
|
# # sudo apt-get install dnsmasq
|
|
# # sudo vi /etc/dnsmasq.conf
|
|
# interface=br-wan
|
|
# dhcp-range=192.168.7.50,192.168.7.150,255.255.255.0,30m
|
|
#
|
|
sudo ip link add dev "$BR_WAN" type bridge
|
|
sudo ip link set dev "$BR_WAN" up
|
|
sudo ip addr add 192.168.7.1/24 dev "$BR_WAN"
|
|
|
|
# guest internet access
|
|
sudo sysctl -w "net.ipv4.ip_forward=1"
|
|
sudo sysctl -w "net.ipv4.conf.$BR_WAN.proxy_arp=1"
|
|
while sudo iptables -t nat -D POSTROUTING -o "$IF_INET" -j MASQUERADE 2>/dev/null; do true; done
|
|
sudo iptables -t nat -A POSTROUTING -o "$IF_INET" -j MASQUERADE
|
|
}
|
|
|
|
check_setup_() {
|
|
ip link show "$BR_LAN" >/dev/null || return 1
|
|
ip link show "$BR_WAN" >/dev/null || return 1
|
|
[ -x "$HELPER" ] || {
|
|
__errmsg "helper $HELPER is not an executable"
|
|
return 1
|
|
}
|
|
}
|
|
|
|
check_setup() {
|
|
[ -n "$o_network" ] || return 0
|
|
check_setup_ || {
|
|
__errmsg "please check the script content to see the environment requirement"
|
|
return 1
|
|
}
|
|
}
|
|
#do_setup; check_setup; exit $?
|
|
|
|
usage() {
|
|
cat >&2 <<EOF
|
|
Usage: $SELF [-h|--help]
|
|
$SELF <target>
|
|
[<subtarget> [<extra-qemu-options>]]
|
|
[--kernel <kernel>]
|
|
[--rootfs <rootfs>]
|
|
[--machine <machine>]
|
|
[-n|--network]
|
|
|
|
<subtarget> will default to "generic" and must be specified if
|
|
<extra-qemu-options> are present
|
|
|
|
e.g. <subtarget> for malta can be le, be, le64, be64, le-glibc, le64-glibc, etc
|
|
|
|
<kernel>, <rootfs> can be required or optional arguments to qemu depending on
|
|
the actual <target> in use. They will default to files under bin/targets/
|
|
|
|
Examples
|
|
|
|
$SELF x86 64
|
|
$SELF x86 64 --machine q35,accel=kvm -device virtio-balloon-pci
|
|
$SELF x86 64 -incoming tcp:0:4444
|
|
$SELF x86 64-glibc
|
|
$SELF malta be -m 64
|
|
$SELF malta le64
|
|
$SELF malta be-glibc
|
|
$SELF armvirt 32 \\
|
|
--machine virt,highmem=off \\
|
|
--kernel bin/targets/armvirt/32/openwrt-armvirt-32-zImage \\
|
|
--rootfs bin/targets/armvirt/32/openwrt-armvirt-32-root.ext4
|
|
EOF
|
|
}
|
|
|
|
rand_mac() {
|
|
hexdump -n 3 -e '"52:54:00" 3/1 ":%02x"' /dev/urandom
|
|
}
|
|
|
|
parse_args() {
|
|
o_network=
|
|
o_qemu_extra=()
|
|
while [ "$#" -gt 0 ]; do
|
|
# Cmdline options for the script itself SHOULD try to be
|
|
# prefixed with two dashes to distinguish them from those for
|
|
# qemu executables.
|
|
#
|
|
# Also note that qemu accepts both --opt and -opt
|
|
case "$1" in
|
|
--kernel) o_kernel="$2"; shift 2 ;;
|
|
--rootfs) o_rootfs="$2"; shift 2 ;;
|
|
--machine|-machine|-M) o_mach="$2"; shift 2 ;;
|
|
--network|-n) o_network=1; shift ;;
|
|
--help|-h)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
if [ -z "$o_target" ]; then
|
|
o_target="$1"
|
|
elif [ -z "$o_subtarget" ]; then
|
|
o_subtarget="$1"
|
|
else
|
|
o_qemu_extra+=("$1")
|
|
fi
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
MAC_LAN="$(rand_mac)"
|
|
MAC_WAN="$(rand_mac)"
|
|
[ -n "$o_target" ] || {
|
|
usage
|
|
return 1
|
|
}
|
|
[ -n "$o_subtarget" ] || o_subtarget="generic"
|
|
o_bindir="bin/targets/$o_target/$o_subtarget"
|
|
}
|
|
|
|
start_qemu_armvirt() {
|
|
local kernel="$o_kernel"
|
|
local rootfs="$o_rootfs"
|
|
local mach="${o_mach:-virt}"
|
|
local cpu
|
|
local qemu_exe
|
|
|
|
case "${o_subtarget%-*}" in
|
|
32)
|
|
qemu_exe="qemu-system-arm"
|
|
cpu="cortex-a15"
|
|
[ -n "$kernel" ] || kernel="$o_bindir/openwrt-$o_target-${o_subtarget%-*}-zImage-initramfs"
|
|
;;
|
|
64)
|
|
qemu_exe="qemu-system-aarch64"
|
|
cpu="cortex-a57"
|
|
[ -n "$kernel" ] || kernel="$o_bindir/openwrt-$o_target-${o_subtarget%-*}-Image-initramfs"
|
|
;;
|
|
*)
|
|
__errmsg "target $o_target: unknown subtarget $o_subtarget"
|
|
return 1
|
|
;;
|
|
esac
|
|
[ -z "$rootfs" ] || {
|
|
if [ ! -f "$rootfs" -a -s "$rootfs.gz" ]; then
|
|
gunzip "$rootfs.gz"
|
|
fi
|
|
o_qemu_extra+=( \
|
|
"-drive" "file=$rootfs,format=raw,if=virtio" \
|
|
"-append" "root=/dev/vda rootwait" \
|
|
)
|
|
}
|
|
|
|
[ -z "$o_network" ] || {
|
|
o_qemu_extra+=( \
|
|
"-netdev" "bridge,id=lan,br=$BR_LAN,helper=$HELPER" \
|
|
"-device" "virtio-net-pci,id=devlan,netdev=lan,mac=$MAC_LAN" \
|
|
"-netdev" "bridge,id=wan,br=$BR_WAN,helper=$HELPER" "-device" \
|
|
"virtio-net-pci,id=devwan,netdev=wan,mac=$MAC_WAN" \
|
|
)
|
|
}
|
|
|
|
"$qemu_exe" -machine "$mach" -cpu "$cpu" -nographic \
|
|
-kernel "$kernel" \
|
|
"${o_qemu_extra[@]}"
|
|
}
|
|
|
|
start_qemu_malta() {
|
|
local is64
|
|
local isel
|
|
local qemu_exe
|
|
local cpu
|
|
local rootfs="$o_rootfs"
|
|
local kernel="$o_kernel"
|
|
local mach="${o_mach:-malta}"
|
|
|
|
# o_subtarget can be le, be, le64, be64, le-glibc, le64-glibc, etc..
|
|
is64="$(echo $o_subtarget | grep -o 64)"
|
|
[ "$(echo "$o_subtarget" | grep -o '^..')" = "le" ] && isel="el"
|
|
qemu_exe="qemu-system-mips$is64$isel"
|
|
[ -n "$is64" ] && cpu="MIPS64R2-generic" || cpu="24Kc"
|
|
|
|
[ -n "$kernel" ] || kernel="$o_bindir/openwrt-malta-${o_subtarget%-*}-vmlinux-initramfs.elf"
|
|
|
|
[ -z "$rootfs" ] || {
|
|
if [ ! -f "$rootfs" -a -s "$rootfs.gz" ]; then
|
|
gunzip "$rootfs.gz"
|
|
fi
|
|
o_qemu_extra+=( \
|
|
"-drive" "file=$rootfs,format=raw" \
|
|
"-append" "root=/dev/sda rootwait" \
|
|
)
|
|
}
|
|
|
|
# NOTE: order of wan, lan -device arguments matters as it will affect which
|
|
# one will be actually used as the wan, lan network interface inside the
|
|
# guest machine
|
|
[ -z "$o_network" ] || {
|
|
o_qemu_extra+=(
|
|
-netdev bridge,id=wan,br="$BR_WAN,helper=$HELPER" -device pcnet,netdev=wan,mac="$MAC_WAN"
|
|
-netdev bridge,id=lan,br="$BR_LAN,helper=$HELPER" -device pcnet,netdev=lan,mac="$MAC_LAN"
|
|
)
|
|
}
|
|
|
|
"$qemu_exe" -machine "$mach" -cpu "$cpu" -nographic \
|
|
-kernel "$kernel" \
|
|
"${o_qemu_extra[@]}"
|
|
}
|
|
|
|
start_qemu_x86() {
|
|
local qemu_exe
|
|
local kernel="$o_kernel"
|
|
local rootfs="$o_rootfs"
|
|
local mach="${o_mach:-pc}"
|
|
|
|
[ -n "$rootfs" ] || {
|
|
rootfs="$o_bindir/openwrt-$o_target-${o_subtarget%-*}-generic-squashfs-combined.img"
|
|
if [ ! -f "$rootfs" -a -s "$rootfs.gz" ]; then
|
|
gunzip "$rootfs.gz"
|
|
fi
|
|
}
|
|
#
|
|
# generic: 32-bit, pentium4 (CONFIG_MPENTIUM4), kvm guest, virtio
|
|
# legacy: 32-bit, i486 (CONFIG_M486)
|
|
# 64: 64-bit, kvm guest, virtio
|
|
#
|
|
case "${o_subtarget%-*}" in
|
|
legacy) qemu_exe="qemu-system-i386" ;;
|
|
generic|64) qemu_exe="qemu-system-x86_64" ;;
|
|
*)
|
|
__errmsg "target $o_target: unknown subtarget $o_subtarget"
|
|
return 1
|
|
;;
|
|
esac
|
|
|
|
[ -n "$kernel" ] && {
|
|
o_qemu_extra+=( \
|
|
"-kernel" "$kernel" \
|
|
"-append" "root=/dev/vda console=ttyS0 rootwait" \
|
|
)
|
|
}
|
|
|
|
[ -z "$o_network" ] || {
|
|
case "${o_subtarget%-*}" in
|
|
legacy)
|
|
o_qemu_extra+=(
|
|
-netdev "bridge,id=lan,br=$BR_LAN,helper=$HELPER" -device "e1000,id=devlan,netdev=lan,mac=$MAC_LAN"
|
|
-netdev "bridge,id=wan,br=$BR_WAN,helper=$HELPER" -device "e1000,id=devwan,netdev=wan,mac=$MAC_WAN"
|
|
)
|
|
;;
|
|
generic|64)
|
|
o_qemu_extra+=(
|
|
-netdev "bridge,id=lan,br=$BR_LAN,helper=$HELPER" -device "virtio-net-pci,id=devlan,netdev=lan,mac=$MAC_LAN"
|
|
-netdev "bridge,id=wan,br=$BR_WAN,helper=$HELPER" -device "virtio-net-pci,id=devwan,netdev=wan,mac=$MAC_WAN"
|
|
)
|
|
;;
|
|
esac
|
|
}
|
|
|
|
case "${o_subtarget%-*}" in
|
|
legacy)
|
|
# use IDE (PATA) disk instead of AHCI (SATA). Refer to link
|
|
# [1] for related discussions
|
|
#
|
|
# To use AHCI interface
|
|
#
|
|
# -device ich9-ahci,id=ahci \
|
|
# -device ide-drive,drive=drv0,bus=ahci.0 \
|
|
# -drive "file=$rootfs,format=raw,id=drv0,if=none" \
|
|
#
|
|
# [1] https://dev.openwrt.org/ticket/17947
|
|
"$qemu_exe" -machine "$mach" -nographic \
|
|
-device ide-drive,drive=drv0 \
|
|
-drive "file=$rootfs,format=raw,id=drv0,if=none" \
|
|
"${o_qemu_extra[@]}"
|
|
;;
|
|
generic|64)
|
|
"$qemu_exe" -machine "$mach" -nographic \
|
|
-drive "file=$rootfs,format=raw,if=virtio" \
|
|
"${o_qemu_extra[@]}"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
start_qemu() {
|
|
case "$o_target" in
|
|
armvirt) start_qemu_armvirt ;;
|
|
malta) start_qemu_malta ;;
|
|
x86) start_qemu_x86 ;;
|
|
*)
|
|
__errmsg "target $o_target is not supported yet"
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
parse_args "$@" \
|
|
&& check_setup \
|
|
&& start_qemu
|