vlan.py 8.8 KB
Newer Older
L
Lucas Meneghel Rodrigues 已提交
1 2 3
import logging
import time
import re
4
from autotest.client.shared import error
5
from virttest import utils_misc, utils_test, aexpect, utils_net
6 7


8
@error.context_aware
9
def run(test, params, env):
10
    """
11
    Test 802.1Q vlan of NIC, config it by vconfig/ip command.
12 13

    1) Create two VMs.
14 15
    2) load 8021q module in guest.
    3) Setup vlans by vconfig/ip in guest and using hard-coded ip address.
16 17 18 19 20 21 22
    4) Enable arp_ignore for all ipv4 device in guest.
    5) Repeat steps 2 - 4 in every guest.
    6) Test by ping between same and different vlans of two VMs.
    7) Test by flood ping between same vlan of two VMs.
    8) Test by TCP data transfer between same vlan of two VMs.
    9) Remove the named vlan-device.
    10) Test maximal plumb/unplumb vlans.
23

L
Lucas Meneghel Rodrigues 已提交
24 25 26
    :param test: QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env: Dictionary with test environment.
27
    """
28 29 30 31 32
    def add_vlan(session, v_id, iface="eth0", cmd_type="ip"):
        """
        Creates a vlan-device on iface by cmd that assigned by cmd_type
        now only support 'ip' and 'vconfig'
        """
33 34 35
        txt = "Create a vlan-device on interface %s with vlan id %s" % (iface,
                                                                        v_id)
        error.context(txt, logging.info)
36 37 38 39 40 41 42
        if cmd_type == "vconfig":
            cmd = "vconfig add %s %s" % (iface, v_id)
        elif cmd_type == "ip":
            v_name = "%s.%s" % (iface, v_id)
            cmd = "ip link add link %s %s type vlan id %s " % (iface,
                                                               v_name, v_id)
        else:
L
Lucas Meneghel Rodrigues 已提交
43
            err_msg = "Unexpected vlan operation command: %s" % cmd_type
44 45 46
            err_msg += "only support 'ip' and 'vconfig' now"
            raise error.TestError(err_msg)
        session.cmd(cmd)
47 48

    def set_ip_vlan(session, v_id, ip, iface="eth0"):
49 50 51
        """
        Set ip address of vlan interface
        """
52
        iface = "%s.%s" % (iface, v_id)
53 54
        txt = "Set ip to '%s' for interface '%s'" % (iface, ip)
        error.context(txt, logging.info)
55 56
        session.cmd("ifconfig %s %s" % (iface, ip))

57 58 59 60 61
    def set_arp_ignore(session):
        """
        Enable arp_ignore for all ipv4 device in guest
        """
        error.context("Enable arp_ignore for all ipv4 device in guest",
L
Lucas Meneghel Rodrigues 已提交
62
                      logging.info)
63 64 65
        ignore_cmd = "echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore"
        session.cmd(ignore_cmd)

66 67 68 69 70 71 72 73 74 75
    def rem_vlan(session, v_id, iface="eth0", cmd_type="ip"):
        """
        Removes the named vlan interface(iface+v_id)
        """
        v_iface = '%s.%s' % (iface, v_id)
        if cmd_type == "vconfig":
            rem_vlan_cmd = "vconfig rem %s" % v_iface
        elif cmd_type == "ip":
            rem_vlan_cmd = "ip link delete %s" % v_iface
        else:
L
Lucas Meneghel Rodrigues 已提交
76
            err_msg = "Unexpected vlan operation command: %s" % cmd_type
77 78 79 80 81 82
            err_msg += "only support 'ip' and 'vconfig' now"
            raise error.TestError(err_msg)

        send_cmd = "[ -e /proc/net/vlan/%s ] && %s" % (v_iface, rem_vlan_cmd)
        error.context("Remove the vlan-device '%s'." % v_iface, logging.info)
        return session.cmd_status(send_cmd)
83 84 85 86 87 88 89 90 91 92

    def nc_transfer(src, dst):
        nc_port = utils_misc.find_free_port(1025, 5334, vm_ip[dst])
        listen_cmd = params.get("listen_cmd")
        send_cmd = params.get("send_cmd")

        #listen in dst
        listen_cmd = listen_cmd % (nc_port, "receive")
        session[dst].sendline(listen_cmd)
        time.sleep(2)
L
Lucas Meneghel Rodrigues 已提交
93
        # send file from src to dst
94 95 96 97 98
        send_cmd = send_cmd % (vlan_ip[dst], str(nc_port), "file")
        session[src].cmd(send_cmd, timeout=60)
        try:
            session[dst].read_up_to_prompt(timeout=60)
        except aexpect.ExpectError:
L
Lucas Meneghel Rodrigues 已提交
99 100 101
            raise error.TestFail("Fail to receive file"
                                 " from vm%s to vm%s" % (src + 1, dst + 1))
        # check MD5 message digest of receive file in dst
102 103 104 105 106 107 108
        output = session[dst].cmd_output("md5sum receive").strip()
        digest_receive = re.findall(r'(\w+)', output)[0]
        if digest_receive == digest_origin[src]:
            logging.info("file succeed received in vm %s", vlan_ip[dst])
        else:
            logging.info("digest_origin is  %s", digest_origin[src])
            logging.info("digest_receive is %s", digest_receive)
L
Lucas Meneghel Rodrigues 已提交
109
            raise error.TestFail("File transferred differ from origin")
110
        session[dst].cmd("rm -f receive")
111

112
    def flood_ping(src, dst):
L
Lucas Meneghel Rodrigues 已提交
113
        # we must use a dedicated session because the aexpect
