Home | History | Annotate | Download | only in tests
      1 import logging, time, re
      2 from autotest_lib.client.common_lib import error
      3 from autotest_lib.client.virt import virt_utils, virt_test_utils, aexpect
      4 
      5 
      6 def run_vlan(test, params, env):
      7     """
      8     Test 802.1Q vlan of NIC, config it by vconfig command.
      9 
     10     1) Create two VMs.
     11     2) Setup guests in 10 different vlans by vconfig and using hard-coded
     12        ip address.
     13     3) Test by ping between same and different vlans of two VMs.
     14     4) Test by TCP data transfer, floop ping between same vlan of two VMs.
     15     5) Test maximal plumb/unplumb vlans.
     16     6) Recover the vlan config.
     17 
     18     @param test: KVM test object.
     19     @param params: Dictionary with the test parameters.
     20     @param env: Dictionary with test environment.
     21     """
     22     vm = []
     23     session = []
     24     ifname = []
     25     vm_ip = []
     26     digest_origin = []
     27     vlan_ip = ['', '']
     28     ip_unit = ['1', '2']
     29     subnet = params.get("subnet")
     30     vlan_num = int(params.get("vlan_num"))
     31     maximal = int(params.get("maximal"))
     32     file_size = params.get("file_size")
     33 
     34     vm.append(env.get_vm(params["main_vm"]))
     35     vm.append(env.get_vm("vm2"))
     36     for vm_ in vm:
     37         vm_.verify_alive()
     38 
     39     def add_vlan(session, v_id, iface="eth0"):
     40         session.cmd("vconfig add %s %s" % (iface, v_id))
     41 
     42     def set_ip_vlan(session, v_id, ip, iface="eth0"):
     43         iface = "%s.%s" % (iface, v_id)
     44         session.cmd("ifconfig %s %s" % (iface, ip))
     45 
     46     def set_arp_ignore(session, iface="eth0"):
     47         ignore_cmd = "echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore"
     48         session.cmd(ignore_cmd)
     49 
     50     def rem_vlan(session, v_id, iface="eth0"):
     51         rem_vlan_cmd = "if [[ -e /proc/net/vlan/%s ]];then vconfig rem %s;fi"
     52         iface = "%s.%s" % (iface, v_id)
     53         return session.cmd_status(rem_vlan_cmd % (iface, iface))
     54 
     55     def nc_transfer(src, dst):
     56         nc_port = virt_utils.find_free_port(1025, 5334, vm_ip[dst])
     57         listen_cmd = params.get("listen_cmd")
     58         send_cmd = params.get("send_cmd")
     59 
     60         #listen in dst
     61         listen_cmd = listen_cmd % (nc_port, "receive")
     62         session[dst].sendline(listen_cmd)
     63         time.sleep(2)
     64         #send file from src to dst
     65         send_cmd = send_cmd % (vlan_ip[dst], str(nc_port), "file")
     66         session[src].cmd(send_cmd, timeout=60)
     67         try:
     68             session[dst].read_up_to_prompt(timeout=60)
     69         except aexpect.ExpectError:
     70             raise error.TestFail ("Fail to receive file"
     71                                     " from vm%s to vm%s" % (src+1, dst+1))
     72         #check MD5 message digest of receive file in dst
     73         output = session[dst].cmd_output("md5sum receive").strip()
     74         digest_receive = re.findall(r'(\w+)', output)[0]
     75         if digest_receive == digest_origin[src]:
     76             logging.info("file succeed received in vm %s", vlan_ip[dst])
     77         else:
     78             logging.info("digest_origin is  %s", digest_origin[src])
     79             logging.info("digest_receive is %s", digest_receive)
     80             raise error.TestFail("File transfered differ from origin")
     81         session[dst].cmd_output("rm -f receive")
     82 
     83     for i in range(2):
     84         session.append(vm[i].wait_for_login(
     85             timeout=int(params.get("login_timeout", 360))))
     86         if not session[i] :
     87             raise error.TestError("Could not log into guest(vm%d)" % i)
     88         logging.info("Logged in")
     89 
     90         ifname.append(virt_test_utils.get_linux_ifname(session[i],
     91                       vm[i].get_mac_address()))
     92         #get guest ip
     93         vm_ip.append(vm[i].get_address())
     94 
     95         #produce sized file in vm
     96         dd_cmd = "dd if=/dev/urandom of=file bs=1024k count=%s"
     97         session[i].cmd(dd_cmd % file_size)
     98         #record MD5 message digest of file
     99         output = session[i].cmd("md5sum file", timeout=60)
    100         digest_origin.append(re.findall(r'(\w+)', output)[0])
    101 
    102         #stop firewall in vm
    103         session[i].cmd_output("/etc/init.d/iptables stop")
    104 
    105         #load 8021q module for vconfig
    106         session[i].cmd("modprobe 8021q")
    107 
    108     try:
    109         for i in range(2):
    110             for vlan_i in range(1, vlan_num+1):
    111                 add_vlan(session[i], vlan_i, ifname[i])
    112                 set_ip_vlan(session[i], vlan_i, "%s.%s.%s" %
    113                             (subnet, vlan_i, ip_unit[i]), ifname[i])
    114             set_arp_ignore(session[i], ifname[i])
    115 
    116         for vlan in range(1, vlan_num+1):
    117             logging.info("Test for vlan %s", vlan)
    118 
    119             logging.info("Ping between vlans")
    120             interface = ifname[0] + '.' + str(vlan)
    121             for vlan2 in range(1, vlan_num+1):
    122                 for i in range(2):
    123                     interface = ifname[i] + '.' + str(vlan)
    124                     dest = subnet +'.'+ str(vlan2)+ '.' + ip_unit[(i+1)%2]
    125                     s, o = virt_test_utils.ping(dest, count=2,
    126                                               interface=interface,
    127                                               session=session[i], timeout=30)
    128                     if ((vlan == vlan2) ^ (s == 0)):
    129                         raise error.TestFail ("%s ping %s unexpected" %
    130                                                     (interface, dest))
    131 
    132             vlan_ip[0] = subnet + '.' + str(vlan) + '.' + ip_unit[0]
    133             vlan_ip[1] = subnet + '.' + str(vlan) + '.' + ip_unit[1]
    134 
    135             logging.info("Flood ping")
    136             def flood_ping(src, dst):
    137                 # we must use a dedicated session becuase the aexpect
    138                 # does not have the other method to interrupt the process in
    139                 # the guest rather than close the session.
    140                 session_flood = vm[src].wait_for_login(timeout=60)
    141                 virt_test_utils.ping(vlan_ip[dst], flood=True,
    142                                    interface=ifname[src],
    143                                    session=session_flood, timeout=10)
    144                 session_flood.close()
    145 
    146             flood_ping(0, 1)
    147             flood_ping(1, 0)
    148 
    149             logging.info("Transfering data through nc")
    150             nc_transfer(0, 1)
    151             nc_transfer(1, 0)
    152 
    153     finally:
    154         for vlan in range(1, vlan_num+1):
    155             rem_vlan(session[0], vlan, ifname[0])
    156             rem_vlan(session[1], vlan, ifname[1])
    157             logging.info("rem vlan: %s", vlan)
    158 
    159     # Plumb/unplumb maximal number of vlan interfaces
    160     i = 1
    161     s = 0
    162     try:
    163         logging.info("Testing the plumb of vlan interface")
    164         for i in range (1, maximal+1):
    165             add_vlan(session[0], i, ifname[0])
    166     finally:
    167         for j in range (1, i+1):
    168             s = s or rem_vlan(session[0], j, ifname[0])
    169         if s == 0:
    170             logging.info("maximal interface plumb test done")
    171         else:
    172             logging.error("maximal interface plumb test failed")
    173 
    174     session[0].close()
    175     session[1].close()
    176