Skip to content

Commit af5569e

Browse files
Manciukicbchalios
authored andcommitted
test(pci): make test_net_change_mac_address pass with PCI devices
This patch makes 2 changes to make the test work on PCI: - simplify logic to find device address to be generic irrespective of ACPI/no-ACPI, PCI/no-PCI - move config offset from within the C program to the python test, as it's different between MMIO (0x100) and PCI (0x4000) Signed-off-by: Riccardo Mancini <[email protected]> Signed-off-by: Babis Chalios <[email protected]>
1 parent 162f419 commit af5569e

File tree

2 files changed

+27
-99
lines changed

2 files changed

+27
-99
lines changed

tests/host_tools/change_net_config_space.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include <unistd.h>
1515

1616
int show_usage() {
17-
printf("Usage: ./change_net_config_space.bin [dev_addr_start] [mac_addr]\n");
17+
printf("Usage: ./change_net_config_space.bin [dev_addr] [mac_addr]\n");
1818
printf("Example:\n");
1919
printf("> ./change_net_config_space.bin 0xd00001000 0x060504030201\n");
2020
return 0;
@@ -25,18 +25,17 @@ int main(int argc, char *argv[]) {
2525
uint8_t *map_base;
2626
volatile uint8_t *virt_addr;
2727

28-
uint64_t mapped_size, page_size, offset_in_page, target;
28+
uint64_t mapped_size, page_size, page_addr, offset_in_page;
2929
uint64_t width = 6;
3030

31-
uint64_t config_offset = 0x100;
32-
uint64_t device_start_addr = 0x00000000;
31+
uint64_t dev_addr = 0x00000000;
3332
uint64_t mac = 0;
3433

3534
if (argc != 3) {
3635
return show_usage();
3736
}
3837

39-
device_start_addr = strtoull(argv[1], NULL, 0);
38+
dev_addr = strtoull(argv[1], NULL, 0);
4039
mac = strtoull(argv[2], NULL, 0);
4140

4241
fd = open("/dev/mem", O_RDWR | O_SYNC);
@@ -45,11 +44,11 @@ int main(int argc, char *argv[]) {
4544
return 1;
4645
}
4746

48-
target = device_start_addr + config_offset;
4947
// Get the page size.
5048
mapped_size = page_size = getpagesize();
5149
// Get the target address physical frame page offset.
52-
offset_in_page = (unsigned) target & (page_size - 1);
50+
offset_in_page = (unsigned) dev_addr & (page_size - 1);
51+
page_addr = dev_addr & ~(page_size - 1);
5352
/* If the data length goes out of the current page,
5453
* double the needed map size. */
5554
if (offset_in_page + width > page_size) {
@@ -64,7 +63,8 @@ int main(int argc, char *argv[]) {
6463
PROT_READ | PROT_WRITE,
6564
MAP_SHARED,
6665
fd,
67-
target & ~(off_t)(page_size - 1));
66+
page_addr
67+
);
6868
if (map_base == MAP_FAILED) {
6969
perror("Failed to mmap '/dev/mem'.");
7070
return 2;

tests/integration_tests/functional/test_net_config_space.py

Lines changed: 19 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
# SPDX-License-Identifier: Apache-2.0
33
"""Tests on devices config space."""
44

5-
import platform
65
import random
7-
import re
86
import string
97
import subprocess
108
from threading import Thread
@@ -15,14 +13,16 @@
1513
PAYLOAD_DATA_SIZE = 20
1614

1715

18-
def test_net_change_mac_address(uvm_plain_any, change_net_config_space_bin):
16+
def test_net_change_mac_address(
17+
uvm_plain_any, pci_enabled, change_net_config_space_bin
18+
):
1919
"""
2020
Test changing the MAC address of the network device.
2121
"""
2222

2323
test_microvm = uvm_plain_any
2424
test_microvm.help.enable_console()
25-
test_microvm.spawn()
25+
test_microvm.spawn(pci=pci_enabled)
2626
test_microvm.basic_config(boot_args="ipv6.disable=1")
2727

2828
# Data exchange interface ('eth0' in guest).
@@ -64,6 +64,8 @@ def test_net_change_mac_address(uvm_plain_any, change_net_config_space_bin):
6464

6565
net_addr_base = _get_net_mem_addr_base(ssh_conn, guest_if1_name)
6666
assert net_addr_base is not None
67+
config_offset = 0x4000 if test_microvm.pci_enabled else 0x100
68+
dev_addr = net_addr_base + config_offset
6769

6870
# Write into '/dev/mem' the same mac address, byte by byte.
6971
# This changes the MAC address physically, in the network device registers.
@@ -72,7 +74,7 @@ def test_net_change_mac_address(uvm_plain_any, change_net_config_space_bin):
7274
# `tx_spoofed_mac_count` metric shouldn't be incremented later on.
7375
rmt_path = "/tmp/change_net_config_space"
7476
test_microvm.ssh.scp_put(change_net_config_space_bin, rmt_path)
75-
cmd = f"chmod u+x {rmt_path} && {rmt_path} {net_addr_base} {mac_hex}"
77+
cmd = f"chmod u+x {rmt_path} && {rmt_path} {dev_addr} {mac_hex}"
7678

7779
# This should be executed successfully.
7880
_, stdout, _ = ssh_conn.check_output(cmd)
@@ -219,8 +221,7 @@ def _find_iomem_range(ssh_connection, dev_name):
219221
# its contents and grep for the VirtIO device name, which
220222
# with ACPI is "LNRO0005:XY".
221223
cmd = f"cat /proc/iomem | grep -m 1 {dev_name}"
222-
rc, stdout, stderr = ssh_connection.run(cmd)
223-
assert rc == 0, stderr
224+
_, stdout, _ = ssh_connection.check_output(cmd)
224225

225226
# Take range in the form 'start-end' from line. The line looks like this:
226227
# d00002000-d0002fff : LNRO0005:02
@@ -231,89 +232,16 @@ def _find_iomem_range(ssh_connection, dev_name):
231232
return (int(tokens[0], 16), int(tokens[1], 16))
232233

233234

234-
def _get_net_mem_addr_base_x86_acpi(ssh_connection, if_name):
235-
"""Check for net device memory start address via ACPI info"""
236-
# On x86 we define VirtIO devices through ACPI AML bytecode. VirtIO devices
237-
# are identified as "LNRO0005" and appear under /sys/devices/platform
238-
sys_virtio_mmio_cmdline = "/sys/devices/platform/"
239-
cmd = "ls {}"
240-
_, stdout, _ = ssh_connection.check_output(cmd.format(sys_virtio_mmio_cmdline))
241-
virtio_devs = list(filter(lambda x: "LNRO0005" in x, stdout.strip().split()))
242-
243-
# For virtio-net LNRO0005 devices, we should have a path like:
244-
# /sys/devices/platform/LNRO0005::XY/virtioXY/net which is a directory
245-
# that includes a subdirectory `ethZ` which represents the network device
246-
# that corresponds to the virtio-net device.
247-
cmd = "ls {}/{}/virtio{}/net"
248-
for idx, dev in enumerate(virtio_devs):
249-
_, guest_if_name, _ = ssh_connection.run(
250-
cmd.format(sys_virtio_mmio_cmdline, dev, idx)
251-
)
252-
if guest_if_name.strip() == if_name:
253-
return _find_iomem_range(ssh_connection, dev)[0]
254-
255-
return None
256-
257-
258-
def _get_net_mem_addr_base_x86_cmdline(ssh_connection, if_name):
259-
"""Check for net device memory start address via command line arguments"""
260-
sys_virtio_mmio_cmdline = "/sys/devices/virtio-mmio-cmdline/"
261-
cmd = "ls {} | grep virtio-mmio. | sed 's/virtio-mmio.//'"
262-
exit_code, stdout, stderr = ssh_connection.run(cmd.format(sys_virtio_mmio_cmdline))
263-
assert exit_code == 0, stderr
264-
virtio_devs_idx = stdout.strip().split()
265-
266-
cmd = "cat /proc/cmdline"
267-
_, cmd_line, _ = ssh_connection.check_output(cmd)
268-
pattern_dev = re.compile("(virtio_mmio.device=4K@0x[0-9a-f]+:[0-9]+)+")
269-
pattern_addr = re.compile("virtio_mmio.device=4K@(0x[0-9a-f]+):[0-9]+")
270-
devs_addr = []
271-
for dev in re.findall(pattern_dev, cmd_line):
272-
matched_addr = pattern_addr.search(dev)
273-
# The 1st group which matches this pattern
274-
# is the device start address. `0` group is
275-
# full match
276-
addr = matched_addr.group(1)
277-
devs_addr.append(addr)
278-
279-
cmd = "ls {}/virtio-mmio.{}/virtio{}/net"
280-
for idx in virtio_devs_idx:
281-
_, guest_if_name, _ = ssh_connection.run(
282-
cmd.format(sys_virtio_mmio_cmdline, idx, idx)
283-
)
284-
if guest_if_name.strip() == if_name:
285-
return devs_addr[int(idx)]
286-
287-
return None
288-
289-
290235
def _get_net_mem_addr_base(ssh_connection, if_name):
291236
"""Get the net device memory start address."""
292-
if platform.machine() == "x86_64":
293-
acpi_info = _get_net_mem_addr_base_x86_acpi(ssh_connection, if_name)
294-
if acpi_info is not None:
295-
return acpi_info
296-
297-
return _get_net_mem_addr_base_x86_cmdline(ssh_connection, if_name)
298-
299-
if platform.machine() == "aarch64":
300-
sys_virtio_mmio_cmdline = "/sys/devices/platform"
301-
cmd = "ls {} | grep .virtio_mmio".format(sys_virtio_mmio_cmdline)
302-
rc, stdout, _ = ssh_connection.run(cmd)
303-
assert rc == 0
304-
305-
virtio_devs = stdout.split()
306-
devs_addr = list(map(lambda dev: dev.split(".")[0], virtio_devs))
307-
308-
cmd = "ls {}/{}/virtio{}/net"
309-
# Device start addresses lack the hex prefix and are not interpreted
310-
# accordingly when parsed inside `change_config_space.c`.
311-
hex_prefix = "0x"
312-
for idx, dev in enumerate(virtio_devs):
313-
_, guest_if_name, _ = ssh_connection.run(
314-
cmd.format(sys_virtio_mmio_cmdline, dev, idx)
315-
)
316-
if guest_if_name.strip() == if_name:
317-
return hex_prefix + devs_addr[int(idx)]
318-
319-
return None
237+
_, stdout, _ = ssh_connection.check_output(f"find /sys/devices -name {if_name}")
238+
device_paths = stdout.strip().split("\n")
239+
assert (
240+
len(device_paths) == 1
241+
), f"No or multiple devices found for {if_name}:\n{stdout}"
242+
device_path = device_paths[0]
243+
parts = device_path.split("/")
244+
assert len(parts) >= 6, f"Unexpected device path: {device_path}"
245+
device = parts[-4]
246+
start_addr, _ = _find_iomem_range(ssh_connection, device)
247+
return start_addr

0 commit comments

Comments
 (0)