xref: /qemu/tests/qtest/e1000e-test.c (revision dfa644b231a55e50571b99bc65a2fff530e6913c)
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"
307c375e22SDmitry Fleytman #include "qemu/sockets.h"
317c375e22SDmitry Fleytman #include "qemu/iov.h"
320b8fa32fSMarkus Armbruster #include "qemu/module.h"
337c375e22SDmitry Fleytman #include "qemu/bitops.h"
34b243c73cSXuzhou Cheng #include "libqos/libqos-malloc.h"
35b026393cSEmanuele Giuseppe Esposito #include "libqos/e1000e.h"
36*dfa644b2SAkihiko Odaki #include "hw/net/e1000_regs.h"
377c375e22SDmitry Fleytman 
38b026393cSEmanuele Giuseppe Esposito static void e1000e_send_verify(QE1000E *d, int *test_sockets, QGuestAllocator *alloc)
397c375e22SDmitry Fleytman {
40*dfa644b2SAkihiko Odaki     struct e1000_tx_desc descr;
417c375e22SDmitry Fleytman     static const int data_len = 64;
427c375e22SDmitry Fleytman     char buffer[64];
437c375e22SDmitry Fleytman     int ret;
447c375e22SDmitry Fleytman     uint32_t recv_len;
457c375e22SDmitry Fleytman 
467c375e22SDmitry Fleytman     /* Prepare test data buffer */
47b026393cSEmanuele Giuseppe Esposito     uint64_t data = guest_alloc(alloc, data_len);
487c375e22SDmitry Fleytman     memwrite(data, "TEST", 5);
497c375e22SDmitry Fleytman 
507c375e22SDmitry Fleytman     /* Prepare TX descriptor */
517c375e22SDmitry Fleytman     memset(&descr, 0, sizeof(descr));
527c375e22SDmitry Fleytman     descr.buffer_addr = cpu_to_le64(data);
53*dfa644b2SAkihiko Odaki     descr.lower.data = cpu_to_le32(E1000_TXD_CMD_RS   |
54*dfa644b2SAkihiko Odaki                                    E1000_TXD_CMD_EOP  |
55*dfa644b2SAkihiko Odaki                                    E1000_TXD_CMD_DEXT |
56*dfa644b2SAkihiko Odaki                                    E1000_TXD_DTYP_D   |
577c375e22SDmitry Fleytman                                    data_len);
587c375e22SDmitry Fleytman 
597c375e22SDmitry Fleytman     /* Put descriptor to the ring */
607c375e22SDmitry Fleytman     e1000e_tx_ring_push(d, &descr);
617c375e22SDmitry Fleytman 
627c375e22SDmitry Fleytman     /* Wait for TX WB interrupt */
637c375e22SDmitry Fleytman     e1000e_wait_isr(d, E1000E_TX0_MSG_ID);
647c375e22SDmitry Fleytman 
657c375e22SDmitry Fleytman     /* Check DD bit */
66*dfa644b2SAkihiko Odaki     g_assert_cmphex(le32_to_cpu(descr.upper.data) & E1000_TXD_STAT_DD, ==,
67*dfa644b2SAkihiko Odaki                     E1000_TXD_STAT_DD);
687c375e22SDmitry Fleytman 
697c375e22SDmitry Fleytman     /* Check data sent to the backend */
70e7b79428SMarc-André Lureau     ret = recv(test_sockets[0], &recv_len, sizeof(recv_len), 0);
717c375e22SDmitry Fleytman     g_assert_cmpint(ret, == , sizeof(recv_len));
72e7b79428SMarc-André Lureau     ret = recv(test_sockets[0], buffer, 64, 0);
73380822edSPeter Maydell     g_assert_cmpint(ret, >=, 5);
747c375e22SDmitry Fleytman     g_assert_cmpstr(buffer, == , "TEST");
757c375e22SDmitry Fleytman 
767c375e22SDmitry Fleytman     /* Free test data buffer */
77b026393cSEmanuele Giuseppe Esposito     guest_free(alloc, data);
787c375e22SDmitry Fleytman }
797c375e22SDmitry Fleytman 
80b026393cSEmanuele Giuseppe Esposito static void e1000e_receive_verify(QE1000E *d, int *test_sockets, QGuestAllocator *alloc)
817c375e22SDmitry Fleytman {
82*dfa644b2SAkihiko Odaki     union e1000_rx_desc_extended descr;
837c375e22SDmitry Fleytman 
847c375e22SDmitry Fleytman     char test[] = "TEST";
857c375e22SDmitry Fleytman     int len = htonl(sizeof(test));
867c375e22SDmitry Fleytman     struct iovec iov[] = {
877c375e22SDmitry Fleytman         {
887c375e22SDmitry Fleytman             .iov_base = &len,
897c375e22SDmitry Fleytman             .iov_len = sizeof(len),
907c375e22SDmitry Fleytman         },{
917c375e22SDmitry Fleytman             .iov_base = test,
927c375e22SDmitry Fleytman             .iov_len = sizeof(test),
937c375e22SDmitry Fleytman         },
947c375e22SDmitry Fleytman     };
957c375e22SDmitry Fleytman 
967c375e22SDmitry Fleytman     static const int data_len = 64;
977c375e22SDmitry Fleytman     char buffer[64];
987c375e22SDmitry Fleytman     int ret;
997c375e22SDmitry Fleytman 
1007c375e22SDmitry Fleytman     /* Send a dummy packet to device's socket*/
1017c375e22SDmitry Fleytman     ret = iov_send(test_sockets[0], iov, 2, 0, sizeof(len) + sizeof(test));
1027c375e22SDmitry Fleytman     g_assert_cmpint(ret, == , sizeof(test) + sizeof(len));
1037c375e22SDmitry Fleytman 
1047c375e22SDmitry Fleytman     /* Prepare test data buffer */
105b026393cSEmanuele Giuseppe Esposito     uint64_t data = guest_alloc(alloc, data_len);
1067c375e22SDmitry Fleytman 
1077c375e22SDmitry Fleytman     /* Prepare RX descriptor */
1087c375e22SDmitry Fleytman     memset(&descr, 0, sizeof(descr));
1097c375e22SDmitry Fleytman     descr.read.buffer_addr = cpu_to_le64(data);
1107c375e22SDmitry Fleytman 
1117c375e22SDmitry Fleytman     /* Put descriptor to the ring */
1127c375e22SDmitry Fleytman     e1000e_rx_ring_push(d, &descr);
1137c375e22SDmitry Fleytman 
1147c375e22SDmitry Fleytman     /* Wait for TX WB interrupt */
1157c375e22SDmitry Fleytman     e1000e_wait_isr(d, E1000E_RX0_MSG_ID);
1167c375e22SDmitry Fleytman 
1177c375e22SDmitry Fleytman     /* Check DD bit */
1187c375e22SDmitry Fleytman     g_assert_cmphex(le32_to_cpu(descr.wb.upper.status_error) &
119*dfa644b2SAkihiko Odaki         E1000_RXD_STAT_DD, ==, E1000_RXD_STAT_DD);
1207c375e22SDmitry Fleytman 
1217c375e22SDmitry Fleytman     /* Check data sent to the backend */
1227c375e22SDmitry Fleytman     memread(data, buffer, sizeof(buffer));
1237c375e22SDmitry Fleytman     g_assert_cmpstr(buffer, == , "TEST");
1247c375e22SDmitry Fleytman 
1257c375e22SDmitry Fleytman     /* Free test data buffer */
126b026393cSEmanuele Giuseppe Esposito     guest_free(alloc, data);
1277c375e22SDmitry Fleytman }
1287c375e22SDmitry Fleytman 
129b026393cSEmanuele Giuseppe Esposito static void test_e1000e_init(void *obj, void *data, QGuestAllocator * alloc)
1307c375e22SDmitry Fleytman {
131b026393cSEmanuele Giuseppe Esposito     /* init does nothing */
1327c375e22SDmitry Fleytman }
1337c375e22SDmitry Fleytman 
134b026393cSEmanuele Giuseppe Esposito static void test_e1000e_tx(void *obj, void *data, QGuestAllocator * alloc)
1357c375e22SDmitry Fleytman {
136b026393cSEmanuele Giuseppe Esposito     QE1000E_PCI *e1000e = obj;
137b026393cSEmanuele Giuseppe Esposito     QE1000E *d = &e1000e->e1000e;
138b026393cSEmanuele Giuseppe Esposito     QOSGraphObject *e_object = obj;
139b026393cSEmanuele Giuseppe Esposito     QPCIDevice *dev = e_object->get_driver(e_object, "pci-device");
1407c375e22SDmitry Fleytman 
141b026393cSEmanuele Giuseppe Esposito     /* FIXME: add spapr support */
142b026393cSEmanuele Giuseppe Esposito     if (qpci_check_buggy_msi(dev)) {
143b026393cSEmanuele Giuseppe Esposito         return;
1447c375e22SDmitry Fleytman     }
1457c375e22SDmitry Fleytman 
146b026393cSEmanuele Giuseppe Esposito     e1000e_send_verify(d, data, alloc);
147b026393cSEmanuele Giuseppe Esposito }
148b026393cSEmanuele Giuseppe Esposito 
149b026393cSEmanuele Giuseppe Esposito static void test_e1000e_rx(void *obj, void *data, QGuestAllocator * alloc)
1507c375e22SDmitry Fleytman {
151b026393cSEmanuele Giuseppe Esposito     QE1000E_PCI *e1000e = obj;
152b026393cSEmanuele Giuseppe Esposito     QE1000E *d = &e1000e->e1000e;
153b026393cSEmanuele Giuseppe Esposito     QOSGraphObject *e_object = obj;
154b026393cSEmanuele Giuseppe Esposito     QPCIDevice *dev = e_object->get_driver(e_object, "pci-device");
155b026393cSEmanuele Giuseppe Esposito 
156b026393cSEmanuele Giuseppe Esposito     /* FIXME: add spapr support */
157b026393cSEmanuele Giuseppe Esposito     if (qpci_check_buggy_msi(dev)) {
158b026393cSEmanuele Giuseppe Esposito         return;
1597c375e22SDmitry Fleytman     }
1607c375e22SDmitry Fleytman 
161b026393cSEmanuele Giuseppe Esposito     e1000e_receive_verify(d, data, alloc);
1627c375e22SDmitry Fleytman }
1637c375e22SDmitry Fleytman 
164b026393cSEmanuele Giuseppe Esposito static void test_e1000e_multiple_transfers(void *obj, void *data,
165b026393cSEmanuele Giuseppe Esposito                                            QGuestAllocator *alloc)
1667c375e22SDmitry Fleytman {
1677c375e22SDmitry Fleytman     static const long iterations = 4 * 1024;
1687c375e22SDmitry Fleytman     long i;
1697c375e22SDmitry Fleytman 
170b026393cSEmanuele Giuseppe Esposito     QE1000E_PCI *e1000e = obj;
171b026393cSEmanuele Giuseppe Esposito     QE1000E *d = &e1000e->e1000e;
172b026393cSEmanuele Giuseppe Esposito     QOSGraphObject *e_object = obj;
173b026393cSEmanuele Giuseppe Esposito     QPCIDevice *dev = e_object->get_driver(e_object, "pci-device");
1747c375e22SDmitry Fleytman 
175b026393cSEmanuele Giuseppe Esposito     /* FIXME: add spapr support */
176b026393cSEmanuele Giuseppe Esposito     if (qpci_check_buggy_msi(dev)) {
177b026393cSEmanuele Giuseppe Esposito         return;
178b026393cSEmanuele Giuseppe Esposito     }
1797c375e22SDmitry Fleytman 
1807c375e22SDmitry Fleytman     for (i = 0; i < iterations; i++) {
181b026393cSEmanuele Giuseppe Esposito         e1000e_send_verify(d, data, alloc);
182b026393cSEmanuele Giuseppe Esposito         e1000e_receive_verify(d, data, alloc);
1837c375e22SDmitry Fleytman     }
1847c375e22SDmitry Fleytman 
1857c375e22SDmitry Fleytman }
1867c375e22SDmitry Fleytman 
187b026393cSEmanuele Giuseppe Esposito static void test_e1000e_hotplug(void *obj, void *data, QGuestAllocator * alloc)
1887c375e22SDmitry Fleytman {
1896ebb8d2aSThomas Huth     QTestState *qts = global_qtest;  /* TODO: get rid of global_qtest here */
19002ee7a8aSEric Auger     QE1000E_PCI *dev = obj;
19102ee7a8aSEric Auger 
19202ee7a8aSEric Auger     if (dev->pci_dev.bus->not_hotpluggable) {
19302ee7a8aSEric Auger         g_test_skip("pci bus does not support hotplug");
19402ee7a8aSEric Auger         return;
19502ee7a8aSEric Auger     }
1966ebb8d2aSThomas Huth 
197e5758de4SThomas Huth     qtest_qmp_device_add(qts, "e1000e", "e1000e_net", "{'addr': '0x06'}");
1986ebb8d2aSThomas Huth     qpci_unplug_acpi_device_test(qts, "e1000e_net", 0x06);
1997c375e22SDmitry Fleytman }
2007c375e22SDmitry Fleytman 
201b026393cSEmanuele Giuseppe Esposito static void data_test_clear(void *sockets)
2027c375e22SDmitry Fleytman {
203b026393cSEmanuele Giuseppe Esposito     int *test_sockets = sockets;
2047c375e22SDmitry Fleytman 
205b026393cSEmanuele Giuseppe Esposito     close(test_sockets[0]);
206b026393cSEmanuele Giuseppe Esposito     qos_invalidate_command_line();
207b026393cSEmanuele Giuseppe Esposito     close(test_sockets[1]);
208b026393cSEmanuele Giuseppe Esposito     g_free(test_sockets);
2097c375e22SDmitry Fleytman }
210b026393cSEmanuele Giuseppe Esposito 
211b026393cSEmanuele Giuseppe Esposito static void *data_test_init(GString *cmd_line, void *arg)
212b026393cSEmanuele Giuseppe Esposito {
213b026393cSEmanuele Giuseppe Esposito     int *test_sockets = g_new(int, 2);
214b026393cSEmanuele Giuseppe Esposito     int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, test_sockets);
215b026393cSEmanuele Giuseppe Esposito     g_assert_cmpint(ret, != , -1);
216b026393cSEmanuele Giuseppe Esposito 
217b026393cSEmanuele Giuseppe Esposito     g_string_append_printf(cmd_line, " -netdev socket,fd=%d,id=hs0 ",
218b026393cSEmanuele Giuseppe Esposito                            test_sockets[1]);
219b026393cSEmanuele Giuseppe Esposito 
220b026393cSEmanuele Giuseppe Esposito     g_test_queue_destroy(data_test_clear, test_sockets);
221b026393cSEmanuele Giuseppe Esposito     return test_sockets;
222b026393cSEmanuele Giuseppe Esposito }
223b026393cSEmanuele Giuseppe Esposito 
224b026393cSEmanuele Giuseppe Esposito static void register_e1000e_test(void)
225b026393cSEmanuele Giuseppe Esposito {
226b026393cSEmanuele Giuseppe Esposito     QOSGraphTestOptions opts = {
227b026393cSEmanuele Giuseppe Esposito         .before = data_test_init,
228b026393cSEmanuele Giuseppe Esposito     };
229b026393cSEmanuele Giuseppe Esposito 
230b026393cSEmanuele Giuseppe Esposito     qos_add_test("init", "e1000e", test_e1000e_init, &opts);
231b026393cSEmanuele Giuseppe Esposito     qos_add_test("tx", "e1000e", test_e1000e_tx, &opts);
232b026393cSEmanuele Giuseppe Esposito     qos_add_test("rx", "e1000e", test_e1000e_rx, &opts);
233b026393cSEmanuele Giuseppe Esposito     qos_add_test("multiple_transfers", "e1000e",
234b026393cSEmanuele Giuseppe Esposito                       test_e1000e_multiple_transfers, &opts);
235b026393cSEmanuele Giuseppe Esposito     qos_add_test("hotplug", "e1000e", test_e1000e_hotplug, &opts);
236b026393cSEmanuele Giuseppe Esposito }
237b026393cSEmanuele Giuseppe Esposito 
238b026393cSEmanuele Giuseppe Esposito libqos_init(register_e1000e_test);
239