On Sat, May 21, 2011 at 01:23:27AM -0300, Lucas Meneghel Rodrigues wrote: > This patch adds some helpers to assist virt test to setup the bridge or > macvtap based guest networking. > > Changes from v1: > * Fixed undefined variable errors on the exception class definitions > > Signed-off-by: Jason Wang <jasowang@xxxxxxxxxx> > Signed-off-by: Lucas Meneghel Rodrigues <lmr@xxxxxxxxxx> > --- > client/virt/virt_utils.py | 218 +++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 218 insertions(+), 0 deletions(-) > > diff --git a/client/virt/virt_utils.py b/client/virt/virt_utils.py > index 5510c89..96b9c84 100644 > --- a/client/virt/virt_utils.py > +++ b/client/virt/virt_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, threading, sys, UserDict, inspect > +import struct > from autotest_lib.client.bin import utils, os_dep > from autotest_lib.client.common_lib import error, logging_config > import rss_client, aexpect > @@ -15,6 +16,20 @@ try: > except ImportError: > KOJI_INSTALLED = False > > +# From include/linux/sockios.h > +SIOCSIFHWADDR = 0x8924 > +SIOCGIFHWADDR = 0x8927 > +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") > @@ -36,6 +51,76 @@ def is_vm(obj): > return obj.__class__.__name__ == "VM" > > > +class NetError(Exception): > + pass > + > + > +class TAPModuleError(NetError): > + def __init__(self, devname): > + NetError.__init__(self, devname) > + self.devname = devname > + > + def __str__(self): > + return "Can't open %s" % self.devname > + > +class TAPNotExistError(NetError): > + def __init__(self, ifname): > + NetError.__init__(self, ifname) > + self.ifname = ifname > + > + def __str__(self): > + return "Interface %s does not exist" % self.ifname > + > + > +class TAPCreationError(NetError): > + def __init__(self, ifname): > + NetError.__init__(self, ifname) > + self.ifname = ifname > + > + def __str__(self): > + return "Cannot create TAP device %s" % self.ifname > + > + > +class TAPBringUpError(NetError): > + def __init__(self, ifname): > + NetError.__init__(self, ifname) > + self.ifname = ifname > + > + def __str__(self): > + return "Cannot bring up TAP %s" % self.ifname > + > + > +class BRAddIfError(NetError): > + def __init__(self, ifname, brname, details): > + NetError.__init__(self, ifname, brname, details) > + self.ifname = ifname > + self.brname = brname > + self.details = details > + > + def __str__(self): > + return ("Can not add if %s to bridge %s: %s" % > + (self.ifname, self.brname, self.details)) > + > + > +class HwAddrSetError(NetError): > + def __init__(self, ifname, mac): > + NetError.__init__(self, ifname, mac) > + self.ifname = ifname > + self.mac = mac > + > + def __str__(self): > + return "Can not set mac %s to interface %s" % (self.mac, self.ifname) > + > + > +class HwAddrGetError(NetError): > + def __init__(self, ifname): > + NetError.__init__(self, ifname) > + self.ifname = ifname > + > + def __str__(self): > + return "Can not get mac of interface %s" % self.ifname > + > + > class Env(UserDict.IterableUserDict): > """ > A dict-like object containing global objects used by tests. > @@ -2307,3 +2392,136 @@ def install_host_kernel(job, params): > else: > logging.info('Chose %s, using the current kernel for the host', > install_type) > + > + > +def bridge_auto_detect(): > + """ > + Automatically detect a bridge for tap through brctl. > + """ > + try: > + brctl_output = utils.system_output("ip route list", > + retain_output=True) > + brname = re.findall("default.*dev (.*) ", brctl_output)[0] > + except: > + raise BRAutoDetectError > + return brname > + > + > +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 # ../../bin/autotest control --verbose --args="kill_vm=yes only=boot iterations=2" 05/23 13:24:41 INFO | test:0286| Test started. Number of iterations: 2 05/23 13:24:41 INFO | test:0289| Executing iteration 1 of 2 _PASS_ 05/23 13:25:36 INFO | test:0289| Executing iteration 2 of 2 ... File "/project/rh/autotest-upstream/client/virt/virt_env_process.py", line 185, in process vm_func(test, vm_params, env, vm_name) File "/project/rh/autotest-upstream/client/virt/virt_env_process.py", line 82, in preprocess_vm migration_mode=params.get("migration_mode")) File "/project/rh/autotest-upstream/client/common_lib/error.py", line 138, in new_fn return fn(*args, **kwargs) File "/project/rh/autotest-upstream/client/virt/kvm_vm.py", line 643, in create tapfd = virt_utils.open_tap("/dev/net/tun", ifname) File "/project/rh/autotest-upstream/client/virt/virt_utils.py", line 2461, in open_tap raise TAPCreationError(ifname) TAPCreationError: Cannot create TAP device t0-081158-LeCM Tap device is not closed after iteration.1, iteration.2 fails of creating an existed tap device. So we need a 'close_tap()' function, and call it in vm.destroy() > +def open_tap(devname, 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(devname, os.O_RDWR) > + except OSError: > + raise TAPModuleError(devname) > + 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 IOError: > + raise TAPCreationError(ifname) > + 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: > + raise TAPNotExistError(ifname) > + ifr = struct.pack("16si", brname, index) > + try: > + r = fcntl.ioctl(ctrl_sock, SIOCBRADDIF, ifr) > + except IOError, details: > + raise BRAddIfError(ifname, brname, details) > + ctrl_sock.close() > + > + > +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 IOError: > + raise TAPBringUpError(ifname) > + ctrl_sock.close() > + > + > +def if_set_macaddress(ifname, mac): > + """ > + Set the mac address for an interface > + > + @param ifname: Name of the interface > + @mac: Mac address > + """ > + ctrl_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0) > + > + ifr = struct.pack("256s", ifname) > + try: > + mac_dev = fcntl.ioctl(ctrl_sock, SIOCGIFHWADDR, ifr)[18:24] > + mac_dev = ":".join(["%02x" % ord(m) for m in mac_dev]) > + except IOError, e: > + raise HwAddrGetError(ifname) > + > + if mac_dev.lower() == mac.lower(): > + return > + > + ifr = struct.pack("16sH14s", ifname, 1, > + "".join([chr(int(m, 16)) for m in mac.split(":")])) > + try: > + fcntl.ioctl(ctrl_sock, SIOCSIFHWADDR, ifr) > + except IOError, e: > + logging.info(e) > + raise HwAddrSetError(ifname, mac) > + ctrl_sock.close() > + > -- > 1.7.5.1 > > -- > To unsubscribe from this list: send the line "unsubscribe kvm" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html