Skip to content

Instantly share code, notes, and snippets.

@catalsdevelop
Forked from yousong/qemustart.sh
Created December 8, 2016 14:22
Show Gist options
  • Save catalsdevelop/4b50f53b786d6c5ac2a3273f3f723455 to your computer and use it in GitHub Desktop.
Save catalsdevelop/4b50f53b786d6c5ac2a3273f3f723455 to your computer and use it in GitHub Desktop.
Run OpenWrt on QEMU virtual machines with LAN and WAN network.
#
# The following script will
# - Create Linux bridge $BR_WAN, $BR_LAN
# - Install IP addresses and basic routes
# - Enable proxy_arp on $BR_WAN
# - Enable ip_forward
# - Enable MASQUERADE on $IF_INET
# - $BR_LAN, $BR_WAN has to be allowed in ~/.usr/etc/qemu/bridge.conf
#
# Sample content:
#
# allow br-lan
# allow br-wan
#
# See qemu-bridge-helper.c of QEMU source code for details (`allow all`, `deny all`, `include xxx` can also be used).
#
# config variables
BR_WAN="br-wan"
BR_LAN="br-lan"
IF_INET="eth0"
# - qemu-bridge-help has to be root setuid program.
HELPER="$HOME/.usr/libexec/qemu-bridge-helper"
mac_rand() {
hexdump -n 3 -e '"52:54:00:" 2/1 "%02x:" 1/1 "%02x"' /dev/urandom
}
# 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 dev "$BR_LAN"
sudo ip route add 192.168.1.0/24 dev "$BR_LAN"
# setup bridge for WAN network
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 dev "$BR_WAN"
#sudo ip link set dev tap0 master "$BR_WAN"
sudo ip route add 192.168.7.0/24 dev "$BR_WAN"
# Internet access setup
sudo sysctl -w net.ipv4.ip_forward=1
sudo sysctl -w net.ipv4.conf."$BR_WAN".proxy_arp=1
sudo iptables -t nat -A POSTROUTING -o "$IF_INET" -j MASQUERADE
openwrt_wan_static() {
# Run this within OpenWrt
uci batch <<EOF
delete network.wan
set network.wan=interface
set network.wan.ifname=eth1
set network.wan.proto=static
set network.wan.ipaddr=192.168.7.2
set network.wan.netmask=255.255.255.0
set network.wan.gateway=192.168.7.1
add_list network.wan.dns=208.67.222.222
add_list network.wan.dns=208.67.220.220
commit
EOF
/etc/init.d/network reload
}
host_dnsmasq_br_wan() {
# Run this within host machine
#
#sudo apt-get install dnsmasq
#sudo vi /etc/dnsmasq.conf
#
# Minimal conf. The netmask is needed as br-wan is a bridge otherwise dnsmasq would complain "no address range available for DHCP request via br-wan"
#
# interface=br-wan
# dhcp-range=192.168.7.50,192.168.7.150,255.255.255.0,30m
}
#!/bin/sh
BR_WAN="br-wan"
BR_LAN="br-lan"
IF_INET="eth1"
# qemu-bridge-helper needs to be root setuid program.
HELPER="$HOME/.usr/libexec/qemu-bridge-helper"
SELF="$0"
usage() {
cat >&2 <<EOF
usage: $SELF <target> [<subtarget> [<extra-qemu-options>]] [--qga]
$SELF [-h|--help]
<subtarget> will default to "generic" and it must be explicitly specified if <extra-qemu-options> are to be used
Examples
$SELF x86 64
$SELF x86 64 --qga
$SELF x86 64 --qga --incoming tcp:0:4444
$SELF x86 64-glibc
$SELF malta be
$SELF malta le64
$SELF malta be-glibc
EOF
}
__errmsg() {
echo "$*" >&2
}
mac_rand() {
hexdump -n 3 -e '"52:54:00:" 2/1 "%02x:" 1/1 "%02x"' /dev/urandom
}
OPT_MEM=256
while [ "$#" -gt 0 ]; do
case "$1" in
--qga)
if [ -z "$OPT_QGA" ]; then
OPT_QGA=" -device virtio-serial"
OPT_QGA="$OPT_QGA -chardev socket,path=/tmp/qga.sock,server,nowait,id=qga0"
OPT_QGA="$OPT_QGA -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0"
shift
fi
;;
-m)
OPT_MEM="$2"
shift 2
;;
--help|\
-h)
usage
exit 0
;;
*)
if [ -z "$TARGET" ]; then
TARGET="$1"
elif [ -z "$SUBTARGET" ]; then
SUBTARGET="$1"
else
OPT_QEMU_EXTRA="$OPT_QEMU_EXTRA $1"
fi
shift
;;
esac
done
if [ -z "$TARGET" ]; then
usage
exit 1
fi
if [ -z "$SUBTARGET" ]; then
SUBTARGET="generic"
fi
OPT_QEMU_EXTRA="$OPT_QEMU_EXTRA $OPT_QGA"
MAC_LAN="$(mac_rand)"
MAC_WAN="$(mac_rand)"
case "$TARGET" in
malta)
# SUBTARGET can be le, be, le64, be64, le-glibc, le64-glibc, etc..
is64="$(echo $SUBTARGET | grep -o 64)"
if [ "$(echo "$SUBTARGET" | grep -o '^..')" = "le" ]; then
isel="el"
fi
IMG="bin/targets/$TARGET/$SUBTARGET/lede-malta-${SUBTARGET%-*}-vmlinux-initramfs.elf"
"qemu-system-mips$is64$isel" -M malta -kernel "$IMG" -m "$OPT_MEM" -nographic \
-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" \
$OPT_QEMU_EXTRA
;;
x86)
IMG="bin/targets/$TARGET/$SUBTARGET/lede-$TARGET-${SUBTARGET%-*}-combined-ext4.img"
if [ -s "$IMG.gz" ]; then
gunzip "$IMG.gz"
fi
#
# generic: 32-bit, pentium4 (CONFIG_MPENTIUM4), kvm guest, virtio
# legacy: 32-bit, i486 (CONFIG_M486)
# 64: 64-bit, kvm guest, virtio
#
case "$SUBTARGET" in
legacy)
QEMU="qemu-system-i386"
;;
generic|\
64)
QEMU="qemu-system-x86_64"
;;
*)
__errmsg "target $TARGET: subtarget $SUBTARGET: cannot decide qemu executable to use"
exit 1
;;
esac
case "$SUBTARGET" in
64|\
generic)
$QEMU -nographic -m "$OPT_MEM" \
-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" \
-drive "file=$IMG,format=raw,if=virtio" \
-device virtio-balloon-pci \
$OPT_QEMU_EXTRA
;;
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=$IMG,format=raw,id=drv0,if=none" \
#
# [1] https://dev.openwrt.org/ticket/17947
$QEMU -nographic -m "$OPT_MEM" \
-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" \
-device ide-drive,drive=drv0 \
-drive "file=$IMG,format=raw,id=drv0,if=none" \
$OPT_QEMU_EXTRA
;;
*)
__errmsg "target $TARGET: subtarget $SUBTARGET is not supported yet"
exit 1
;;
esac
;;
realview)
IMG="bin/targets/$TARGET/$SUBTARGET/lede-$TARGET-vmlinux-initramfs.elf"
qemu-system-arm -M realview-eb-mpcore -nographic -m "$OPT_MEM" \
-kernel "$IMG" \
$OPT_QEMU_EXTRA
;;
*)
__errmsg "target $TARGET is not supported yet"
exit 1
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment