From patchwork Mon Dec 14 15:23:00 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: yogi X-Patchwork-Id: 67302 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id nBEFNH5B014850 for ; Mon, 14 Dec 2009 15:23:17 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757514AbZLNPXP (ORCPT ); Mon, 14 Dec 2009 10:23:15 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1757513AbZLNPXP (ORCPT ); Mon, 14 Dec 2009 10:23:15 -0500 Received: from e1.ny.us.ibm.com ([32.97.182.141]:50213 "EHLO e1.ny.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757506AbZLNPXN (ORCPT ); Mon, 14 Dec 2009 10:23:13 -0500 Received: from d01relay01.pok.ibm.com (d01relay01.pok.ibm.com [9.56.227.233]) by e1.ny.us.ibm.com (8.14.3/8.13.1) with ESMTP id nBEFKeEI013256 for ; Mon, 14 Dec 2009 10:20:40 -0500 Received: from d01av03.pok.ibm.com (d01av03.pok.ibm.com [9.56.224.217]) by d01relay01.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id nBEFN6hR061556 for ; Mon, 14 Dec 2009 10:23:07 -0500 Received: from d01av03.pok.ibm.com (loopback [127.0.0.1]) by d01av03.pok.ibm.com (8.14.3/8.13.1/NCO v10.0 AVout) with ESMTP id nBEFN5Sf028847 for ; Mon, 14 Dec 2009 13:23:06 -0200 Received: from [9.124.158.97] (yogi-laptop.in.ibm.com [9.124.158.97]) by d01av03.pok.ibm.com (8.14.3/8.13.1/NCO v10.0 AVin) with ESMTP id nBEFN2kV028666; Mon, 14 Dec 2009 13:23:03 -0200 Subject: [Autotest] [KVM-AUTOTEST PATCH] Add support for ipv6 address From: yogi To: autotest@test.kernel.org, kvm@vger.kernel.org, anantyog@linux.vnet.ibm.com Date: Mon, 14 Dec 2009 20:53:00 +0530 Message-Id: <1260804180.11275.63.camel@yogi-laptop> Mime-Version: 1.0 X-Mailer: Evolution 2.26.1 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org diff -aurpN autotest/client/tests/kvm/kvm_preprocessing.py autotest-new/client/tests/kvm/kvm_preprocessing.py --- autotest/client/tests/kvm/kvm_preprocessing.py 2009-12-14 09:20:56.000000000 +0000 +++ autotest-new/client/tests/kvm/kvm_preprocessing.py 2009-12-14 09:47:34.000000000 +0000 @@ -51,7 +51,8 @@ def preprocess_vm(test, params, env, nam logging.debug("VM object found in environment") else: logging.debug("VM object does not exist; creating it") - vm = kvm_vm.VM(name, params, test.bindir, env.get("address_cache")) + vm = kvm_vm.VM(name, params, test.bindir, env.get("address_cache"), + env.get("address6_cache")) kvm_utils.env_register_vm(env, name, vm) start_vm = False @@ -200,6 +201,14 @@ def preprocess(test, params, env): command=command, output_func=_update_address_cache, output_params=(env["address_cache"],)) + + env["address6_cache"] = {} + command6 = "/usr/sbin/tcpdump -npv ip6 -i any 'dst net ff02::2'" + env["tcpdump6"] = kvm_subprocess.kvm_tail( + command=command6, + output_func=_update_address6_cache, + output_params=(env["address6_cache"],)) + if kvm_utils.wait_for(lambda: not env["tcpdump"].is_alive(), 0.1, 0.1, 1.0): logging.warn("Could not start tcpdump") @@ -317,6 +326,8 @@ def postprocess(test, params, env): if not living_vms and env.has_key("tcpdump"): env["tcpdump"].close() del env["tcpdump"] + env["tcpdump6"].close() + del env["tcpdump6"] def postprocess_on_error(test, params, env): @@ -343,3 +354,17 @@ def _update_address_cache(address_cache, mac_address, address_cache.get("last_seen")) address_cache[mac_address] = address_cache.get("last_seen") del address_cache["last_seen"] + +def _update_address6_cache(address6_cache, line): + if re.search("ff02::2:", line, re.IGNORECASE): + matches = re.findall(r"(fe80.+) >", line) + if matches: + address6_cache["last_seen"] = matches[0] + if re.search("source link-address option", line, re.IGNORECASE): + matches = re.findall(r"\w*:\w*:\w*:\w*:\w*:\w*", line) + if matches and address6_cache.get("last_seen"): + mac_address = matches[0].lower() + logging.debug("(address cache) Adding cache entry: %s ---> %s", + mac_address, address6_cache.get("last_seen")) + address6_cache[mac_address] = address6_cache.get("last_seen") + del address6_cache["last_seen"] diff -aurpN autotest/client/tests/kvm/kvm_utils.py autotest-new/client/tests/kvm/kvm_utils.py --- autotest/client/tests/kvm/kvm_utils.py 2009-12-14 09:20:56.000000000 +0000 +++ autotest-new/client/tests/kvm/kvm_utils.py 2009-12-14 09:45:58.000000000 +0000 @@ -208,6 +208,34 @@ def verify_ip_address_ownership(ip, macs o = commands.getoutput("/sbin/arping -f -c 3 -I %s %s" % (dev, ip)) return bool(regex.search(o)) +def verify_ip6_address_ownership(ip, macs, timeout=10.0): + """ + Use ping6 and the ND cache to make sure a given IP address belongs to one + of the given MAC addresses. + + @param ip: An IP6 address. + @param macs: A list or tuple of MAC addresses. + @return: True iff ip is assigned to a MAC address in macs. + """ + # Compile a regex that matches the given IP6 address and any of the given + # MAC addresses + mac_regex = "|".join("(%s)" % mac for mac in macs) + regex = re.compile(r"\b%s\b.*\b(%s)\b" % (ip, mac_regex), re.IGNORECASE) + + # Get the name of the bridge device for ping6 + o = commands.getoutput("/sbin/ip route get ff02::1" ) + dev = re.findall("dev\s+\S+", o, re.IGNORECASE) + if not dev: + return False + dev = dev[0].split()[-1] + + if bool(commands.getstatusoutput("/bin/ping6 -c 11 -I %s %s"% (dev, ip)[0])): + return False + + # Check the ND cache + o = commands.getoutput("/sbin/ip -6 neigh show") + if regex.search(o): + return True # Functions for working with the environment (a dict-like object) diff -aurpN autotest/client/tests/kvm/kvm_vm.py autotest-new/client/tests/kvm/kvm_vm.py --- autotest/client/tests/kvm/kvm_vm.py 2009-12-14 09:20:56.000000000 +0000 +++ autotest-new/client/tests/kvm/kvm_vm.py 2009-12-14 09:49:45.000000000 +0000 @@ -100,7 +100,7 @@ class VM: This class handles all basic VM operations. """ - def __init__(self, name, params, root_dir, address_cache): + def __init__(self, name, params, root_dir, address_cache, address6_cache): """ Initialize the object and set a few attributes. @@ -109,6 +109,7 @@ class VM: (see method make_qemu_command for a full description) @param root_dir: Base directory for relative filenames @param address_cache: A dict that maps MAC addresses to IP addresses + @param address_cache: A dict that maps MAC addresses to IP6 addresses """ self.process = None self.redirs = {} @@ -119,6 +120,7 @@ class VM: self.params = params self.root_dir = root_dir self.address_cache = address_cache + self.address6_cache = address6_cache # Find available monitor filename while True: @@ -131,7 +133,8 @@ class VM: break - def clone(self, name=None, params=None, root_dir=None, address_cache=None): + def clone(self, name=None, params=None, root_dir=None, address_cache=None, + address6_cache=None): """ Return a clone of the VM object with optionally modified parameters. The clone is initially not alive and needs to be started using create(). @@ -142,6 +145,7 @@ class VM: @param params: Optional new VM creation parameters @param root_dir: Optional new base directory for relative filenames @param address_cache: A dict that maps MAC addresses to IP addresses + @param address_cache: A dict that maps MAC addresses to IP6 addresses """ if name is None: name = self.name @@ -151,7 +155,9 @@ class VM: root_dir = self.root_dir if address_cache is None: address_cache = self.address_cache - return VM(name, params, root_dir, address_cache) + if address6_cache is None: + address6_cache = self.address6_cache + return VM(name, params, root_dir, address_cache, address6_cache) def make_qemu_command(self, name=None, params=None, root_dir=None): @@ -658,6 +664,43 @@ class VM: logging.debug("Could not verify MAC-IP address mapping: " "%s ---> %s" % (mac, ip)) return None + return ip + else: + return "localhost" + + def get_address6(self, index=0): + """ + Return the address of a NIC of the guest, in host space. + + If port redirection is used, return 'localhost' (the NIC has no IP + address of its own). Otherwise return the NIC's IP6 address. + + @param index: Index of the NIC whose address is requested. + """ + nics = kvm_utils.get_sub_dict_names(self.params, "nics") + nic_name = nics[index] + nic_params = kvm_utils.get_sub_dict(self.params, nic_name) + if nic_params.get("nic_mode") == "tap": + mac, ip = kvm_utils.get_mac_ip_pair_from_dict(nic_params) + if not mac: + logging.debug("MAC address unavailable") + return None + if not ip or nic_params.get("always_use_tcpdump") == "yes": + # Get the IP6 address from the cache + ip = self.address6_cache.get(mac) + if not ip: + logging.debug("Could not find IP address for MAC address: " + "%s" % mac) + return None + # Make sure the IP6 address is assigned to this guest + nic_dicts = [kvm_utils.get_sub_dict(self.params, nic) + for nic in nics] + macs = [kvm_utils.get_mac_ip_pair_from_dict(dict)[0] + for dict in nic_dicts] + if not kvm_utils.verify_ip6_address_ownership(ip, macs): + logging.debug("Could not verify MAC-IP address mapping: " + "%s ---> %s" % (mac, ip)) + return None return ip else: return "localhost"