Add vhost support in NAT mode

Add vhost support in NAT mode
This commit is contained in:
Kroese 2023-05-06 16:39:27 +02:00 committed by GitHub
commit 72651f0265
6 changed files with 38 additions and 32 deletions

View file

@ -10,6 +10,7 @@ services:
BOOT: "http://www.example.com/image.iso" BOOT: "http://www.example.com/image.iso"
devices: devices:
- /dev/kvm - /dev/kvm
- /dev/vhost-net
cap_add: cap_add:
- NET_ADMIN - NET_ADMIN
ports: ports:

View file

@ -5,7 +5,7 @@
<div align="center"> <div align="center">
[![Build]][build_url] [![Build]][build_url]
[![Version]][build_url] [![Version]][ghcr_url]
[![Size]][ghcr_url] [![Size]][ghcr_url]
[build_url]: https://github.com/qemu-tools/qemu-docker/ [build_url]: https://github.com/qemu-tools/qemu-docker/
@ -38,6 +38,7 @@ services:
BOOT: "http://www.example.com/image.iso" BOOT: "http://www.example.com/image.iso"
devices: devices:
- /dev/kvm - /dev/kvm
- /dev/vhost-net
cap_add: cap_add:
- NET_ADMIN - NET_ADMIN
ports: ports:

View file

@ -23,7 +23,7 @@ if [ -f "${DATA}" ]; then
echo "INFO: Resizing data disk from $OLD_SIZE to $DATA_SIZE bytes.." echo "INFO: Resizing data disk from $OLD_SIZE to $DATA_SIZE bytes.."
if [ "$ALLOCATE" = "N" ]; then if [[ "${ALLOCATE}" == [Nn]* ]]; then
# Resize file by changing its length # Resize file by changing its length
truncate -s "${DATA_SIZE}" "${DATA}"; truncate -s "${DATA_SIZE}" "${DATA}";
@ -45,7 +45,7 @@ if [ -f "${DATA}" ]; then
echo "ERROR: Could not allocate a file for the data disk." && exit 85 echo "ERROR: Could not allocate a file for the data disk." && exit 85
fi fi
if [ "$ALLOCATE" = "Z" ]; then if [[ "${ALLOCATE}" == [Zz]* ]]; then
GB=$(( (REQ + 1073741823)/1073741824 )) GB=$(( (REQ + 1073741823)/1073741824 ))
@ -68,7 +68,7 @@ fi
if [ ! -f "${DATA}" ]; then if [ ! -f "${DATA}" ]; then
if [ "$ALLOCATE" = "N" ]; then if [[ "${ALLOCATE}" == [Nn]* ]]; then
# Create an empty file # Create an empty file
truncate -s "${DATA_SIZE}" "${DATA}" truncate -s "${DATA_SIZE}" "${DATA}"
@ -89,7 +89,7 @@ if [ ! -f "${DATA}" ]; then
echo "ERROR: Could not allocate a file for the data disk." && exit 87 echo "ERROR: Could not allocate a file for the data disk." && exit 87
fi fi
if [ "$ALLOCATE" = "Z" ]; then if [[ "${ALLOCATE}" == [Zz]* ]]; then
echo "INFO: Preallocating ${DISK_SIZE} of diskspace, please wait..." echo "INFO: Preallocating ${DISK_SIZE} of diskspace, please wait..."
dd if=/dev/urandom of="${DATA}" count="${DATA_SIZE}" bs=1M iflag=count_bytes status=none dd if=/dev/urandom of="${DATA}" count="${DATA_SIZE}" bs=1M iflag=count_bytes status=none

View file

@ -13,7 +13,7 @@ else
PROGRESS="--progress=dot:giga" PROGRESS="--progress=dot:giga"
fi fi
[ "$DEBUG" = "Y" ] && set -x [[ "${DEBUG}" == [Yy1]* ]] && set -x
{ wget "$BOOT" -O "$TMP" -q --no-check-certificate --show-progress "$PROGRESS"; rc=$?; } || : { wget "$BOOT" -O "$TMP" -q --no-check-certificate --show-progress "$PROGRESS"; rc=$?; } || :
(( rc != 0 )) && echo "ERROR: Failed to download ${BOOT}, reason: $rc" && exit 60 (( rc != 0 )) && echo "ERROR: Failed to download ${BOOT}, reason: $rc" && exit 60
@ -31,6 +31,6 @@ FILE="$STORAGE/boot.img"
mv -f "$TMP" "$FILE" mv -f "$TMP" "$FILE"
{ set +x; } 2>/dev/null { set +x; } 2>/dev/null
[ "$DEBUG" = "Y" ] && echo [[ "${DEBUG}" == [Yy1]* ]] && echo
return 0 return 0

View file

