On Mon, 2011-05-23 at 14:16 +0800, Amos Kong wrote: > 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() Oh, OK, let's do this. Thanks for having noticed that, Amos! > > +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 -- 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