diff mbox

[4/5] KVM test: setup tap fd and pass it to qemu-kvm

Message ID 1305951810-5933-5-git-send-email-lmr@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Lucas Meneghel Rodrigues May 21, 2011, 4:23 a.m. UTC
We used to use qemu-ifup to manage the tap which have several
limitations:

1) If we want to specify a bridge, we must create a customized
qemu-ifup file as the default script always match the first bridge.
2) It's hard to add support for macvtap device.

So this patch let kvm subtest control the tap creation and setup then
pass it to qemu-kvm. User could specify the bridge he want to used in
configuration file.

The original autoconfiguration was changed by private bridge setup.

Changes from v1:
* Combine the private bridge config and TAP fd in one patchset,
dropped the "auto" mode

Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Lucas Meneghel Rodrigues <lmr@redhat.com>
---
 client/tests/kvm/scripts/qemu-ifup |   11 -------
 client/virt/kvm_vm.py              |   57 +++++++++++++++++++++++------------
 2 files changed, 37 insertions(+), 31 deletions(-)
 delete mode 100755 client/tests/kvm/scripts/qemu-ifup
diff mbox

Patch

diff --git a/client/tests/kvm/scripts/qemu-ifup b/client/tests/kvm/scripts/qemu-ifup
deleted file mode 100755
index c4debf5..0000000
--- a/client/tests/kvm/scripts/qemu-ifup
+++ /dev/null
@@ -1,11 +0,0 @@ 
-#!/bin/sh
-
-# The following expression selects the first bridge listed by 'brctl show'.
-# Modify it to suit your needs.
-switch=$(/usr/sbin/brctl show | awk 'NR==2 { print $1 }')
-
-/bin/echo 1 > /proc/sys/net/ipv6/conf/${switch}/disable_ipv6
-/sbin/ifconfig $1 0.0.0.0 up
-/usr/sbin/brctl addif ${switch} $1
-/usr/sbin/brctl setfd ${switch} 0
-/usr/sbin/brctl stp ${switch} off
diff --git a/client/virt/kvm_vm.py b/client/virt/kvm_vm.py
index 57fc61b..d925fe7 100644
--- a/client/virt/kvm_vm.py
+++ b/client/virt/kvm_vm.py
@@ -7,7 +7,7 @@  Utility classes and functions to handle Virtual Machine creation using qemu.
 import time, os, logging, fcntl, re, commands, glob
 from autotest_lib.client.common_lib import error
 from autotest_lib.client.bin import utils
-import virt_utils, virt_vm, kvm_monitor, aexpect
+import virt_utils, virt_vm, virt_test_setup, kvm_monitor, aexpect
 
 
 class VM(virt_vm.BaseVM):
@@ -41,6 +41,7 @@  class VM(virt_vm.BaseVM):
             self.pci_assignable = None
             self.netdev_id = []
             self.device_id = []
+            self.tapfds = []
             self.uuid = None
 
 
@@ -231,19 +232,17 @@  class VM(virt_vm.BaseVM):
                 cmd += ",id='%s'" % device_id
             return cmd
 
-        def add_net(help, vlan, mode, ifname=None, script=None,
-                    downscript=None, tftp=None, bootfile=None, hostfwd=[],
-                    netdev_id=None, netdev_extra_params=None):
+        def add_net(help, vlan, mode, ifname=None, tftp=None, bootfile=None,
+                    hostfwd=[], netdev_id=None, netdev_extra_params=None,
+                    tapfd=None):
             if has_option(help, "netdev"):
                 cmd = " -netdev %s,id=%s" % (mode, netdev_id)
                 if netdev_extra_params:
                     cmd += ",%s" % netdev_extra_params
             else:
                 cmd = " -net %s,vlan=%d" % (mode, vlan)
-            if mode == "tap":
-                if ifname: cmd += ",ifname='%s'" % ifname
-                if script: cmd += ",script='%s'" % script
-                cmd += ",downscript='%s'" % (downscript or "no")
+            if mode == "tap" and tapfd:
+                cmd += ",fd=%d" % tapfd
             elif mode == "user":
                 if tftp and "[,tftp=" in help:
                     cmd += ",tftp='%s'" % tftp
@@ -413,20 +412,22 @@  class VM(virt_vm.BaseVM):
             qemu_cmd += add_nic(help, vlan, nic_params.get("nic_model"), mac,
                                 device_id, netdev_id, nic_params.get("nic_extra_params"))
             # Handle the '-net tap' or '-net user' or '-netdev' part
-            script = nic_params.get("nic_script")
-            downscript = nic_params.get("nic_downscript")
             tftp = nic_params.get("tftp")
-            if script:
-                script = virt_utils.get_path(root_dir, script)
-            if downscript:
-                downscript = virt_utils.get_path(root_dir, downscript)
             if tftp:
                 tftp = virt_utils.get_path(root_dir, tftp)
-            qemu_cmd += add_net(help, vlan, nic_params.get("nic_mode", "user"),
-                                vm.get_ifname(vlan),
-                                script, downscript, tftp,
+            if nic_params.get("nic_mode") == "tap":
+                try:
+                    tapfd = vm.tapfds[vlan]
+                except IndexError:
+                    tapfd = None
+            else:
+                tapfd = None
+            qemu_cmd += add_net(help, vlan,
+                                nic_params.get("nic_mode", "user"),
+                                vm.get_ifname(vlan), tftp,
                                 nic_params.get("bootp"), redirs, netdev_id,
-                                nic_params.get("netdev_extra_params"))
+                                nic_params.get("netdev_extra_params"),
+                                tapfd)
             # Proceed to next NIC
             vlan += 1
 
@@ -549,6 +550,10 @@  class VM(virt_vm.BaseVM):
         @raise VMBadPATypeError: If an unsupported PCI assignment type is
                 requested
         @raise VMPAError: If no PCI assignable devices could be assigned
+        @raise TAPCreationError: If fail to create tap fd
+        @raise BRAddIfError: If fail to add a tap to a bridge
+        @raise TAPBringUpError: If fail to bring up a tap
+        @raise PrivateBridgeError: If fail to bring the private bridge
         """
         error.context("creating '%s'" % self.name)
         self.destroy(free_mac_addresses=False)
@@ -612,12 +617,24 @@  class VM(virt_vm.BaseVM):
                 guest_port = int(redir_params.get("guest_port"))
                 self.redirs[guest_port] = host_ports[i]
 
-            # Generate netdev/device IDs for all NICs
+            # Generate netdev IDs for all NICs and create TAP fd
             self.netdev_id = []
-            self.device_id = []
+            self.tapfds = []
+            vlan = 0
             for nic in params.objects("nics"):
                 self.netdev_id.append(virt_utils.generate_random_id())
                 self.device_id.append(virt_utils.generate_random_id())
+                nic_params = params.object_params(nic)
+                if nic_params.get("nic_mode") == "tap":
+                    ifname = self.get_ifname(vlan)
+                    brname = nic_params.get("bridge")
+                    if brname == "private":
+                        brname = virt_test_setup.PrivateBridgeConfig().brname
+                    tapfd = virt_utils.open_tap("/dev/net/tun", ifname)
+                    virt_utils.add_to_bridge(ifname, brname)
+                    virt_utils.bring_up_ifname(ifname)
+                    self.tapfds.append(tapfd)
+                vlan += 1
 
             # Find available VNC port, if needed
             if params.get("display") == "vnc":