114 115 116 117 118 119
        # does not have the other method to interrupt the process in
        # the guest rather than close the session.
        error.context("Flood ping from %s interface %s to %s" % (vm[src].name,
                      ifname[src], vlan_ip[dst]), logging.info)
        session_flood = vm[src].wait_for_login(timeout=60)
        utils_test.ping(vlan_ip[dst], flood=True,
L
Lucas Meneghel Rodrigues 已提交
120 121
                        interface=ifname[src],
                        session=session_flood, timeout=10)
122 123 124 125 126 127 128 129 130
        session_flood.close()

    vm = []
    session = []
    ifname = []
    vm_ip = []
    digest_origin = []
    vlan_ip = ['', '']
    ip_unit = ['1', '2']
131 132
    subnet = params.get("subnet", "192.168")
    vlan_num = int(params.get("vlan_num", 5))
133
    maximal = int(params.get("maximal"))
134 135 136
    file_size = params.get("file_size", 4094)
    cmd_type = params.get("cmd_type", "ip")
    login_timeout = int(params.get("login_timeout", 360))
137 138 139 140 141 142

    vm.append(env.get_vm(params["main_vm"]))
    vm.append(env.get_vm("vm2"))
    for vm_ in vm:
        vm_.verify_alive()

143
    for i in range(2):
144
        session.append(vm[i].wait_for_login(timeout=login_timeout))
L
Lucas Meneghel Rodrigues 已提交
145
        if not session[i]:
146
            raise error.TestError("Could not log into guest %s" % vm[i].name)
L
Lucas Meneghel Rodrigues 已提交
147
        logging.info("Logged in %s successful" % vm[i].name)
148

149
        ifname.append(utils_net.get_linux_ifname(session[i],
150
                      vm[i].get_mac_address()))
L
Lucas Meneghel Rodrigues 已提交
151
        # get guest ip
152 153
        vm_ip.append(vm[i].get_address())

L
Lucas Meneghel Rodrigues 已提交
154
        # produce sized file in vm
155 156
        dd_cmd = "dd if=/dev/urandom of=file bs=1024k count=%s"
        session[i].cmd(dd_cmd % file_size)
L
Lucas Meneghel Rodrigues 已提交
157
        # record MD5 message digest of file
158 159 160
        output = session[i].cmd("md5sum file", timeout=60)
        digest_origin.append(re.findall(r'(\w+)', output)[0])

L
Lucas Meneghel Rodrigues 已提交
161
        # stop firewall in vm
162
        session[i].cmd("service iptables stop; true")
163

164 165
        error.context("load 8021q module in guest %s" % vm[i].name,
                      logging.info)
166 167 168 169
        session[i].cmd("modprobe 8021q")

    try:
        for i in range(2):
170
            logging.info("Setup vlan environment in guest %s" % vm[i].name)
L
Lucas Meneghel Rodrigues 已提交
171
            for vlan_i in range(1, vlan_num + 1):
172 173 174 175
                add_vlan(session[i], vlan_i, ifname[i], cmd_type)
                v_ip = "%s.%s.%s" % (subnet, vlan_i, ip_unit[i])
                set_ip_vlan(session[i], vlan_i, v_ip, ifname[i])
            set_arp_ignore(session[i])
176

L
Lucas Meneghel Rodrigues 已提交
177
        for vlan in range(1, vlan_num + 1):
178
            error.context("Test for vlan %s" % vlan, logging.info)
179

180
            error.context("Ping test between vlans", logging.info)
181
            interface = ifname[0] + '.' + str(vlan)
L
Lucas Meneghel Rodrigues 已提交
182
            for vlan2 in range(1, vlan_num + 1):
183 184
                for i in range(2):
                    interface = ifname[i] + '.' + str(vlan)
L
Lucas Meneghel Rodrigues 已提交
185 186
                    dest = subnet + '.' + \
                        str(vlan2) + '.' + ip_unit[(i + 1) % 2]
187
                    s, o = utils_test.ping(dest, count=2,
L
Lucas Meneghel Rodrigues 已提交
188 189
                                           interface=interface,
                                           session=session[i], timeout=30)
190
                    if ((vlan == vlan2) ^ (s == 0)):
L
Lucas Meneghel Rodrigues 已提交
191 192
                        raise error.TestFail("%s ping %s unexpected" %
                                            (interface, dest))
193 194 195 196 197 198 199

            vlan_ip[0] = subnet + '.' + str(vlan) + '.' + ip_unit[0]
            vlan_ip[1] = subnet + '.' + str(vlan) + '.' + ip_unit[1]

            flood_ping(0, 1)
            flood_ping(1, 0)

L
Lucas Meneghel Rodrigues 已提交
200
            error.context("Transferring data through nc", logging.info)
201 202 203 204
            nc_transfer(0, 1)
            nc_transfer(1, 0)

    finally:
L
Lucas Meneghel Rodrigues 已提交
205
        for vlan in range(1, vlan_num + 1):
206
            logging.info("rem vlan: %s", vlan)
207 208
            rem_vlan(session[0], vlan, ifname[0], cmd_type)
            rem_vlan(session[1], vlan, ifname[1], cmd_type)
209 210 211 212 213

    # Plumb/unplumb maximal number of vlan interfaces
    i = 1
    s = 0
    try:
214
        error.context("Testing the plumb of vlan interface", logging.info)
L
Lucas Meneghel Rodrigues 已提交
215
        for i in range(1, maximal + 1):
216
            add_vlan(session[0], i, ifname[0], cmd_type)
217
    finally:
L
Lucas Meneghel Rodrigues 已提交
218
        for j in range(1, i + 1):
219
            s = s or rem_vlan(session[0], j, ifname[0], cmd_type)
220 221 222 223 224 225 226
        if s == 0:
            logging.info("maximal interface plumb test done")
        else:
            logging.error("maximal interface plumb test failed")

    session[0].close()
    session[1].close()