2 * QTest testcase for igb NIC
4 * Copyright (c) 2022-2023 Red Hat, Inc.
5 * Copyright (c) 2015 Ravello Systems LTD (http://ravellosystems.com)
6 * Developed by Daynix Computing LTD (http://www.daynix.com)
9 * Akihiko Odaki <akihiko.odaki@daynix.com>
10 * Dmitry Fleytman <dmitry@daynix.com>
11 * Leonid Bloch <leonid@daynix.com>
12 * Yan Vugenfirer <yan@daynix.com>
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2.1 of the License, or (at your option) any later version.
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
29 #include "qemu/osdep.h"
30 #include "libqtest-single.h"
31 #include "libqos/pci-pc.h"
33 #include "qemu/sockets.h"
35 #include "qemu/module.h"
36 #include "qemu/bitops.h"
37 #include "libqos/libqos-malloc.h"
38 #include "libqos/e1000e.h"
39 #include "hw/net/igb_regs.h"
43 static const struct eth_header packet
= {
44 .h_dest
= E1000E_ADDRESS
,
45 .h_source
= E1000E_ADDRESS
,
48 static void igb_send_verify(QE1000E
*d
, int *test_sockets
, QGuestAllocator
*alloc
)
50 union e1000_adv_tx_desc descr
;
55 /* Prepare test data buffer */
56 uint64_t data
= guest_alloc(alloc
, sizeof(buffer
));
57 memwrite(data
, &packet
, sizeof(packet
));
59 /* Prepare TX descriptor */
60 memset(&descr
, 0, sizeof(descr
));
61 descr
.read
.buffer_addr
= cpu_to_le64(data
);
62 descr
.read
.cmd_type_len
= cpu_to_le32(E1000_TXD_CMD_RS
|
67 /* Put descriptor to the ring */
68 e1000e_tx_ring_push(d
, &descr
);
70 /* Wait for TX WB interrupt */
71 e1000e_wait_isr(d
, E1000E_TX0_MSG_ID
);
74 g_assert_cmphex(le32_to_cpu(descr
.wb
.status
) & E1000_TXD_STAT_DD
, ==,
77 /* Check data sent to the backend */
78 ret
= recv(test_sockets
[0], &recv_len
, sizeof(recv_len
), 0);
79 g_assert_cmpint(ret
, == , sizeof(recv_len
));
80 ret
= recv(test_sockets
[0], buffer
, sizeof(buffer
), 0);
81 g_assert_cmpint(ret
, ==, sizeof(buffer
));
82 g_assert_false(memcmp(buffer
, &packet
, sizeof(packet
)));
84 /* Free test data buffer */
85 guest_free(alloc
, data
);
88 static void igb_receive_verify(QE1000E
*d
, int *test_sockets
, QGuestAllocator
*alloc
)
90 union e1000_adv_rx_desc descr
;
92 struct eth_header test_iov
= packet
;
93 int len
= htonl(sizeof(packet
));
94 struct iovec iov
[] = {
97 .iov_len
= sizeof(len
),
99 .iov_base
= &test_iov
,
100 .iov_len
= sizeof(packet
),
107 /* Send a dummy packet to device's socket*/
108 ret
= iov_send(test_sockets
[0], iov
, 2, 0, sizeof(len
) + sizeof(packet
));
109 g_assert_cmpint(ret
, == , sizeof(packet
) + sizeof(len
));
111 /* Prepare test data buffer */
112 uint64_t data
= guest_alloc(alloc
, sizeof(buffer
));
114 /* Prepare RX descriptor */
115 memset(&descr
, 0, sizeof(descr
));
116 descr
.read
.pkt_addr
= cpu_to_le64(data
);
118 /* Put descriptor to the ring */
119 e1000e_rx_ring_push(d
, &descr
);
121 /* Wait for TX WB interrupt */
122 e1000e_wait_isr(d
, E1000E_RX0_MSG_ID
);
125 g_assert_cmphex(le32_to_cpu(descr
.wb
.upper
.status_error
) &
126 E1000_RXD_STAT_DD
, ==, E1000_RXD_STAT_DD
);
128 /* Check data sent to the backend */
129 memread(data
, buffer
, sizeof(buffer
));
130 g_assert_false(memcmp(buffer
, &packet
, sizeof(packet
)));
132 /* Free test data buffer */
133 guest_free(alloc
, data
);
136 static void test_e1000e_init(void *obj
, void *data
, QGuestAllocator
* alloc
)
138 /* init does nothing */
141 static void test_igb_tx(void *obj
, void *data
, QGuestAllocator
* alloc
)
143 QE1000E_PCI
*e1000e
= obj
;
144 QE1000E
*d
= &e1000e
->e1000e
;
145 QOSGraphObject
*e_object
= obj
;
146 QPCIDevice
*dev
= e_object
->get_driver(e_object
, "pci-device");
148 /* FIXME: add spapr support */
149 if (qpci_check_buggy_msi(dev
)) {
153 igb_send_verify(d
, data
, alloc
);
156 static void test_igb_rx(void *obj
, void *data
, QGuestAllocator
* alloc
)
158 QE1000E_PCI
*e1000e
= obj
;
159 QE1000E
*d
= &e1000e
->e1000e
;
160 QOSGraphObject
*e_object
= obj
;
161 QPCIDevice
*dev
= e_object
->get_driver(e_object
, "pci-device");
163 /* FIXME: add spapr support */
164 if (qpci_check_buggy_msi(dev
)) {
168 igb_receive_verify(d
, data
, alloc
);
171 static void test_igb_multiple_transfers(void *obj
, void *data
,
172 QGuestAllocator
*alloc
)
174 static const long iterations
= 4 * 1024;
177 QE1000E_PCI
*e1000e
= obj
;
178 QE1000E
*d
= &e1000e
->e1000e
;
179 QOSGraphObject
*e_object
= obj
;
180 QPCIDevice
*dev
= e_object
->get_driver(e_object
, "pci-device");
182 /* FIXME: add spapr support */
183 if (qpci_check_buggy_msi(dev
)) {
187 for (i
= 0; i
< iterations
; i
++) {
188 igb_send_verify(d
, data
, alloc
);
189 igb_receive_verify(d
, data
, alloc
);
194 static void data_test_clear(void *sockets
)
196 int *test_sockets
= sockets
;
198 close(test_sockets
[0]);
199 qos_invalidate_command_line();
200 close(test_sockets
[1]);
201 g_free(test_sockets
);
204 static void *data_test_init(GString
*cmd_line
, void *arg
)
206 int *test_sockets
= g_new(int, 2);
207 int ret
= socketpair(PF_UNIX
, SOCK_STREAM
, 0, test_sockets
);
208 g_assert_cmpint(ret
, != , -1);
210 g_string_append_printf(cmd_line
, " -netdev socket,fd=%d,id=hs0 ",
213 g_test_queue_destroy(data_test_clear
, test_sockets
);
219 static void *data_test_init_no_socket(GString
*cmd_line
, void *arg
)
221 g_string_append(cmd_line
, " -netdev hubport,hubid=0,id=hs0 ");
225 static void test_igb_hotplug(void *obj
, void *data
, QGuestAllocator
* alloc
)
227 QTestState
*qts
= global_qtest
; /* TODO: get rid of global_qtest here */
228 QE1000E_PCI
*dev
= obj
;
230 if (dev
->pci_dev
.bus
->not_hotpluggable
) {
231 g_test_skip("pci bus does not support hotplug");
235 qtest_qmp_device_add(qts
, "igb", "igb_net", "{'addr': '0x06'}");
236 qpci_unplug_acpi_device_test(qts
, "igb_net", 0x06);
239 static void register_igb_test(void)
241 QOSGraphTestOptions opts
= { 0 };
244 opts
.before
= data_test_init
,
245 qos_add_test("init", "igb", test_e1000e_init
, &opts
);
246 qos_add_test("tx", "igb", test_igb_tx
, &opts
);
247 qos_add_test("rx", "igb", test_igb_rx
, &opts
);
248 qos_add_test("multiple_transfers", "igb",
249 test_igb_multiple_transfers
, &opts
);
252 opts
.before
= data_test_init_no_socket
;
253 qos_add_test("hotplug", "igb", test_igb_hotplug
, &opts
);
256 libqos_init(register_igb_test
);