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

Reply via email to