Skip to content

Commit 3a59ffd

Browse files
committed
Add case to support jumbo frame test
Automate VIRT-95907 Jumbo Frame Signed-off-by: Lei Yang <leiyang@redhat.com>
1 parent 875c970 commit 3a59ffd

File tree

2 files changed

+234
-0
lines changed

2 files changed

+234
-0
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
- virtual_network.qemu_test.jumbo: image_copy
2+
requires_root = yes
3+
create_vm_libvirt = yes
4+
master_images_clone = img1
5+
kill_vm_libvirt = yes
6+
type = jumbo
7+
start_vm = no
8+
mtu = 9000
9+
e1000e:
10+
only Linux
11+
virtio_net:
12+
Windows:
13+
mtu_key = MTU
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
import random
2+
import re
3+
4+
from avocado.utils import process
5+
from virttest import (
6+
env_process,
7+
error_context,
8+
utils_misc,
9+
utils_net,
10+
utils_test,
11+
)
12+
from virttest.utils_test import libvirt
13+
14+
15+
@error_context.context_aware
16+
def run(test, params, env):
17+
"""
18+
Test the RX jumbo frame function of vnics:
19+
20+
1) Boot the VM.
21+
2) Change the MTU of guest nics and host taps depending on the NIC model.
22+
3) Add the static ARP entry for guest NIC.
23+
4) Wait for the MTU ok.
24+
5) Verify the path MTU using ping.
25+
6) Ping the guest with large frames.
26+
7) Increment size ping.
27+
8) Flood ping the guest with large frames.
28+
9) Verify the path MTU.
29+
10) Recover the MTU.
30+
31+
:param test: LIBVIRT test object.
32+
:param params: Dictionary with the test parameters.
33+
:param env: Dictionary with test environment.
34+
"""
35+
36+
def get_ovs_ports(ovs):
37+
"""
38+
get the ovs bridge all Interface list.
39+
40+
:param ovs: Ovs bridge name
41+
"""
42+
cmd = "ovs-vsctl list-ports %s" % ovs
43+
return process.getoutput(cmd, shell=True)
44+
45+
netdst = params.get("netdst", "switch")
46+
host_bridges = utils_net.find_bridge_manager(netdst)
47+
if not isinstance(host_bridges, utils_net.Bridge):
48+
host_hw_interface = get_ovs_ports(netdst)
49+
tmp_ports = re.findall(r"t[0-9]{1,}-[a-zA-Z0-9]{6}", host_hw_interface)
50+
if tmp_ports:
51+
for p in tmp_ports:
52+
process.system_output("ovs-vsctl del-port %s %s" % (netdst, p))
53+
54+
params["start_vm"] = "yes"
55+
env_process.preprocess_vm(test, params, env, params["main_vm"])
56+
57+
timeout = params.get_numeric("login_timeout", 360)
58+
mtu_default = 1500
59+
mtu = params.get_numeric("mtu", "1500")
60+
def_max_icmp_size = int(mtu) - 28
61+
max_icmp_pkt_size = params.get_numeric("max_icmp_pkt_size", def_max_icmp_size)
62+
flood_time = params.get_numeric("flood_time", "300")
63+
os_type = params.get("os_type")
64+
hint = params.get("hint", "do")
65+
66+
vm = env.get_vm(params["main_vm"])
67+
vm.verify_alive()
68+
session = vm.wait_for_login(timeout=timeout)
69+
session_serial = vm.wait_for_serial_login(timeout=timeout)
70+
71+
iface_mac = vm.get_mac_address(0)
72+
vm_name = params.get("main_vm")
73+
ifname = libvirt.get_ifname_host(vm_name, iface_mac)
74+
guest_ip = vm.get_address(0)
75+
if guest_ip is None:
76+
test.error("Could not get the guest ip address")
77+
78+
host_mtu_cmd = "ip link set dev %s mtu %s"
79+
if not isinstance(host_bridges, utils_net.Bridge):
80+
target_ifaces = set(get_ovs_ports(netdst).splitlines())
81+
else:
82+
br_in_use = host_bridges.list_br()
83+
ifaces_in_use = host_bridges.list_iface()
84+
target_ifaces = set(ifaces_in_use) - set(br_in_use)
85+
86+
error_context.context("Change all Bridge NICs MTU to %s" % mtu, test.log.info)
87+
for iface in target_ifaces:
88+
process.run(host_mtu_cmd % (iface, mtu), shell=True)
89+
90+
try:
91+
error_context.context("Changing the MTU of guest", test.log.info)
92+
# Environment preparation
93+
if os_type == "linux":
94+
ethname = utils_net.get_linux_ifname(session, iface_mac)
95+
guest_mtu_cmd = "ip link set dev %s mtu %s" % (ethname, mtu)
96+
else:
97+
connection_id = utils_net.get_windows_nic_attribute(
98+
session, "macaddress", iface_mac, "netconnectionid"
99+
)
100+
101+
index = utils_net.get_windows_nic_attribute(
102+
session, "netconnectionid", connection_id, "index"
103+
)
104+
105+
reg_set_mtu_pattern = params.get("reg_mtu_cmd")
106+
mtu_key_word = params.get("mtu_key", "MTU")
107+
reg_set_mtu = reg_set_mtu_pattern % (int(index), mtu_key_word, int(mtu))
108+
guest_mtu_cmd = "%s " % reg_set_mtu
109+
110+
session.cmd(guest_mtu_cmd)
111+
if os_type == "windows":
112+
mode = "netsh"
113+
utils_net.restart_windows_guest_network(
114+
session_serial, connection_id, mode=mode
115+
)
116+
117+
error_context.context("Chaning the MTU of host tap ...", test.log.info)
118+
process.run(host_mtu_cmd % (ifname, mtu), shell=True)
119+
120+
error_context.context("Add a temporary static ARP entry ...", test.log.info)
121+
arp_add_cmd = "arp -s %s %s -i %s" % (guest_ip, iface_mac, ifname)
122+
process.run(arp_add_cmd, shell=True)
123+
124+
def is_mtu_ok():
125+
status, _ = utils_test.ping(
126+
guest_ip, 1, packetsize=max_icmp_pkt_size, hint="do", timeout=2
127+
)
128+
return status == 0
129+
130+
def verify_mtu():
131+
test.log.info("Verify the path MTU")
132+
status, output = utils_test.ping(
133+
guest_ip, 10, packetsize=max_icmp_pkt_size, hint="do", timeout=15
134+
)
135+
if status != 0:
136+
test.log.error(output)
137+
test.fail("Path MTU is not as expected")
138+
if utils_test.get_loss_ratio(output) != 0:
139+
test.log.error(output)
140+
test.fail("Packet loss ratio during MTU verification is not zero")
141+
142+
def flood_ping():
143+
test.log.info("Flood with large frames")
144+
utils_test.ping(
145+
guest_ip,
146+
packetsize=max_icmp_pkt_size,
147+
flood=True,
148+
timeout=float(flood_time),
149+
)
150+
151+
def large_frame_ping(count=100):
152+
test.log.info("Large frame ping")
153+
_, output = utils_test.ping(
154+
guest_ip, count, packetsize=max_icmp_pkt_size, timeout=float(count) * 2
155+
)
156+
ratio = utils_test.get_loss_ratio(output)
157+
if ratio != 0:
158+
test.fail("Loss ratio of large frame ping is %s" % ratio)
159+
160+
def size_increase_ping(step=None):
161+
test.log.info("Size increase ping")
162+
if step is None:
163+
step = random.randrange(90, 110)
164+
for size in range(0, max_icmp_pkt_size + 1, step):
165+
test.log.info("Ping %s with size %s", guest_ip, size)
166+
status, output = utils_test.ping(
167+
guest_ip, 1, packetsize=size, hint=hint, timeout=1
168+
)
169+
if status != 0:
170+
status, output = utils_test.ping(
171+
guest_ip,
172+
10,
173+
packetsize=size,
174+
adaptive=True,
175+
hint=hint,
176+
timeout=20,
177+
)
178+
179+
fail_ratio = params.get_numeric("fail_ratio", 50)
180+
loss = utils_test.get_loss_ratio(output)
181+
if loss > fail_ratio:
182+
test.fail(
183+
"Ping loss ratio %s is greater than %s%% for size %s"
184+
% (loss, fail_ratio, size)
185+
)
186+
187+
test.log.info("Waiting for the MTU to be OK")
188+
wait_mtu_ok = 20
189+
if not utils_misc.wait_for(is_mtu_ok, wait_mtu_ok, 0, 1):
190+
test.log.debug(
191+
process.getoutput(
192+
"ifconfig -a", verbose=False, ignore_status=True, shell=True
193+
)
194+
)
195+
test.error("MTU is not as expected even after %s seconds" % wait_mtu_ok)
196+
197+
# Functional Test
198+
error_context.context("Checking whether MTU change is ok", test.log.info)
199+
200+
verify_mtu()
201+
large_frame_ping()
202+
size_increase_ping()
203+
204+
# Stress test
205+
flood_ping()
206+
verify_mtu()
207+
208+
finally:
209+
# Environment clean
210+
if session:
211+
session.close()
212+
if 'session_serial' in locals() and session_serial:
213+
session_serial.close()
214+
grep_cmd = "grep '%s.*%s' /proc/net/arp" % (guest_ip, ifname)
215+
if process.system(grep_cmd, shell=True) == 0:
216+
process.run("arp -d %s -i %s" % (guest_ip, ifname), shell=True)
217+
test.log.info("Removing the temporary ARP entry successfully")
218+
219+
test.log.info("Change back Bridge NICs MTU to %s", mtu_default)
220+
for iface in target_ifaces:
221+
process.run(host_mtu_cmd % (iface, mtu_default), shell=True)

0 commit comments

Comments
 (0)