On Mon, 2011-02-28 at 17:03 +0800, Jason Wang wrote: > 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.
I see why you've chose to not raise exceptions on the helpers themselves (historically we don't put exception raising functions on kvm_utils), but we've changed things (see the LoginError functions). So I propose the NetError exceptions to come here, and make the helpers throw the exceptions directly, so we have code slightly more concise. > Signed-off-by: Jason Wang <jasow...@redhat.com> > --- > 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 Autotest@test.kernel.org http://test.kernel.org/cgi-bin/mailman/listinfo/autotest