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

Reply via email to