17e949c46SKenneth D. Merry /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni *
47e949c46SKenneth D. Merry * Copyright (c) 2009-2011 Spectra Logic Corporation
57e949c46SKenneth D. Merry * All rights reserved.
67e949c46SKenneth D. Merry *
77e949c46SKenneth D. Merry * Redistribution and use in source and binary forms, with or without
87e949c46SKenneth D. Merry * modification, are permitted provided that the following conditions
97e949c46SKenneth D. Merry * are met:
107e949c46SKenneth D. Merry * 1. Redistributions of source code must retain the above copyright
117e949c46SKenneth D. Merry * notice, this list of conditions, and the following disclaimer,
127e949c46SKenneth D. Merry * without modification.
137e949c46SKenneth D. Merry * 2. Redistributions in binary form must reproduce at minimum a disclaimer
147e949c46SKenneth D. Merry * substantially similar to the "NO WARRANTY" disclaimer below
157e949c46SKenneth D. Merry * ("Disclaimer") and any redistribution must be conditioned upon
167e949c46SKenneth D. Merry * including a substantially similar Disclaimer requirement for further
177e949c46SKenneth D. Merry * binary redistribution.
187e949c46SKenneth D. Merry *
197e949c46SKenneth D. Merry * NO WARRANTY
207e949c46SKenneth D. Merry * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
217e949c46SKenneth D. Merry * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
227e949c46SKenneth D. Merry * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
237e949c46SKenneth D. Merry * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
247e949c46SKenneth D. Merry * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
257e949c46SKenneth D. Merry * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
267e949c46SKenneth D. Merry * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
277e949c46SKenneth D. Merry * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
287e949c46SKenneth D. Merry * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
297e949c46SKenneth D. Merry * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
307e949c46SKenneth D. Merry * POSSIBILITY OF SUCH DAMAGES.
317e949c46SKenneth D. Merry *
327e949c46SKenneth D. Merry * Authors: Justin T. Gibbs (Spectra Logic Corporation)
337e949c46SKenneth D. Merry * Alan Somers (Spectra Logic Corporation)
347e949c46SKenneth D. Merry * John Suykerbuyk (Spectra Logic Corporation)
357e949c46SKenneth D. Merry */
367e949c46SKenneth D. Merry
377e949c46SKenneth D. Merry #include <sys/cdefs.h>
38*a8b70cf2SRichard Scheffenegger #include <netinet/tcp.h>
397e949c46SKenneth D. Merry /**
407e949c46SKenneth D. Merry * \file netback_unit_tests.c
417e949c46SKenneth D. Merry *
427e949c46SKenneth D. Merry * \brief Unit tests for the Xen netback driver.
437e949c46SKenneth D. Merry *
447e949c46SKenneth D. Merry * Due to the driver's use of static functions, these tests cannot be compiled
457e949c46SKenneth D. Merry * standalone; they must be #include'd from the driver's .c file.
467e949c46SKenneth D. Merry */
477e949c46SKenneth D. Merry
487e949c46SKenneth D. Merry /** Helper macro used to snprintf to a buffer and update the buffer pointer */
497e949c46SKenneth D. Merry #define SNCATF(buffer, buflen, ...) do { \
507e949c46SKenneth D. Merry size_t new_chars = snprintf(buffer, buflen, __VA_ARGS__); \
517e949c46SKenneth D. Merry buffer += new_chars; \
527e949c46SKenneth D. Merry /* be careful; snprintf's return value can be > buflen */ \
537e949c46SKenneth D. Merry buflen -= MIN(buflen, new_chars); \
547e949c46SKenneth D. Merry } while (0)
557e949c46SKenneth D. Merry
567e949c46SKenneth D. Merry /* STRINGIFY and TOSTRING are used only to help turn __LINE__ into a string */
577e949c46SKenneth D. Merry #define STRINGIFY(x) #x
587e949c46SKenneth D. Merry #define TOSTRING(x) STRINGIFY(x)
597e949c46SKenneth D. Merry
607e949c46SKenneth D. Merry /**
619c715a09SDimitry Andric * Writes an error message to buffer if cond is false
629c715a09SDimitry Andric * Note the implied parameters buffer and
637e949c46SKenneth D. Merry * buflen
647e949c46SKenneth D. Merry */
659c715a09SDimitry Andric #define XNB_ASSERT(cond) ({ \
667e949c46SKenneth D. Merry int passed = (cond); \
677e949c46SKenneth D. Merry char *_buffer = (buffer); \
687e949c46SKenneth D. Merry size_t _buflen = (buflen); \
697e949c46SKenneth D. Merry if (! passed) { \
707e949c46SKenneth D. Merry strlcat(_buffer, __func__, _buflen); \
717e949c46SKenneth D. Merry strlcat(_buffer, ":" TOSTRING(__LINE__) \
727e949c46SKenneth D. Merry " Assertion Error: " #cond "\n", _buflen); \
737e949c46SKenneth D. Merry } \
749c715a09SDimitry Andric })
757e949c46SKenneth D. Merry
767e949c46SKenneth D. Merry /**
777e949c46SKenneth D. Merry * The signature used by all testcases. If the test writes anything
787e949c46SKenneth D. Merry * to buffer, then it will be considered a failure
797e949c46SKenneth D. Merry * \param buffer Return storage for error messages
807e949c46SKenneth D. Merry * \param buflen The space available in the buffer
817e949c46SKenneth D. Merry */
827e949c46SKenneth D. Merry typedef void testcase_t(char *buffer, size_t buflen);
837e949c46SKenneth D. Merry
847e949c46SKenneth D. Merry /**
857e949c46SKenneth D. Merry * Signature used by setup functions
867e949c46SKenneth D. Merry * \return nonzero on error
877e949c46SKenneth D. Merry */
887e949c46SKenneth D. Merry typedef int setup_t(void);
897e949c46SKenneth D. Merry
907e949c46SKenneth D. Merry typedef void teardown_t(void);
917e949c46SKenneth D. Merry
927e949c46SKenneth D. Merry /** A simple test fixture comprising setup, teardown, and test */
937e949c46SKenneth D. Merry struct test_fixture {
947e949c46SKenneth D. Merry /** Will be run before the test to allocate and initialize variables */
957e949c46SKenneth D. Merry setup_t *setup;
967e949c46SKenneth D. Merry
977e949c46SKenneth D. Merry /** Will be run if setup succeeds */
987e949c46SKenneth D. Merry testcase_t *test;
997e949c46SKenneth D. Merry
100453130d9SPedro F. Giffuni /** Cleans up test data whether or not the setup succeeded */
1017e949c46SKenneth D. Merry teardown_t *teardown;
1027e949c46SKenneth D. Merry };
1037e949c46SKenneth D. Merry
1047e949c46SKenneth D. Merry typedef struct test_fixture test_fixture_t;
1057e949c46SKenneth D. Merry
1067e949c46SKenneth D. Merry static int xnb_get1pkt(struct xnb_pkt *pkt, size_t size, uint16_t flags);
1077e949c46SKenneth D. Merry static int xnb_unit_test_runner(test_fixture_t const tests[], int ntests,
1087e949c46SKenneth D. Merry char *buffer, size_t buflen);
1097e949c46SKenneth D. Merry
1107e949c46SKenneth D. Merry static int __unused
null_setup(void)1117e949c46SKenneth D. Merry null_setup(void) { return 0; }
1127e949c46SKenneth D. Merry
1137e949c46SKenneth D. Merry static void __unused
null_teardown(void)1147e949c46SKenneth D. Merry null_teardown(void) { }
1157e949c46SKenneth D. Merry
1167e949c46SKenneth D. Merry static setup_t setup_pvt_data;
1177e949c46SKenneth D. Merry static teardown_t teardown_pvt_data;
1187e949c46SKenneth D. Merry static testcase_t xnb_ring2pkt_emptyring;
1197e949c46SKenneth D. Merry static testcase_t xnb_ring2pkt_1req;
1207e949c46SKenneth D. Merry static testcase_t xnb_ring2pkt_2req;
1217e949c46SKenneth D. Merry static testcase_t xnb_ring2pkt_3req;
1227e949c46SKenneth D. Merry static testcase_t xnb_ring2pkt_extra;
1237e949c46SKenneth D. Merry static testcase_t xnb_ring2pkt_partial;
1247e949c46SKenneth D. Merry static testcase_t xnb_ring2pkt_wraps;
1257e949c46SKenneth D. Merry static testcase_t xnb_txpkt2rsp_emptypkt;
1267e949c46SKenneth D. Merry static testcase_t xnb_txpkt2rsp_1req;
1277e949c46SKenneth D. Merry static testcase_t xnb_txpkt2rsp_extra;
1287e949c46SKenneth D. Merry static testcase_t xnb_txpkt2rsp_long;
1297e949c46SKenneth D. Merry static testcase_t xnb_txpkt2rsp_invalid;
1307e949c46SKenneth D. Merry static testcase_t xnb_txpkt2rsp_error;
1317e949c46SKenneth D. Merry static testcase_t xnb_txpkt2rsp_wraps;
1327e949c46SKenneth D. Merry static testcase_t xnb_pkt2mbufc_empty;
1337e949c46SKenneth D. Merry static testcase_t xnb_pkt2mbufc_short;
1347e949c46SKenneth D. Merry static testcase_t xnb_pkt2mbufc_csum;
1357e949c46SKenneth D. Merry static testcase_t xnb_pkt2mbufc_1cluster;
1367e949c46SKenneth D. Merry static testcase_t xnb_pkt2mbufc_largecluster;
1377e949c46SKenneth D. Merry static testcase_t xnb_pkt2mbufc_2cluster;
1387e949c46SKenneth D. Merry static testcase_t xnb_txpkt2gnttab_empty;
1397e949c46SKenneth D. Merry static testcase_t xnb_txpkt2gnttab_short;
1407e949c46SKenneth D. Merry static testcase_t xnb_txpkt2gnttab_2req;
1417e949c46SKenneth D. Merry static testcase_t xnb_txpkt2gnttab_2cluster;
1427e949c46SKenneth D. Merry static testcase_t xnb_update_mbufc_short;
1437e949c46SKenneth D. Merry static testcase_t xnb_update_mbufc_2req;
1447e949c46SKenneth D. Merry static testcase_t xnb_update_mbufc_2cluster;
1457e949c46SKenneth D. Merry static testcase_t xnb_mbufc2pkt_empty;
1467e949c46SKenneth D. Merry static testcase_t xnb_mbufc2pkt_short;
1477e949c46SKenneth D. Merry static testcase_t xnb_mbufc2pkt_1cluster;
1487e949c46SKenneth D. Merry static testcase_t xnb_mbufc2pkt_2short;
1497e949c46SKenneth D. Merry static testcase_t xnb_mbufc2pkt_long;
1507e949c46SKenneth D. Merry static testcase_t xnb_mbufc2pkt_extra;
1517e949c46SKenneth D. Merry static testcase_t xnb_mbufc2pkt_nospace;
1527e949c46SKenneth D. Merry static testcase_t xnb_rxpkt2gnttab_empty;
1537e949c46SKenneth D. Merry static testcase_t xnb_rxpkt2gnttab_short;
1547e949c46SKenneth D. Merry static testcase_t xnb_rxpkt2gnttab_2req;
1557e949c46SKenneth D. Merry static testcase_t xnb_rxpkt2rsp_empty;
1567e949c46SKenneth D. Merry static testcase_t xnb_rxpkt2rsp_short;
1577e949c46SKenneth D. Merry static testcase_t xnb_rxpkt2rsp_extra;
1587e949c46SKenneth D. Merry static testcase_t xnb_rxpkt2rsp_2short;
1597e949c46SKenneth D. Merry static testcase_t xnb_rxpkt2rsp_2slots;
1607e949c46SKenneth D. Merry static testcase_t xnb_rxpkt2rsp_copyerror;
161f909bbb4SGleb Smirnoff static testcase_t xnb_sscanf_llu;
162f909bbb4SGleb Smirnoff static testcase_t xnb_sscanf_lld;
163f909bbb4SGleb Smirnoff static testcase_t xnb_sscanf_hhu;
164f909bbb4SGleb Smirnoff static testcase_t xnb_sscanf_hhd;
165f909bbb4SGleb Smirnoff static testcase_t xnb_sscanf_hhn;
166f909bbb4SGleb Smirnoff
167f909bbb4SGleb Smirnoff #if defined(INET) || defined(INET6)
1687e949c46SKenneth D. Merry /* TODO: add test cases for xnb_add_mbuf_cksum for IPV6 tcp and udp */
1697e949c46SKenneth D. Merry static testcase_t xnb_add_mbuf_cksum_arp;
1707e949c46SKenneth D. Merry static testcase_t xnb_add_mbuf_cksum_tcp;
1717e949c46SKenneth D. Merry static testcase_t xnb_add_mbuf_cksum_udp;
1727e949c46SKenneth D. Merry static testcase_t xnb_add_mbuf_cksum_icmp;
1737e949c46SKenneth D. Merry static testcase_t xnb_add_mbuf_cksum_tcp_swcksum;
174f909bbb4SGleb Smirnoff static void xnb_fill_eh_and_ip(struct mbuf *m, uint16_t ip_len,
175f909bbb4SGleb Smirnoff uint16_t ip_id, uint16_t ip_p,
176f909bbb4SGleb Smirnoff uint16_t ip_off, uint16_t ip_sum);
177f909bbb4SGleb Smirnoff static void xnb_fill_tcp(struct mbuf *m);
178f909bbb4SGleb Smirnoff #endif /* INET || INET6 */
1797e949c46SKenneth D. Merry
1807e949c46SKenneth D. Merry /** Private data used by unit tests */
1817e949c46SKenneth D. Merry static struct {
1827e949c46SKenneth D. Merry gnttab_copy_table gnttab;
1837e949c46SKenneth D. Merry netif_rx_back_ring_t rxb;
1847e949c46SKenneth D. Merry netif_rx_front_ring_t rxf;
1857e949c46SKenneth D. Merry netif_tx_back_ring_t txb;
1867e949c46SKenneth D. Merry netif_tx_front_ring_t txf;
1877e949c46SKenneth D. Merry struct ifnet* ifp;
1887e949c46SKenneth D. Merry netif_rx_sring_t* rxs;
1897e949c46SKenneth D. Merry netif_tx_sring_t* txs;
1907e949c46SKenneth D. Merry } xnb_unit_pvt;
1917e949c46SKenneth D. Merry
safe_m_freem(struct mbuf ** ppMbuf)1927e949c46SKenneth D. Merry static inline void safe_m_freem(struct mbuf **ppMbuf) {
1937e949c46SKenneth D. Merry if (*ppMbuf != NULL) {
1947e949c46SKenneth D. Merry m_freem(*ppMbuf);
1957e949c46SKenneth D. Merry *ppMbuf = NULL;
1967e949c46SKenneth D. Merry }
1977e949c46SKenneth D. Merry }
1987e949c46SKenneth D. Merry
1997e949c46SKenneth D. Merry /**
2007e949c46SKenneth D. Merry * The unit test runner. It will run every supplied test and return an
2017e949c46SKenneth D. Merry * output message as a string
2027e949c46SKenneth D. Merry * \param tests An array of tests. Every test will be attempted.
2037e949c46SKenneth D. Merry * \param ntests The length of tests
2047e949c46SKenneth D. Merry * \param buffer Return storage for the result string
2057e949c46SKenneth D. Merry * \param buflen The length of buffer
2067e949c46SKenneth D. Merry * \return The number of tests that failed
2077e949c46SKenneth D. Merry */
2087e949c46SKenneth D. Merry static int
xnb_unit_test_runner(test_fixture_t const tests[],int ntests,char * buffer,size_t buflen)2097e949c46SKenneth D. Merry xnb_unit_test_runner(test_fixture_t const tests[], int ntests, char *buffer,
2107e949c46SKenneth D. Merry size_t buflen)
2117e949c46SKenneth D. Merry {
2127e949c46SKenneth D. Merry int i;
2137e949c46SKenneth D. Merry int n_passes;
2147e949c46SKenneth D. Merry int n_failures = 0;
2157e949c46SKenneth D. Merry
2167e949c46SKenneth D. Merry for (i = 0; i < ntests; i++) {
2177e949c46SKenneth D. Merry int error = tests[i].setup();
2187e949c46SKenneth D. Merry if (error != 0) {
2197e949c46SKenneth D. Merry SNCATF(buffer, buflen,
2207e949c46SKenneth D. Merry "Setup failed for test idx %d\n", i);
2217e949c46SKenneth D. Merry n_failures++;
2227e949c46SKenneth D. Merry } else {
2237e949c46SKenneth D. Merry size_t new_chars;
2247e949c46SKenneth D. Merry
2257e949c46SKenneth D. Merry tests[i].test(buffer, buflen);
2267e949c46SKenneth D. Merry new_chars = strnlen(buffer, buflen);
2277e949c46SKenneth D. Merry buffer += new_chars;
2287e949c46SKenneth D. Merry buflen -= new_chars;
2297e949c46SKenneth D. Merry
2307e949c46SKenneth D. Merry if (new_chars > 0) {
2317e949c46SKenneth D. Merry n_failures++;
2327e949c46SKenneth D. Merry }
2337e949c46SKenneth D. Merry }
2347e949c46SKenneth D. Merry tests[i].teardown();
2357e949c46SKenneth D. Merry }
2367e949c46SKenneth D. Merry
2377e949c46SKenneth D. Merry n_passes = ntests - n_failures;
2387e949c46SKenneth D. Merry if (n_passes > 0) {
2397e949c46SKenneth D. Merry SNCATF(buffer, buflen, "%d Tests Passed\n", n_passes);
2407e949c46SKenneth D. Merry }
2417e949c46SKenneth D. Merry if (n_failures > 0) {
2427e949c46SKenneth D. Merry SNCATF(buffer, buflen, "%d Tests FAILED\n", n_failures);
2437e949c46SKenneth D. Merry }
2447e949c46SKenneth D. Merry
2457e949c46SKenneth D. Merry return n_failures;
2467e949c46SKenneth D. Merry }
2477e949c46SKenneth D. Merry
2487e949c46SKenneth D. Merry /** Number of unit tests. Must match the length of the tests array below */
2497e949c46SKenneth D. Merry #define TOTAL_TESTS (53)
2507e949c46SKenneth D. Merry /**
2517e949c46SKenneth D. Merry * Max memory available for returning results. 400 chars/test should give
2527e949c46SKenneth D. Merry * enough space for a five line error message for every test
2537e949c46SKenneth D. Merry */
2547e949c46SKenneth D. Merry #define TOTAL_BUFLEN (400 * TOTAL_TESTS + 2)
2557e949c46SKenneth D. Merry
2567e949c46SKenneth D. Merry /**
2577e949c46SKenneth D. Merry * Called from userspace by a sysctl. Runs all internal unit tests, and
2587e949c46SKenneth D. Merry * returns the results to userspace as a string
2597e949c46SKenneth D. Merry * \param oidp unused
2607e949c46SKenneth D. Merry * \param arg1 pointer to an xnb_softc for a specific xnb device
2617e949c46SKenneth D. Merry * \param arg2 unused
2627e949c46SKenneth D. Merry * \param req sysctl access structure
2637e949c46SKenneth D. Merry * \return a string via the special SYSCTL_OUT macro.
2647e949c46SKenneth D. Merry */
2657e949c46SKenneth D. Merry
2667e949c46SKenneth D. Merry static int
xnb_unit_test_main(SYSCTL_HANDLER_ARGS)2677e949c46SKenneth D. Merry xnb_unit_test_main(SYSCTL_HANDLER_ARGS) {
2687e949c46SKenneth D. Merry test_fixture_t const tests[TOTAL_TESTS] = {
2697e949c46SKenneth D. Merry {setup_pvt_data, xnb_ring2pkt_emptyring, teardown_pvt_data},
2707e949c46SKenneth D. Merry {setup_pvt_data, xnb_ring2pkt_1req, teardown_pvt_data},
2717e949c46SKenneth D. Merry {setup_pvt_data, xnb_ring2pkt_2req, teardown_pvt_data},
2727e949c46SKenneth D. Merry {setup_pvt_data, xnb_ring2pkt_3req, teardown_pvt_data},
2737e949c46SKenneth D. Merry {setup_pvt_data, xnb_ring2pkt_extra, teardown_pvt_data},
2747e949c46SKenneth D. Merry {setup_pvt_data, xnb_ring2pkt_partial, teardown_pvt_data},
2757e949c46SKenneth D. Merry {setup_pvt_data, xnb_ring2pkt_wraps, teardown_pvt_data},
2767e949c46SKenneth D. Merry {setup_pvt_data, xnb_txpkt2rsp_emptypkt, teardown_pvt_data},
2777e949c46SKenneth D. Merry {setup_pvt_data, xnb_txpkt2rsp_1req, teardown_pvt_data},
2787e949c46SKenneth D. Merry {setup_pvt_data, xnb_txpkt2rsp_extra, teardown_pvt_data},
2797e949c46SKenneth D. Merry {setup_pvt_data, xnb_txpkt2rsp_long, teardown_pvt_data},
2807e949c46SKenneth D. Merry {setup_pvt_data, xnb_txpkt2rsp_invalid, teardown_pvt_data},
2817e949c46SKenneth D. Merry {setup_pvt_data, xnb_txpkt2rsp_error, teardown_pvt_data},
2827e949c46SKenneth D. Merry {setup_pvt_data, xnb_txpkt2rsp_wraps, teardown_pvt_data},
2837e949c46SKenneth D. Merry {setup_pvt_data, xnb_pkt2mbufc_empty, teardown_pvt_data},
2847e949c46SKenneth D. Merry {setup_pvt_data, xnb_pkt2mbufc_short, teardown_pvt_data},
2857e949c46SKenneth D. Merry {setup_pvt_data, xnb_pkt2mbufc_csum, teardown_pvt_data},
2867e949c46SKenneth D. Merry {setup_pvt_data, xnb_pkt2mbufc_1cluster, teardown_pvt_data},
2877e949c46SKenneth D. Merry {setup_pvt_data, xnb_pkt2mbufc_largecluster, teardown_pvt_data},
2887e949c46SKenneth D. Merry {setup_pvt_data, xnb_pkt2mbufc_2cluster, teardown_pvt_data},
2897e949c46SKenneth D. Merry {setup_pvt_data, xnb_txpkt2gnttab_empty, teardown_pvt_data},
2907e949c46SKenneth D. Merry {setup_pvt_data, xnb_txpkt2gnttab_short, teardown_pvt_data},
2917e949c46SKenneth D. Merry {setup_pvt_data, xnb_txpkt2gnttab_2req, teardown_pvt_data},
2927e949c46SKenneth D. Merry {setup_pvt_data, xnb_txpkt2gnttab_2cluster, teardown_pvt_data},
2937e949c46SKenneth D. Merry {setup_pvt_data, xnb_update_mbufc_short, teardown_pvt_data},
2947e949c46SKenneth D. Merry {setup_pvt_data, xnb_update_mbufc_2req, teardown_pvt_data},
2957e949c46SKenneth D. Merry {setup_pvt_data, xnb_update_mbufc_2cluster, teardown_pvt_data},
2967e949c46SKenneth D. Merry {setup_pvt_data, xnb_mbufc2pkt_empty, teardown_pvt_data},
2977e949c46SKenneth D. Merry {setup_pvt_data, xnb_mbufc2pkt_short, teardown_pvt_data},
2987e949c46SKenneth D. Merry {setup_pvt_data, xnb_mbufc2pkt_1cluster, teardown_pvt_data},
2997e949c46SKenneth D. Merry {setup_pvt_data, xnb_mbufc2pkt_2short, teardown_pvt_data},
3007e949c46SKenneth D. Merry {setup_pvt_data, xnb_mbufc2pkt_long, teardown_pvt_data},
3017e949c46SKenneth D. Merry {setup_pvt_data, xnb_mbufc2pkt_extra, teardown_pvt_data},
3027e949c46SKenneth D. Merry {setup_pvt_data, xnb_mbufc2pkt_nospace, teardown_pvt_data},
3037e949c46SKenneth D. Merry {setup_pvt_data, xnb_rxpkt2gnttab_empty, teardown_pvt_data},
3047e949c46SKenneth D. Merry {setup_pvt_data, xnb_rxpkt2gnttab_short, teardown_pvt_data},
3057e949c46SKenneth D. Merry {setup_pvt_data, xnb_rxpkt2gnttab_2req, teardown_pvt_data},
3067e949c46SKenneth D. Merry {setup_pvt_data, xnb_rxpkt2rsp_empty, teardown_pvt_data},
3077e949c46SKenneth D. Merry {setup_pvt_data, xnb_rxpkt2rsp_short, teardown_pvt_data},
3087e949c46SKenneth D. Merry {setup_pvt_data, xnb_rxpkt2rsp_extra, teardown_pvt_data},
3097e949c46SKenneth D. Merry {setup_pvt_data, xnb_rxpkt2rsp_2short, teardown_pvt_data},
3107e949c46SKenneth D. Merry {setup_pvt_data, xnb_rxpkt2rsp_2slots, teardown_pvt_data},
3117e949c46SKenneth D. Merry {setup_pvt_data, xnb_rxpkt2rsp_copyerror, teardown_pvt_data},
312f909bbb4SGleb Smirnoff #if defined(INET) || defined(INET6)
3137e949c46SKenneth D. Merry {null_setup, xnb_add_mbuf_cksum_arp, null_teardown},
3147e949c46SKenneth D. Merry {null_setup, xnb_add_mbuf_cksum_icmp, null_teardown},
3157e949c46SKenneth D. Merry {null_setup, xnb_add_mbuf_cksum_tcp, null_teardown},
3167e949c46SKenneth D. Merry {null_setup, xnb_add_mbuf_cksum_tcp_swcksum, null_teardown},
3177e949c46SKenneth D. Merry {null_setup, xnb_add_mbuf_cksum_udp, null_teardown},
318f909bbb4SGleb Smirnoff #endif
3197e949c46SKenneth D. Merry {null_setup, xnb_sscanf_hhd, null_teardown},
3207e949c46SKenneth D. Merry {null_setup, xnb_sscanf_hhu, null_teardown},
3217e949c46SKenneth D. Merry {null_setup, xnb_sscanf_lld, null_teardown},
3227e949c46SKenneth D. Merry {null_setup, xnb_sscanf_llu, null_teardown},
3237e949c46SKenneth D. Merry {null_setup, xnb_sscanf_hhn, null_teardown},
3247e949c46SKenneth D. Merry };
3257e949c46SKenneth D. Merry /**
3267e949c46SKenneth D. Merry * results is static so that the data will persist after this function
3277e949c46SKenneth D. Merry * returns. The sysctl code expects us to return a constant string.
3287e949c46SKenneth D. Merry * \todo: the static variable is not thread safe. Put a mutex around
3297e949c46SKenneth D. Merry * it.
3307e949c46SKenneth D. Merry */
3317e949c46SKenneth D. Merry static char results[TOTAL_BUFLEN];
3327e949c46SKenneth D. Merry
3337e949c46SKenneth D. Merry /* empty the result strings */
3347e949c46SKenneth D. Merry results[0] = 0;
3357e949c46SKenneth D. Merry xnb_unit_test_runner(tests, TOTAL_TESTS, results, TOTAL_BUFLEN);
3367e949c46SKenneth D. Merry
3377e949c46SKenneth D. Merry return (SYSCTL_OUT(req, results, strnlen(results, TOTAL_BUFLEN)));
3387e949c46SKenneth D. Merry }
3397e949c46SKenneth D. Merry
3407e949c46SKenneth D. Merry static int
setup_pvt_data(void)3417e949c46SKenneth D. Merry setup_pvt_data(void)
3427e949c46SKenneth D. Merry {
3437e949c46SKenneth D. Merry int error = 0;
3447e949c46SKenneth D. Merry
3457e949c46SKenneth D. Merry bzero(xnb_unit_pvt.gnttab, sizeof(xnb_unit_pvt.gnttab));
3467e949c46SKenneth D. Merry
3477e949c46SKenneth D. Merry xnb_unit_pvt.txs = malloc(PAGE_SIZE, M_XENNETBACK, M_WAITOK|M_ZERO);
3487e949c46SKenneth D. Merry if (xnb_unit_pvt.txs != NULL) {
3497e949c46SKenneth D. Merry SHARED_RING_INIT(xnb_unit_pvt.txs);
3507e949c46SKenneth D. Merry BACK_RING_INIT(&xnb_unit_pvt.txb, xnb_unit_pvt.txs, PAGE_SIZE);
3517e949c46SKenneth D. Merry FRONT_RING_INIT(&xnb_unit_pvt.txf, xnb_unit_pvt.txs, PAGE_SIZE);
3527e949c46SKenneth D. Merry } else {
3537e949c46SKenneth D. Merry error = 1;
3547e949c46SKenneth D. Merry }
3557e949c46SKenneth D. Merry
3567e949c46SKenneth D. Merry xnb_unit_pvt.ifp = if_alloc(IFT_ETHER);
3577e949c46SKenneth D. Merry if (xnb_unit_pvt.ifp == NULL) {
3587e949c46SKenneth D. Merry error = 1;
3597e949c46SKenneth D. Merry }
3607e949c46SKenneth D. Merry
3617e949c46SKenneth D. Merry xnb_unit_pvt.rxs = malloc(PAGE_SIZE, M_XENNETBACK, M_WAITOK|M_ZERO);
3627e949c46SKenneth D. Merry if (xnb_unit_pvt.rxs != NULL) {
3637e949c46SKenneth D. Merry SHARED_RING_INIT(xnb_unit_pvt.rxs);
3647e949c46SKenneth D. Merry BACK_RING_INIT(&xnb_unit_pvt.rxb, xnb_unit_pvt.rxs, PAGE_SIZE);
3657e949c46SKenneth D. Merry FRONT_RING_INIT(&xnb_unit_pvt.rxf, xnb_unit_pvt.rxs, PAGE_SIZE);
3667e949c46SKenneth D. Merry } else {
3677e949c46SKenneth D. Merry error = 1;
3687e949c46SKenneth D. Merry }
3697e949c46SKenneth D. Merry
3707e949c46SKenneth D. Merry return error;
3717e949c46SKenneth D. Merry }
3727e949c46SKenneth D. Merry
3737e949c46SKenneth D. Merry static void
teardown_pvt_data(void)3747e949c46SKenneth D. Merry teardown_pvt_data(void)
3757e949c46SKenneth D. Merry {
3767e949c46SKenneth D. Merry if (xnb_unit_pvt.txs != NULL) {
3777e949c46SKenneth D. Merry free(xnb_unit_pvt.txs, M_XENNETBACK);
3787e949c46SKenneth D. Merry }
3797e949c46SKenneth D. Merry if (xnb_unit_pvt.rxs != NULL) {
3807e949c46SKenneth D. Merry free(xnb_unit_pvt.rxs, M_XENNETBACK);
3817e949c46SKenneth D. Merry }
3827e949c46SKenneth D. Merry if (xnb_unit_pvt.ifp != NULL) {
3837e949c46SKenneth D. Merry if_free(xnb_unit_pvt.ifp);
3847e949c46SKenneth D. Merry }
3857e949c46SKenneth D. Merry }
3867e949c46SKenneth D. Merry
3877e949c46SKenneth D. Merry /**
3887e949c46SKenneth D. Merry * Verify that xnb_ring2pkt will not consume any requests from an empty ring
3897e949c46SKenneth D. Merry */
3907e949c46SKenneth D. Merry static void
xnb_ring2pkt_emptyring(char * buffer,size_t buflen)3917e949c46SKenneth D. Merry xnb_ring2pkt_emptyring(char *buffer, size_t buflen)
3927e949c46SKenneth D. Merry {
3937e949c46SKenneth D. Merry struct xnb_pkt pkt;
3947e949c46SKenneth D. Merry int num_consumed;
3957e949c46SKenneth D. Merry
3967e949c46SKenneth D. Merry num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
3977e949c46SKenneth D. Merry xnb_unit_pvt.txb.req_cons);
3987e949c46SKenneth D. Merry XNB_ASSERT(num_consumed == 0);
3997e949c46SKenneth D. Merry }
4007e949c46SKenneth D. Merry
4017e949c46SKenneth D. Merry /**
4027e949c46SKenneth D. Merry * Verify that xnb_ring2pkt can convert a single request packet correctly
4037e949c46SKenneth D. Merry */
4047e949c46SKenneth D. Merry static void
xnb_ring2pkt_1req(char * buffer,size_t buflen)4057e949c46SKenneth D. Merry xnb_ring2pkt_1req(char *buffer, size_t buflen)
4067e949c46SKenneth D. Merry {
4077e949c46SKenneth D. Merry struct xnb_pkt pkt;
4087e949c46SKenneth D. Merry int num_consumed;
4097e949c46SKenneth D. Merry struct netif_tx_request *req;
4107e949c46SKenneth D. Merry
4117e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
4127e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
4137e949c46SKenneth D. Merry
4147e949c46SKenneth D. Merry req->flags = 0;
4157e949c46SKenneth D. Merry req->size = 69; /* arbitrary number for test */
4167e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
4177e949c46SKenneth D. Merry
4187e949c46SKenneth D. Merry RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
4197e949c46SKenneth D. Merry
4207e949c46SKenneth D. Merry num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
4217e949c46SKenneth D. Merry xnb_unit_pvt.txb.req_cons);
4227e949c46SKenneth D. Merry XNB_ASSERT(num_consumed == 1);
4237e949c46SKenneth D. Merry XNB_ASSERT(pkt.size == 69);
4247e949c46SKenneth D. Merry XNB_ASSERT(pkt.car_size == 69);
4257e949c46SKenneth D. Merry XNB_ASSERT(pkt.flags == 0);
4267e949c46SKenneth D. Merry XNB_ASSERT(xnb_pkt_is_valid(&pkt));
4277e949c46SKenneth D. Merry XNB_ASSERT(pkt.list_len == 1);
4287e949c46SKenneth D. Merry XNB_ASSERT(pkt.car == 0);
4297e949c46SKenneth D. Merry }
4307e949c46SKenneth D. Merry
4317e949c46SKenneth D. Merry /**
4327e949c46SKenneth D. Merry * Verify that xnb_ring2pkt can convert a two request packet correctly.
4337e949c46SKenneth D. Merry * This tests handling of the MORE_DATA flag and cdr
4347e949c46SKenneth D. Merry */
4357e949c46SKenneth D. Merry static void
xnb_ring2pkt_2req(char * buffer,size_t buflen)4367e949c46SKenneth D. Merry xnb_ring2pkt_2req(char *buffer, size_t buflen)
4377e949c46SKenneth D. Merry {
4387e949c46SKenneth D. Merry struct xnb_pkt pkt;
4397e949c46SKenneth D. Merry int num_consumed;
4407e949c46SKenneth D. Merry struct netif_tx_request *req;
4417e949c46SKenneth D. Merry RING_IDX start_idx = xnb_unit_pvt.txf.req_prod_pvt;
4427e949c46SKenneth D. Merry
4437e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
4447e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
4457e949c46SKenneth D. Merry req->flags = NETTXF_more_data;
4467e949c46SKenneth D. Merry req->size = 100;
4477e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
4487e949c46SKenneth D. Merry
4497e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
4507e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
4517e949c46SKenneth D. Merry req->flags = 0;
4527e949c46SKenneth D. Merry req->size = 40;
4537e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
4547e949c46SKenneth D. Merry
4557e949c46SKenneth D. Merry RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
4567e949c46SKenneth D. Merry
4577e949c46SKenneth D. Merry num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
4587e949c46SKenneth D. Merry xnb_unit_pvt.txb.req_cons);
4597e949c46SKenneth D. Merry XNB_ASSERT(num_consumed == 2);
4607e949c46SKenneth D. Merry XNB_ASSERT(pkt.size == 100);
4617e949c46SKenneth D. Merry XNB_ASSERT(pkt.car_size == 60);
4627e949c46SKenneth D. Merry XNB_ASSERT(pkt.flags == 0);
4637e949c46SKenneth D. Merry XNB_ASSERT(xnb_pkt_is_valid(&pkt));
4647e949c46SKenneth D. Merry XNB_ASSERT(pkt.list_len == 2);
4657e949c46SKenneth D. Merry XNB_ASSERT(pkt.car == start_idx);
4667e949c46SKenneth D. Merry XNB_ASSERT(pkt.cdr == start_idx + 1);
4677e949c46SKenneth D. Merry }
4687e949c46SKenneth D. Merry
4697e949c46SKenneth D. Merry /**
4707e949c46SKenneth D. Merry * Verify that xnb_ring2pkt can convert a three request packet correctly
4717e949c46SKenneth D. Merry */
4727e949c46SKenneth D. Merry static void
xnb_ring2pkt_3req(char * buffer,size_t buflen)4737e949c46SKenneth D. Merry xnb_ring2pkt_3req(char *buffer, size_t buflen)
4747e949c46SKenneth D. Merry {
4757e949c46SKenneth D. Merry struct xnb_pkt pkt;
4767e949c46SKenneth D. Merry int num_consumed;
4777e949c46SKenneth D. Merry struct netif_tx_request *req;
4787e949c46SKenneth D. Merry RING_IDX start_idx = xnb_unit_pvt.txf.req_prod_pvt;
4797e949c46SKenneth D. Merry
4807e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
4817e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
4827e949c46SKenneth D. Merry req->flags = NETTXF_more_data;
4837e949c46SKenneth D. Merry req->size = 200;
4847e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
4857e949c46SKenneth D. Merry
4867e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
4877e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
4887e949c46SKenneth D. Merry req->flags = NETTXF_more_data;
4897e949c46SKenneth D. Merry req->size = 40;
4907e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
4917e949c46SKenneth D. Merry
4927e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
4937e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
4947e949c46SKenneth D. Merry req->flags = 0;
4957e949c46SKenneth D. Merry req->size = 50;
4967e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
4977e949c46SKenneth D. Merry
4987e949c46SKenneth D. Merry RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
4997e949c46SKenneth D. Merry
5007e949c46SKenneth D. Merry num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
5017e949c46SKenneth D. Merry xnb_unit_pvt.txb.req_cons);
5027e949c46SKenneth D. Merry XNB_ASSERT(num_consumed == 3);
5037e949c46SKenneth D. Merry XNB_ASSERT(pkt.size == 200);
5047e949c46SKenneth D. Merry XNB_ASSERT(pkt.car_size == 110);
5057e949c46SKenneth D. Merry XNB_ASSERT(pkt.flags == 0);
5067e949c46SKenneth D. Merry XNB_ASSERT(xnb_pkt_is_valid(&pkt));
5077e949c46SKenneth D. Merry XNB_ASSERT(pkt.list_len == 3);
5087e949c46SKenneth D. Merry XNB_ASSERT(pkt.car == start_idx);
5097e949c46SKenneth D. Merry XNB_ASSERT(pkt.cdr == start_idx + 1);
5107e949c46SKenneth D. Merry XNB_ASSERT(RING_GET_REQUEST(&xnb_unit_pvt.txb, pkt.cdr + 1) == req);
5117e949c46SKenneth D. Merry }
5127e949c46SKenneth D. Merry
5137e949c46SKenneth D. Merry /**
5147e949c46SKenneth D. Merry * Verify that xnb_ring2pkt can read extra inf
5157e949c46SKenneth D. Merry */
5167e949c46SKenneth D. Merry static void
xnb_ring2pkt_extra(char * buffer,size_t buflen)5177e949c46SKenneth D. Merry xnb_ring2pkt_extra(char *buffer, size_t buflen)
5187e949c46SKenneth D. Merry {
5197e949c46SKenneth D. Merry struct xnb_pkt pkt;
5207e949c46SKenneth D. Merry int num_consumed;
5217e949c46SKenneth D. Merry struct netif_tx_request *req;
5227e949c46SKenneth D. Merry struct netif_extra_info *ext;
5237e949c46SKenneth D. Merry RING_IDX start_idx = xnb_unit_pvt.txf.req_prod_pvt;
5247e949c46SKenneth D. Merry
5257e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
5267e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
5277e949c46SKenneth D. Merry req->flags = NETTXF_extra_info | NETTXF_more_data;
5287e949c46SKenneth D. Merry req->size = 150;
5297e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
5307e949c46SKenneth D. Merry
5317e949c46SKenneth D. Merry ext = (struct netif_extra_info*) RING_GET_REQUEST(&xnb_unit_pvt.txf,
5327e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
5337e949c46SKenneth D. Merry ext->flags = 0;
5347e949c46SKenneth D. Merry ext->type = XEN_NETIF_EXTRA_TYPE_GSO;
5357e949c46SKenneth D. Merry ext->u.gso.size = 250;
5367e949c46SKenneth D. Merry ext->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
5377e949c46SKenneth D. Merry ext->u.gso.features = 0;
5387e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
5397e949c46SKenneth D. Merry
5407e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
5417e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
5427e949c46SKenneth D. Merry req->flags = 0;
5437e949c46SKenneth D. Merry req->size = 50;
5447e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
5457e949c46SKenneth D. Merry
5467e949c46SKenneth D. Merry RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
5477e949c46SKenneth D. Merry
5487e949c46SKenneth D. Merry num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
5497e949c46SKenneth D. Merry xnb_unit_pvt.txb.req_cons);
5507e949c46SKenneth D. Merry XNB_ASSERT(num_consumed == 3);
5517e949c46SKenneth D. Merry XNB_ASSERT(pkt.extra.flags == 0);
5527e949c46SKenneth D. Merry XNB_ASSERT(pkt.extra.type == XEN_NETIF_EXTRA_TYPE_GSO);
5537e949c46SKenneth D. Merry XNB_ASSERT(pkt.extra.u.gso.size == 250);
5547e949c46SKenneth D. Merry XNB_ASSERT(pkt.extra.u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4);
5557e949c46SKenneth D. Merry XNB_ASSERT(pkt.size == 150);
5567e949c46SKenneth D. Merry XNB_ASSERT(pkt.car_size == 100);
5577e949c46SKenneth D. Merry XNB_ASSERT(pkt.flags == NETTXF_extra_info);
5587e949c46SKenneth D. Merry XNB_ASSERT(xnb_pkt_is_valid(&pkt));
5597e949c46SKenneth D. Merry XNB_ASSERT(pkt.list_len == 2);
5607e949c46SKenneth D. Merry XNB_ASSERT(pkt.car == start_idx);
5617e949c46SKenneth D. Merry XNB_ASSERT(pkt.cdr == start_idx + 2);
5627e949c46SKenneth D. Merry XNB_ASSERT(RING_GET_REQUEST(&xnb_unit_pvt.txb, pkt.cdr) == req);
5637e949c46SKenneth D. Merry }
5647e949c46SKenneth D. Merry
5657e949c46SKenneth D. Merry /**
5667e949c46SKenneth D. Merry * Verify that xnb_ring2pkt will consume no requests if the entire packet is
5677e949c46SKenneth D. Merry * not yet in the ring
5687e949c46SKenneth D. Merry */
5697e949c46SKenneth D. Merry static void
xnb_ring2pkt_partial(char * buffer,size_t buflen)5707e949c46SKenneth D. Merry xnb_ring2pkt_partial(char *buffer, size_t buflen)
5717e949c46SKenneth D. Merry {
5727e949c46SKenneth D. Merry struct xnb_pkt pkt;
5737e949c46SKenneth D. Merry int num_consumed;
5747e949c46SKenneth D. Merry struct netif_tx_request *req;
5757e949c46SKenneth D. Merry
5767e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
5777e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
5787e949c46SKenneth D. Merry req->flags = NETTXF_more_data;
5797e949c46SKenneth D. Merry req->size = 150;
5807e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
5817e949c46SKenneth D. Merry
5827e949c46SKenneth D. Merry RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
5837e949c46SKenneth D. Merry
5847e949c46SKenneth D. Merry num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
5857e949c46SKenneth D. Merry xnb_unit_pvt.txb.req_cons);
5867e949c46SKenneth D. Merry XNB_ASSERT(num_consumed == 0);
5877e949c46SKenneth D. Merry XNB_ASSERT(! xnb_pkt_is_valid(&pkt));
5887e949c46SKenneth D. Merry }
5897e949c46SKenneth D. Merry
5907e949c46SKenneth D. Merry /**
5917e949c46SKenneth D. Merry * Verity that xnb_ring2pkt can read a packet whose requests wrap around
5927e949c46SKenneth D. Merry * the end of the ring
5937e949c46SKenneth D. Merry */
5947e949c46SKenneth D. Merry static void
xnb_ring2pkt_wraps(char * buffer,size_t buflen)5957e949c46SKenneth D. Merry xnb_ring2pkt_wraps(char *buffer, size_t buflen)
5967e949c46SKenneth D. Merry {
5977e949c46SKenneth D. Merry struct xnb_pkt pkt;
5987e949c46SKenneth D. Merry int num_consumed;
5997e949c46SKenneth D. Merry struct netif_tx_request *req;
6007e949c46SKenneth D. Merry unsigned int rsize;
6017e949c46SKenneth D. Merry
6027e949c46SKenneth D. Merry /*
6037e949c46SKenneth D. Merry * Manually tweak the ring indices to create a ring with no responses
6047e949c46SKenneth D. Merry * and the next request slot at position 2 from the end
6057e949c46SKenneth D. Merry */
6067e949c46SKenneth D. Merry rsize = RING_SIZE(&xnb_unit_pvt.txf);
6077e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt = rsize - 2;
6087e949c46SKenneth D. Merry xnb_unit_pvt.txf.rsp_cons = rsize - 2;
6097e949c46SKenneth D. Merry xnb_unit_pvt.txs->req_prod = rsize - 2;
6107e949c46SKenneth D. Merry xnb_unit_pvt.txs->req_event = rsize - 1;
6117e949c46SKenneth D. Merry xnb_unit_pvt.txs->rsp_prod = rsize - 2;
6127e949c46SKenneth D. Merry xnb_unit_pvt.txs->rsp_event = rsize - 1;
6137e949c46SKenneth D. Merry xnb_unit_pvt.txb.rsp_prod_pvt = rsize - 2;
6147e949c46SKenneth D. Merry xnb_unit_pvt.txb.req_cons = rsize - 2;
6157e949c46SKenneth D. Merry
6167e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
6177e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
6187e949c46SKenneth D. Merry req->flags = NETTXF_more_data;
6197e949c46SKenneth D. Merry req->size = 550;
6207e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
6217e949c46SKenneth D. Merry
6227e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
6237e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
6247e949c46SKenneth D. Merry req->flags = NETTXF_more_data;
6257e949c46SKenneth D. Merry req->size = 100;
6267e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
6277e949c46SKenneth D. Merry
6287e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
6297e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
6307e949c46SKenneth D. Merry req->flags = 0;
6317e949c46SKenneth D. Merry req->size = 50;
6327e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
6337e949c46SKenneth D. Merry
6347e949c46SKenneth D. Merry RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
6357e949c46SKenneth D. Merry
6367e949c46SKenneth D. Merry num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
6377e949c46SKenneth D. Merry xnb_unit_pvt.txb.req_cons);
6387e949c46SKenneth D. Merry XNB_ASSERT(num_consumed == 3);
6397e949c46SKenneth D. Merry XNB_ASSERT(xnb_pkt_is_valid(&pkt));
6407e949c46SKenneth D. Merry XNB_ASSERT(pkt.list_len == 3);
6417e949c46SKenneth D. Merry XNB_ASSERT(RING_GET_REQUEST(&xnb_unit_pvt.txb, pkt.cdr + 1) == req);
6427e949c46SKenneth D. Merry }
6437e949c46SKenneth D. Merry
6447e949c46SKenneth D. Merry /**
6457e949c46SKenneth D. Merry * xnb_txpkt2rsp should do nothing for an empty packet
6467e949c46SKenneth D. Merry */
6477e949c46SKenneth D. Merry static void
xnb_txpkt2rsp_emptypkt(char * buffer,size_t buflen)6487e949c46SKenneth D. Merry xnb_txpkt2rsp_emptypkt(char *buffer, size_t buflen)
6497e949c46SKenneth D. Merry {
6507e949c46SKenneth D. Merry struct xnb_pkt pkt;
6517e949c46SKenneth D. Merry netif_tx_back_ring_t txb_backup = xnb_unit_pvt.txb;
6527e949c46SKenneth D. Merry netif_tx_sring_t txs_backup = *xnb_unit_pvt.txs;
6537e949c46SKenneth D. Merry pkt.list_len = 0;
6547e949c46SKenneth D. Merry
6557e949c46SKenneth D. Merry /* must call xnb_ring2pkt just to intialize pkt */
6567650d4b6SJohn Baldwin xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb, xnb_unit_pvt.txb.req_cons);
6577e949c46SKenneth D. Merry xnb_txpkt2rsp(&pkt, &xnb_unit_pvt.txb, 0);
6587e949c46SKenneth D. Merry XNB_ASSERT(
6597e949c46SKenneth D. Merry memcmp(&txb_backup, &xnb_unit_pvt.txb, sizeof(txb_backup)) == 0);
6607e949c46SKenneth D. Merry XNB_ASSERT(
6617e949c46SKenneth D. Merry memcmp(&txs_backup, xnb_unit_pvt.txs, sizeof(txs_backup)) == 0);
6627e949c46SKenneth D. Merry }
6637e949c46SKenneth D. Merry
6647e949c46SKenneth D. Merry /**
6657e949c46SKenneth D. Merry * xnb_txpkt2rsp responding to one request
6667e949c46SKenneth D. Merry */
6677e949c46SKenneth D. Merry static void
xnb_txpkt2rsp_1req(char * buffer,size_t buflen)6687e949c46SKenneth D. Merry xnb_txpkt2rsp_1req(char *buffer, size_t buflen)
6697e949c46SKenneth D. Merry {
6707e949c46SKenneth D. Merry uint16_t num_consumed;
6717e949c46SKenneth D. Merry struct xnb_pkt pkt;
6727e949c46SKenneth D. Merry struct netif_tx_request *req;
6737e949c46SKenneth D. Merry struct netif_tx_response *rsp;
6747e949c46SKenneth D. Merry
6757e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
6767e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
6777e949c46SKenneth D. Merry req->size = 1000;
6787e949c46SKenneth D. Merry req->flags = 0;
6797e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
6807e949c46SKenneth D. Merry
6817e949c46SKenneth D. Merry RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
6827e949c46SKenneth D. Merry
6837e949c46SKenneth D. Merry num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
6847e949c46SKenneth D. Merry xnb_unit_pvt.txb.req_cons);
6857e949c46SKenneth D. Merry xnb_unit_pvt.txb.req_cons += num_consumed;
6867e949c46SKenneth D. Merry
6877e949c46SKenneth D. Merry xnb_txpkt2rsp(&pkt, &xnb_unit_pvt.txb, 0);
6887e949c46SKenneth D. Merry rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb, xnb_unit_pvt.txf.rsp_cons);
6897e949c46SKenneth D. Merry
6907e949c46SKenneth D. Merry XNB_ASSERT(
6917e949c46SKenneth D. Merry xnb_unit_pvt.txb.rsp_prod_pvt == xnb_unit_pvt.txs->req_prod);
6927e949c46SKenneth D. Merry XNB_ASSERT(rsp->id == req->id);
6937e949c46SKenneth D. Merry XNB_ASSERT(rsp->status == NETIF_RSP_OKAY);
6947e949c46SKenneth D. Merry };
6957e949c46SKenneth D. Merry
6967e949c46SKenneth D. Merry /**
6977e949c46SKenneth D. Merry * xnb_txpkt2rsp responding to 1 data request and 1 extra info
6987e949c46SKenneth D. Merry */
6997e949c46SKenneth D. Merry static void
xnb_txpkt2rsp_extra(char * buffer,size_t buflen)7007e949c46SKenneth D. Merry xnb_txpkt2rsp_extra(char *buffer, size_t buflen)
7017e949c46SKenneth D. Merry {
7027e949c46SKenneth D. Merry uint16_t num_consumed;
7037e949c46SKenneth D. Merry struct xnb_pkt pkt;
7047e949c46SKenneth D. Merry struct netif_tx_request *req;
7057e949c46SKenneth D. Merry netif_extra_info_t *ext;
7067e949c46SKenneth D. Merry struct netif_tx_response *rsp;
7077e949c46SKenneth D. Merry
7087e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
7097e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
7107e949c46SKenneth D. Merry req->size = 1000;
7117e949c46SKenneth D. Merry req->flags = NETTXF_extra_info;
7127e949c46SKenneth D. Merry req->id = 69;
7137e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
7147e949c46SKenneth D. Merry
7157e949c46SKenneth D. Merry ext = (netif_extra_info_t*) RING_GET_REQUEST(&xnb_unit_pvt.txf,
7167e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
7177e949c46SKenneth D. Merry ext->type = XEN_NETIF_EXTRA_TYPE_GSO;
7187e949c46SKenneth D. Merry ext->flags = 0;
7197e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
7207e949c46SKenneth D. Merry
7217e949c46SKenneth D. Merry RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
7227e949c46SKenneth D. Merry
7237e949c46SKenneth D. Merry num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
7247e949c46SKenneth D. Merry xnb_unit_pvt.txb.req_cons);
7257e949c46SKenneth D. Merry xnb_unit_pvt.txb.req_cons += num_consumed;
7267e949c46SKenneth D. Merry
7277e949c46SKenneth D. Merry xnb_txpkt2rsp(&pkt, &xnb_unit_pvt.txb, 0);
7287e949c46SKenneth D. Merry
7297e949c46SKenneth D. Merry XNB_ASSERT(
7307e949c46SKenneth D. Merry xnb_unit_pvt.txb.rsp_prod_pvt == xnb_unit_pvt.txs->req_prod);
7317e949c46SKenneth D. Merry
7327e949c46SKenneth D. Merry rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb, xnb_unit_pvt.txf.rsp_cons);
7337e949c46SKenneth D. Merry XNB_ASSERT(rsp->id == req->id);
7347e949c46SKenneth D. Merry XNB_ASSERT(rsp->status == NETIF_RSP_OKAY);
7357e949c46SKenneth D. Merry
7367e949c46SKenneth D. Merry rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb,
7377e949c46SKenneth D. Merry xnb_unit_pvt.txf.rsp_cons + 1);
7387e949c46SKenneth D. Merry XNB_ASSERT(rsp->status == NETIF_RSP_NULL);
7397e949c46SKenneth D. Merry };
7407e949c46SKenneth D. Merry
7417e949c46SKenneth D. Merry /**
7427e949c46SKenneth D. Merry * xnb_pkg2rsp responding to 3 data requests and 1 extra info
7437e949c46SKenneth D. Merry */
7447e949c46SKenneth D. Merry static void
xnb_txpkt2rsp_long(char * buffer,size_t buflen)7457e949c46SKenneth D. Merry xnb_txpkt2rsp_long(char *buffer, size_t buflen)
7467e949c46SKenneth D. Merry {
7477e949c46SKenneth D. Merry uint16_t num_consumed;
7487e949c46SKenneth D. Merry struct xnb_pkt pkt;
7497e949c46SKenneth D. Merry struct netif_tx_request *req;
7507e949c46SKenneth D. Merry netif_extra_info_t *ext;
7517e949c46SKenneth D. Merry struct netif_tx_response *rsp;
7527e949c46SKenneth D. Merry
7537e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
7547e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
7557e949c46SKenneth D. Merry req->size = 1000;
7567e949c46SKenneth D. Merry req->flags = NETTXF_extra_info | NETTXF_more_data;
7577e949c46SKenneth D. Merry req->id = 254;
7587e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
7597e949c46SKenneth D. Merry
7607e949c46SKenneth D. Merry ext = (netif_extra_info_t*) RING_GET_REQUEST(&xnb_unit_pvt.txf,
7617e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
7627e949c46SKenneth D. Merry ext->type = XEN_NETIF_EXTRA_TYPE_GSO;
7637e949c46SKenneth D. Merry ext->flags = 0;
7647e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
7657e949c46SKenneth D. Merry
7667e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
7677e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
7687e949c46SKenneth D. Merry req->size = 300;
7697e949c46SKenneth D. Merry req->flags = NETTXF_more_data;
7707e949c46SKenneth D. Merry req->id = 1034;
7717e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
7727e949c46SKenneth D. Merry
7737e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
7747e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
7757e949c46SKenneth D. Merry req->size = 400;
7767e949c46SKenneth D. Merry req->flags = 0;
7777e949c46SKenneth D. Merry req->id = 34;
7787e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
7797e949c46SKenneth D. Merry
7807e949c46SKenneth D. Merry RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
7817e949c46SKenneth D. Merry
7827e949c46SKenneth D. Merry num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
7837e949c46SKenneth D. Merry xnb_unit_pvt.txb.req_cons);
7847e949c46SKenneth D. Merry xnb_unit_pvt.txb.req_cons += num_consumed;
7857e949c46SKenneth D. Merry
7867e949c46SKenneth D. Merry xnb_txpkt2rsp(&pkt, &xnb_unit_pvt.txb, 0);
7877e949c46SKenneth D. Merry
7887e949c46SKenneth D. Merry XNB_ASSERT(
7897e949c46SKenneth D. Merry xnb_unit_pvt.txb.rsp_prod_pvt == xnb_unit_pvt.txs->req_prod);
7907e949c46SKenneth D. Merry
7917e949c46SKenneth D. Merry rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb, xnb_unit_pvt.txf.rsp_cons);
7927e949c46SKenneth D. Merry XNB_ASSERT(rsp->id ==
7937e949c46SKenneth D. Merry RING_GET_REQUEST(&xnb_unit_pvt.txf, 0)->id);
7947e949c46SKenneth D. Merry XNB_ASSERT(rsp->status == NETIF_RSP_OKAY);
7957e949c46SKenneth D. Merry
7967e949c46SKenneth D. Merry rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb,
7977e949c46SKenneth D. Merry xnb_unit_pvt.txf.rsp_cons + 1);
7987e949c46SKenneth D. Merry XNB_ASSERT(rsp->status == NETIF_RSP_NULL);
7997e949c46SKenneth D. Merry
8007e949c46SKenneth D. Merry rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb,
8017e949c46SKenneth D. Merry xnb_unit_pvt.txf.rsp_cons + 2);
8027e949c46SKenneth D. Merry XNB_ASSERT(rsp->id ==
8037e949c46SKenneth D. Merry RING_GET_REQUEST(&xnb_unit_pvt.txf, 2)->id);
8047e949c46SKenneth D. Merry XNB_ASSERT(rsp->status == NETIF_RSP_OKAY);
8057e949c46SKenneth D. Merry
8067e949c46SKenneth D. Merry rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb,
8077e949c46SKenneth D. Merry xnb_unit_pvt.txf.rsp_cons + 3);
8087e949c46SKenneth D. Merry XNB_ASSERT(rsp->id ==
8097e949c46SKenneth D. Merry RING_GET_REQUEST(&xnb_unit_pvt.txf, 3)->id);
8107e949c46SKenneth D. Merry XNB_ASSERT(rsp->status == NETIF_RSP_OKAY);
8117e949c46SKenneth D. Merry }
8127e949c46SKenneth D. Merry
8137e949c46SKenneth D. Merry /**
8147e949c46SKenneth D. Merry * xnb_txpkt2rsp responding to an invalid packet.
8157e949c46SKenneth D. Merry * Note: this test will result in an error message being printed to the console
8167e949c46SKenneth D. Merry * such as:
8177e949c46SKenneth D. Merry * xnb(xnb_ring2pkt:1306): Unknown extra info type 255. Discarding packet
8187e949c46SKenneth D. Merry */
8197e949c46SKenneth D. Merry static void
xnb_txpkt2rsp_invalid(char * buffer,size_t buflen)8207e949c46SKenneth D. Merry xnb_txpkt2rsp_invalid(char *buffer, size_t buflen)
8217e949c46SKenneth D. Merry {
8227e949c46SKenneth D. Merry uint16_t num_consumed;
8237e949c46SKenneth D. Merry struct xnb_pkt pkt;
8247e949c46SKenneth D. Merry struct netif_tx_request *req;
8257e949c46SKenneth D. Merry netif_extra_info_t *ext;
8267e949c46SKenneth D. Merry struct netif_tx_response *rsp;
8277e949c46SKenneth D. Merry
8287e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
8297e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
8307e949c46SKenneth D. Merry req->size = 1000;
8317e949c46SKenneth D. Merry req->flags = NETTXF_extra_info;
8327e949c46SKenneth D. Merry req->id = 69;
8337e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
8347e949c46SKenneth D. Merry
8357e949c46SKenneth D. Merry ext = (netif_extra_info_t*) RING_GET_REQUEST(&xnb_unit_pvt.txf,
8367e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
8377e949c46SKenneth D. Merry ext->type = 0xFF; /* Invalid extra type */
8387e949c46SKenneth D. Merry ext->flags = 0;
8397e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
8407e949c46SKenneth D. Merry
8417e949c46SKenneth D. Merry RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
8427e949c46SKenneth D. Merry
8437e949c46SKenneth D. Merry num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
8447e949c46SKenneth D. Merry xnb_unit_pvt.txb.req_cons);
8457e949c46SKenneth D. Merry xnb_unit_pvt.txb.req_cons += num_consumed;
8467e949c46SKenneth D. Merry XNB_ASSERT(! xnb_pkt_is_valid(&pkt));
8477e949c46SKenneth D. Merry
8487e949c46SKenneth D. Merry xnb_txpkt2rsp(&pkt, &xnb_unit_pvt.txb, 0);
8497e949c46SKenneth D. Merry
8507e949c46SKenneth D. Merry XNB_ASSERT(
8517e949c46SKenneth D. Merry xnb_unit_pvt.txb.rsp_prod_pvt == xnb_unit_pvt.txs->req_prod);
8527e949c46SKenneth D. Merry
8537e949c46SKenneth D. Merry rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb, xnb_unit_pvt.txf.rsp_cons);
8547e949c46SKenneth D. Merry XNB_ASSERT(rsp->id == req->id);
8557e949c46SKenneth D. Merry XNB_ASSERT(rsp->status == NETIF_RSP_ERROR);
8567e949c46SKenneth D. Merry
8577e949c46SKenneth D. Merry rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb,
8587e949c46SKenneth D. Merry xnb_unit_pvt.txf.rsp_cons + 1);
8597e949c46SKenneth D. Merry XNB_ASSERT(rsp->status == NETIF_RSP_NULL);
8607e949c46SKenneth D. Merry };
8617e949c46SKenneth D. Merry
8627e949c46SKenneth D. Merry /**
8637e949c46SKenneth D. Merry * xnb_txpkt2rsp responding to one request which caused an error
8647e949c46SKenneth D. Merry */
8657e949c46SKenneth D. Merry static void
xnb_txpkt2rsp_error(char * buffer,size_t buflen)8667e949c46SKenneth D. Merry xnb_txpkt2rsp_error(char *buffer, size_t buflen)
8677e949c46SKenneth D. Merry {
8687e949c46SKenneth D. Merry uint16_t num_consumed;
8697e949c46SKenneth D. Merry struct xnb_pkt pkt;
8707e949c46SKenneth D. Merry struct netif_tx_request *req;
8717e949c46SKenneth D. Merry struct netif_tx_response *rsp;
8727e949c46SKenneth D. Merry
8737e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
8747e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
8757e949c46SKenneth D. Merry req->size = 1000;
8767e949c46SKenneth D. Merry req->flags = 0;
8777e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
8787e949c46SKenneth D. Merry
8797e949c46SKenneth D. Merry RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
8807e949c46SKenneth D. Merry
8817e949c46SKenneth D. Merry num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
8827e949c46SKenneth D. Merry xnb_unit_pvt.txb.req_cons);
8837e949c46SKenneth D. Merry xnb_unit_pvt.txb.req_cons += num_consumed;
8847e949c46SKenneth D. Merry
8857e949c46SKenneth D. Merry xnb_txpkt2rsp(&pkt, &xnb_unit_pvt.txb, 1);
8867e949c46SKenneth D. Merry rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb, xnb_unit_pvt.txf.rsp_cons);
8877e949c46SKenneth D. Merry
8887e949c46SKenneth D. Merry XNB_ASSERT(
8897e949c46SKenneth D. Merry xnb_unit_pvt.txb.rsp_prod_pvt == xnb_unit_pvt.txs->req_prod);
8907e949c46SKenneth D. Merry XNB_ASSERT(rsp->id == req->id);
8917e949c46SKenneth D. Merry XNB_ASSERT(rsp->status == NETIF_RSP_ERROR);
8927e949c46SKenneth D. Merry };
8937e949c46SKenneth D. Merry
8947e949c46SKenneth D. Merry /**
8957e949c46SKenneth D. Merry * xnb_txpkt2rsp's responses wrap around the end of the ring
8967e949c46SKenneth D. Merry */
8977e949c46SKenneth D. Merry static void
xnb_txpkt2rsp_wraps(char * buffer,size_t buflen)8987e949c46SKenneth D. Merry xnb_txpkt2rsp_wraps(char *buffer, size_t buflen)
8997e949c46SKenneth D. Merry {
9007e949c46SKenneth D. Merry struct xnb_pkt pkt;
9017e949c46SKenneth D. Merry struct netif_tx_request *req;
9027e949c46SKenneth D. Merry struct netif_tx_response *rsp;
9037e949c46SKenneth D. Merry unsigned int rsize;
9047e949c46SKenneth D. Merry
9057e949c46SKenneth D. Merry /*
9067e949c46SKenneth D. Merry * Manually tweak the ring indices to create a ring with no responses
9077e949c46SKenneth D. Merry * and the next request slot at position 2 from the end
9087e949c46SKenneth D. Merry */
9097e949c46SKenneth D. Merry rsize = RING_SIZE(&xnb_unit_pvt.txf);
9107e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt = rsize - 2;
9117e949c46SKenneth D. Merry xnb_unit_pvt.txf.rsp_cons = rsize - 2;
9127e949c46SKenneth D. Merry xnb_unit_pvt.txs->req_prod = rsize - 2;
9137e949c46SKenneth D. Merry xnb_unit_pvt.txs->req_event = rsize - 1;
9147e949c46SKenneth D. Merry xnb_unit_pvt.txs->rsp_prod = rsize - 2;
9157e949c46SKenneth D. Merry xnb_unit_pvt.txs->rsp_event = rsize - 1;
9167e949c46SKenneth D. Merry xnb_unit_pvt.txb.rsp_prod_pvt = rsize - 2;
9177e949c46SKenneth D. Merry xnb_unit_pvt.txb.req_cons = rsize - 2;
9187e949c46SKenneth D. Merry
9197e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
9207e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
9217e949c46SKenneth D. Merry req->flags = NETTXF_more_data;
9227e949c46SKenneth D. Merry req->size = 550;
9237e949c46SKenneth D. Merry req->id = 1;
9247e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
9257e949c46SKenneth D. Merry
9267e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
9277e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
9287e949c46SKenneth D. Merry req->flags = NETTXF_more_data;
9297e949c46SKenneth D. Merry req->size = 100;
9307e949c46SKenneth D. Merry req->id = 2;
9317e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
9327e949c46SKenneth D. Merry
9337e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
9347e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
9357e949c46SKenneth D. Merry req->flags = 0;
9367e949c46SKenneth D. Merry req->size = 50;
9377e949c46SKenneth D. Merry req->id = 3;
9387e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
9397e949c46SKenneth D. Merry
9407e949c46SKenneth D. Merry RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
9417e949c46SKenneth D. Merry
9427650d4b6SJohn Baldwin xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb, xnb_unit_pvt.txb.req_cons);
9437e949c46SKenneth D. Merry
9447e949c46SKenneth D. Merry xnb_txpkt2rsp(&pkt, &xnb_unit_pvt.txb, 0);
9457e949c46SKenneth D. Merry
9467e949c46SKenneth D. Merry XNB_ASSERT(
9477e949c46SKenneth D. Merry xnb_unit_pvt.txb.rsp_prod_pvt == xnb_unit_pvt.txs->req_prod);
9487e949c46SKenneth D. Merry rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb,
9497e949c46SKenneth D. Merry xnb_unit_pvt.txf.rsp_cons + 2);
9507e949c46SKenneth D. Merry XNB_ASSERT(rsp->id == req->id);
9517e949c46SKenneth D. Merry XNB_ASSERT(rsp->status == NETIF_RSP_OKAY);
9527e949c46SKenneth D. Merry }
9537e949c46SKenneth D. Merry
9547e949c46SKenneth D. Merry /**
9557e949c46SKenneth D. Merry * Helper function used to setup pkt2mbufc tests
9567e949c46SKenneth D. Merry * \param size size in bytes of the single request to push to the ring
9577e949c46SKenneth D. Merry * \param flags optional flags to put in the netif request
9587e949c46SKenneth D. Merry * \param[out] pkt the returned packet object
9597e949c46SKenneth D. Merry * \return number of requests consumed from the ring
9607e949c46SKenneth D. Merry */
9617e949c46SKenneth D. Merry static int
xnb_get1pkt(struct xnb_pkt * pkt,size_t size,uint16_t flags)9627e949c46SKenneth D. Merry xnb_get1pkt(struct xnb_pkt *pkt, size_t size, uint16_t flags)
9637e949c46SKenneth D. Merry {
9647e949c46SKenneth D. Merry struct netif_tx_request *req;
9657e949c46SKenneth D. Merry
9667e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
9677e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
9687e949c46SKenneth D. Merry req->flags = flags;
9697e949c46SKenneth D. Merry req->size = size;
9707e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
9717e949c46SKenneth D. Merry
9727e949c46SKenneth D. Merry RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
9737e949c46SKenneth D. Merry
9747e949c46SKenneth D. Merry return xnb_ring2pkt(pkt, &xnb_unit_pvt.txb,
9757e949c46SKenneth D. Merry xnb_unit_pvt.txb.req_cons);
9767e949c46SKenneth D. Merry }
9777e949c46SKenneth D. Merry
9787e949c46SKenneth D. Merry /**
9797e949c46SKenneth D. Merry * xnb_pkt2mbufc on an empty packet
9807e949c46SKenneth D. Merry */
9817e949c46SKenneth D. Merry static void
xnb_pkt2mbufc_empty(char * buffer,size_t buflen)9827e949c46SKenneth D. Merry xnb_pkt2mbufc_empty(char *buffer, size_t buflen)
9837e949c46SKenneth D. Merry {
9847e949c46SKenneth D. Merry struct xnb_pkt pkt;
9857e949c46SKenneth D. Merry struct mbuf *pMbuf;
9867e949c46SKenneth D. Merry pkt.list_len = 0;
9877e949c46SKenneth D. Merry
9887e949c46SKenneth D. Merry /* must call xnb_ring2pkt just to intialize pkt */
9897650d4b6SJohn Baldwin xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb, xnb_unit_pvt.txb.req_cons);
9907e949c46SKenneth D. Merry pkt.size = 0;
9917e949c46SKenneth D. Merry pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
9927e949c46SKenneth D. Merry safe_m_freem(&pMbuf);
9937e949c46SKenneth D. Merry }
9947e949c46SKenneth D. Merry
9957e949c46SKenneth D. Merry /**
9967e949c46SKenneth D. Merry * xnb_pkt2mbufc on short packet that can fit in an mbuf internal buffer
9977e949c46SKenneth D. Merry */
9987e949c46SKenneth D. Merry static void
xnb_pkt2mbufc_short(char * buffer,size_t buflen)9997e949c46SKenneth D. Merry xnb_pkt2mbufc_short(char *buffer, size_t buflen)
10007e949c46SKenneth D. Merry {
10017e949c46SKenneth D. Merry const size_t size = MINCLSIZE - 1;
10027e949c46SKenneth D. Merry struct xnb_pkt pkt;
10037e949c46SKenneth D. Merry struct mbuf *pMbuf;
10047e949c46SKenneth D. Merry
10057e949c46SKenneth D. Merry xnb_get1pkt(&pkt, size, 0);
10067e949c46SKenneth D. Merry
10077e949c46SKenneth D. Merry pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
10087e949c46SKenneth D. Merry XNB_ASSERT(M_TRAILINGSPACE(pMbuf) >= size);
10097e949c46SKenneth D. Merry safe_m_freem(&pMbuf);
10107e949c46SKenneth D. Merry }
10117e949c46SKenneth D. Merry
10127e949c46SKenneth D. Merry /**
10137e949c46SKenneth D. Merry * xnb_pkt2mbufc on short packet whose checksum was validated by the netfron
10147e949c46SKenneth D. Merry */
10157e949c46SKenneth D. Merry static void
xnb_pkt2mbufc_csum(char * buffer,size_t buflen)10167e949c46SKenneth D. Merry xnb_pkt2mbufc_csum(char *buffer, size_t buflen)
10177e949c46SKenneth D. Merry {
10187e949c46SKenneth D. Merry const size_t size = MINCLSIZE - 1;
10197e949c46SKenneth D. Merry struct xnb_pkt pkt;
10207e949c46SKenneth D. Merry struct mbuf *pMbuf;
10217e949c46SKenneth D. Merry
10227e949c46SKenneth D. Merry xnb_get1pkt(&pkt, size, NETTXF_data_validated);
10237e949c46SKenneth D. Merry
10247e949c46SKenneth D. Merry pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
10257e949c46SKenneth D. Merry XNB_ASSERT(M_TRAILINGSPACE(pMbuf) >= size);
10267e949c46SKenneth D. Merry XNB_ASSERT(pMbuf->m_pkthdr.csum_flags & CSUM_IP_CHECKED);
10277e949c46SKenneth D. Merry XNB_ASSERT(pMbuf->m_pkthdr.csum_flags & CSUM_IP_VALID);
10287e949c46SKenneth D. Merry XNB_ASSERT(pMbuf->m_pkthdr.csum_flags & CSUM_DATA_VALID);
10297e949c46SKenneth D. Merry XNB_ASSERT(pMbuf->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR);
10307e949c46SKenneth D. Merry safe_m_freem(&pMbuf);
10317e949c46SKenneth D. Merry }
10327e949c46SKenneth D. Merry
10337e949c46SKenneth D. Merry /**
10347e949c46SKenneth D. Merry * xnb_pkt2mbufc on packet that can fit in one cluster
10357e949c46SKenneth D. Merry */
10367e949c46SKenneth D. Merry static void
xnb_pkt2mbufc_1cluster(char * buffer,size_t buflen)10377e949c46SKenneth D. Merry xnb_pkt2mbufc_1cluster(char *buffer, size_t buflen)
10387e949c46SKenneth D. Merry {
10397e949c46SKenneth D. Merry const size_t size = MINCLSIZE;
10407e949c46SKenneth D. Merry struct xnb_pkt pkt;
10417e949c46SKenneth D. Merry struct mbuf *pMbuf;
10427e949c46SKenneth D. Merry
10437e949c46SKenneth D. Merry xnb_get1pkt(&pkt, size, 0);
10447e949c46SKenneth D. Merry
10457e949c46SKenneth D. Merry pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
10467e949c46SKenneth D. Merry XNB_ASSERT(M_TRAILINGSPACE(pMbuf) >= size);
10477e949c46SKenneth D. Merry safe_m_freem(&pMbuf);
10487e949c46SKenneth D. Merry }
10497e949c46SKenneth D. Merry
10507e949c46SKenneth D. Merry /**
10517e949c46SKenneth D. Merry * xnb_pkt2mbufc on packet that cannot fit in one regular cluster
10527e949c46SKenneth D. Merry */
10537e949c46SKenneth D. Merry static void
xnb_pkt2mbufc_largecluster(char * buffer,size_t buflen)10547e949c46SKenneth D. Merry xnb_pkt2mbufc_largecluster(char *buffer, size_t buflen)
10557e949c46SKenneth D. Merry {
10567e949c46SKenneth D. Merry const size_t size = MCLBYTES + 1;
10577e949c46SKenneth D. Merry struct xnb_pkt pkt;
10587e949c46SKenneth D. Merry struct mbuf *pMbuf;
10597e949c46SKenneth D. Merry
10607e949c46SKenneth D. Merry xnb_get1pkt(&pkt, size, 0);
10617e949c46SKenneth D. Merry
10627e949c46SKenneth D. Merry pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
10637e949c46SKenneth D. Merry XNB_ASSERT(M_TRAILINGSPACE(pMbuf) >= size);
10647e949c46SKenneth D. Merry safe_m_freem(&pMbuf);
10657e949c46SKenneth D. Merry }
10667e949c46SKenneth D. Merry
10677e949c46SKenneth D. Merry /**
10687e949c46SKenneth D. Merry * xnb_pkt2mbufc on packet that cannot fit in one clusters
10697e949c46SKenneth D. Merry */
10707e949c46SKenneth D. Merry static void
xnb_pkt2mbufc_2cluster(char * buffer,size_t buflen)10717e949c46SKenneth D. Merry xnb_pkt2mbufc_2cluster(char *buffer, size_t buflen)
10727e949c46SKenneth D. Merry {
10737e949c46SKenneth D. Merry const size_t size = 2 * MCLBYTES + 1;
10747e949c46SKenneth D. Merry size_t space = 0;
10757e949c46SKenneth D. Merry struct xnb_pkt pkt;
10767e949c46SKenneth D. Merry struct mbuf *pMbuf;
10777e949c46SKenneth D. Merry struct mbuf *m;
10787e949c46SKenneth D. Merry
10797e949c46SKenneth D. Merry xnb_get1pkt(&pkt, size, 0);
10807e949c46SKenneth D. Merry
10817e949c46SKenneth D. Merry pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
10827e949c46SKenneth D. Merry
10837e949c46SKenneth D. Merry for (m = pMbuf; m != NULL; m = m->m_next) {
10847e949c46SKenneth D. Merry space += M_TRAILINGSPACE(m);
10857e949c46SKenneth D. Merry }
10867e949c46SKenneth D. Merry XNB_ASSERT(space >= size);
10877e949c46SKenneth D. Merry safe_m_freem(&pMbuf);
10887e949c46SKenneth D. Merry }
10897e949c46SKenneth D. Merry
10907e949c46SKenneth D. Merry /**
10917e949c46SKenneth D. Merry * xnb_txpkt2gnttab on an empty packet. Should return empty gnttab
10927e949c46SKenneth D. Merry */
10937e949c46SKenneth D. Merry static void
xnb_txpkt2gnttab_empty(char * buffer,size_t buflen)10947e949c46SKenneth D. Merry xnb_txpkt2gnttab_empty(char *buffer, size_t buflen)
10957e949c46SKenneth D. Merry {
10967e949c46SKenneth D. Merry int n_entries;
10977e949c46SKenneth D. Merry struct xnb_pkt pkt;
10987e949c46SKenneth D. Merry struct mbuf *pMbuf;
10997e949c46SKenneth D. Merry pkt.list_len = 0;
11007e949c46SKenneth D. Merry
11017e949c46SKenneth D. Merry /* must call xnb_ring2pkt just to intialize pkt */
11027e949c46SKenneth D. Merry xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb, xnb_unit_pvt.txb.req_cons);
11037e949c46SKenneth D. Merry pkt.size = 0;
11047e949c46SKenneth D. Merry pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
11057e949c46SKenneth D. Merry n_entries = xnb_txpkt2gnttab(&pkt, pMbuf, xnb_unit_pvt.gnttab,
11067e949c46SKenneth D. Merry &xnb_unit_pvt.txb, DOMID_FIRST_RESERVED);
11077e949c46SKenneth D. Merry XNB_ASSERT(n_entries == 0);
11087e949c46SKenneth D. Merry safe_m_freem(&pMbuf);
11097e949c46SKenneth D. Merry }
11107e949c46SKenneth D. Merry
11117e949c46SKenneth D. Merry /**
11127e949c46SKenneth D. Merry * xnb_txpkt2gnttab on a short packet, that can fit in one mbuf internal buffer
11137e949c46SKenneth D. Merry * and has one request
11147e949c46SKenneth D. Merry */
11157e949c46SKenneth D. Merry static void
xnb_txpkt2gnttab_short(char * buffer,size_t buflen)11167e949c46SKenneth D. Merry xnb_txpkt2gnttab_short(char *buffer, size_t buflen)
11177e949c46SKenneth D. Merry {
11187e949c46SKenneth D. Merry const size_t size = MINCLSIZE - 1;
11197e949c46SKenneth D. Merry int n_entries;
11207e949c46SKenneth D. Merry struct xnb_pkt pkt;
11217e949c46SKenneth D. Merry struct mbuf *pMbuf;
11227e949c46SKenneth D. Merry
11237e949c46SKenneth D. Merry struct netif_tx_request *req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
11247e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
11257e949c46SKenneth D. Merry req->flags = 0;
11267e949c46SKenneth D. Merry req->size = size;
11277e949c46SKenneth D. Merry req->gref = 7;
11287e949c46SKenneth D. Merry req->offset = 17;
11297e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
11307e949c46SKenneth D. Merry
11317e949c46SKenneth D. Merry RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
11327e949c46SKenneth D. Merry
11337e949c46SKenneth D. Merry xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb, xnb_unit_pvt.txb.req_cons);
11347e949c46SKenneth D. Merry
11357e949c46SKenneth D. Merry pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
11367e949c46SKenneth D. Merry n_entries = xnb_txpkt2gnttab(&pkt, pMbuf, xnb_unit_pvt.gnttab,
11377e949c46SKenneth D. Merry &xnb_unit_pvt.txb, DOMID_FIRST_RESERVED);
11387e949c46SKenneth D. Merry XNB_ASSERT(n_entries == 1);
11397e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[0].len == size);
11407e949c46SKenneth D. Merry /* flags should indicate gref's for source */
11417e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[0].flags & GNTCOPY_source_gref);
11427e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[0].source.offset == req->offset);
11437e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[0].source.domid == DOMID_SELF);
11447e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[0].dest.offset == virt_to_offset(
11457e949c46SKenneth D. Merry mtod(pMbuf, vm_offset_t)));
11467e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[0].dest.u.gmfn ==
11477e949c46SKenneth D. Merry virt_to_mfn(mtod(pMbuf, vm_offset_t)));
11487e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[0].dest.domid == DOMID_FIRST_RESERVED);
11497e949c46SKenneth D. Merry safe_m_freem(&pMbuf);
11507e949c46SKenneth D. Merry }
11517e949c46SKenneth D. Merry
11527e949c46SKenneth D. Merry /**
11537e949c46SKenneth D. Merry * xnb_txpkt2gnttab on a packet with two requests, that can fit into a single
11547e949c46SKenneth D. Merry * mbuf cluster
11557e949c46SKenneth D. Merry */
11567e949c46SKenneth D. Merry static void
xnb_txpkt2gnttab_2req(char * buffer,size_t buflen)11577e949c46SKenneth D. Merry xnb_txpkt2gnttab_2req(char *buffer, size_t buflen)
11587e949c46SKenneth D. Merry {
11597e949c46SKenneth D. Merry int n_entries;
11607e949c46SKenneth D. Merry struct xnb_pkt pkt;
11617e949c46SKenneth D. Merry struct mbuf *pMbuf;
11627e949c46SKenneth D. Merry
11637e949c46SKenneth D. Merry struct netif_tx_request *req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
11647e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
11657e949c46SKenneth D. Merry req->flags = NETTXF_more_data;
11667e949c46SKenneth D. Merry req->size = 1900;
11677e949c46SKenneth D. Merry req->gref = 7;
11687e949c46SKenneth D. Merry req->offset = 0;
11697e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
11707e949c46SKenneth D. Merry
11717e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
11727e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
11737e949c46SKenneth D. Merry req->flags = 0;
11747e949c46SKenneth D. Merry req->size = 500;
11757e949c46SKenneth D. Merry req->gref = 8;
11767e949c46SKenneth D. Merry req->offset = 0;
11777e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
11787e949c46SKenneth D. Merry
11797e949c46SKenneth D. Merry RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
11807e949c46SKenneth D. Merry
11817e949c46SKenneth D. Merry xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb, xnb_unit_pvt.txb.req_cons);
11827e949c46SKenneth D. Merry
11837e949c46SKenneth D. Merry pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
11847e949c46SKenneth D. Merry n_entries = xnb_txpkt2gnttab(&pkt, pMbuf, xnb_unit_pvt.gnttab,
11857e949c46SKenneth D. Merry &xnb_unit_pvt.txb, DOMID_FIRST_RESERVED);
11867e949c46SKenneth D. Merry
11877e949c46SKenneth D. Merry XNB_ASSERT(n_entries == 2);
11887e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[0].len == 1400);
11897e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[0].dest.offset == virt_to_offset(
11907e949c46SKenneth D. Merry mtod(pMbuf, vm_offset_t)));
11917e949c46SKenneth D. Merry
11927e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[1].len == 500);
11937e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[1].dest.offset == virt_to_offset(
11947e949c46SKenneth D. Merry mtod(pMbuf, vm_offset_t) + 1400));
11957e949c46SKenneth D. Merry safe_m_freem(&pMbuf);
11967e949c46SKenneth D. Merry }
11977e949c46SKenneth D. Merry
11987e949c46SKenneth D. Merry /**
11997e949c46SKenneth D. Merry * xnb_txpkt2gnttab on a single request that spans two mbuf clusters
12007e949c46SKenneth D. Merry */
12017e949c46SKenneth D. Merry static void
xnb_txpkt2gnttab_2cluster(char * buffer,size_t buflen)12027e949c46SKenneth D. Merry xnb_txpkt2gnttab_2cluster(char *buffer, size_t buflen)
12037e949c46SKenneth D. Merry {
12047e949c46SKenneth D. Merry int n_entries;
12057e949c46SKenneth D. Merry struct xnb_pkt pkt;
12067e949c46SKenneth D. Merry struct mbuf *pMbuf;
12077e949c46SKenneth D. Merry const uint16_t data_this_transaction = (MCLBYTES*2) + 1;
12087e949c46SKenneth D. Merry
12097e949c46SKenneth D. Merry struct netif_tx_request *req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
12107e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
12117e949c46SKenneth D. Merry req->flags = 0;
12127e949c46SKenneth D. Merry req->size = data_this_transaction;
12137e949c46SKenneth D. Merry req->gref = 8;
12147e949c46SKenneth D. Merry req->offset = 0;
12157e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
12167e949c46SKenneth D. Merry
12177e949c46SKenneth D. Merry RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
12187e949c46SKenneth D. Merry xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb, xnb_unit_pvt.txb.req_cons);
12197e949c46SKenneth D. Merry
12207e949c46SKenneth D. Merry pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
1221407d708cSAlan Somers XNB_ASSERT(pMbuf != NULL);
1222407d708cSAlan Somers if (pMbuf == NULL)
1223407d708cSAlan Somers return;
1224407d708cSAlan Somers
12257e949c46SKenneth D. Merry n_entries = xnb_txpkt2gnttab(&pkt, pMbuf, xnb_unit_pvt.gnttab,
12267e949c46SKenneth D. Merry &xnb_unit_pvt.txb, DOMID_FIRST_RESERVED);
12277e949c46SKenneth D. Merry
12287e949c46SKenneth D. Merry if (M_TRAILINGSPACE(pMbuf) == MCLBYTES) {
12297e949c46SKenneth D. Merry /* there should be three mbufs and three gnttab entries */
12307e949c46SKenneth D. Merry XNB_ASSERT(n_entries == 3);
12317e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[0].len == MCLBYTES);
12327e949c46SKenneth D. Merry XNB_ASSERT(
12337e949c46SKenneth D. Merry xnb_unit_pvt.gnttab[0].dest.offset == virt_to_offset(
12347e949c46SKenneth D. Merry mtod(pMbuf, vm_offset_t)));
12357e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[0].source.offset == 0);
12367e949c46SKenneth D. Merry
12377e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[1].len == MCLBYTES);
12387e949c46SKenneth D. Merry XNB_ASSERT(
12397e949c46SKenneth D. Merry xnb_unit_pvt.gnttab[1].dest.offset == virt_to_offset(
12407e949c46SKenneth D. Merry mtod(pMbuf->m_next, vm_offset_t)));
12417e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[1].source.offset == MCLBYTES);
12427e949c46SKenneth D. Merry
12437e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[2].len == 1);
12447e949c46SKenneth D. Merry XNB_ASSERT(
12457e949c46SKenneth D. Merry xnb_unit_pvt.gnttab[2].dest.offset == virt_to_offset(
12467e949c46SKenneth D. Merry mtod(pMbuf->m_next, vm_offset_t)));
12477e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[2].source.offset == 2 *
12487e949c46SKenneth D. Merry MCLBYTES);
12497e949c46SKenneth D. Merry } else if (M_TRAILINGSPACE(pMbuf) == 2 * MCLBYTES) {
12507e949c46SKenneth D. Merry /* there should be two mbufs and two gnttab entries */
12517e949c46SKenneth D. Merry XNB_ASSERT(n_entries == 2);
12527e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[0].len == 2 * MCLBYTES);
12537e949c46SKenneth D. Merry XNB_ASSERT(
12547e949c46SKenneth D. Merry xnb_unit_pvt.gnttab[0].dest.offset == virt_to_offset(
12557e949c46SKenneth D. Merry mtod(pMbuf, vm_offset_t)));
12567e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[0].source.offset == 0);
12577e949c46SKenneth D. Merry
12587e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[1].len == 1);
12597e949c46SKenneth D. Merry XNB_ASSERT(
12607e949c46SKenneth D. Merry xnb_unit_pvt.gnttab[1].dest.offset == virt_to_offset(
12617e949c46SKenneth D. Merry mtod(pMbuf->m_next, vm_offset_t)));
12627e949c46SKenneth D. Merry XNB_ASSERT(
12637e949c46SKenneth D. Merry xnb_unit_pvt.gnttab[1].source.offset == 2 * MCLBYTES);
12647e949c46SKenneth D. Merry
12657e949c46SKenneth D. Merry } else {
12667e949c46SKenneth D. Merry /* should never get here */
12677e949c46SKenneth D. Merry XNB_ASSERT(0);
12687e949c46SKenneth D. Merry }
12697e949c46SKenneth D. Merry m_freem(pMbuf);
12707e949c46SKenneth D. Merry }
12717e949c46SKenneth D. Merry
12727e949c46SKenneth D. Merry /**
12737e949c46SKenneth D. Merry * xnb_update_mbufc on a short packet that only has one gnttab entry
12747e949c46SKenneth D. Merry */
12757e949c46SKenneth D. Merry static void
xnb_update_mbufc_short(char * buffer,size_t buflen)12767e949c46SKenneth D. Merry xnb_update_mbufc_short(char *buffer, size_t buflen)
12777e949c46SKenneth D. Merry {
12787e949c46SKenneth D. Merry const size_t size = MINCLSIZE - 1;
12797e949c46SKenneth D. Merry int n_entries;
12807e949c46SKenneth D. Merry struct xnb_pkt pkt;
12817e949c46SKenneth D. Merry struct mbuf *pMbuf;
12827e949c46SKenneth D. Merry
12837e949c46SKenneth D. Merry struct netif_tx_request *req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
12847e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
12857e949c46SKenneth D. Merry req->flags = 0;
12867e949c46SKenneth D. Merry req->size = size;
12877e949c46SKenneth D. Merry req->gref = 7;
12887e949c46SKenneth D. Merry req->offset = 17;
12897e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
12907e949c46SKenneth D. Merry
12917e949c46SKenneth D. Merry RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
12927e949c46SKenneth D. Merry
12937e949c46SKenneth D. Merry xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb, xnb_unit_pvt.txb.req_cons);
12947e949c46SKenneth D. Merry
12957e949c46SKenneth D. Merry pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
12967e949c46SKenneth D. Merry n_entries = xnb_txpkt2gnttab(&pkt, pMbuf, xnb_unit_pvt.gnttab,
12977e949c46SKenneth D. Merry &xnb_unit_pvt.txb, DOMID_FIRST_RESERVED);
12987e949c46SKenneth D. Merry
12997e949c46SKenneth D. Merry /* Update grant table's status fields as the hypervisor call would */
13007e949c46SKenneth D. Merry xnb_unit_pvt.gnttab[0].status = GNTST_okay;
13017e949c46SKenneth D. Merry
13027e949c46SKenneth D. Merry xnb_update_mbufc(pMbuf, xnb_unit_pvt.gnttab, n_entries);
13037e949c46SKenneth D. Merry XNB_ASSERT(pMbuf->m_len == size);
13047e949c46SKenneth D. Merry XNB_ASSERT(pMbuf->m_pkthdr.len == size);
13057e949c46SKenneth D. Merry safe_m_freem(&pMbuf);
13067e949c46SKenneth D. Merry }
13077e949c46SKenneth D. Merry
13087e949c46SKenneth D. Merry /**
13097e949c46SKenneth D. Merry * xnb_update_mbufc on a packet with two requests, that can fit into a single
13107e949c46SKenneth D. Merry * mbuf cluster
13117e949c46SKenneth D. Merry */
13127e949c46SKenneth D. Merry static void
xnb_update_mbufc_2req(char * buffer,size_t buflen)13137e949c46SKenneth D. Merry xnb_update_mbufc_2req(char *buffer, size_t buflen)
13147e949c46SKenneth D. Merry {
13157e949c46SKenneth D. Merry int n_entries;
13167e949c46SKenneth D. Merry struct xnb_pkt pkt;
13177e949c46SKenneth D. Merry struct mbuf *pMbuf;
13187e949c46SKenneth D. Merry
13197e949c46SKenneth D. Merry struct netif_tx_request *req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
13207e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
13217e949c46SKenneth D. Merry req->flags = NETTXF_more_data;
13227e949c46SKenneth D. Merry req->size = 1900;
13237e949c46SKenneth D. Merry req->gref = 7;
13247e949c46SKenneth D. Merry req->offset = 0;
13257e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
13267e949c46SKenneth D. Merry
13277e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
13287e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
13297e949c46SKenneth D. Merry req->flags = 0;
13307e949c46SKenneth D. Merry req->size = 500;
13317e949c46SKenneth D. Merry req->gref = 8;
13327e949c46SKenneth D. Merry req->offset = 0;
13337e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
13347e949c46SKenneth D. Merry
13357e949c46SKenneth D. Merry RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
13367e949c46SKenneth D. Merry
13377e949c46SKenneth D. Merry xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb, xnb_unit_pvt.txb.req_cons);
13387e949c46SKenneth D. Merry
13397e949c46SKenneth D. Merry pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
13407e949c46SKenneth D. Merry n_entries = xnb_txpkt2gnttab(&pkt, pMbuf, xnb_unit_pvt.gnttab,
13417e949c46SKenneth D. Merry &xnb_unit_pvt.txb, DOMID_FIRST_RESERVED);
13427e949c46SKenneth D. Merry
13437e949c46SKenneth D. Merry /* Update grant table's status fields as the hypervisor call would */
13447e949c46SKenneth D. Merry xnb_unit_pvt.gnttab[0].status = GNTST_okay;
13457e949c46SKenneth D. Merry xnb_unit_pvt.gnttab[1].status = GNTST_okay;
13467e949c46SKenneth D. Merry
13477e949c46SKenneth D. Merry xnb_update_mbufc(pMbuf, xnb_unit_pvt.gnttab, n_entries);
13487e949c46SKenneth D. Merry XNB_ASSERT(n_entries == 2);
13497e949c46SKenneth D. Merry XNB_ASSERT(pMbuf->m_pkthdr.len == 1900);
13507e949c46SKenneth D. Merry XNB_ASSERT(pMbuf->m_len == 1900);
13517e949c46SKenneth D. Merry
13527e949c46SKenneth D. Merry safe_m_freem(&pMbuf);
13537e949c46SKenneth D. Merry }
13547e949c46SKenneth D. Merry
13557e949c46SKenneth D. Merry /**
13567e949c46SKenneth D. Merry * xnb_update_mbufc on a single request that spans two mbuf clusters
13577e949c46SKenneth D. Merry */
13587e949c46SKenneth D. Merry static void
xnb_update_mbufc_2cluster(char * buffer,size_t buflen)13597e949c46SKenneth D. Merry xnb_update_mbufc_2cluster(char *buffer, size_t buflen)
13607e949c46SKenneth D. Merry {
13617e949c46SKenneth D. Merry int i;
13627e949c46SKenneth D. Merry int n_entries;
13637e949c46SKenneth D. Merry struct xnb_pkt pkt;
13647e949c46SKenneth D. Merry struct mbuf *pMbuf;
13657e949c46SKenneth D. Merry const uint16_t data_this_transaction = (MCLBYTES*2) + 1;
13667e949c46SKenneth D. Merry
13677e949c46SKenneth D. Merry struct netif_tx_request *req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
13687e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
13697e949c46SKenneth D. Merry req->flags = 0;
13707e949c46SKenneth D. Merry req->size = data_this_transaction;
13717e949c46SKenneth D. Merry req->gref = 8;
13727e949c46SKenneth D. Merry req->offset = 0;
13737e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt++;
13747e949c46SKenneth D. Merry
13757e949c46SKenneth D. Merry RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
13767e949c46SKenneth D. Merry xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb, xnb_unit_pvt.txb.req_cons);
13777e949c46SKenneth D. Merry
13787e949c46SKenneth D. Merry pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
13797e949c46SKenneth D. Merry n_entries = xnb_txpkt2gnttab(&pkt, pMbuf, xnb_unit_pvt.gnttab,
13807e949c46SKenneth D. Merry &xnb_unit_pvt.txb, DOMID_FIRST_RESERVED);
13817e949c46SKenneth D. Merry
13827e949c46SKenneth D. Merry /* Update grant table's status fields */
13837e949c46SKenneth D. Merry for (i = 0; i < n_entries; i++) {
13847e949c46SKenneth D. Merry xnb_unit_pvt.gnttab[0].status = GNTST_okay;
13857e949c46SKenneth D. Merry }
13867e949c46SKenneth D. Merry xnb_update_mbufc(pMbuf, xnb_unit_pvt.gnttab, n_entries);
13877e949c46SKenneth D. Merry
13887e949c46SKenneth D. Merry if (n_entries == 3) {
13897e949c46SKenneth D. Merry /* there should be three mbufs and three gnttab entries */
13907e949c46SKenneth D. Merry XNB_ASSERT(pMbuf->m_pkthdr.len == data_this_transaction);
13917e949c46SKenneth D. Merry XNB_ASSERT(pMbuf->m_len == MCLBYTES);
13927e949c46SKenneth D. Merry XNB_ASSERT(pMbuf->m_next->m_len == MCLBYTES);
13937e949c46SKenneth D. Merry XNB_ASSERT(pMbuf->m_next->m_next->m_len == 1);
13947e949c46SKenneth D. Merry } else if (n_entries == 2) {
13957e949c46SKenneth D. Merry /* there should be two mbufs and two gnttab entries */
13967e949c46SKenneth D. Merry XNB_ASSERT(n_entries == 2);
13977e949c46SKenneth D. Merry XNB_ASSERT(pMbuf->m_pkthdr.len == data_this_transaction);
13987e949c46SKenneth D. Merry XNB_ASSERT(pMbuf->m_len == 2 * MCLBYTES);
13997e949c46SKenneth D. Merry XNB_ASSERT(pMbuf->m_next->m_len == 1);
14007e949c46SKenneth D. Merry } else {
14017e949c46SKenneth D. Merry /* should never get here */
14027e949c46SKenneth D. Merry XNB_ASSERT(0);
14037e949c46SKenneth D. Merry }
14047e949c46SKenneth D. Merry safe_m_freem(&pMbuf);
14057e949c46SKenneth D. Merry }
14067e949c46SKenneth D. Merry
14077e949c46SKenneth D. Merry /** xnb_mbufc2pkt on an empty mbufc */
14087e949c46SKenneth D. Merry static void
xnb_mbufc2pkt_empty(char * buffer,size_t buflen)14097e949c46SKenneth D. Merry xnb_mbufc2pkt_empty(char *buffer, size_t buflen) {
14107e949c46SKenneth D. Merry struct xnb_pkt pkt;
14117e949c46SKenneth D. Merry int free_slots = 64;
14127e949c46SKenneth D. Merry struct mbuf *mbuf;
14137e949c46SKenneth D. Merry
14147e949c46SKenneth D. Merry mbuf = m_get(M_WAITOK, MT_DATA);
14157e949c46SKenneth D. Merry /*
14167e949c46SKenneth D. Merry * note: it is illegal to set M_PKTHDR on a mbuf with no data. Doing so
14177e949c46SKenneth D. Merry * will cause m_freem to segfault
14187e949c46SKenneth D. Merry */
14197e949c46SKenneth D. Merry XNB_ASSERT(mbuf->m_len == 0);
14207e949c46SKenneth D. Merry
14217e949c46SKenneth D. Merry xnb_mbufc2pkt(mbuf, &pkt, 0, free_slots);
14227e949c46SKenneth D. Merry XNB_ASSERT(! xnb_pkt_is_valid(&pkt));
14237e949c46SKenneth D. Merry
14247e949c46SKenneth D. Merry safe_m_freem(&mbuf);
14257e949c46SKenneth D. Merry }
14267e949c46SKenneth D. Merry
14277e949c46SKenneth D. Merry /** xnb_mbufc2pkt on a short mbufc */
14287e949c46SKenneth D. Merry static void
xnb_mbufc2pkt_short(char * buffer,size_t buflen)14297e949c46SKenneth D. Merry xnb_mbufc2pkt_short(char *buffer, size_t buflen) {
14307e949c46SKenneth D. Merry struct xnb_pkt pkt;
14317e949c46SKenneth D. Merry size_t size = 128;
14327e949c46SKenneth D. Merry int free_slots = 64;
14337e949c46SKenneth D. Merry RING_IDX start = 9;
14347e949c46SKenneth D. Merry struct mbuf *mbuf;
14357e949c46SKenneth D. Merry
14367e949c46SKenneth D. Merry mbuf = m_getm(NULL, size, M_WAITOK, MT_DATA);
14377e949c46SKenneth D. Merry mbuf->m_flags |= M_PKTHDR;
14387e949c46SKenneth D. Merry mbuf->m_pkthdr.len = size;
14397e949c46SKenneth D. Merry mbuf->m_len = size;
14407e949c46SKenneth D. Merry
14417e949c46SKenneth D. Merry xnb_mbufc2pkt(mbuf, &pkt, start, free_slots);
14427e949c46SKenneth D. Merry XNB_ASSERT(xnb_pkt_is_valid(&pkt));
14437e949c46SKenneth D. Merry XNB_ASSERT(pkt.size == size);
14447e949c46SKenneth D. Merry XNB_ASSERT(pkt.car_size == size);
14457e949c46SKenneth D. Merry XNB_ASSERT(! (pkt.flags &
14467e949c46SKenneth D. Merry (NETRXF_more_data | NETRXF_extra_info)));
14477e949c46SKenneth D. Merry XNB_ASSERT(pkt.list_len == 1);
14487e949c46SKenneth D. Merry XNB_ASSERT(pkt.car == start);
14497e949c46SKenneth D. Merry
14507e949c46SKenneth D. Merry safe_m_freem(&mbuf);
14517e949c46SKenneth D. Merry }
14527e949c46SKenneth D. Merry
14537e949c46SKenneth D. Merry /** xnb_mbufc2pkt on a single mbuf with an mbuf cluster */
14547e949c46SKenneth D. Merry static void
xnb_mbufc2pkt_1cluster(char * buffer,size_t buflen)14557e949c46SKenneth D. Merry xnb_mbufc2pkt_1cluster(char *buffer, size_t buflen) {
14567e949c46SKenneth D. Merry struct xnb_pkt pkt;
14577e949c46SKenneth D. Merry size_t size = MCLBYTES;
14587e949c46SKenneth D. Merry int free_slots = 32;
14597e949c46SKenneth D. Merry RING_IDX start = 12;
14607e949c46SKenneth D. Merry struct mbuf *mbuf;
14617e949c46SKenneth D. Merry
14627e949c46SKenneth D. Merry mbuf = m_getm(NULL, size, M_WAITOK, MT_DATA);
14637e949c46SKenneth D. Merry mbuf->m_flags |= M_PKTHDR;
14647e949c46SKenneth D. Merry mbuf->m_pkthdr.len = size;
14657e949c46SKenneth D. Merry mbuf->m_len = size;
14667e949c46SKenneth D. Merry
14677e949c46SKenneth D. Merry xnb_mbufc2pkt(mbuf, &pkt, start, free_slots);
14687e949c46SKenneth D. Merry XNB_ASSERT(xnb_pkt_is_valid(&pkt));
14697e949c46SKenneth D. Merry XNB_ASSERT(pkt.size == size);
14707e949c46SKenneth D. Merry XNB_ASSERT(pkt.car_size == size);
14717e949c46SKenneth D. Merry XNB_ASSERT(! (pkt.flags &
14727e949c46SKenneth D. Merry (NETRXF_more_data | NETRXF_extra_info)));
14737e949c46SKenneth D. Merry XNB_ASSERT(pkt.list_len == 1);
14747e949c46SKenneth D. Merry XNB_ASSERT(pkt.car == start);
14757e949c46SKenneth D. Merry
14767e949c46SKenneth D. Merry safe_m_freem(&mbuf);
14777e949c46SKenneth D. Merry }
14787e949c46SKenneth D. Merry
14790af1b472SEitan Adler /** xnb_mbufc2pkt on a two-mbuf chain with short data regions */
14807e949c46SKenneth D. Merry static void
xnb_mbufc2pkt_2short(char * buffer,size_t buflen)14817e949c46SKenneth D. Merry xnb_mbufc2pkt_2short(char *buffer, size_t buflen) {
14827e949c46SKenneth D. Merry struct xnb_pkt pkt;
14837e949c46SKenneth D. Merry size_t size1 = MHLEN - 5;
14847e949c46SKenneth D. Merry size_t size2 = MHLEN - 15;
14857e949c46SKenneth D. Merry int free_slots = 32;
14867e949c46SKenneth D. Merry RING_IDX start = 14;
14877e949c46SKenneth D. Merry struct mbuf *mbufc, *mbufc2;
14887e949c46SKenneth D. Merry
14897e949c46SKenneth D. Merry mbufc = m_getm(NULL, size1, M_WAITOK, MT_DATA);
14907e949c46SKenneth D. Merry XNB_ASSERT(mbufc != NULL);
1491407d708cSAlan Somers if (mbufc == NULL)
14927e949c46SKenneth D. Merry return;
1493407d708cSAlan Somers mbufc->m_flags |= M_PKTHDR;
14947e949c46SKenneth D. Merry
14957e949c46SKenneth D. Merry mbufc2 = m_getm(mbufc, size2, M_WAITOK, MT_DATA);
14967e949c46SKenneth D. Merry XNB_ASSERT(mbufc2 != NULL);
1497407d708cSAlan Somers if (mbufc2 == NULL) {
14987e949c46SKenneth D. Merry safe_m_freem(&mbufc);
14997e949c46SKenneth D. Merry return;
15007e949c46SKenneth D. Merry }
15017e949c46SKenneth D. Merry mbufc2->m_pkthdr.len = size1 + size2;
15027e949c46SKenneth D. Merry mbufc2->m_len = size1;
15037e949c46SKenneth D. Merry
15047e949c46SKenneth D. Merry xnb_mbufc2pkt(mbufc2, &pkt, start, free_slots);
15057e949c46SKenneth D. Merry XNB_ASSERT(xnb_pkt_is_valid(&pkt));
15067e949c46SKenneth D. Merry XNB_ASSERT(pkt.size == size1 + size2);
15077e949c46SKenneth D. Merry XNB_ASSERT(pkt.car == start);
15087e949c46SKenneth D. Merry /*
15097e949c46SKenneth D. Merry * The second m_getm may allocate a new mbuf and append
15107e949c46SKenneth D. Merry * it to the chain, or it may simply extend the first mbuf.
15117e949c46SKenneth D. Merry */
15127e949c46SKenneth D. Merry if (mbufc2->m_next != NULL) {
15137e949c46SKenneth D. Merry XNB_ASSERT(pkt.car_size == size1);
15147e949c46SKenneth D. Merry XNB_ASSERT(pkt.list_len == 1);
15157e949c46SKenneth D. Merry XNB_ASSERT(pkt.cdr == start + 1);
15167e949c46SKenneth D. Merry }
15177e949c46SKenneth D. Merry
15187e949c46SKenneth D. Merry safe_m_freem(&mbufc2);
15197e949c46SKenneth D. Merry }
15207e949c46SKenneth D. Merry
15210af1b472SEitan Adler /** xnb_mbufc2pkt on a mbuf chain with >1 mbuf cluster */
15227e949c46SKenneth D. Merry static void
xnb_mbufc2pkt_long(char * buffer,size_t buflen)15237e949c46SKenneth D. Merry xnb_mbufc2pkt_long(char *buffer, size_t buflen) {
15247e949c46SKenneth D. Merry struct xnb_pkt pkt;
15257e949c46SKenneth D. Merry size_t size = 14 * MCLBYTES / 3;
15267e949c46SKenneth D. Merry size_t size_remaining;
15277e949c46SKenneth D. Merry int free_slots = 15;
15287e949c46SKenneth D. Merry RING_IDX start = 3;
15297e949c46SKenneth D. Merry struct mbuf *mbufc, *m;
15307e949c46SKenneth D. Merry
15317e949c46SKenneth D. Merry mbufc = m_getm(NULL, size, M_WAITOK, MT_DATA);
15327e949c46SKenneth D. Merry XNB_ASSERT(mbufc != NULL);
1533407d708cSAlan Somers if (mbufc == NULL)
15347e949c46SKenneth D. Merry return;
1535407d708cSAlan Somers mbufc->m_flags |= M_PKTHDR;
15367e949c46SKenneth D. Merry
15377e949c46SKenneth D. Merry mbufc->m_pkthdr.len = size;
15387e949c46SKenneth D. Merry size_remaining = size;
15397e949c46SKenneth D. Merry for (m = mbufc; m != NULL; m = m->m_next) {
15407e949c46SKenneth D. Merry m->m_len = MAX(M_TRAILINGSPACE(m), size_remaining);
15417e949c46SKenneth D. Merry size_remaining -= m->m_len;
15427e949c46SKenneth D. Merry }
15437e949c46SKenneth D. Merry
15447e949c46SKenneth D. Merry xnb_mbufc2pkt(mbufc, &pkt, start, free_slots);
15457e949c46SKenneth D. Merry XNB_ASSERT(xnb_pkt_is_valid(&pkt));
15467e949c46SKenneth D. Merry XNB_ASSERT(pkt.size == size);
15477e949c46SKenneth D. Merry XNB_ASSERT(pkt.car == start);
15487e949c46SKenneth D. Merry XNB_ASSERT(pkt.car_size = mbufc->m_len);
15497e949c46SKenneth D. Merry /*
15507e949c46SKenneth D. Merry * There should be >1 response in the packet, and there is no
15517e949c46SKenneth D. Merry * extra info.
15527e949c46SKenneth D. Merry */
15537e949c46SKenneth D. Merry XNB_ASSERT(! (pkt.flags & NETRXF_extra_info));
15547e949c46SKenneth D. Merry XNB_ASSERT(pkt.cdr == pkt.car + 1);
15557e949c46SKenneth D. Merry
15567e949c46SKenneth D. Merry safe_m_freem(&mbufc);
15577e949c46SKenneth D. Merry }
15587e949c46SKenneth D. Merry
15590af1b472SEitan Adler /** xnb_mbufc2pkt on a mbuf chain with >1 mbuf cluster and extra info */
15607e949c46SKenneth D. Merry static void
xnb_mbufc2pkt_extra(char * buffer,size_t buflen)15617e949c46SKenneth D. Merry xnb_mbufc2pkt_extra(char *buffer, size_t buflen) {
15627e949c46SKenneth D. Merry struct xnb_pkt pkt;
15637e949c46SKenneth D. Merry size_t size = 14 * MCLBYTES / 3;
15647e949c46SKenneth D. Merry size_t size_remaining;
15657e949c46SKenneth D. Merry int free_slots = 15;
15667e949c46SKenneth D. Merry RING_IDX start = 3;
15677e949c46SKenneth D. Merry struct mbuf *mbufc, *m;
15687e949c46SKenneth D. Merry
15697e949c46SKenneth D. Merry mbufc = m_getm(NULL, size, M_WAITOK, MT_DATA);
15707e949c46SKenneth D. Merry XNB_ASSERT(mbufc != NULL);
1571407d708cSAlan Somers if (mbufc == NULL)
15727e949c46SKenneth D. Merry return;
15737e949c46SKenneth D. Merry
15747e949c46SKenneth D. Merry mbufc->m_flags |= M_PKTHDR;
15757e949c46SKenneth D. Merry mbufc->m_pkthdr.len = size;
15767e949c46SKenneth D. Merry mbufc->m_pkthdr.csum_flags |= CSUM_TSO;
15777e949c46SKenneth D. Merry mbufc->m_pkthdr.tso_segsz = TCP_MSS - 40;
15787e949c46SKenneth D. Merry size_remaining = size;
15797e949c46SKenneth D. Merry for (m = mbufc; m != NULL; m = m->m_next) {
15807e949c46SKenneth D. Merry m->m_len = MAX(M_TRAILINGSPACE(m), size_remaining);
15817e949c46SKenneth D. Merry size_remaining -= m->m_len;
15827e949c46SKenneth D. Merry }
15837e949c46SKenneth D. Merry
15847e949c46SKenneth D. Merry xnb_mbufc2pkt(mbufc, &pkt, start, free_slots);
15857e949c46SKenneth D. Merry XNB_ASSERT(xnb_pkt_is_valid(&pkt));
15867e949c46SKenneth D. Merry XNB_ASSERT(pkt.size == size);
15877e949c46SKenneth D. Merry XNB_ASSERT(pkt.car == start);
15887e949c46SKenneth D. Merry XNB_ASSERT(pkt.car_size = mbufc->m_len);
15897e949c46SKenneth D. Merry /* There should be >1 response in the packet, there is extra info */
15907e949c46SKenneth D. Merry XNB_ASSERT(pkt.flags & NETRXF_extra_info);
15917e949c46SKenneth D. Merry XNB_ASSERT(pkt.flags & NETRXF_data_validated);
15927e949c46SKenneth D. Merry XNB_ASSERT(pkt.cdr == pkt.car + 2);
15937e949c46SKenneth D. Merry XNB_ASSERT(pkt.extra.u.gso.size = mbufc->m_pkthdr.tso_segsz);
15947e949c46SKenneth D. Merry XNB_ASSERT(pkt.extra.type == XEN_NETIF_EXTRA_TYPE_GSO);
15957e949c46SKenneth D. Merry XNB_ASSERT(! (pkt.extra.flags & XEN_NETIF_EXTRA_FLAG_MORE));
15967e949c46SKenneth D. Merry
15977e949c46SKenneth D. Merry safe_m_freem(&mbufc);
15987e949c46SKenneth D. Merry }
15997e949c46SKenneth D. Merry
16007e949c46SKenneth D. Merry /** xnb_mbufc2pkt with insufficient space in the ring */
16017e949c46SKenneth D. Merry static void
xnb_mbufc2pkt_nospace(char * buffer,size_t buflen)16027e949c46SKenneth D. Merry xnb_mbufc2pkt_nospace(char *buffer, size_t buflen) {
16037e949c46SKenneth D. Merry struct xnb_pkt pkt;
16047e949c46SKenneth D. Merry size_t size = 14 * MCLBYTES / 3;
16057e949c46SKenneth D. Merry size_t size_remaining;
16067e949c46SKenneth D. Merry int free_slots = 2;
16077e949c46SKenneth D. Merry RING_IDX start = 3;
16087e949c46SKenneth D. Merry struct mbuf *mbufc, *m;
16097e949c46SKenneth D. Merry int error;
16107e949c46SKenneth D. Merry
16117e949c46SKenneth D. Merry mbufc = m_getm(NULL, size, M_WAITOK, MT_DATA);
16127e949c46SKenneth D. Merry XNB_ASSERT(mbufc != NULL);
1613407d708cSAlan Somers if (mbufc == NULL)
16147e949c46SKenneth D. Merry return;
1615407d708cSAlan Somers mbufc->m_flags |= M_PKTHDR;
16167e949c46SKenneth D. Merry
16177e949c46SKenneth D. Merry mbufc->m_pkthdr.len = size;
16187e949c46SKenneth D. Merry size_remaining = size;
16197e949c46SKenneth D. Merry for (m = mbufc; m != NULL; m = m->m_next) {
16207e949c46SKenneth D. Merry m->m_len = MAX(M_TRAILINGSPACE(m), size_remaining);
16217e949c46SKenneth D. Merry size_remaining -= m->m_len;
16227e949c46SKenneth D. Merry }
16237e949c46SKenneth D. Merry
16247e949c46SKenneth D. Merry error = xnb_mbufc2pkt(mbufc, &pkt, start, free_slots);
16257e949c46SKenneth D. Merry XNB_ASSERT(error == EAGAIN);
16267e949c46SKenneth D. Merry XNB_ASSERT(! xnb_pkt_is_valid(&pkt));
16277e949c46SKenneth D. Merry
16287e949c46SKenneth D. Merry safe_m_freem(&mbufc);
16297e949c46SKenneth D. Merry }
16307e949c46SKenneth D. Merry
16317e949c46SKenneth D. Merry /**
16327e949c46SKenneth D. Merry * xnb_rxpkt2gnttab on an empty packet. Should return empty gnttab
16337e949c46SKenneth D. Merry */
16347e949c46SKenneth D. Merry static void
xnb_rxpkt2gnttab_empty(char * buffer,size_t buflen)16357e949c46SKenneth D. Merry xnb_rxpkt2gnttab_empty(char *buffer, size_t buflen)
16367e949c46SKenneth D. Merry {
16377e949c46SKenneth D. Merry struct xnb_pkt pkt;
16387e949c46SKenneth D. Merry int nr_entries;
16397e949c46SKenneth D. Merry int free_slots = 60;
16407e949c46SKenneth D. Merry struct mbuf *mbuf;
16417e949c46SKenneth D. Merry
16427e949c46SKenneth D. Merry mbuf = m_get(M_WAITOK, MT_DATA);
16437e949c46SKenneth D. Merry
16447e949c46SKenneth D. Merry xnb_mbufc2pkt(mbuf, &pkt, 0, free_slots);
16457e949c46SKenneth D. Merry nr_entries = xnb_rxpkt2gnttab(&pkt, mbuf, xnb_unit_pvt.gnttab,
16467e949c46SKenneth D. Merry &xnb_unit_pvt.rxb, DOMID_FIRST_RESERVED);
16477e949c46SKenneth D. Merry
16487e949c46SKenneth D. Merry XNB_ASSERT(nr_entries == 0);
16497e949c46SKenneth D. Merry
16507e949c46SKenneth D. Merry safe_m_freem(&mbuf);
16517e949c46SKenneth D. Merry }
16527e949c46SKenneth D. Merry
16537e949c46SKenneth D. Merry /** xnb_rxpkt2gnttab on a short packet without extra data */
16547e949c46SKenneth D. Merry static void
xnb_rxpkt2gnttab_short(char * buffer,size_t buflen)16557e949c46SKenneth D. Merry xnb_rxpkt2gnttab_short(char *buffer, size_t buflen) {
16567e949c46SKenneth D. Merry struct xnb_pkt pkt;
16577e949c46SKenneth D. Merry int nr_entries;
16587e949c46SKenneth D. Merry size_t size = 128;
16597e949c46SKenneth D. Merry int free_slots = 60;
16607e949c46SKenneth D. Merry RING_IDX start = 9;
16617e949c46SKenneth D. Merry struct netif_rx_request *req;
16627e949c46SKenneth D. Merry struct mbuf *mbuf;
16637e949c46SKenneth D. Merry
16647e949c46SKenneth D. Merry mbuf = m_getm(NULL, size, M_WAITOK, MT_DATA);
16657e949c46SKenneth D. Merry mbuf->m_flags |= M_PKTHDR;
16667e949c46SKenneth D. Merry mbuf->m_pkthdr.len = size;
16677e949c46SKenneth D. Merry mbuf->m_len = size;
16687e949c46SKenneth D. Merry
16697e949c46SKenneth D. Merry xnb_mbufc2pkt(mbuf, &pkt, start, free_slots);
16707e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.rxf,
16717e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
16727e949c46SKenneth D. Merry req->gref = 7;
16737e949c46SKenneth D. Merry
16747e949c46SKenneth D. Merry nr_entries = xnb_rxpkt2gnttab(&pkt, mbuf, xnb_unit_pvt.gnttab,
16757e949c46SKenneth D. Merry &xnb_unit_pvt.rxb, DOMID_FIRST_RESERVED);
16767e949c46SKenneth D. Merry
16777e949c46SKenneth D. Merry XNB_ASSERT(nr_entries == 1);
16787e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[0].len == size);
16797e949c46SKenneth D. Merry /* flags should indicate gref's for dest */
16807e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[0].flags & GNTCOPY_dest_gref);
16817e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[0].dest.offset == 0);
16827e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[0].source.domid == DOMID_SELF);
16837e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[0].source.offset == virt_to_offset(
16847e949c46SKenneth D. Merry mtod(mbuf, vm_offset_t)));
16857e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[0].source.u.gmfn ==
16867e949c46SKenneth D. Merry virt_to_mfn(mtod(mbuf, vm_offset_t)));
16877e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.gnttab[0].dest.domid == DOMID_FIRST_RESERVED);
16887e949c46SKenneth D. Merry
16897e949c46SKenneth D. Merry safe_m_freem(&mbuf);
16907e949c46SKenneth D. Merry }
16917e949c46SKenneth D. Merry
16927e949c46SKenneth D. Merry /**
16937e949c46SKenneth D. Merry * xnb_rxpkt2gnttab on a packet with two different mbufs in a single chai
16947e949c46SKenneth D. Merry */
16957e949c46SKenneth D. Merry static void
xnb_rxpkt2gnttab_2req(char * buffer,size_t buflen)16967e949c46SKenneth D. Merry xnb_rxpkt2gnttab_2req(char *buffer, size_t buflen)
16977e949c46SKenneth D. Merry {
16987e949c46SKenneth D. Merry struct xnb_pkt pkt;
16997e949c46SKenneth D. Merry int nr_entries;
17007e949c46SKenneth D. Merry int i, num_mbufs;
17017e949c46SKenneth D. Merry size_t total_granted_size = 0;
17027e949c46SKenneth D. Merry size_t size = MJUMPAGESIZE + 1;
17037e949c46SKenneth D. Merry int free_slots = 60;
17047e949c46SKenneth D. Merry RING_IDX start = 11;
17057e949c46SKenneth D. Merry struct netif_rx_request *req;
17067e949c46SKenneth D. Merry struct mbuf *mbuf, *m;
17077e949c46SKenneth D. Merry
17087e949c46SKenneth D. Merry mbuf = m_getm(NULL, size, M_WAITOK, MT_DATA);
17097e949c46SKenneth D. Merry mbuf->m_flags |= M_PKTHDR;
17107e949c46SKenneth D. Merry mbuf->m_pkthdr.len = size;
17117e949c46SKenneth D. Merry mbuf->m_len = size;
17127e949c46SKenneth D. Merry
17137e949c46SKenneth D. Merry xnb_mbufc2pkt(mbuf, &pkt, start, free_slots);
17147e949c46SKenneth D. Merry
17157e949c46SKenneth D. Merry for (i = 0, m=mbuf; m != NULL; i++, m = m->m_next) {
17167e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.rxf,
17177e949c46SKenneth D. Merry xnb_unit_pvt.txf.req_prod_pvt);
17187e949c46SKenneth D. Merry req->gref = i;
17197e949c46SKenneth D. Merry req->id = 5;
17207e949c46SKenneth D. Merry }
17217e949c46SKenneth D. Merry num_mbufs = i;
17227e949c46SKenneth D. Merry
17237e949c46SKenneth D. Merry nr_entries = xnb_rxpkt2gnttab(&pkt, mbuf, xnb_unit_pvt.gnttab,
17247e949c46SKenneth D. Merry &xnb_unit_pvt.rxb, DOMID_FIRST_RESERVED);
17257e949c46SKenneth D. Merry
17267e949c46SKenneth D. Merry XNB_ASSERT(nr_entries >= num_mbufs);
17277e949c46SKenneth D. Merry for (i = 0; i < nr_entries; i++) {
17287e949c46SKenneth D. Merry int end_offset = xnb_unit_pvt.gnttab[i].len +
17297e949c46SKenneth D. Merry xnb_unit_pvt.gnttab[i].dest.offset;
17307e949c46SKenneth D. Merry XNB_ASSERT(end_offset <= PAGE_SIZE);
17317e949c46SKenneth D. Merry total_granted_size += xnb_unit_pvt.gnttab[i].len;
17327e949c46SKenneth D. Merry }
17337e949c46SKenneth D. Merry XNB_ASSERT(total_granted_size == size);
17347e949c46SKenneth D. Merry }
17357e949c46SKenneth D. Merry
17367e949c46SKenneth D. Merry /**
17377e949c46SKenneth D. Merry * xnb_rxpkt2rsp on an empty packet. Shouldn't make any response
17387e949c46SKenneth D. Merry */
17397e949c46SKenneth D. Merry static void
xnb_rxpkt2rsp_empty(char * buffer,size_t buflen)17407e949c46SKenneth D. Merry xnb_rxpkt2rsp_empty(char *buffer, size_t buflen)
17417e949c46SKenneth D. Merry {
17427e949c46SKenneth D. Merry struct xnb_pkt pkt;
17437e949c46SKenneth D. Merry int nr_entries;
17447e949c46SKenneth D. Merry int nr_reqs;
17457e949c46SKenneth D. Merry int free_slots = 60;
17467e949c46SKenneth D. Merry netif_rx_back_ring_t rxb_backup = xnb_unit_pvt.rxb;
17477e949c46SKenneth D. Merry netif_rx_sring_t rxs_backup = *xnb_unit_pvt.rxs;
17487e949c46SKenneth D. Merry struct mbuf *mbuf;
17497e949c46SKenneth D. Merry
17507e949c46SKenneth D. Merry mbuf = m_get(M_WAITOK, MT_DATA);
17517e949c46SKenneth D. Merry
17527e949c46SKenneth D. Merry xnb_mbufc2pkt(mbuf, &pkt, 0, free_slots);
17537e949c46SKenneth D. Merry nr_entries = xnb_rxpkt2gnttab(&pkt, mbuf, xnb_unit_pvt.gnttab,
17547e949c46SKenneth D. Merry &xnb_unit_pvt.rxb, DOMID_FIRST_RESERVED);
17557e949c46SKenneth D. Merry
17567e949c46SKenneth D. Merry nr_reqs = xnb_rxpkt2rsp(&pkt, xnb_unit_pvt.gnttab, nr_entries,
17577e949c46SKenneth D. Merry &xnb_unit_pvt.rxb);
17587e949c46SKenneth D. Merry XNB_ASSERT(nr_reqs == 0);
17597e949c46SKenneth D. Merry XNB_ASSERT(
17607e949c46SKenneth D. Merry memcmp(&rxb_backup, &xnb_unit_pvt.rxb, sizeof(rxb_backup)) == 0);
17617e949c46SKenneth D. Merry XNB_ASSERT(
17627e949c46SKenneth D. Merry memcmp(&rxs_backup, xnb_unit_pvt.rxs, sizeof(rxs_backup)) == 0);
17637e949c46SKenneth D. Merry
17647e949c46SKenneth D. Merry safe_m_freem(&mbuf);
17657e949c46SKenneth D. Merry }
17667e949c46SKenneth D. Merry
17677e949c46SKenneth D. Merry /**
17687e949c46SKenneth D. Merry * xnb_rxpkt2rsp on a short packet with no extras
17697e949c46SKenneth D. Merry */
17707e949c46SKenneth D. Merry static void
xnb_rxpkt2rsp_short(char * buffer,size_t buflen)17717e949c46SKenneth D. Merry xnb_rxpkt2rsp_short(char *buffer, size_t buflen)
17727e949c46SKenneth D. Merry {
17737e949c46SKenneth D. Merry struct xnb_pkt pkt;
17747e949c46SKenneth D. Merry int nr_entries, nr_reqs;
17757e949c46SKenneth D. Merry size_t size = 128;
17767e949c46SKenneth D. Merry int free_slots = 60;
17777e949c46SKenneth D. Merry RING_IDX start = 5;
17787e949c46SKenneth D. Merry struct netif_rx_request *req;
17797e949c46SKenneth D. Merry struct netif_rx_response *rsp;
17807e949c46SKenneth D. Merry struct mbuf *mbuf;
17817e949c46SKenneth D. Merry
17827e949c46SKenneth D. Merry mbuf = m_getm(NULL, size, M_WAITOK, MT_DATA);
17837e949c46SKenneth D. Merry mbuf->m_flags |= M_PKTHDR;
17847e949c46SKenneth D. Merry mbuf->m_pkthdr.len = size;
17857e949c46SKenneth D. Merry mbuf->m_len = size;
17867e949c46SKenneth D. Merry
17877e949c46SKenneth D. Merry xnb_mbufc2pkt(mbuf, &pkt, start, free_slots);
17887e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.rxf, start);
17897e949c46SKenneth D. Merry req->gref = 7;
17907e949c46SKenneth D. Merry xnb_unit_pvt.rxb.req_cons = start;
17917e949c46SKenneth D. Merry xnb_unit_pvt.rxb.rsp_prod_pvt = start;
17927e949c46SKenneth D. Merry xnb_unit_pvt.rxs->req_prod = start + 1;
17937e949c46SKenneth D. Merry xnb_unit_pvt.rxs->rsp_prod = start;
17947e949c46SKenneth D. Merry
17957e949c46SKenneth D. Merry nr_entries = xnb_rxpkt2gnttab(&pkt, mbuf, xnb_unit_pvt.gnttab,
17967e949c46SKenneth D. Merry &xnb_unit_pvt.rxb, DOMID_FIRST_RESERVED);
17977e949c46SKenneth D. Merry
17987e949c46SKenneth D. Merry nr_reqs = xnb_rxpkt2rsp(&pkt, xnb_unit_pvt.gnttab, nr_entries,
17997e949c46SKenneth D. Merry &xnb_unit_pvt.rxb);
18007e949c46SKenneth D. Merry
18017e949c46SKenneth D. Merry XNB_ASSERT(nr_reqs == 1);
18027e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.rxb.rsp_prod_pvt == start + 1);
18037e949c46SKenneth D. Merry rsp = RING_GET_RESPONSE(&xnb_unit_pvt.rxb, start);
18047e949c46SKenneth D. Merry XNB_ASSERT(rsp->id == req->id);
18057e949c46SKenneth D. Merry XNB_ASSERT(rsp->offset == 0);
18067e949c46SKenneth D. Merry XNB_ASSERT((rsp->flags & (NETRXF_more_data | NETRXF_extra_info)) == 0);
18077e949c46SKenneth D. Merry XNB_ASSERT(rsp->status == size);
18087e949c46SKenneth D. Merry
18097e949c46SKenneth D. Merry safe_m_freem(&mbuf);
18107e949c46SKenneth D. Merry }
18117e949c46SKenneth D. Merry
18127e949c46SKenneth D. Merry /**
18137e949c46SKenneth D. Merry * xnb_rxpkt2rsp with extra data
18147e949c46SKenneth D. Merry */
18157e949c46SKenneth D. Merry static void
xnb_rxpkt2rsp_extra(char * buffer,size_t buflen)18167e949c46SKenneth D. Merry xnb_rxpkt2rsp_extra(char *buffer, size_t buflen)
18177e949c46SKenneth D. Merry {
18187e949c46SKenneth D. Merry struct xnb_pkt pkt;
18197e949c46SKenneth D. Merry int nr_entries, nr_reqs;
18207e949c46SKenneth D. Merry size_t size = 14;
18217e949c46SKenneth D. Merry int free_slots = 15;
18227e949c46SKenneth D. Merry RING_IDX start = 3;
18237e949c46SKenneth D. Merry uint16_t id = 49;
18247e949c46SKenneth D. Merry uint16_t gref = 65;
18257e949c46SKenneth D. Merry uint16_t mss = TCP_MSS - 40;
18267e949c46SKenneth D. Merry struct mbuf *mbufc;
18277e949c46SKenneth D. Merry struct netif_rx_request *req;
18287e949c46SKenneth D. Merry struct netif_rx_response *rsp;
18297e949c46SKenneth D. Merry struct netif_extra_info *ext;
18307e949c46SKenneth D. Merry
18317e949c46SKenneth D. Merry mbufc = m_getm(NULL, size, M_WAITOK, MT_DATA);
18327e949c46SKenneth D. Merry XNB_ASSERT(mbufc != NULL);
1833407d708cSAlan Somers if (mbufc == NULL)
18347e949c46SKenneth D. Merry return;
18357e949c46SKenneth D. Merry
18367e949c46SKenneth D. Merry mbufc->m_flags |= M_PKTHDR;
18377e949c46SKenneth D. Merry mbufc->m_pkthdr.len = size;
18387e949c46SKenneth D. Merry mbufc->m_pkthdr.csum_flags |= CSUM_TSO;
18397e949c46SKenneth D. Merry mbufc->m_pkthdr.tso_segsz = mss;
18407e949c46SKenneth D. Merry mbufc->m_len = size;
18417e949c46SKenneth D. Merry
18427e949c46SKenneth D. Merry xnb_mbufc2pkt(mbufc, &pkt, start, free_slots);
18437e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.rxf, start);
18447e949c46SKenneth D. Merry req->id = id;
18457e949c46SKenneth D. Merry req->gref = gref;
18467e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.rxf, start + 1);
18477e949c46SKenneth D. Merry req->id = id + 1;
18487e949c46SKenneth D. Merry req->gref = gref + 1;
18497e949c46SKenneth D. Merry xnb_unit_pvt.rxb.req_cons = start;
18507e949c46SKenneth D. Merry xnb_unit_pvt.rxb.rsp_prod_pvt = start;
18517e949c46SKenneth D. Merry xnb_unit_pvt.rxs->req_prod = start + 2;
18527e949c46SKenneth D. Merry xnb_unit_pvt.rxs->rsp_prod = start;
18537e949c46SKenneth D. Merry
18547e949c46SKenneth D. Merry nr_entries = xnb_rxpkt2gnttab(&pkt, mbufc, xnb_unit_pvt.gnttab,
18557e949c46SKenneth D. Merry &xnb_unit_pvt.rxb, DOMID_FIRST_RESERVED);
18567e949c46SKenneth D. Merry
18577e949c46SKenneth D. Merry nr_reqs = xnb_rxpkt2rsp(&pkt, xnb_unit_pvt.gnttab, nr_entries,
18587e949c46SKenneth D. Merry &xnb_unit_pvt.rxb);
18597e949c46SKenneth D. Merry
18607e949c46SKenneth D. Merry XNB_ASSERT(nr_reqs == 2);
18617e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.rxb.rsp_prod_pvt == start + 2);
18627e949c46SKenneth D. Merry rsp = RING_GET_RESPONSE(&xnb_unit_pvt.rxb, start);
18637e949c46SKenneth D. Merry XNB_ASSERT(rsp->id == id);
18647e949c46SKenneth D. Merry XNB_ASSERT((rsp->flags & NETRXF_more_data) == 0);
18657e949c46SKenneth D. Merry XNB_ASSERT((rsp->flags & NETRXF_extra_info));
18667e949c46SKenneth D. Merry XNB_ASSERT((rsp->flags & NETRXF_data_validated));
18677e949c46SKenneth D. Merry XNB_ASSERT((rsp->flags & NETRXF_csum_blank));
18687e949c46SKenneth D. Merry XNB_ASSERT(rsp->status == size);
18697e949c46SKenneth D. Merry
18707e949c46SKenneth D. Merry ext = (struct netif_extra_info*)
18717e949c46SKenneth D. Merry RING_GET_RESPONSE(&xnb_unit_pvt.rxb, start + 1);
18727e949c46SKenneth D. Merry XNB_ASSERT(ext->type == XEN_NETIF_EXTRA_TYPE_GSO);
18737e949c46SKenneth D. Merry XNB_ASSERT(! (ext->flags & XEN_NETIF_EXTRA_FLAG_MORE));
18747e949c46SKenneth D. Merry XNB_ASSERT(ext->u.gso.size == mss);
18757e949c46SKenneth D. Merry XNB_ASSERT(ext->u.gso.type == XEN_NETIF_EXTRA_TYPE_GSO);
18767e949c46SKenneth D. Merry
18777e949c46SKenneth D. Merry safe_m_freem(&mbufc);
18787e949c46SKenneth D. Merry }
18797e949c46SKenneth D. Merry
18807e949c46SKenneth D. Merry /**
18817e949c46SKenneth D. Merry * xnb_rxpkt2rsp on a packet with more than a pages's worth of data. It should
18827e949c46SKenneth D. Merry * generate two response slot
18837e949c46SKenneth D. Merry */
18847e949c46SKenneth D. Merry static void
xnb_rxpkt2rsp_2slots(char * buffer,size_t buflen)18857e949c46SKenneth D. Merry xnb_rxpkt2rsp_2slots(char *buffer, size_t buflen)
18867e949c46SKenneth D. Merry {
18877e949c46SKenneth D. Merry struct xnb_pkt pkt;
18887e949c46SKenneth D. Merry int nr_entries, nr_reqs;
18897e949c46SKenneth D. Merry size_t size = PAGE_SIZE + 100;
18907e949c46SKenneth D. Merry int free_slots = 3;
18917e949c46SKenneth D. Merry uint16_t id1 = 17;
18927e949c46SKenneth D. Merry uint16_t id2 = 37;
18937e949c46SKenneth D. Merry uint16_t gref1 = 24;
18947e949c46SKenneth D. Merry uint16_t gref2 = 34;
18957e949c46SKenneth D. Merry RING_IDX start = 15;
18967e949c46SKenneth D. Merry struct netif_rx_request *req;
18977e949c46SKenneth D. Merry struct netif_rx_response *rsp;
18987e949c46SKenneth D. Merry struct mbuf *mbuf;
18997e949c46SKenneth D. Merry
19007e949c46SKenneth D. Merry mbuf = m_getm(NULL, size, M_WAITOK, MT_DATA);
19017e949c46SKenneth D. Merry mbuf->m_flags |= M_PKTHDR;
19027e949c46SKenneth D. Merry mbuf->m_pkthdr.len = size;
19037e949c46SKenneth D. Merry if (mbuf->m_next != NULL) {
19047e949c46SKenneth D. Merry size_t first_len = MIN(M_TRAILINGSPACE(mbuf), size);
19057e949c46SKenneth D. Merry mbuf->m_len = first_len;
19067e949c46SKenneth D. Merry mbuf->m_next->m_len = size - first_len;
19077e949c46SKenneth D. Merry
19087e949c46SKenneth D. Merry } else {
19097e949c46SKenneth D. Merry mbuf->m_len = size;
19107e949c46SKenneth D. Merry }
19117e949c46SKenneth D. Merry
19127e949c46SKenneth D. Merry xnb_mbufc2pkt(mbuf, &pkt, start, free_slots);
19137e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.rxf, start);
19147e949c46SKenneth D. Merry req->gref = gref1;
19157e949c46SKenneth D. Merry req->id = id1;
19167e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.rxf, start + 1);
19177e949c46SKenneth D. Merry req->gref = gref2;
19187e949c46SKenneth D. Merry req->id = id2;
19197e949c46SKenneth D. Merry xnb_unit_pvt.rxb.req_cons = start;
19207e949c46SKenneth D. Merry xnb_unit_pvt.rxb.rsp_prod_pvt = start;
19217e949c46SKenneth D. Merry xnb_unit_pvt.rxs->req_prod = start + 2;
19227e949c46SKenneth D. Merry xnb_unit_pvt.rxs->rsp_prod = start;
19237e949c46SKenneth D. Merry
19247e949c46SKenneth D. Merry nr_entries = xnb_rxpkt2gnttab(&pkt, mbuf, xnb_unit_pvt.gnttab,
19257e949c46SKenneth D. Merry &xnb_unit_pvt.rxb, DOMID_FIRST_RESERVED);
19267e949c46SKenneth D. Merry
19277e949c46SKenneth D. Merry nr_reqs = xnb_rxpkt2rsp(&pkt, xnb_unit_pvt.gnttab, nr_entries,
19287e949c46SKenneth D. Merry &xnb_unit_pvt.rxb);
19297e949c46SKenneth D. Merry
19307e949c46SKenneth D. Merry XNB_ASSERT(nr_reqs == 2);
19317e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.rxb.rsp_prod_pvt == start + 2);
19327e949c46SKenneth D. Merry rsp = RING_GET_RESPONSE(&xnb_unit_pvt.rxb, start);
19337e949c46SKenneth D. Merry XNB_ASSERT(rsp->id == id1);
19347e949c46SKenneth D. Merry XNB_ASSERT(rsp->offset == 0);
19357e949c46SKenneth D. Merry XNB_ASSERT((rsp->flags & NETRXF_extra_info) == 0);
19367e949c46SKenneth D. Merry XNB_ASSERT(rsp->flags & NETRXF_more_data);
19377e949c46SKenneth D. Merry XNB_ASSERT(rsp->status == PAGE_SIZE);
19387e949c46SKenneth D. Merry
19397e949c46SKenneth D. Merry rsp = RING_GET_RESPONSE(&xnb_unit_pvt.rxb, start + 1);
19407e949c46SKenneth D. Merry XNB_ASSERT(rsp->id == id2);
19417e949c46SKenneth D. Merry XNB_ASSERT(rsp->offset == 0);
19427e949c46SKenneth D. Merry XNB_ASSERT((rsp->flags & NETRXF_extra_info) == 0);
19437e949c46SKenneth D. Merry XNB_ASSERT(! (rsp->flags & NETRXF_more_data));
19447e949c46SKenneth D. Merry XNB_ASSERT(rsp->status == size - PAGE_SIZE);
19457e949c46SKenneth D. Merry
19467e949c46SKenneth D. Merry safe_m_freem(&mbuf);
19477e949c46SKenneth D. Merry }
19487e949c46SKenneth D. Merry
19497e949c46SKenneth D. Merry /** xnb_rxpkt2rsp on a grant table with two sub-page entries */
19507e949c46SKenneth D. Merry static void
xnb_rxpkt2rsp_2short(char * buffer,size_t buflen)19517e949c46SKenneth D. Merry xnb_rxpkt2rsp_2short(char *buffer, size_t buflen) {
19527e949c46SKenneth D. Merry struct xnb_pkt pkt;
19537e949c46SKenneth D. Merry int nr_reqs, nr_entries;
19547e949c46SKenneth D. Merry size_t size1 = MHLEN - 5;
19557e949c46SKenneth D. Merry size_t size2 = MHLEN - 15;
19567e949c46SKenneth D. Merry int free_slots = 32;
19577e949c46SKenneth D. Merry RING_IDX start = 14;
19587e949c46SKenneth D. Merry uint16_t id = 47;
19597e949c46SKenneth D. Merry uint16_t gref = 54;
19607e949c46SKenneth D. Merry struct netif_rx_request *req;
19617e949c46SKenneth D. Merry struct netif_rx_response *rsp;
19627e949c46SKenneth D. Merry struct mbuf *mbufc;
19637e949c46SKenneth D. Merry
19647e949c46SKenneth D. Merry mbufc = m_getm(NULL, size1, M_WAITOK, MT_DATA);
19657e949c46SKenneth D. Merry XNB_ASSERT(mbufc != NULL);
1966407d708cSAlan Somers if (mbufc == NULL)
19677e949c46SKenneth D. Merry return;
1968407d708cSAlan Somers mbufc->m_flags |= M_PKTHDR;
19697e949c46SKenneth D. Merry
19707e949c46SKenneth D. Merry m_getm(mbufc, size2, M_WAITOK, MT_DATA);
19717e949c46SKenneth D. Merry XNB_ASSERT(mbufc->m_next != NULL);
19727e949c46SKenneth D. Merry mbufc->m_pkthdr.len = size1 + size2;
19737e949c46SKenneth D. Merry mbufc->m_len = size1;
19747e949c46SKenneth D. Merry mbufc->m_next->m_len = size2;
19757e949c46SKenneth D. Merry
19767e949c46SKenneth D. Merry xnb_mbufc2pkt(mbufc, &pkt, start, free_slots);
19777e949c46SKenneth D. Merry
19787e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.rxf, start);
19797e949c46SKenneth D. Merry req->gref = gref;
19807e949c46SKenneth D. Merry req->id = id;
19817e949c46SKenneth D. Merry xnb_unit_pvt.rxb.req_cons = start;
19827e949c46SKenneth D. Merry xnb_unit_pvt.rxb.rsp_prod_pvt = start;
19837e949c46SKenneth D. Merry xnb_unit_pvt.rxs->req_prod = start + 1;
19847e949c46SKenneth D. Merry xnb_unit_pvt.rxs->rsp_prod = start;
19857e949c46SKenneth D. Merry
19867e949c46SKenneth D. Merry nr_entries = xnb_rxpkt2gnttab(&pkt, mbufc, xnb_unit_pvt.gnttab,
19877e949c46SKenneth D. Merry &xnb_unit_pvt.rxb, DOMID_FIRST_RESERVED);
19887e949c46SKenneth D. Merry
19897e949c46SKenneth D. Merry nr_reqs = xnb_rxpkt2rsp(&pkt, xnb_unit_pvt.gnttab, nr_entries,
19907e949c46SKenneth D. Merry &xnb_unit_pvt.rxb);
19917e949c46SKenneth D. Merry
19927e949c46SKenneth D. Merry XNB_ASSERT(nr_entries == 2);
19937e949c46SKenneth D. Merry XNB_ASSERT(nr_reqs == 1);
19947e949c46SKenneth D. Merry rsp = RING_GET_RESPONSE(&xnb_unit_pvt.rxb, start);
19957e949c46SKenneth D. Merry XNB_ASSERT(rsp->id == id);
19967e949c46SKenneth D. Merry XNB_ASSERT(rsp->status == size1 + size2);
19977e949c46SKenneth D. Merry XNB_ASSERT(rsp->offset == 0);
19987e949c46SKenneth D. Merry XNB_ASSERT(! (rsp->flags & (NETRXF_more_data | NETRXF_extra_info)));
19997e949c46SKenneth D. Merry
20007e949c46SKenneth D. Merry safe_m_freem(&mbufc);
20017e949c46SKenneth D. Merry }
20027e949c46SKenneth D. Merry
20037e949c46SKenneth D. Merry /**
20047e949c46SKenneth D. Merry * xnb_rxpkt2rsp on a long packet with a hypervisor gnttab_copy error
20057e949c46SKenneth D. Merry * Note: this test will result in an error message being printed to the console
20067e949c46SKenneth D. Merry * such as:
20077e949c46SKenneth D. Merry * xnb(xnb_rxpkt2rsp:1720): Got error -1 for hypervisor gnttab_copy status
20087e949c46SKenneth D. Merry */
20097e949c46SKenneth D. Merry static void
xnb_rxpkt2rsp_copyerror(char * buffer,size_t buflen)20107e949c46SKenneth D. Merry xnb_rxpkt2rsp_copyerror(char *buffer, size_t buflen)
20117e949c46SKenneth D. Merry {
20127e949c46SKenneth D. Merry struct xnb_pkt pkt;
20137e949c46SKenneth D. Merry int nr_entries, nr_reqs;
20147e949c46SKenneth D. Merry int id = 7;
20157e949c46SKenneth D. Merry int gref = 42;
20167e949c46SKenneth D. Merry uint16_t canary = 6859;
20177e949c46SKenneth D. Merry size_t size = 7 * MCLBYTES;
20187e949c46SKenneth D. Merry int free_slots = 9;
20197e949c46SKenneth D. Merry RING_IDX start = 2;
20207e949c46SKenneth D. Merry struct netif_rx_request *req;
20217e949c46SKenneth D. Merry struct netif_rx_response *rsp;
20227e949c46SKenneth D. Merry struct mbuf *mbuf;
20237e949c46SKenneth D. Merry
20247e949c46SKenneth D. Merry mbuf = m_getm(NULL, size, M_WAITOK, MT_DATA);
20257e949c46SKenneth D. Merry mbuf->m_flags |= M_PKTHDR;
20267e949c46SKenneth D. Merry mbuf->m_pkthdr.len = size;
20277e949c46SKenneth D. Merry mbuf->m_len = size;
20287e949c46SKenneth D. Merry
20297e949c46SKenneth D. Merry xnb_mbufc2pkt(mbuf, &pkt, start, free_slots);
20307e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.rxf, start);
20317e949c46SKenneth D. Merry req->gref = gref;
20327e949c46SKenneth D. Merry req->id = id;
20337e949c46SKenneth D. Merry xnb_unit_pvt.rxb.req_cons = start;
20347e949c46SKenneth D. Merry xnb_unit_pvt.rxb.rsp_prod_pvt = start;
20357e949c46SKenneth D. Merry xnb_unit_pvt.rxs->req_prod = start + 1;
20367e949c46SKenneth D. Merry xnb_unit_pvt.rxs->rsp_prod = start;
20377e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.rxf, start + 1);
20387e949c46SKenneth D. Merry req->gref = canary;
20397e949c46SKenneth D. Merry req->id = canary;
20407e949c46SKenneth D. Merry
20417e949c46SKenneth D. Merry nr_entries = xnb_rxpkt2gnttab(&pkt, mbuf, xnb_unit_pvt.gnttab,
20427e949c46SKenneth D. Merry &xnb_unit_pvt.rxb, DOMID_FIRST_RESERVED);
20437e949c46SKenneth D. Merry /* Inject the error*/
20447e949c46SKenneth D. Merry xnb_unit_pvt.gnttab[2].status = GNTST_general_error;
20457e949c46SKenneth D. Merry
20467e949c46SKenneth D. Merry nr_reqs = xnb_rxpkt2rsp(&pkt, xnb_unit_pvt.gnttab, nr_entries,
20477e949c46SKenneth D. Merry &xnb_unit_pvt.rxb);
20487e949c46SKenneth D. Merry
20497e949c46SKenneth D. Merry XNB_ASSERT(nr_reqs == 1);
20507e949c46SKenneth D. Merry XNB_ASSERT(xnb_unit_pvt.rxb.rsp_prod_pvt == start + 1);
20517e949c46SKenneth D. Merry rsp = RING_GET_RESPONSE(&xnb_unit_pvt.rxb, start);
20527e949c46SKenneth D. Merry XNB_ASSERT(rsp->id == id);
20537e949c46SKenneth D. Merry XNB_ASSERT(rsp->status == NETIF_RSP_ERROR);
20547e949c46SKenneth D. Merry req = RING_GET_REQUEST(&xnb_unit_pvt.rxf, start + 1);
20557e949c46SKenneth D. Merry XNB_ASSERT(req->gref == canary);
20567e949c46SKenneth D. Merry XNB_ASSERT(req->id == canary);
20577e949c46SKenneth D. Merry
20587e949c46SKenneth D. Merry safe_m_freem(&mbuf);
20597e949c46SKenneth D. Merry }
20607e949c46SKenneth D. Merry
2061f909bbb4SGleb Smirnoff #if defined(INET) || defined(INET6)
20627e949c46SKenneth D. Merry /**
20637e949c46SKenneth D. Merry * xnb_add_mbuf_cksum on an ARP request packet
20647e949c46SKenneth D. Merry */
20657e949c46SKenneth D. Merry static void
xnb_add_mbuf_cksum_arp(char * buffer,size_t buflen)20667e949c46SKenneth D. Merry xnb_add_mbuf_cksum_arp(char *buffer, size_t buflen)
20677e949c46SKenneth D. Merry {
20687e949c46SKenneth D. Merry const size_t pkt_len = sizeof(struct ether_header) +
20697e949c46SKenneth D. Merry sizeof(struct ether_arp);
20707e949c46SKenneth D. Merry struct mbuf *mbufc;
20717e949c46SKenneth D. Merry struct ether_header *eh;
20727e949c46SKenneth D. Merry struct ether_arp *ep;
20737e949c46SKenneth D. Merry unsigned char pkt_orig[pkt_len];
20747e949c46SKenneth D. Merry
20757e949c46SKenneth D. Merry mbufc = m_getm(NULL, pkt_len, M_WAITOK, MT_DATA);
20767e949c46SKenneth D. Merry /* Fill in an example arp request */
20777e949c46SKenneth D. Merry eh = mtod(mbufc, struct ether_header*);
20787e949c46SKenneth D. Merry eh->ether_dhost[0] = 0xff;
20797e949c46SKenneth D. Merry eh->ether_dhost[1] = 0xff;
20807e949c46SKenneth D. Merry eh->ether_dhost[2] = 0xff;
20817e949c46SKenneth D. Merry eh->ether_dhost[3] = 0xff;
20827e949c46SKenneth D. Merry eh->ether_dhost[4] = 0xff;
20837e949c46SKenneth D. Merry eh->ether_dhost[5] = 0xff;
20847e949c46SKenneth D. Merry eh->ether_shost[0] = 0x00;
20857e949c46SKenneth D. Merry eh->ether_shost[1] = 0x15;
20867e949c46SKenneth D. Merry eh->ether_shost[2] = 0x17;
20877e949c46SKenneth D. Merry eh->ether_shost[3] = 0xe9;
20887e949c46SKenneth D. Merry eh->ether_shost[4] = 0x30;
20897e949c46SKenneth D. Merry eh->ether_shost[5] = 0x68;
20907e949c46SKenneth D. Merry eh->ether_type = htons(ETHERTYPE_ARP);
20917e949c46SKenneth D. Merry ep = (struct ether_arp*)(eh + 1);
20927e949c46SKenneth D. Merry ep->ea_hdr.ar_hrd = htons(ARPHRD_ETHER);
20937e949c46SKenneth D. Merry ep->ea_hdr.ar_pro = htons(ETHERTYPE_IP);
20947e949c46SKenneth D. Merry ep->ea_hdr.ar_hln = 6;
20957e949c46SKenneth D. Merry ep->ea_hdr.ar_pln = 4;
20967e949c46SKenneth D. Merry ep->ea_hdr.ar_op = htons(ARPOP_REQUEST);
20977e949c46SKenneth D. Merry ep->arp_sha[0] = 0x00;
20987e949c46SKenneth D. Merry ep->arp_sha[1] = 0x15;
20997e949c46SKenneth D. Merry ep->arp_sha[2] = 0x17;
21007e949c46SKenneth D. Merry ep->arp_sha[3] = 0xe9;
21017e949c46SKenneth D. Merry ep->arp_sha[4] = 0x30;
21027e949c46SKenneth D. Merry ep->arp_sha[5] = 0x68;
21037e949c46SKenneth D. Merry ep->arp_spa[0] = 0xc0;
21047e949c46SKenneth D. Merry ep->arp_spa[1] = 0xa8;
21057e949c46SKenneth D. Merry ep->arp_spa[2] = 0x0a;
21067e949c46SKenneth D. Merry ep->arp_spa[3] = 0x04;
21077e949c46SKenneth D. Merry bzero(&(ep->arp_tha), ETHER_ADDR_LEN);
21087e949c46SKenneth D. Merry ep->arp_tpa[0] = 0xc0;
21097e949c46SKenneth D. Merry ep->arp_tpa[1] = 0xa8;
21107e949c46SKenneth D. Merry ep->arp_tpa[2] = 0x0a;
21117e949c46SKenneth D. Merry ep->arp_tpa[3] = 0x06;
21127e949c46SKenneth D. Merry
21137e949c46SKenneth D. Merry /* fill in the length field */
21147e949c46SKenneth D. Merry mbufc->m_len = pkt_len;
21157e949c46SKenneth D. Merry mbufc->m_pkthdr.len = pkt_len;
21167e949c46SKenneth D. Merry /* indicate that the netfront uses hw-assisted checksums */
21177e949c46SKenneth D. Merry mbufc->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID |
21187e949c46SKenneth D. Merry CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
21197e949c46SKenneth D. Merry
21207e949c46SKenneth D. Merry /* Make a backup copy of the packet */
21217e949c46SKenneth D. Merry bcopy(mtod(mbufc, const void*), pkt_orig, pkt_len);
21227e949c46SKenneth D. Merry
21237e949c46SKenneth D. Merry /* Function under test */
21247e949c46SKenneth D. Merry xnb_add_mbuf_cksum(mbufc);
21257e949c46SKenneth D. Merry
21267e949c46SKenneth D. Merry /* Verify that the packet's data did not change */
21277e949c46SKenneth D. Merry XNB_ASSERT(bcmp(mtod(mbufc, const void*), pkt_orig, pkt_len) == 0);
21287e949c46SKenneth D. Merry m_freem(mbufc);
21297e949c46SKenneth D. Merry }
21307e949c46SKenneth D. Merry
21317e949c46SKenneth D. Merry /**
21327e949c46SKenneth D. Merry * Helper function that populates the ethernet header and IP header used by
21337e949c46SKenneth D. Merry * some of the xnb_add_mbuf_cksum unit tests. m must already be allocated
21347e949c46SKenneth D. Merry * and must be large enough
21357e949c46SKenneth D. Merry */
21367e949c46SKenneth D. Merry static void
xnb_fill_eh_and_ip(struct mbuf * m,uint16_t ip_len,uint16_t ip_id,uint16_t ip_p,uint16_t ip_off,uint16_t ip_sum)21377e949c46SKenneth D. Merry xnb_fill_eh_and_ip(struct mbuf *m, uint16_t ip_len, uint16_t ip_id,
21387e949c46SKenneth D. Merry uint16_t ip_p, uint16_t ip_off, uint16_t ip_sum)
21397e949c46SKenneth D. Merry {
21407e949c46SKenneth D. Merry struct ether_header *eh;
21417e949c46SKenneth D. Merry struct ip *iph;
21427e949c46SKenneth D. Merry
21437e949c46SKenneth D. Merry eh = mtod(m, struct ether_header*);
21447e949c46SKenneth D. Merry eh->ether_dhost[0] = 0x00;
21457e949c46SKenneth D. Merry eh->ether_dhost[1] = 0x16;
21467e949c46SKenneth D. Merry eh->ether_dhost[2] = 0x3e;
21477e949c46SKenneth D. Merry eh->ether_dhost[3] = 0x23;
21487e949c46SKenneth D. Merry eh->ether_dhost[4] = 0x50;
21497e949c46SKenneth D. Merry eh->ether_dhost[5] = 0x0b;
21507e949c46SKenneth D. Merry eh->ether_shost[0] = 0x00;
21517e949c46SKenneth D. Merry eh->ether_shost[1] = 0x16;
21527e949c46SKenneth D. Merry eh->ether_shost[2] = 0x30;
21537e949c46SKenneth D. Merry eh->ether_shost[3] = 0x00;
21547e949c46SKenneth D. Merry eh->ether_shost[4] = 0x00;
21557e949c46SKenneth D. Merry eh->ether_shost[5] = 0x00;
21567e949c46SKenneth D. Merry eh->ether_type = htons(ETHERTYPE_IP);
21577e949c46SKenneth D. Merry iph = (struct ip*)(eh + 1);
21587e949c46SKenneth D. Merry iph->ip_hl = 0x5; /* 5 dwords == 20 bytes */
21597e949c46SKenneth D. Merry iph->ip_v = 4; /* IP v4 */
21607e949c46SKenneth D. Merry iph->ip_tos = 0;
21617e949c46SKenneth D. Merry iph->ip_len = htons(ip_len);
21627e949c46SKenneth D. Merry iph->ip_id = htons(ip_id);
21637e949c46SKenneth D. Merry iph->ip_off = htons(ip_off);
21647e949c46SKenneth D. Merry iph->ip_ttl = 64;
21657e949c46SKenneth D. Merry iph->ip_p = ip_p;
21667e949c46SKenneth D. Merry iph->ip_sum = htons(ip_sum);
21677e949c46SKenneth D. Merry iph->ip_src.s_addr = htonl(0xc0a80a04);
21687e949c46SKenneth D. Merry iph->ip_dst.s_addr = htonl(0xc0a80a05);
21697e949c46SKenneth D. Merry }
21707e949c46SKenneth D. Merry
21717e949c46SKenneth D. Merry /**
21727e949c46SKenneth D. Merry * xnb_add_mbuf_cksum on an ICMP packet, based on a tcpdump of an actual
21737e949c46SKenneth D. Merry * ICMP packet
21747e949c46SKenneth D. Merry */
21757e949c46SKenneth D. Merry static void
xnb_add_mbuf_cksum_icmp(char * buffer,size_t buflen)21767e949c46SKenneth D. Merry xnb_add_mbuf_cksum_icmp(char *buffer, size_t buflen)
21777e949c46SKenneth D. Merry {
21787e949c46SKenneth D. Merry const size_t icmp_len = 64; /* set by ping(1) */
21797e949c46SKenneth D. Merry const size_t pkt_len = sizeof(struct ether_header) +
21807e949c46SKenneth D. Merry sizeof(struct ip) + icmp_len;
21817e949c46SKenneth D. Merry struct mbuf *mbufc;
21827e949c46SKenneth D. Merry struct ether_header *eh;
21837e949c46SKenneth D. Merry struct ip *iph;
21847e949c46SKenneth D. Merry struct icmp *icmph;
21857e949c46SKenneth D. Merry unsigned char pkt_orig[icmp_len];
21867e949c46SKenneth D. Merry uint32_t *tv_field;
21877e949c46SKenneth D. Merry uint8_t *data_payload;
21887e949c46SKenneth D. Merry int i;
21897e949c46SKenneth D. Merry const uint16_t ICMP_CSUM = 0xaed7;
21907e949c46SKenneth D. Merry const uint16_t IP_CSUM = 0xe533;
21917e949c46SKenneth D. Merry
21927e949c46SKenneth D. Merry mbufc = m_getm(NULL, pkt_len, M_WAITOK, MT_DATA);
21937e949c46SKenneth D. Merry /* Fill in an example ICMP ping request */
21947e949c46SKenneth D. Merry eh = mtod(mbufc, struct ether_header*);
21957e949c46SKenneth D. Merry xnb_fill_eh_and_ip(mbufc, 84, 28, IPPROTO_ICMP, 0, 0);
21967e949c46SKenneth D. Merry iph = (struct ip*)(eh + 1);
21977e949c46SKenneth D. Merry icmph = (struct icmp*)(iph + 1);
21987e949c46SKenneth D. Merry icmph->icmp_type = ICMP_ECHO;
21997e949c46SKenneth D. Merry icmph->icmp_code = 0;
22007e949c46SKenneth D. Merry icmph->icmp_cksum = htons(ICMP_CSUM);
22017e949c46SKenneth D. Merry icmph->icmp_id = htons(31492);
22027e949c46SKenneth D. Merry icmph->icmp_seq = htons(0);
22037e949c46SKenneth D. Merry /*
22047e949c46SKenneth D. Merry * ping(1) uses bcopy to insert a native-endian timeval after icmp_seq.
22057e949c46SKenneth D. Merry * For this test, we will set the bytes individually for portability.
22067e949c46SKenneth D. Merry */
22077e949c46SKenneth D. Merry tv_field = (uint32_t*)(&(icmph->icmp_hun));
22087e949c46SKenneth D. Merry tv_field[0] = 0x4f02cfac;
22097e949c46SKenneth D. Merry tv_field[1] = 0x0007c46a;
22107e949c46SKenneth D. Merry /*
22117e949c46SKenneth D. Merry * Remainder of packet is an incrmenting 8 bit integer, starting with 8
22127e949c46SKenneth D. Merry */
22137e949c46SKenneth D. Merry data_payload = (uint8_t*)(&tv_field[2]);
22147e949c46SKenneth D. Merry for (i = 8; i < 37; i++) {
22157e949c46SKenneth D. Merry *data_payload++ = i;
22167e949c46SKenneth D. Merry }
22177e949c46SKenneth D. Merry
22187e949c46SKenneth D. Merry /* fill in the length field */
22197e949c46SKenneth D. Merry mbufc->m_len = pkt_len;
22207e949c46SKenneth D. Merry mbufc->m_pkthdr.len = pkt_len;
22217e949c46SKenneth D. Merry /* indicate that the netfront uses hw-assisted checksums */
22227e949c46SKenneth D. Merry mbufc->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID |
22237e949c46SKenneth D. Merry CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
22247e949c46SKenneth D. Merry
22257e949c46SKenneth D. Merry bcopy(mtod(mbufc, const void*), pkt_orig, icmp_len);
22267e949c46SKenneth D. Merry /* Function under test */
22277e949c46SKenneth D. Merry xnb_add_mbuf_cksum(mbufc);
22287e949c46SKenneth D. Merry
22297e949c46SKenneth D. Merry /* Check the IP checksum */
22307e949c46SKenneth D. Merry XNB_ASSERT(iph->ip_sum == htons(IP_CSUM));
22317e949c46SKenneth D. Merry
22327e949c46SKenneth D. Merry /* Check that the ICMP packet did not change */
22337e949c46SKenneth D. Merry XNB_ASSERT(bcmp(icmph, pkt_orig, icmp_len));
22347e949c46SKenneth D. Merry m_freem(mbufc);
22357e949c46SKenneth D. Merry }
22367e949c46SKenneth D. Merry
22377e949c46SKenneth D. Merry /**
22387e949c46SKenneth D. Merry * xnb_add_mbuf_cksum on a UDP packet, based on a tcpdump of an actual
22397e949c46SKenneth D. Merry * UDP packet
22407e949c46SKenneth D. Merry */
22417e949c46SKenneth D. Merry static void
xnb_add_mbuf_cksum_udp(char * buffer,size_t buflen)22427e949c46SKenneth D. Merry xnb_add_mbuf_cksum_udp(char *buffer, size_t buflen)
22437e949c46SKenneth D. Merry {
22447e949c46SKenneth D. Merry const size_t udp_len = 16;
22457e949c46SKenneth D. Merry const size_t pkt_len = sizeof(struct ether_header) +
22467e949c46SKenneth D. Merry sizeof(struct ip) + udp_len;
22477e949c46SKenneth D. Merry struct mbuf *mbufc;
22487e949c46SKenneth D. Merry struct ether_header *eh;
22497e949c46SKenneth D. Merry struct ip *iph;
22507e949c46SKenneth D. Merry struct udphdr *udp;
22517e949c46SKenneth D. Merry uint8_t *data_payload;
22527e949c46SKenneth D. Merry const uint16_t IP_CSUM = 0xe56b;
22537e949c46SKenneth D. Merry const uint16_t UDP_CSUM = 0xdde2;
22547e949c46SKenneth D. Merry
22557e949c46SKenneth D. Merry mbufc = m_getm(NULL, pkt_len, M_WAITOK, MT_DATA);
22567e949c46SKenneth D. Merry /* Fill in an example UDP packet made by 'uname | nc -u <host> 2222 */
22577e949c46SKenneth D. Merry eh = mtod(mbufc, struct ether_header*);
22587e949c46SKenneth D. Merry xnb_fill_eh_and_ip(mbufc, 36, 4, IPPROTO_UDP, 0, 0xbaad);
22597e949c46SKenneth D. Merry iph = (struct ip*)(eh + 1);
22607e949c46SKenneth D. Merry udp = (struct udphdr*)(iph + 1);
22617e949c46SKenneth D. Merry udp->uh_sport = htons(0x51ae);
22627e949c46SKenneth D. Merry udp->uh_dport = htons(0x08ae);
22637e949c46SKenneth D. Merry udp->uh_ulen = htons(udp_len);
22647e949c46SKenneth D. Merry udp->uh_sum = htons(0xbaad); /* xnb_add_mbuf_cksum will fill this in */
22657e949c46SKenneth D. Merry data_payload = (uint8_t*)(udp + 1);
22667e949c46SKenneth D. Merry data_payload[0] = 'F';
22677e949c46SKenneth D. Merry data_payload[1] = 'r';
22687e949c46SKenneth D. Merry data_payload[2] = 'e';
22697e949c46SKenneth D. Merry data_payload[3] = 'e';
22707e949c46SKenneth D. Merry data_payload[4] = 'B';
22717e949c46SKenneth D. Merry data_payload[5] = 'S';
22727e949c46SKenneth D. Merry data_payload[6] = 'D';
22737e949c46SKenneth D. Merry data_payload[7] = '\n';
22747e949c46SKenneth D. Merry
22757e949c46SKenneth D. Merry /* fill in the length field */
22767e949c46SKenneth D. Merry mbufc->m_len = pkt_len;
22777e949c46SKenneth D. Merry mbufc->m_pkthdr.len = pkt_len;
22787e949c46SKenneth D. Merry /* indicate that the netfront uses hw-assisted checksums */
22797e949c46SKenneth D. Merry mbufc->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID |
22807e949c46SKenneth D. Merry CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
22817e949c46SKenneth D. Merry
22827e949c46SKenneth D. Merry /* Function under test */
22837e949c46SKenneth D. Merry xnb_add_mbuf_cksum(mbufc);
22847e949c46SKenneth D. Merry
22857e949c46SKenneth D. Merry /* Check the checksums */
22867e949c46SKenneth D. Merry XNB_ASSERT(iph->ip_sum == htons(IP_CSUM));
22877e949c46SKenneth D. Merry XNB_ASSERT(udp->uh_sum == htons(UDP_CSUM));
22887e949c46SKenneth D. Merry
22897e949c46SKenneth D. Merry m_freem(mbufc);
22907e949c46SKenneth D. Merry }
22917e949c46SKenneth D. Merry
22927e949c46SKenneth D. Merry /**
22937e949c46SKenneth D. Merry * Helper function that populates a TCP packet used by all of the
22947e949c46SKenneth D. Merry * xnb_add_mbuf_cksum tcp unit tests. m must already be allocated and must be
22957e949c46SKenneth D. Merry * large enough
22967e949c46SKenneth D. Merry */
22977e949c46SKenneth D. Merry static void
xnb_fill_tcp(struct mbuf * m)22987e949c46SKenneth D. Merry xnb_fill_tcp(struct mbuf *m)
22997e949c46SKenneth D. Merry {
23007e949c46SKenneth D. Merry struct ether_header *eh;
23017e949c46SKenneth D. Merry struct ip *iph;
23027e949c46SKenneth D. Merry struct tcphdr *tcp;
23037e949c46SKenneth D. Merry uint32_t *options;
23047e949c46SKenneth D. Merry uint8_t *data_payload;
23057e949c46SKenneth D. Merry
23067e949c46SKenneth D. Merry /* Fill in an example TCP packet made by 'uname | nc <host> 2222' */
23077e949c46SKenneth D. Merry eh = mtod(m, struct ether_header*);
23087e949c46SKenneth D. Merry xnb_fill_eh_and_ip(m, 60, 8, IPPROTO_TCP, IP_DF, 0);
23097e949c46SKenneth D. Merry iph = (struct ip*)(eh + 1);
23107e949c46SKenneth D. Merry tcp = (struct tcphdr*)(iph + 1);
23117e949c46SKenneth D. Merry tcp->th_sport = htons(0x9cd9);
23127e949c46SKenneth D. Merry tcp->th_dport = htons(2222);
23137e949c46SKenneth D. Merry tcp->th_seq = htonl(0x00f72b10);
23147e949c46SKenneth D. Merry tcp->th_ack = htonl(0x7f37ba6c);
2315*a8b70cf2SRichard Scheffenegger tcp_set_flags(tcp, TH_ACK | TH_PUSH);
23167e949c46SKenneth D. Merry tcp->th_off = 8;
23177e949c46SKenneth D. Merry tcp->th_win = htons(0x410);
23187e949c46SKenneth D. Merry /* th_sum is incorrect; will be inserted by function under test */
23197e949c46SKenneth D. Merry tcp->th_sum = htons(0xbaad);
23207e949c46SKenneth D. Merry tcp->th_urp = htons(0);
23217e949c46SKenneth D. Merry /*
23227e949c46SKenneth D. Merry * The following 12 bytes of options encode:
23237e949c46SKenneth D. Merry * [nop, nop, TS val 33247 ecr 3457687679]
23247e949c46SKenneth D. Merry */
23257e949c46SKenneth D. Merry options = (uint32_t*)(tcp + 1);
23267e949c46SKenneth D. Merry options[0] = htonl(0x0101080a);
23277e949c46SKenneth D. Merry options[1] = htonl(0x000081df);
23287e949c46SKenneth D. Merry options[2] = htonl(0xce18207f);
23297e949c46SKenneth D. Merry data_payload = (uint8_t*)(&options[3]);
23307e949c46SKenneth D. Merry data_payload[0] = 'F';
23317e949c46SKenneth D. Merry data_payload[1] = 'r';
23327e949c46SKenneth D. Merry data_payload[2] = 'e';
23337e949c46SKenneth D. Merry data_payload[3] = 'e';
23347e949c46SKenneth D. Merry data_payload[4] = 'B';
23357e949c46SKenneth D. Merry data_payload[5] = 'S';
23367e949c46SKenneth D. Merry data_payload[6] = 'D';
23377e949c46SKenneth D. Merry data_payload[7] = '\n';
23387e949c46SKenneth D. Merry }
23397e949c46SKenneth D. Merry
23407e949c46SKenneth D. Merry /**
23417e949c46SKenneth D. Merry * xnb_add_mbuf_cksum on a TCP packet, based on a tcpdump of an actual TCP
23427e949c46SKenneth D. Merry * packet
23437e949c46SKenneth D. Merry */
23447e949c46SKenneth D. Merry static void
xnb_add_mbuf_cksum_tcp(char * buffer,size_t buflen)23457e949c46SKenneth D. Merry xnb_add_mbuf_cksum_tcp(char *buffer, size_t buflen)
23467e949c46SKenneth D. Merry {
23477e949c46SKenneth D. Merry const size_t payload_len = 8;
23487e949c46SKenneth D. Merry const size_t tcp_options_len = 12;
23497e949c46SKenneth D. Merry const size_t pkt_len = sizeof(struct ether_header) + sizeof(struct ip) +
23507e949c46SKenneth D. Merry sizeof(struct tcphdr) + tcp_options_len + payload_len;
23517e949c46SKenneth D. Merry struct mbuf *mbufc;
23527e949c46SKenneth D. Merry struct ether_header *eh;
23537e949c46SKenneth D. Merry struct ip *iph;
23547e949c46SKenneth D. Merry struct tcphdr *tcp;
23557e949c46SKenneth D. Merry const uint16_t IP_CSUM = 0xa55a;
23567e949c46SKenneth D. Merry const uint16_t TCP_CSUM = 0x2f64;
23577e949c46SKenneth D. Merry
23587e949c46SKenneth D. Merry mbufc = m_getm(NULL, pkt_len, M_WAITOK, MT_DATA);
23597e949c46SKenneth D. Merry /* Fill in an example TCP packet made by 'uname | nc <host> 2222' */
23607e949c46SKenneth D. Merry xnb_fill_tcp(mbufc);
23617e949c46SKenneth D. Merry eh = mtod(mbufc, struct ether_header*);
23627e949c46SKenneth D. Merry iph = (struct ip*)(eh + 1);
23637e949c46SKenneth D. Merry tcp = (struct tcphdr*)(iph + 1);
23647e949c46SKenneth D. Merry
23657e949c46SKenneth D. Merry /* fill in the length field */
23667e949c46SKenneth D. Merry mbufc->m_len = pkt_len;
23677e949c46SKenneth D. Merry mbufc->m_pkthdr.len = pkt_len;
23687e949c46SKenneth D. Merry /* indicate that the netfront uses hw-assisted checksums */
23697e949c46SKenneth D. Merry mbufc->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID |
23707e949c46SKenneth D. Merry CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
23717e949c46SKenneth D. Merry
23727e949c46SKenneth D. Merry /* Function under test */
23737e949c46SKenneth D. Merry xnb_add_mbuf_cksum(mbufc);
23747e949c46SKenneth D. Merry
23757e949c46SKenneth D. Merry /* Check the checksums */
23767e949c46SKenneth D. Merry XNB_ASSERT(iph->ip_sum == htons(IP_CSUM));
23777e949c46SKenneth D. Merry XNB_ASSERT(tcp->th_sum == htons(TCP_CSUM));
23787e949c46SKenneth D. Merry
23797e949c46SKenneth D. Merry m_freem(mbufc);
23807e949c46SKenneth D. Merry }
23817e949c46SKenneth D. Merry
23827e949c46SKenneth D. Merry /**
23837e949c46SKenneth D. Merry * xnb_add_mbuf_cksum on a TCP packet that does not use HW assisted checksums
23847e949c46SKenneth D. Merry */
23857e949c46SKenneth D. Merry static void
xnb_add_mbuf_cksum_tcp_swcksum(char * buffer,size_t buflen)23867e949c46SKenneth D. Merry xnb_add_mbuf_cksum_tcp_swcksum(char *buffer, size_t buflen)
23877e949c46SKenneth D. Merry {
23887e949c46SKenneth D. Merry const size_t payload_len = 8;
23897e949c46SKenneth D. Merry const size_t tcp_options_len = 12;
23907e949c46SKenneth D. Merry const size_t pkt_len = sizeof(struct ether_header) + sizeof(struct ip) +
23917e949c46SKenneth D. Merry sizeof(struct tcphdr) + tcp_options_len + payload_len;
23927e949c46SKenneth D. Merry struct mbuf *mbufc;
23937e949c46SKenneth D. Merry struct ether_header *eh;
23947e949c46SKenneth D. Merry struct ip *iph;
23957e949c46SKenneth D. Merry struct tcphdr *tcp;
23967e949c46SKenneth D. Merry /* Use deliberately bad checksums, and verify that they don't get */
23977e949c46SKenneth D. Merry /* corrected by xnb_add_mbuf_cksum */
23987e949c46SKenneth D. Merry const uint16_t IP_CSUM = 0xdead;
23997e949c46SKenneth D. Merry const uint16_t TCP_CSUM = 0xbeef;
24007e949c46SKenneth D. Merry
24017e949c46SKenneth D. Merry mbufc = m_getm(NULL, pkt_len, M_WAITOK, MT_DATA);
24027e949c46SKenneth D. Merry /* Fill in an example TCP packet made by 'uname | nc <host> 2222' */
24037e949c46SKenneth D. Merry xnb_fill_tcp(mbufc);
24047e949c46SKenneth D. Merry eh = mtod(mbufc, struct ether_header*);
24057e949c46SKenneth D. Merry iph = (struct ip*)(eh + 1);
24067e949c46SKenneth D. Merry iph->ip_sum = htons(IP_CSUM);
24077e949c46SKenneth D. Merry tcp = (struct tcphdr*)(iph + 1);
24087e949c46SKenneth D. Merry tcp->th_sum = htons(TCP_CSUM);
24097e949c46SKenneth D. Merry
24107e949c46SKenneth D. Merry /* fill in the length field */
24117e949c46SKenneth D. Merry mbufc->m_len = pkt_len;
24127e949c46SKenneth D. Merry mbufc->m_pkthdr.len = pkt_len;
24137e949c46SKenneth D. Merry /* indicate that the netfront does not use hw-assisted checksums */
24147e949c46SKenneth D. Merry mbufc->m_pkthdr.csum_flags = 0;
24157e949c46SKenneth D. Merry
24167e949c46SKenneth D. Merry /* Function under test */
24177e949c46SKenneth D. Merry xnb_add_mbuf_cksum(mbufc);
24187e949c46SKenneth D. Merry
24197e949c46SKenneth D. Merry /* Check that the checksums didn't change */
24207e949c46SKenneth D. Merry XNB_ASSERT(iph->ip_sum == htons(IP_CSUM));
24217e949c46SKenneth D. Merry XNB_ASSERT(tcp->th_sum == htons(TCP_CSUM));
24227e949c46SKenneth D. Merry
24237e949c46SKenneth D. Merry m_freem(mbufc);
24247e949c46SKenneth D. Merry }
2425f909bbb4SGleb Smirnoff #endif /* INET || INET6 */
24267e949c46SKenneth D. Merry
24277e949c46SKenneth D. Merry /**
24287e949c46SKenneth D. Merry * sscanf on unsigned chars
24297e949c46SKenneth D. Merry */
24307e949c46SKenneth D. Merry static void
xnb_sscanf_hhu(char * buffer,size_t buflen)24317e949c46SKenneth D. Merry xnb_sscanf_hhu(char *buffer, size_t buflen)
24327e949c46SKenneth D. Merry {
24337e949c46SKenneth D. Merry const char mystr[] = "137";
24347e949c46SKenneth D. Merry uint8_t dest[12];
24357e949c46SKenneth D. Merry int i;
24367e949c46SKenneth D. Merry
24377e949c46SKenneth D. Merry for (i = 0; i < 12; i++)
24387e949c46SKenneth D. Merry dest[i] = 'X';
24397e949c46SKenneth D. Merry
2440407d708cSAlan Somers XNB_ASSERT(sscanf(mystr, "%hhu", &dest[4]) == 1);
24417e949c46SKenneth D. Merry for (i = 0; i < 12; i++)
24427e949c46SKenneth D. Merry XNB_ASSERT(dest[i] == (i == 4 ? 137 : 'X'));
24437e949c46SKenneth D. Merry }
24447e949c46SKenneth D. Merry
24457e949c46SKenneth D. Merry /**
24467e949c46SKenneth D. Merry * sscanf on signed chars
24477e949c46SKenneth D. Merry */
24487e949c46SKenneth D. Merry static void
xnb_sscanf_hhd(char * buffer,size_t buflen)24497e949c46SKenneth D. Merry xnb_sscanf_hhd(char *buffer, size_t buflen)
24507e949c46SKenneth D. Merry {
24517e949c46SKenneth D. Merry const char mystr[] = "-27";
24527e949c46SKenneth D. Merry int8_t dest[12];
24537e949c46SKenneth D. Merry int i;
24547e949c46SKenneth D. Merry
24557e949c46SKenneth D. Merry for (i = 0; i < 12; i++)
24567e949c46SKenneth D. Merry dest[i] = 'X';
24577e949c46SKenneth D. Merry
2458407d708cSAlan Somers XNB_ASSERT(sscanf(mystr, "%hhd", &dest[4]) == 1);
24597e949c46SKenneth D. Merry for (i = 0; i < 12; i++)
24607e949c46SKenneth D. Merry XNB_ASSERT(dest[i] == (i == 4 ? -27 : 'X'));
24617e949c46SKenneth D. Merry }
24627e949c46SKenneth D. Merry
24637e949c46SKenneth D. Merry /**
24647e949c46SKenneth D. Merry * sscanf on signed long longs
24657e949c46SKenneth D. Merry */
24667e949c46SKenneth D. Merry static void
xnb_sscanf_lld(char * buffer,size_t buflen)24677e949c46SKenneth D. Merry xnb_sscanf_lld(char *buffer, size_t buflen)
24687e949c46SKenneth D. Merry {
24697e949c46SKenneth D. Merry const char mystr[] = "-123456789012345"; /* about -2**47 */
24707e949c46SKenneth D. Merry long long dest[3];
24717e949c46SKenneth D. Merry int i;
24727e949c46SKenneth D. Merry
24737e949c46SKenneth D. Merry for (i = 0; i < 3; i++)
24747e949c46SKenneth D. Merry dest[i] = (long long)0xdeadbeefdeadbeef;
24757e949c46SKenneth D. Merry
2476407d708cSAlan Somers XNB_ASSERT(sscanf(mystr, "%lld", &dest[1]) == 1);
24777e949c46SKenneth D. Merry for (i = 0; i < 3; i++)
24787e949c46SKenneth D. Merry XNB_ASSERT(dest[i] == (i != 1 ? (long long)0xdeadbeefdeadbeef :
24797e949c46SKenneth D. Merry -123456789012345));
24807e949c46SKenneth D. Merry }
24817e949c46SKenneth D. Merry
24827e949c46SKenneth D. Merry /**
24837e949c46SKenneth D. Merry * sscanf on unsigned long longs
24847e949c46SKenneth D. Merry */
24857e949c46SKenneth D. Merry static void
xnb_sscanf_llu(char * buffer,size_t buflen)24867e949c46SKenneth D. Merry xnb_sscanf_llu(char *buffer, size_t buflen)
24877e949c46SKenneth D. Merry {
24887e949c46SKenneth D. Merry const char mystr[] = "12802747070103273189";
24897e949c46SKenneth D. Merry unsigned long long dest[3];
24907e949c46SKenneth D. Merry int i;
24917e949c46SKenneth D. Merry
24927e949c46SKenneth D. Merry for (i = 0; i < 3; i++)
24937e949c46SKenneth D. Merry dest[i] = (long long)0xdeadbeefdeadbeef;
24947e949c46SKenneth D. Merry
2495407d708cSAlan Somers XNB_ASSERT(sscanf(mystr, "%llu", &dest[1]) == 1);
24967e949c46SKenneth D. Merry for (i = 0; i < 3; i++)
24977e949c46SKenneth D. Merry XNB_ASSERT(dest[i] == (i != 1 ? (long long)0xdeadbeefdeadbeef :
24987e949c46SKenneth D. Merry 12802747070103273189ull));
24997e949c46SKenneth D. Merry }
25007e949c46SKenneth D. Merry
25017e949c46SKenneth D. Merry /**
25027e949c46SKenneth D. Merry * sscanf on unsigned short short n's
25037e949c46SKenneth D. Merry */
25047e949c46SKenneth D. Merry static void
xnb_sscanf_hhn(char * buffer,size_t buflen)25057e949c46SKenneth D. Merry xnb_sscanf_hhn(char *buffer, size_t buflen)
25067e949c46SKenneth D. Merry {
25077e949c46SKenneth D. Merry const char mystr[] =
25087e949c46SKenneth D. Merry "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
25097e949c46SKenneth D. Merry "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"
25107e949c46SKenneth D. Merry "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f";
25117e949c46SKenneth D. Merry unsigned char dest[12];
25127e949c46SKenneth D. Merry int i;
25137e949c46SKenneth D. Merry
25147e949c46SKenneth D. Merry for (i = 0; i < 12; i++)
25157e949c46SKenneth D. Merry dest[i] = (unsigned char)'X';
25167e949c46SKenneth D. Merry
2517407d708cSAlan Somers XNB_ASSERT(sscanf(mystr,
25187e949c46SKenneth D. Merry "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
25197e949c46SKenneth D. Merry "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"
252065244d58SAlan Somers "404142434445464748494a4b4c4d4e4f%hhn", &dest[4]) == 0);
25217e949c46SKenneth D. Merry for (i = 0; i < 12; i++)
25227e949c46SKenneth D. Merry XNB_ASSERT(dest[i] == (i == 4 ? 160 : 'X'));
25237e949c46SKenneth D. Merry }
2524