1import logging, commands, random
2from autotest_lib.client.common_lib import error
3from autotest_lib.client.bin import utils
4from autotest_lib.client.virt import virt_utils, virt_test_utils
5
6
7def run_jumbo(test, params, env):
8    """
9    Test the RX jumbo frame function of vnics:
10
11    1) Boot the VM.
12    2) Change the MTU of guest nics and host taps depending on the NIC model.
13    3) Add the static ARP entry for guest NIC.
14    4) Wait for the MTU ok.
15    5) Verify the path MTU using ping.
16    6) Ping the guest with large frames.
17    7) Increment size ping.
18    8) Flood ping the guest with large frames.
19    9) Verify the path MTU.
20    10) Recover the MTU.
21
22    @param test: KVM test object.
23    @param params: Dictionary with the test parameters.
24    @param env: Dictionary with test environment.
25    """
26    vm = env.get_vm(params["main_vm"])
27    vm.verify_alive()
28    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))
29    mtu = params.get("mtu", "1500")
30    flood_time = params.get("flood_time", "300")
31    max_icmp_pkt_size = int(mtu) - 28
32
33    ifname = vm.get_ifname(0)
34    ip = vm.get_address(0)
35    if ip is None:
36        raise error.TestError("Could not get the IP address")
37
38    try:
39        # Environment preparation
40        ethname = virt_test_utils.get_linux_ifname(session, vm.get_mac_address(0))
41
42        logging.info("Changing the MTU of guest ...")
43        guest_mtu_cmd = "ifconfig %s mtu %s" % (ethname , mtu)
44        session.cmd(guest_mtu_cmd)
45
46        logging.info("Chaning the MTU of host tap ...")
47        host_mtu_cmd = "ifconfig %s mtu %s" % (ifname, mtu)
48        utils.run(host_mtu_cmd)
49
50        logging.info("Add a temporary static ARP entry ...")
51        arp_add_cmd = "arp -s %s %s -i %s" % (ip, vm.get_mac_address(0), ifname)
52        utils.run(arp_add_cmd)
53
54        def is_mtu_ok():
55            s, o = virt_test_utils.ping(ip, 1, interface=ifname,
56                                       packetsize=max_icmp_pkt_size,
57                                       hint="do", timeout=2)
58            return s == 0
59
60        def verify_mtu():
61            logging.info("Verify the path MTU")
62            s, o = virt_test_utils.ping(ip, 10, interface=ifname,
63                                       packetsize=max_icmp_pkt_size,
64                                       hint="do", timeout=15)
65            if s != 0 :
66                logging.error(o)
67                raise error.TestFail("Path MTU is not as expected")
68            if virt_test_utils.get_loss_ratio(o) != 0:
69                logging.error(o)
70                raise error.TestFail("Packet loss ratio during MTU "
71                                     "verification is not zero")
72
73        def flood_ping():
74            logging.info("Flood with large frames")
75            virt_test_utils.ping(ip, interface=ifname,
76                                packetsize=max_icmp_pkt_size,
77                                flood=True, timeout=float(flood_time))
78
79        def large_frame_ping(count=100):
80            logging.info("Large frame ping")
81            s, o = virt_test_utils.ping(ip, count, interface=ifname,
82                                       packetsize=max_icmp_pkt_size,
83                                       timeout=float(count) * 2)
84            ratio = virt_test_utils.get_loss_ratio(o)
85            if ratio != 0:
86                raise error.TestFail("Loss ratio of large frame ping is %s" %
87                                     ratio)
88
89        def size_increase_ping(step=random.randrange(90, 110)):
90            logging.info("Size increase ping")
91            for size in range(0, max_icmp_pkt_size + 1, step):
92                logging.info("Ping %s with size %s", ip, size)
93                s, o = virt_test_utils.ping(ip, 1, interface=ifname,
94                                           packetsize=size,
95                                           hint="do", timeout=1)
96                if s != 0:
97                    s, o = virt_test_utils.ping(ip, 10, interface=ifname,
98                                               packetsize=size,
99                                               adaptive=True, hint="do",
100                                               timeout=20)
101
102                    if virt_test_utils.get_loss_ratio(o) > int(params.get(
103                                                      "fail_ratio", 50)):
104                        raise error.TestFail("Ping loss ratio is greater "
105                                             "than 50% for size %s" % size)
106
107        logging.info("Waiting for the MTU to be OK")
108        wait_mtu_ok = 10
109        if not virt_utils.wait_for(is_mtu_ok, wait_mtu_ok, 0, 1):
110            logging.debug(commands.getoutput("ifconfig -a"))
111            raise error.TestError("MTU is not as expected even after %s "
112                                  "seconds" % wait_mtu_ok)
113
114        # Functional Test
115        verify_mtu()
116        large_frame_ping()
117        size_increase_ping()
118
119        # Stress test
120        flood_ping()
121        verify_mtu()
122
123    finally:
124        # Environment clean
125        session.close()
126        logging.info("Removing the temporary ARP entry")
127        utils.run("arp -d %s -i %s" % (ip, ifname))
128