Commit 199b2053 authored by Apollon Oikonomopoulos's avatar Apollon Oikonomopoulos Committed by Guido Trotter
Browse files

KVM: Add auxiliary functions to handle tap devices

Add two new functions, _OpenTap and _ProbeTapVnetHdr, to

_ProbeTapVnetHdr checks if the host kernel supports the virtio net header
(IFF_VNET_HDR) feature. This feature allows KVM to ask the the host kernel to
perform checksumming and segmentation offload of the data passing through a
guest's virtio NIC, using a special header[1] prepended to data sent through
the tap interface. A qemu-kvm version later than 0.12 is required for this
feature to work.

_OpenTap opens a new tap device suitable for use with qemu-kvm's "-net
tap,fd=n" option. It also enables vnet_hdr support if requested and safe to do

[1] struct virtio_net_hdr in include/linux/virtio_net.h
Signed-off-by: default avatarApollon Oikonomopoulos <>
Signed-off-by: default avatarGuido Trotter <>
Reviewed-by: default avatarGuido Trotter <>
parent dc022e01
...@@ -31,6 +31,8 @@ import tempfile ...@@ -31,6 +31,8 @@ import tempfile
import time import time
import logging import logging
import pwd import pwd
import struct
import fcntl
from cStringIO import StringIO from cStringIO import StringIO
from ganeti import utils from ganeti import utils
...@@ -46,6 +48,83 @@ from ganeti import netutils ...@@ -46,6 +48,83 @@ from ganeti import netutils
_KVM_NETWORK_SCRIPT = constants.SYSCONFDIR + "/ganeti/kvm-vif-bridge" _KVM_NETWORK_SCRIPT = constants.SYSCONFDIR + "/ganeti/kvm-vif-bridge"
# TUN/TAP driver constants, taken from <linux/if_tun.h>
# They are architecture-independent and already hardcoded in qemu-kvm source,
# so we can safely include them here.
TUNSETIFF = 0x400454ca
TUNGETIFF = 0x800454d2
IFF_TAP = 0x0002
IFF_NO_PI = 0x1000
IFF_VNET_HDR = 0x4000
def _ProbeTapVnetHdr(fd):
"""Check whether to enable the IFF_VNET_HDR flag.
To do this, _all_ of the following conditions must be met:
1. TUNGETFEATURES ioctl() *must* be implemented
2. TUNGETFEATURES ioctl() result *must* contain the IFF_VNET_HDR flag
3. TUNGETIFF ioctl() *must* be implemented; reading the kernel code in
drivers/net/tun.c there is no way to test this until after the tap device
has been created using TUNSETIFF, and there is no way to change the
IFF_VNET_HDR flag after creating the interface, catch-22! However both
TUNGETIFF and TUNGETFEATURES were introduced in kernel version 2.6.27,
thus we can expect TUNGETIFF to be present if TUNGETFEATURES is.
@type fd: int
@param fd: the file descriptor of /dev/net/tun
req = struct.pack("I", 0)
res = fcntl.ioctl(fd, TUNGETFEATURES, req)
except EnvironmentError:
logging.warning("TUNGETFEATURES ioctl() not implemented")
return False
tunflags = struct.unpack("I", res)[0]
if tunflags & IFF_VNET_HDR:
return True
logging.warning("Host does not support IFF_VNET_HDR, not enabling")
return False
def _OpenTap(vnet_hdr=True):
"""Open a new tap device and return its file descriptor.
This is intended to be used by a qemu-type hypervisor together with the -net
tap,fd=<fd> command line parameter.
@type vnet_hdr: boolean
@param vnet_hdr: Enable the VNET Header
@return: (ifname, tapfd)
@rtype: tuple
tapfd ="/dev/net/tun", os.O_RDWR)
except EnvironmentError:
raise errors.HypervisorError("Failed to open /dev/net/tun")
flags = IFF_TAP | IFF_NO_PI
if vnet_hdr and _ProbeTapVnetHdr(tapfd):
flags |= IFF_VNET_HDR
# The struct ifreq ioctl request (see netdevice(7))
ifr = struct.pack("16sh", "", flags)
res = fcntl.ioctl(tapfd, TUNSETIFF, ifr)
except EnvironmentError:
raise errors.HypervisorError("Failed to allocate a new TAP device")
# Get the interface name from the ioctl
ifname = struct.unpack("16sh", res)[0].strip("\x00")
return (ifname, tapfd)
def _WriteNetScript(instance, nic, index): def _WriteNetScript(instance, nic, index):
"""Write a script to connect a net interface to the proper bridge. """Write a script to connect a net interface to the proper bridge.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment