xref: /qemu/tests/qtest/e1000e-test.c (revision b026393c34779578106d3cc889271b1757b8d287)
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
157c375e22SDmitry Fleytman  * version 2 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"
287c375e22SDmitry Fleytman #include "libqtest.h"
297c375e22SDmitry Fleytman #include "qemu-common.h"
307c375e22SDmitry Fleytman #include "libqos/pci-pc.h"
317c375e22SDmitry Fleytman #include "qemu/sockets.h"
327c375e22SDmitry Fleytman #include "qemu/iov.h"
337c375e22SDmitry Fleytman #include "qemu/bitops.h"
347c375e22SDmitry Fleytman #include "libqos/malloc.h"
35*b026393cSEmanuele Giuseppe Esposito #include "libqos/e1000e.h"
367c375e22SDmitry Fleytman 
37*b026393cSEmanuele Giuseppe Esposito static void e1000e_send_verify(QE1000E *d, int *test_sockets, QGuestAllocator *alloc)
387c375e22SDmitry Fleytman {
397c375e22SDmitry Fleytman     struct {
407c375e22SDmitry Fleytman         uint64_t buffer_addr;
417c375e22SDmitry Fleytman         union {
427c375e22SDmitry Fleytman             uint32_t data;
437c375e22SDmitry Fleytman             struct {
447c375e22SDmitry Fleytman                 uint16_t length;
457c375e22SDmitry Fleytman                 uint8_t cso;
467c375e22SDmitry Fleytman                 uint8_t cmd;
477c375e22SDmitry Fleytman             } flags;
487c375e22SDmitry Fleytman         } lower;
497c375e22SDmitry Fleytman         union {
507c375e22SDmitry Fleytman             uint32_t data;
517c375e22SDmitry Fleytman             struct {
527c375e22SDmitry Fleytman                 uint8_t status;
537c375e22SDmitry Fleytman                 uint8_t css;
547c375e22SDmitry Fleytman                 uint16_t special;
557c375e22SDmitry Fleytman             } fields;
567c375e22SDmitry Fleytman         } upper;
577c375e22SDmitry Fleytman     } descr;
587c375e22SDmitry Fleytman 
597c375e22SDmitry Fleytman     static const uint32_t dtyp_data = BIT(20);
607c375e22SDmitry Fleytman     static const uint32_t dtyp_ext  = BIT(29);
617c375e22SDmitry Fleytman     static const uint32_t dcmd_rs   = BIT(27);
627c375e22SDmitry Fleytman     static const uint32_t dcmd_eop  = BIT(24);
637c375e22SDmitry Fleytman     static const uint32_t dsta_dd   = BIT(0);
647c375e22SDmitry Fleytman     static const int data_len = 64;
657c375e22SDmitry Fleytman     char buffer[64];
667c375e22SDmitry Fleytman     int ret;
677c375e22SDmitry Fleytman     uint32_t recv_len;
687c375e22SDmitry Fleytman 
697c375e22SDmitry Fleytman     /* Prepare test data buffer */
70*b026393cSEmanuele Giuseppe Esposito     uint64_t data = guest_alloc(alloc, data_len);
717c375e22SDmitry Fleytman     memwrite(data, "TEST", 5);
727c375e22SDmitry Fleytman 
737c375e22SDmitry Fleytman     /* Prepare TX descriptor */
747c375e22SDmitry Fleytman     memset(&descr, 0, sizeof(descr));
757c375e22SDmitry Fleytman     descr.buffer_addr = cpu_to_le64(data);
767c375e22SDmitry Fleytman     descr.lower.data = cpu_to_le32(dcmd_rs   |
777c375e22SDmitry Fleytman                                    dcmd_eop  |
787c375e22SDmitry Fleytman                                    dtyp_ext  |
797c375e22SDmitry Fleytman                                    dtyp_data |
807c375e22SDmitry Fleytman                                    data_len);
817c375e22SDmitry Fleytman 
827c375e22SDmitry Fleytman     /* Put descriptor to the ring */
837c375e22SDmitry Fleytman     e1000e_tx_ring_push(d, &descr);
847c375e22SDmitry Fleytman 
857c375e22SDmitry Fleytman     /* Wait for TX WB interrupt */
867c375e22SDmitry Fleytman     e1000e_wait_isr(d, E1000E_TX0_MSG_ID);
877c375e22SDmitry Fleytman 
887c375e22SDmitry Fleytman     /* Check DD bit */
897c375e22SDmitry Fleytman     g_assert_cmphex(le32_to_cpu(descr.upper.data) & dsta_dd, ==, dsta_dd);
907c375e22SDmitry Fleytman 
917c375e22SDmitry Fleytman     /* Check data sent to the backend */
927c375e22SDmitry Fleytman     ret = qemu_recv(test_sockets[0], &recv_len, sizeof(recv_len), 0);
937c375e22SDmitry Fleytman     g_assert_cmpint(ret, == , sizeof(recv_len));
947c375e22SDmitry Fleytman     qemu_recv(test_sockets[0], buffer, 64, 0);
957c375e22SDmitry Fleytman     g_assert_cmpstr(buffer, == , "TEST");
967c375e22SDmitry Fleytman 
977c375e22SDmitry Fleytman     /* Free test data buffer */
98*b026393cSEmanuele Giuseppe Esposito     guest_free(alloc, data);
997c375e22SDmitry Fleytman }
1007c375e22SDmitry Fleytman 
101*b026393cSEmanuele Giuseppe Esposito static void e1000e_receive_verify(QE1000E *d, int *test_sockets, QGuestAllocator *alloc)
1027c375e22SDmitry Fleytman {
1037c375e22SDmitry Fleytman     union {
1047c375e22SDmitry Fleytman         struct {
1057c375e22SDmitry Fleytman             uint64_t buffer_addr;
1067c375e22SDmitry Fleytman             uint64_t reserved;
1077c375e22SDmitry Fleytman         } read;
1087c375e22SDmitry Fleytman         struct {
1097c375e22SDmitry Fleytman             struct {
1107c375e22SDmitry Fleytman                 uint32_t mrq;
1117c375e22SDmitry Fleytman                 union {
1127c375e22SDmitry Fleytman                     uint32_t rss;
1137c375e22SDmitry Fleytman                     struct {
1147c375e22SDmitry Fleytman                         uint16_t ip_id;
1157c375e22SDmitry Fleytman                         uint16_t csum;
1167c375e22SDmitry Fleytman                     } csum_ip;
1177c375e22SDmitry Fleytman                 } hi_dword;
1187c375e22SDmitry Fleytman             } lower;
1197c375e22SDmitry Fleytman             struct {
1207c375e22SDmitry Fleytman                 uint32_t status_error;
1217c375e22SDmitry Fleytman                 uint16_t length;
1227c375e22SDmitry Fleytman                 uint16_t vlan;
1237c375e22SDmitry Fleytman             } upper;
1247c375e22SDmitry Fleytman         } wb;
1257c375e22SDmitry Fleytman     } descr;
1267c375e22SDmitry Fleytman 
1277c375e22SDmitry Fleytman     static const uint32_t esta_dd = BIT(0);
1287c375e22SDmitry Fleytman 
1297c375e22SDmitry Fleytman     char test[] = "TEST";
1307c375e22SDmitry Fleytman     int len = htonl(sizeof(test));
1317c375e22SDmitry Fleytman     struct iovec iov[] = {
1327c375e22SDmitry Fleytman         {
1337c375e22SDmitry Fleytman             .iov_base = &len,
1347c375e22SDmitry Fleytman             .iov_len = sizeof(len),
1357c375e22SDmitry Fleytman         },{
1367c375e22SDmitry Fleytman             .iov_base = test,
1377c375e22SDmitry Fleytman             .iov_len = sizeof(test),
1387c375e22SDmitry Fleytman         },
1397c375e22SDmitry Fleytman     };
1407c375e22SDmitry Fleytman 
1417c375e22SDmitry Fleytman     static const int data_len = 64;
1427c375e22SDmitry Fleytman     char buffer[64];
1437c375e22SDmitry Fleytman     int ret;
1447c375e22SDmitry Fleytman 
1457c375e22SDmitry Fleytman     /* Send a dummy packet to device's socket*/
1467c375e22SDmitry Fleytman     ret = iov_send(test_sockets[0], iov, 2, 0, sizeof(len) + sizeof(test));
1477c375e22SDmitry Fleytman     g_assert_cmpint(ret, == , sizeof(test) + sizeof(len));
1487c375e22SDmitry Fleytman 
1497c375e22SDmitry Fleytman     /* Prepare test data buffer */
150*b026393cSEmanuele Giuseppe Esposito     uint64_t data = guest_alloc(alloc, data_len);
1517c375e22SDmitry Fleytman 
1527c375e22SDmitry Fleytman     /* Prepare RX descriptor */
1537c375e22SDmitry Fleytman     memset(&descr, 0, sizeof(descr));
1547c375e22SDmitry Fleytman     descr.read.buffer_addr = cpu_to_le64(data);
1557c375e22SDmitry Fleytman 
1567c375e22SDmitry Fleytman     /* Put descriptor to the ring */
1577c375e22SDmitry Fleytman     e1000e_rx_ring_push(d, &descr);
1587c375e22SDmitry Fleytman 
1597c375e22SDmitry Fleytman     /* Wait for TX WB interrupt */
1607c375e22SDmitry Fleytman     e1000e_wait_isr(d, E1000E_RX0_MSG_ID);
1617c375e22SDmitry Fleytman 
1627c375e22SDmitry Fleytman     /* Check DD bit */
1637c375e22SDmitry Fleytman     g_assert_cmphex(le32_to_cpu(descr.wb.upper.status_error) &
1647c375e22SDmitry Fleytman         esta_dd, ==, esta_dd);
1657c375e22SDmitry Fleytman 
1667c375e22SDmitry Fleytman     /* Check data sent to the backend */
1677c375e22SDmitry Fleytman     memread(data, buffer, sizeof(buffer));
1687c375e22SDmitry Fleytman     g_assert_cmpstr(buffer, == , "TEST");
1697c375e22SDmitry Fleytman 
1707c375e22SDmitry Fleytman     /* Free test data buffer */
171*b026393cSEmanuele Giuseppe Esposito     guest_free(alloc, data);
1727c375e22SDmitry Fleytman }
1737c375e22SDmitry Fleytman 
174*b026393cSEmanuele Giuseppe Esposito static void test_e1000e_init(void *obj, void *data, QGuestAllocator * alloc)
1757c375e22SDmitry Fleytman {
176*b026393cSEmanuele Giuseppe Esposito     /* init does nothing */
1777c375e22SDmitry Fleytman }
1787c375e22SDmitry Fleytman 
179*b026393cSEmanuele Giuseppe Esposito static void test_e1000e_tx(void *obj, void *data, QGuestAllocator * alloc)
1807c375e22SDmitry Fleytman {
181*b026393cSEmanuele Giuseppe Esposito     QE1000E_PCI *e1000e = obj;
182*b026393cSEmanuele Giuseppe Esposito     QE1000E *d = &e1000e->e1000e;
183*b026393cSEmanuele Giuseppe Esposito     QOSGraphObject *e_object = obj;
184*b026393cSEmanuele Giuseppe Esposito     QPCIDevice *dev = e_object->get_driver(e_object, "pci-device");
1857c375e22SDmitry Fleytman 
186*b026393cSEmanuele Giuseppe Esposito     /* FIXME: add spapr support */
187*b026393cSEmanuele Giuseppe Esposito     if (qpci_check_buggy_msi(dev)) {
188*b026393cSEmanuele Giuseppe Esposito         return;
1897c375e22SDmitry Fleytman     }
1907c375e22SDmitry Fleytman 
191*b026393cSEmanuele Giuseppe Esposito     e1000e_send_verify(d, data, alloc);
192*b026393cSEmanuele Giuseppe Esposito }
193*b026393cSEmanuele Giuseppe Esposito 
194*b026393cSEmanuele Giuseppe Esposito static void test_e1000e_rx(void *obj, void *data, QGuestAllocator * alloc)
1957c375e22SDmitry Fleytman {
196*b026393cSEmanuele Giuseppe Esposito     QE1000E_PCI *e1000e = obj;
197*b026393cSEmanuele Giuseppe Esposito     QE1000E *d = &e1000e->e1000e;
198*b026393cSEmanuele Giuseppe Esposito     QOSGraphObject *e_object = obj;
199*b026393cSEmanuele Giuseppe Esposito     QPCIDevice *dev = e_object->get_driver(e_object, "pci-device");
200*b026393cSEmanuele Giuseppe Esposito 
201*b026393cSEmanuele Giuseppe Esposito     /* FIXME: add spapr support */
202*b026393cSEmanuele Giuseppe Esposito     if (qpci_check_buggy_msi(dev)) {
203*b026393cSEmanuele Giuseppe Esposito         return;
2047c375e22SDmitry Fleytman     }
2057c375e22SDmitry Fleytman 
206*b026393cSEmanuele Giuseppe Esposito     e1000e_receive_verify(d, data, alloc);
2077c375e22SDmitry Fleytman }
2087c375e22SDmitry Fleytman 
209*b026393cSEmanuele Giuseppe Esposito static void test_e1000e_multiple_transfers(void *obj, void *data,
210*b026393cSEmanuele Giuseppe Esposito                                            QGuestAllocator *alloc)
2117c375e22SDmitry Fleytman {
2127c375e22SDmitry Fleytman     static const long iterations = 4 * 1024;
2137c375e22SDmitry Fleytman     long i;
2147c375e22SDmitry Fleytman 
215*b026393cSEmanuele Giuseppe Esposito     QE1000E_PCI *e1000e = obj;
216*b026393cSEmanuele Giuseppe Esposito     QE1000E *d = &e1000e->e1000e;
217*b026393cSEmanuele Giuseppe Esposito     QOSGraphObject *e_object = obj;
218*b026393cSEmanuele Giuseppe Esposito     QPCIDevice *dev = e_object->get_driver(e_object, "pci-device");
2197c375e22SDmitry Fleytman 
220*b026393cSEmanuele Giuseppe Esposito     /* FIXME: add spapr support */
221*b026393cSEmanuele Giuseppe Esposito     if (qpci_check_buggy_msi(dev)) {
222*b026393cSEmanuele Giuseppe Esposito         return;
223*b026393cSEmanuele Giuseppe Esposito     }
2247c375e22SDmitry Fleytman 
2257c375e22SDmitry Fleytman     for (i = 0; i < iterations; i++) {
226*b026393cSEmanuele Giuseppe Esposito         e1000e_send_verify(d, data, alloc);
227*b026393cSEmanuele Giuseppe Esposito         e1000e_receive_verify(d, data, alloc);
2287c375e22SDmitry Fleytman     }
2297c375e22SDmitry Fleytman 
2307c375e22SDmitry Fleytman }
2317c375e22SDmitry Fleytman 
232*b026393cSEmanuele Giuseppe Esposito static void test_e1000e_hotplug(void *obj, void *data, QGuestAllocator * alloc)
2337c375e22SDmitry Fleytman {
23482cab70bSMarkus Armbruster     qtest_qmp_device_add("e1000e", "e1000e_net", "{'addr': '0x06'}");
23582cab70bSMarkus Armbruster     qpci_unplug_acpi_device_test("e1000e_net", 0x06);
2367c375e22SDmitry Fleytman }
2377c375e22SDmitry Fleytman 
238*b026393cSEmanuele Giuseppe Esposito static void data_test_clear(void *sockets)
2397c375e22SDmitry Fleytman {
240*b026393cSEmanuele Giuseppe Esposito     int *test_sockets = sockets;
2417c375e22SDmitry Fleytman 
242*b026393cSEmanuele Giuseppe Esposito     close(test_sockets[0]);
243*b026393cSEmanuele Giuseppe Esposito     qos_invalidate_command_line();
244*b026393cSEmanuele Giuseppe Esposito     close(test_sockets[1]);
245*b026393cSEmanuele Giuseppe Esposito     g_free(test_sockets);
2467c375e22SDmitry Fleytman }
247*b026393cSEmanuele Giuseppe Esposito 
248*b026393cSEmanuele Giuseppe Esposito static void *data_test_init(GString *cmd_line, void *arg)
249*b026393cSEmanuele Giuseppe Esposito {
250*b026393cSEmanuele Giuseppe Esposito     int *test_sockets = g_new(int, 2);
251*b026393cSEmanuele Giuseppe Esposito     int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, test_sockets);
252*b026393cSEmanuele Giuseppe Esposito     g_assert_cmpint(ret, != , -1);
253*b026393cSEmanuele Giuseppe Esposito 
254*b026393cSEmanuele Giuseppe Esposito     g_string_append_printf(cmd_line, " -netdev socket,fd=%d,id=hs0 ",
255*b026393cSEmanuele Giuseppe Esposito                            test_sockets[1]);
256*b026393cSEmanuele Giuseppe Esposito 
257*b026393cSEmanuele Giuseppe Esposito     g_test_queue_destroy(data_test_clear, test_sockets);
258*b026393cSEmanuele Giuseppe Esposito     return test_sockets;
259*b026393cSEmanuele Giuseppe Esposito }
260*b026393cSEmanuele Giuseppe Esposito 
261*b026393cSEmanuele Giuseppe Esposito static void register_e1000e_test(void)
262*b026393cSEmanuele Giuseppe Esposito {
263*b026393cSEmanuele Giuseppe Esposito     QOSGraphTestOptions opts = {
264*b026393cSEmanuele Giuseppe Esposito         .before = data_test_init,
265*b026393cSEmanuele Giuseppe Esposito     };
266*b026393cSEmanuele Giuseppe Esposito 
267*b026393cSEmanuele Giuseppe Esposito     qos_add_test("init", "e1000e", test_e1000e_init, &opts);
268*b026393cSEmanuele Giuseppe Esposito     qos_add_test("tx", "e1000e", test_e1000e_tx, &opts);
269*b026393cSEmanuele Giuseppe Esposito     qos_add_test("rx", "e1000e", test_e1000e_rx, &opts);
270*b026393cSEmanuele Giuseppe Esposito     qos_add_test("multiple_transfers", "e1000e",
271*b026393cSEmanuele Giuseppe Esposito                       test_e1000e_multiple_transfers, &opts);
272*b026393cSEmanuele Giuseppe Esposito     qos_add_test("hotplug", "e1000e", test_e1000e_hotplug, &opts);
273*b026393cSEmanuele Giuseppe Esposito }
274*b026393cSEmanuele Giuseppe Esposito 
275*b026393cSEmanuele Giuseppe Esposito libqos_init(register_e1000e_test);
276