17c375e22SDmitry Fleytman /*
27c375e22SDmitry Fleytman * QTest testcase for e1000e NIC
37c375e22SDmitry Fleytman *
47c375e22SDmitry Fleytman * Copyright (c) 2015 Ravello Systems LTD (http://ravellosystems.com)
57c375e22SDmitry Fleytman * Developed by Daynix Computing LTD (http://www.daynix.com)
67c375e22SDmitry Fleytman *
77c375e22SDmitry Fleytman * Authors:
87c375e22SDmitry Fleytman * Dmitry Fleytman <dmitry@daynix.com>
97c375e22SDmitry Fleytman * Leonid Bloch <leonid@daynix.com>
107c375e22SDmitry Fleytman * Yan Vugenfirer <yan@daynix.com>
117c375e22SDmitry Fleytman *
127c375e22SDmitry Fleytman * This library is free software; you can redistribute it and/or
137c375e22SDmitry Fleytman * modify it under the terms of the GNU Lesser General Public
147c375e22SDmitry Fleytman * License as published by the Free Software Foundation; either
15dc0ad02dSThomas Huth * version 2.1 of the License, or (at your option) any later version.
167c375e22SDmitry Fleytman *
177c375e22SDmitry Fleytman * This library is distributed in the hope that it will be useful,
187c375e22SDmitry Fleytman * but WITHOUT ANY WARRANTY; without even the implied warranty of
197c375e22SDmitry Fleytman * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
207c375e22SDmitry Fleytman * Lesser General Public License for more details.
217c375e22SDmitry Fleytman *
227c375e22SDmitry Fleytman * You should have received a copy of the GNU Lesser General Public
237c375e22SDmitry Fleytman * License along with this library; if not, see <http://www.gnu.org/licenses/>.
247c375e22SDmitry Fleytman */
257c375e22SDmitry Fleytman
267c375e22SDmitry Fleytman
277c375e22SDmitry Fleytman #include "qemu/osdep.h"
28dd210749SThomas Huth #include "libqtest-single.h"
297c375e22SDmitry Fleytman #include "libqos/pci-pc.h"
30*00dc9a59SAkihiko Odaki #include "net/eth.h"
317c375e22SDmitry Fleytman #include "qemu/sockets.h"
327c375e22SDmitry Fleytman #include "qemu/iov.h"
330b8fa32fSMarkus Armbruster #include "qemu/module.h"
347c375e22SDmitry Fleytman #include "qemu/bitops.h"
35b243c73cSXuzhou Cheng #include "libqos/libqos-malloc.h"
36b026393cSEmanuele Giuseppe Esposito #include "libqos/e1000e.h"
37dfa644b2SAkihiko Odaki #include "hw/net/e1000_regs.h"
387c375e22SDmitry Fleytman
39*00dc9a59SAkihiko Odaki static const struct eth_header packet = {
40*00dc9a59SAkihiko Odaki .h_dest = E1000E_ADDRESS,
41*00dc9a59SAkihiko Odaki .h_source = E1000E_ADDRESS,
42*00dc9a59SAkihiko Odaki };
43*00dc9a59SAkihiko Odaki
e1000e_send_verify(QE1000E * d,int * test_sockets,QGuestAllocator * alloc)44b026393cSEmanuele Giuseppe Esposito static void e1000e_send_verify(QE1000E *d, int *test_sockets, QGuestAllocator *alloc)
457c375e22SDmitry Fleytman {
46dfa644b2SAkihiko Odaki struct e1000_tx_desc descr;
477c375e22SDmitry Fleytman char buffer[64];
487c375e22SDmitry Fleytman int ret;
497c375e22SDmitry Fleytman uint32_t recv_len;
507c375e22SDmitry Fleytman
517c375e22SDmitry Fleytman /* Prepare test data buffer */
52f2ae2fabSAkihiko Odaki uint64_t data = guest_alloc(alloc, sizeof(buffer));
53*00dc9a59SAkihiko Odaki memwrite(data, &packet, sizeof(packet));
547c375e22SDmitry Fleytman
557c375e22SDmitry Fleytman /* Prepare TX descriptor */
567c375e22SDmitry Fleytman memset(&descr, 0, sizeof(descr));
577c375e22SDmitry Fleytman descr.buffer_addr = cpu_to_le64(data);
58dfa644b2SAkihiko Odaki descr.lower.data = cpu_to_le32(E1000_TXD_CMD_RS |
59dfa644b2SAkihiko Odaki E1000_TXD_CMD_EOP |
60dfa644b2SAkihiko Odaki E1000_TXD_CMD_DEXT |
61dfa644b2SAkihiko Odaki E1000_TXD_DTYP_D |
62f2ae2fabSAkihiko Odaki sizeof(buffer));
637c375e22SDmitry Fleytman
647c375e22SDmitry Fleytman /* Put descriptor to the ring */
657c375e22SDmitry Fleytman e1000e_tx_ring_push(d, &descr);
667c375e22SDmitry Fleytman
677c375e22SDmitry Fleytman /* Wait for TX WB interrupt */
687c375e22SDmitry Fleytman e1000e_wait_isr(d, E1000E_TX0_MSG_ID);
697c375e22SDmitry Fleytman
707c375e22SDmitry Fleytman /* Check DD bit */
71dfa644b2SAkihiko Odaki g_assert_cmphex(le32_to_cpu(descr.upper.data) & E1000_TXD_STAT_DD, ==,
72dfa644b2SAkihiko Odaki E1000_TXD_STAT_DD);
737c375e22SDmitry Fleytman
747c375e22SDmitry Fleytman /* Check data sent to the backend */
75e7b79428SMarc-André Lureau ret = recv(test_sockets[0], &recv_len, sizeof(recv_len), 0);
767c375e22SDmitry Fleytman g_assert_cmpint(ret, == , sizeof(recv_len));
77f2ae2fabSAkihiko Odaki ret = recv(test_sockets[0], buffer, sizeof(buffer), 0);
78f2ae2fabSAkihiko Odaki g_assert_cmpint(ret, ==, sizeof(buffer));
79*00dc9a59SAkihiko Odaki g_assert_false(memcmp(buffer, &packet, sizeof(packet)));
807c375e22SDmitry Fleytman
817c375e22SDmitry Fleytman /* Free test data buffer */
82b026393cSEmanuele Giuseppe Esposito guest_free(alloc, data);
837c375e22SDmitry Fleytman }
847c375e22SDmitry Fleytman
e1000e_receive_verify(QE1000E * d,int * test_sockets,QGuestAllocator * alloc)85b026393cSEmanuele Giuseppe Esposito static void e1000e_receive_verify(QE1000E *d, int *test_sockets, QGuestAllocator *alloc)
867c375e22SDmitry Fleytman {
87dfa644b2SAkihiko Odaki union e1000_rx_desc_extended descr;
887c375e22SDmitry Fleytman
89*00dc9a59SAkihiko Odaki struct eth_header test_iov = packet;
90*00dc9a59SAkihiko Odaki int len = htonl(sizeof(packet));
917c375e22SDmitry Fleytman struct iovec iov[] = {
927c375e22SDmitry Fleytman {
937c375e22SDmitry Fleytman .iov_base = &len,
947c375e22SDmitry Fleytman .iov_len = sizeof(len),
957c375e22SDmitry Fleytman },{
96*00dc9a59SAkihiko Odaki .iov_base = &test_iov,
97*00dc9a59SAkihiko Odaki .iov_len = sizeof(packet),
987c375e22SDmitry Fleytman },
997c375e22SDmitry Fleytman };
1007c375e22SDmitry Fleytman
1017c375e22SDmitry Fleytman char buffer[64];
1027c375e22SDmitry Fleytman int ret;
1037c375e22SDmitry Fleytman
1047c375e22SDmitry Fleytman /* Send a dummy packet to device's socket*/
105*00dc9a59SAkihiko Odaki ret = iov_send(test_sockets[0], iov, 2, 0, sizeof(len) + sizeof(packet));
106*00dc9a59SAkihiko Odaki g_assert_cmpint(ret, == , sizeof(packet) + sizeof(len));
1077c375e22SDmitry Fleytman
1087c375e22SDmitry Fleytman /* Prepare test data buffer */
109f2ae2fabSAkihiko Odaki uint64_t data = guest_alloc(alloc, sizeof(buffer));
1107c375e22SDmitry Fleytman
1117c375e22SDmitry Fleytman /* Prepare RX descriptor */
1127c375e22SDmitry Fleytman memset(&descr, 0, sizeof(descr));
1137c375e22SDmitry Fleytman descr.read.buffer_addr = cpu_to_le64(data);
1147c375e22SDmitry Fleytman
1157c375e22SDmitry Fleytman /* Put descriptor to the ring */
1167c375e22SDmitry Fleytman e1000e_rx_ring_push(d, &descr);
1177c375e22SDmitry Fleytman
1187c375e22SDmitry Fleytman /* Wait for TX WB interrupt */
1197c375e22SDmitry Fleytman e1000e_wait_isr(d, E1000E_RX0_MSG_ID);
1207c375e22SDmitry Fleytman
1217c375e22SDmitry Fleytman /* Check DD bit */
1227c375e22SDmitry Fleytman g_assert_cmphex(le32_to_cpu(descr.wb.upper.status_error) &
123dfa644b2SAkihiko Odaki E1000_RXD_STAT_DD, ==, E1000_RXD_STAT_DD);
1247c375e22SDmitry Fleytman
1257c375e22SDmitry Fleytman /* Check data sent to the backend */
1267c375e22SDmitry Fleytman memread(data, buffer, sizeof(buffer));
127*00dc9a59SAkihiko Odaki g_assert_false(memcmp(buffer, &packet, sizeof(packet)));
1287c375e22SDmitry Fleytman
1297c375e22SDmitry Fleytman /* Free test data buffer */
130b026393cSEmanuele Giuseppe Esposito guest_free(alloc, data);
1317c375e22SDmitry Fleytman }
1327c375e22SDmitry Fleytman
test_e1000e_init(void * obj,void * data,QGuestAllocator * alloc)133b026393cSEmanuele Giuseppe Esposito static void test_e1000e_init(void *obj, void *data, QGuestAllocator * alloc)
1347c375e22SDmitry Fleytman {
135b026393cSEmanuele Giuseppe Esposito /* init does nothing */
1367c375e22SDmitry Fleytman }
1377c375e22SDmitry Fleytman
test_e1000e_tx(void * obj,void * data,QGuestAllocator * alloc)138b026393cSEmanuele Giuseppe Esposito static void test_e1000e_tx(void *obj, void *data, QGuestAllocator * alloc)
1397c375e22SDmitry Fleytman {
140b026393cSEmanuele Giuseppe Esposito QE1000E_PCI *e1000e = obj;
141b026393cSEmanuele Giuseppe Esposito QE1000E *d = &e1000e->e1000e;
142b026393cSEmanuele Giuseppe Esposito QOSGraphObject *e_object = obj;
143b026393cSEmanuele Giuseppe Esposito QPCIDevice *dev = e_object->get_driver(e_object, "pci-device");
1447c375e22SDmitry Fleytman
145b026393cSEmanuele Giuseppe Esposito /* FIXME: add spapr support */
146b026393cSEmanuele Giuseppe Esposito if (qpci_check_buggy_msi(dev)) {
147b026393cSEmanuele Giuseppe Esposito return;
1487c375e22SDmitry Fleytman }
1497c375e22SDmitry Fleytman
150b026393cSEmanuele Giuseppe Esposito e1000e_send_verify(d, data, alloc);
151b026393cSEmanuele Giuseppe Esposito }
152b026393cSEmanuele Giuseppe Esposito
test_e1000e_rx(void * obj,void * data,QGuestAllocator * alloc)153b026393cSEmanuele Giuseppe Esposito static void test_e1000e_rx(void *obj, void *data, QGuestAllocator * alloc)
1547c375e22SDmitry Fleytman {
155b026393cSEmanuele Giuseppe Esposito QE1000E_PCI *e1000e = obj;
156b026393cSEmanuele Giuseppe Esposito QE1000E *d = &e1000e->e1000e;
157b026393cSEmanuele Giuseppe Esposito QOSGraphObject *e_object = obj;
158b026393cSEmanuele Giuseppe Esposito QPCIDevice *dev = e_object->get_driver(e_object, "pci-device");
159b026393cSEmanuele Giuseppe Esposito
160b026393cSEmanuele Giuseppe Esposito /* FIXME: add spapr support */
161b026393cSEmanuele Giuseppe Esposito if (qpci_check_buggy_msi(dev)) {
162b026393cSEmanuele Giuseppe Esposito return;
1637c375e22SDmitry Fleytman }
1647c375e22SDmitry Fleytman
165b026393cSEmanuele Giuseppe Esposito e1000e_receive_verify(d, data, alloc);
1667c375e22SDmitry Fleytman }
1677c375e22SDmitry Fleytman
test_e1000e_multiple_transfers(void * obj,void * data,QGuestAllocator * alloc)168b026393cSEmanuele Giuseppe Esposito static void test_e1000e_multiple_transfers(void *obj, void *data,
169b026393cSEmanuele Giuseppe Esposito QGuestAllocator *alloc)
1707c375e22SDmitry Fleytman {
1717c375e22SDmitry Fleytman static const long iterations = 4 * 1024;
1727c375e22SDmitry Fleytman long i;
1737c375e22SDmitry Fleytman
174b026393cSEmanuele Giuseppe Esposito QE1000E_PCI *e1000e = obj;
175b026393cSEmanuele Giuseppe Esposito QE1000E *d = &e1000e->e1000e;
176b026393cSEmanuele Giuseppe Esposito QOSGraphObject *e_object = obj;
177b026393cSEmanuele Giuseppe Esposito QPCIDevice *dev = e_object->get_driver(e_object, "pci-device");
1787c375e22SDmitry Fleytman
179b026393cSEmanuele Giuseppe Esposito /* FIXME: add spapr support */
180b026393cSEmanuele Giuseppe Esposito if (qpci_check_buggy_msi(dev)) {
181b026393cSEmanuele Giuseppe Esposito return;
182b026393cSEmanuele Giuseppe Esposito }
1837c375e22SDmitry Fleytman
1847c375e22SDmitry Fleytman for (i = 0; i < iterations; i++) {
185b026393cSEmanuele Giuseppe Esposito e1000e_send_verify(d, data, alloc);
186b026393cSEmanuele Giuseppe Esposito e1000e_receive_verify(d, data, alloc);
1877c375e22SDmitry Fleytman }
1887c375e22SDmitry Fleytman
1897c375e22SDmitry Fleytman }
1907c375e22SDmitry Fleytman
test_e1000e_hotplug(void * obj,void * data,QGuestAllocator * alloc)191b026393cSEmanuele Giuseppe Esposito static void test_e1000e_hotplug(void *obj, void *data, QGuestAllocator * alloc)
1927c375e22SDmitry Fleytman {
1936ebb8d2aSThomas Huth QTestState *qts = global_qtest; /* TODO: get rid of global_qtest here */
19402ee7a8aSEric Auger QE1000E_PCI *dev = obj;
19502ee7a8aSEric Auger
19602ee7a8aSEric Auger if (dev->pci_dev.bus->not_hotpluggable) {
19702ee7a8aSEric Auger g_test_skip("pci bus does not support hotplug");
19802ee7a8aSEric Auger return;
19902ee7a8aSEric Auger }
2006ebb8d2aSThomas Huth
201e5758de4SThomas Huth qtest_qmp_device_add(qts, "e1000e", "e1000e_net", "{'addr': '0x06'}");
2026ebb8d2aSThomas Huth qpci_unplug_acpi_device_test(qts, "e1000e_net", 0x06);
2037c375e22SDmitry Fleytman }
2047c375e22SDmitry Fleytman
data_test_clear(void * sockets)205b026393cSEmanuele Giuseppe Esposito static void data_test_clear(void *sockets)
2067c375e22SDmitry Fleytman {
207b026393cSEmanuele Giuseppe Esposito int *test_sockets = sockets;
2087c375e22SDmitry Fleytman
209b026393cSEmanuele Giuseppe Esposito close(test_sockets[0]);
210b026393cSEmanuele Giuseppe Esposito qos_invalidate_command_line();
211b026393cSEmanuele Giuseppe Esposito close(test_sockets[1]);
212b026393cSEmanuele Giuseppe Esposito g_free(test_sockets);
2137c375e22SDmitry Fleytman }
214b026393cSEmanuele Giuseppe Esposito
data_test_init(GString * cmd_line,void * arg)215b026393cSEmanuele Giuseppe Esposito static void *data_test_init(GString *cmd_line, void *arg)
216b026393cSEmanuele Giuseppe Esposito {
217b026393cSEmanuele Giuseppe Esposito int *test_sockets = g_new(int, 2);
218b026393cSEmanuele Giuseppe Esposito int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, test_sockets);
219b026393cSEmanuele Giuseppe Esposito g_assert_cmpint(ret, != , -1);
220b026393cSEmanuele Giuseppe Esposito
221b026393cSEmanuele Giuseppe Esposito g_string_append_printf(cmd_line, " -netdev socket,fd=%d,id=hs0 ",
222b026393cSEmanuele Giuseppe Esposito test_sockets[1]);
223b026393cSEmanuele Giuseppe Esposito
224b026393cSEmanuele Giuseppe Esposito g_test_queue_destroy(data_test_clear, test_sockets);
225b026393cSEmanuele Giuseppe Esposito return test_sockets;
226b026393cSEmanuele Giuseppe Esposito }
227b026393cSEmanuele Giuseppe Esposito
register_e1000e_test(void)228b026393cSEmanuele Giuseppe Esposito static void register_e1000e_test(void)
229b026393cSEmanuele Giuseppe Esposito {
230b026393cSEmanuele Giuseppe Esposito QOSGraphTestOptions opts = {
231b026393cSEmanuele Giuseppe Esposito .before = data_test_init,
232b026393cSEmanuele Giuseppe Esposito };
233b026393cSEmanuele Giuseppe Esposito
234b026393cSEmanuele Giuseppe Esposito qos_add_test("init", "e1000e", test_e1000e_init, &opts);
235b026393cSEmanuele Giuseppe Esposito qos_add_test("tx", "e1000e", test_e1000e_tx, &opts);
236b026393cSEmanuele Giuseppe Esposito qos_add_test("rx", "e1000e", test_e1000e_rx, &opts);
237b026393cSEmanuele Giuseppe Esposito qos_add_test("multiple_transfers", "e1000e",
238b026393cSEmanuele Giuseppe Esposito test_e1000e_multiple_transfers, &opts);
239b026393cSEmanuele Giuseppe Esposito qos_add_test("hotplug", "e1000e", test_e1000e_hotplug, &opts);
240b026393cSEmanuele Giuseppe Esposito }
241b026393cSEmanuele Giuseppe Esposito
242b026393cSEmanuele Giuseppe Esposito libqos_init(register_e1000e_test);
243