@ -25,7 +25,7 @@ configureDHCP() {
NETWORK=$(ip -o route | grep "${VM_NET_DEV}" | grep -v default | awk '{print $1}') NETWORK=$(ip -o route | grep "${VM_NET_DEV}" | grep -v default | awk '{print $1}')
IP=$(ip address show dev "${VM_NET_DEV}" | grep inet | awk '/inet / { print $2 }' | cut -f1 -d/) IP=$(ip address show dev "${VM_NET_DEV}" | grep inet | awk '/inet / { print $2 }' | cut -f1 -d/)
[ "$DEBUG" = "Y" ] && set -x [[ "${DEBUG}" == [Yy1]* ]] && set -x
{ ip link add link "${VM_NET_DEV}" "${VM_NET_VLAN}" type macvlan mode bridge 2> /dev/null ; rc=$?; } || : { ip link add link "${VM_NET_DEV}" "${VM_NET_VLAN}" type macvlan mode bridge 2> /dev/null ; rc=$?; } || :
if (( rc != 0 )); then if (( rc != 0 )); then
@ -80,12 +80,6 @@ configureDHCP() {
echo "container: --device-cgroup-rule='c ${MAJOR}:* rwm' --device=/dev/vhost-net" && exit 21 echo "container: --device-cgroup-rule='c ${MAJOR}:* rwm' --device=/dev/vhost-net" && exit 21
fi fi
# Create /dev/vhost-net
if [ ! -c /dev/vhost-net ]; then
mknod /dev/vhost-net c 10 238
chmod 660 /dev/vhost-net
fi
{ exec 40>>/dev/vhost-net; rc=$?; } || : { exec 40>>/dev/vhost-net; rc=$?; } || :
if (( rc != 0 )); then if (( rc != 0 )); then
@ -99,7 +93,7 @@ configureDHCP() {
configureNAT () { configureNAT () {
VM_NET_IP='20.20.20.21' VM_NET_IP='20.20.20.21'
[ "$DEBUG" = "Y" ] && set -x [[ "${DEBUG}" == [Yy1]* ]] && set -x
#Create bridge with static IP for the VM guest #Create bridge with static IP for the VM guest
@ -129,7 +123,7 @@ configureNAT () {
fi fi
{ set +x; } 2>/dev/null { set +x; } 2>/dev/null
[ "$DEBUG" = "Y" ] && echo [[ "${DEBUG}" == [Yy1]* ]] && echo
#Check port forwarding flag #Check port forwarding flag
if [[ $(< /proc/sys/net/ipv4/ip_forward) -eq 0 ]]; then if [[ $(< /proc/sys/net/ipv4/ip_forward) -eq 0 ]]; then
@ -149,9 +143,12 @@ configureNAT () {
NET_OPTS="-netdev tap,ifname=${VM_NET_TAP},script=no,downscript=no,id=hostnet0" NET_OPTS="-netdev tap,ifname=${VM_NET_TAP},script=no,downscript=no,id=hostnet0"
{ exec 40>>/dev/vhost-net; rc=$?; } || :
(( rc == 0 )) && NET_OPTS="$NET_OPTS,vhost=on,vhostfd=40"
# Build DNS options from container /etc/resolv.conf # Build DNS options from container /etc/resolv.conf
if [ "$DEBUG" = "Y" ]; then if [[ "${DEBUG}" == [Yy1]* ]]; then
echo "/etc/resolv.conf:" && echo && cat /etc/resolv.conf && echo echo "/etc/resolv.conf:" && echo && cat /etc/resolv.conf && echo
fi fi
@ -178,7 +175,7 @@ configureNAT () {
DNSMASQ_OPTS=$(echo "$DNSMASQ_OPTS" | sed 's/\t/ /g' | tr -s ' ' | sed 's/^ *//') DNSMASQ_OPTS=$(echo "$DNSMASQ_OPTS" | sed 's/\t/ /g' | tr -s ' ' | sed 's/^ *//')
[ "$DEBUG" = "Y" ] && set -x [[ "${DEBUG}" == [Yy1]* ]] && set -x
$DNSMASQ ${DNSMASQ_OPTS:+ $DNSMASQ_OPTS} $DNSMASQ ${DNSMASQ_OPTS:+ $DNSMASQ_OPTS}
@ -198,13 +195,19 @@ fi
[ ! -c /dev/net/tun ] && echo "ERROR: TUN network interface not available..." && exit 85 [ ! -c /dev/net/tun ] && echo "ERROR: TUN network interface not available..." && exit 85
# Create the necessary file structure for /dev/vhost-net
if [ ! -c /dev/vhost-net ]; then
mknod /dev/vhost-net c 10 238
chmod 660 /dev/vhost-net
fi
update-alternatives --set iptables /usr/sbin/iptables-legacy > /dev/null update-alternatives --set iptables /usr/sbin/iptables-legacy > /dev/null
update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy > /dev/null update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy > /dev/null
VM_NET_MAC="${VM_NET_MAC//-/:}" VM_NET_MAC="${VM_NET_MAC//-/:}"
GATEWAY=$(ip r | grep default | awk '{print $3}') GATEWAY=$(ip r | grep default | awk '{print $3}')
if [ "$DEBUG" = "Y" ]; then if [[ "${DEBUG}" == [Yy1]* ]]; then
IP=$(ip address show dev "${VM_NET_DEV}" | grep inet | awk '/inet / { print $2 }' | cut -f1 -d/) IP=$(ip address show dev "${VM_NET_DEV}" | grep inet | awk '/inet / { print $2 }' | cut -f1 -d/)
echo "INFO: Container IP is ${IP} with gateway ${GATEWAY}" && echo echo "INFO: Container IP is ${IP} with gateway ${GATEWAY}" && echo
@ -213,12 +216,7 @@ if [ "$DEBUG" = "Y" ]; then
fi fi
if [ "$DHCP" != "Y" ]; then if [[ "${DHCP}" == [Yy1]* ]]; then
# Configuration for static IP
configureNAT
else
if [[ "$GATEWAY" == "172."* ]]; then if [[ "$GATEWAY" == "172."* ]]; then
echo -n "ERROR: You cannot enable DHCP while the container is " echo -n "ERROR: You cannot enable DHCP while the container is "
@ -228,10 +226,15 @@ else
# Configuration for DHCP IP # Configuration for DHCP IP
configureDHCP configureDHCP
else
# Configuration for static IP
configureNAT
fi fi
NET_OPTS="${NET_OPTS} -device virtio-net-pci,romfile=,netdev=hostnet0,mac=${VM_NET_MAC},id=net0" NET_OPTS="${NET_OPTS} -device virtio-net-pci,romfile=,netdev=hostnet0,mac=${VM_NET_MAC},id=net0"
[ "$DEBUG" = "Y" ] && echo && echo "Finished network setup.." && echo [[ "${DEBUG}" == [Yy1]* ]] && echo && echo "Finished network setup.." && echo
return 0 return 0

View file

@ -11,14 +11,15 @@ set -Eeuo pipefail
: ${RAM_SIZE:='512M'} # Maximum RAM amount : ${RAM_SIZE:='512M'} # Maximum RAM amount
echo "Starting QEMU for Docker v${VERSION}..." echo "Starting QEMU for Docker v${VERSION}..."
trap 'echo >&2 "Error status $? for: ${BASH_COMMAND} (line $LINENO/$BASH_LINENO)"' ERR
[ ! -f "/run/run.sh" ] && echo "ERROR: Script must run inside Docker container!" && exit 11
[ "$(id -u)" -ne "0" ] && echo "ERROR: Script must be executed with root privileges." && exit 12
STORAGE="/storage" STORAGE="/storage"
KERNEL=$(uname -r | cut -b 1) KERNEL=$(uname -r | cut -b 1)
trap 'echo >&2 "Error status $? for: ${BASH_COMMAND} (line $LINENO/$BASH_LINENO)"' ERR [ ! -d "$STORAGE" ] && echo "ERROR: Storage folder (${STORAGE}) not found!" && exit 13
[ ! -d "$STORAGE" ] && echo "Storage folder (${STORAGE}) not found!" && exit 69
[ ! -f "/run/run.sh" ] && echo "Script must run inside Docker container!" && exit 60
if [ ! -f "$STORAGE/boot.img" ]; then if [ ! -f "$STORAGE/boot.img" ]; then
. /run/install.sh . /run/install.sh
@ -46,7 +47,7 @@ fi
if [ -n "${KVM_ERR}" ]; then if [ -n "${KVM_ERR}" ]; then
echo "ERROR: KVM acceleration not detected ${KVM_ERR}, please enable it." echo "ERROR: KVM acceleration not detected ${KVM_ERR}, please enable it."
[ "$DEBUG" != "Y" ] && exit 88 [[ "${DEBUG}" == [Yy1]* ]] && exit 88
else else
KVM_OPTS=",accel=kvm -enable-kvm -cpu host" KVM_OPTS=",accel=kvm -enable-kvm -cpu host"
fi fi
@ -65,7 +66,7 @@ trap - ERR
set -m set -m
( (
[ "$DEBUG" = "Y" ] && set -x [[ "${DEBUG}" == [Yy1]* ]] && set -x
qemu-system-x86_64 ${ARGS:+ $ARGS} & echo $! > "${_QEMU_PID}" qemu-system-x86_64 ${ARGS:+ $ARGS} & echo $! > "${_QEMU_PID}"
{ set +x; } 2>/dev/null { set +x; } 2>/dev/null
) )