This patch adds the following helpers to help autotest to control the tap/bridge by itself instead of depending qemu-ifup script: - Helper to create tap and probe the vnet header. - Helper to convert the interface name to index. - Helper to add a interface to a bridge.
Signed-off-by: Jason Wang <[email protected]> --- client/tests/kvm/kvm_utils.py | 109 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 109 insertions(+), 0 deletions(-) diff --git a/client/tests/kvm/kvm_utils.py b/client/tests/kvm/kvm_utils.py index de52b65..68f27dd 100644 --- a/client/tests/kvm/kvm_utils.py +++ b/client/tests/kvm/kvm_utils.py @@ -6,6 +6,7 @@ KVM test utility functions. import time, string, random, socket, os, signal, re, logging, commands, cPickle import fcntl, shelve, ConfigParser, rss_file_transfer, threading, sys, UserDict +import struct from autotest_lib.client.bin import utils, os_dep from autotest_lib.client.common_lib import error, logging_config import kvm_subprocess @@ -15,6 +16,18 @@ try: except ImportError: KOJI_INSTALLED = False +# From include/linux/sockios.h +SIOCSIFFLAGS = 0x8914 +SIOCGIFINDEX = 0x8933 +SIOCBRADDIF = 0x89a2 +# From linux/include/linux/if_tun.h +TUNSETIFF = 0x400454ca +TUNGETIFF = 0x800454d2 +TUNGETFEATURES = 0x800454cf +IFF_UP = 0x1 +IFF_TAP = 0x0002 +IFF_NO_PI = 0x1000 +IFF_VNET_HDR = 0x4000 def _lock_file(filename): f = open(filename, "w") @@ -1726,3 +1739,99 @@ def mount(src, mount_point, type, perm="rw"): logging.error("Can't find mounted NFS share - /etc/mtab contents \n%s", file("/etc/mtab").read()) return False + + +def if_nametoindex(ifname): + """ + Map an interface name into its corresponding index. + Returns 0 on error, as 0 is not a valid index + + @param ifname: interface name + """ + index = 0 + ctrl_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0) + ifr = struct.pack("16si", ifname, 0) + r = fcntl.ioctl(ctrl_sock, SIOCGIFINDEX, ifr) + index = struct.unpack("16si", r)[1] + ctrl_sock.close() + return index + + +def vnet_hdr_probe(tapfd): + """ + Check if the IFF_VNET_HDR is support by tun. + + @param tapfd: the file descriptor of /dev/net/tun + """ + u = struct.pack("I", 0) + r = fcntl.ioctl(tapfd, TUNGETFEATURES, u) + flags = struct.unpack("I", r)[0] + if flags & IFF_VNET_HDR: + return True + else: + return False + + +def open_tap(ifname, vnet_hdr=True): + """ + Open a tap device and returns its file descriptor which is used by + fd=<fd> parameter of qemu-kvm. + + @param ifname: TAP interface name + @param vnet_hdr: Whether enable the vnet header + """ + try: + tapfd = os.open("/dev/net/tun", os.O_RDWR) + except OSError: + logging.error("Can't not open /dev/net/tun") + return -1 + flags = IFF_TAP | IFF_NO_PI + if vnet_hdr and vnet_hdr_probe(tapfd): + flags |= IFF_VNET_HDR + + ifr = struct.pack("16sh", ifname, flags) + try: + r = fcntl.ioctl(tapfd, TUNSETIFF, ifr) + except EnvironmentError: + logging.error("Could not create tap device") + return -1 + ifname = struct.unpack("16sh", r)[0].strip("\x00") + return tapfd + + +def add_to_bridge(ifname, brname): + """ + Add a TAP device to bridge + + @param ifname: Name of TAP device + @param brname: Name of the bridge + """ + ctrl_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0) + index = if_nametoindex(ifname) + if index == 0: + logging.error("Interface %s does not exist" % ifname) + return -1 + ifr = struct.pack("16si", brname, index) + try: + r = fcntl.ioctl(ctrl_sock, SIOCBRADDIF, ifr) + except EnvironmentError: + logging.error("Fail to add %s to bridge %s" % (ifname, brname)) + return -1 + ctrl_sock.close() + return 0 + +def bring_up_ifname(ifname): + """ + Bring up an interface + + @param ifname: Name of the interface + """ + ctrl_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0) + ifr = struct.pack("16si", ifname, IFF_UP) + try: + fcntl.ioctl(ctrl_sock, SIOCSIFFLAGS, ifr) + except EnvironmentError: + logging.error("Fail to bring up interface %s" % ifname) + return -1 + ctrl_sock.close() + return 0 _______________________________________________ Autotest mailing list [email protected] http://test.kernel.org/cgi-bin/mailman/listinfo/autotest
