The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/xen/netback/netback_unit_tests.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2009-2011 Spectra Logic Corporation
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions, and the following disclaimer,
   12  *    without modification.
   13  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   14  *    substantially similar to the "NO WARRANTY" disclaimer below
   15  *    ("Disclaimer") and any redistribution must be conditioned upon
   16  *    including a substantially similar Disclaimer requirement for further
   17  *    binary redistribution.
   18  *
   19  * NO WARRANTY
   20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
   23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   24  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   28  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
   29  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   30  * POSSIBILITY OF SUCH DAMAGES.
   31  *
   32  * Authors: Justin T. Gibbs     (Spectra Logic Corporation)
   33  *          Alan Somers         (Spectra Logic Corporation)
   34  *          John Suykerbuyk     (Spectra Logic Corporation)
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __FBSDID("$FreeBSD$");
   39 
   40 /**
   41  * \file netback_unit_tests.c
   42  *
   43  * \brief Unit tests for the Xen netback driver.
   44  *
   45  * Due to the driver's use of static functions, these tests cannot be compiled
   46  * standalone; they must be #include'd from the driver's .c file.
   47  */
   48 
   49 /** Helper macro used to snprintf to a buffer and update the buffer pointer */
   50 #define SNCATF(buffer, buflen, ...) do {                                \
   51         size_t new_chars = snprintf(buffer, buflen, __VA_ARGS__);       \
   52         buffer += new_chars;                                            \
   53         /* be careful; snprintf's return value can be  > buflen */      \
   54         buflen -= MIN(buflen, new_chars);                               \
   55 } while (0)
   56 
   57 /* STRINGIFY and TOSTRING are used only to help turn __LINE__ into a string */
   58 #define STRINGIFY(x) #x
   59 #define TOSTRING(x) STRINGIFY(x)
   60 
   61 /**
   62  * Writes an error message to buffer if cond is false
   63  * Note the implied parameters buffer and
   64  * buflen
   65  */
   66 #define XNB_ASSERT(cond) ({                                             \
   67         int passed = (cond);                                            \
   68         char *_buffer = (buffer);                                       \
   69         size_t _buflen = (buflen);                                      \
   70         if (! passed) {                                                 \
   71                 strlcat(_buffer, __func__, _buflen);                    \
   72                 strlcat(_buffer, ":" TOSTRING(__LINE__)                 \
   73                   " Assertion Error: " #cond "\n", _buflen);            \
   74         }                                                               \
   75         })
   76 
   77 /**
   78  * The signature used by all testcases.  If the test writes anything
   79  * to buffer, then it will be considered a failure
   80  * \param buffer        Return storage for error messages
   81  * \param buflen        The space available in the buffer
   82  */
   83 typedef void testcase_t(char *buffer, size_t buflen);
   84 
   85 /**
   86  * Signature used by setup functions
   87  * \return nonzero on error
   88  */
   89 typedef int setup_t(void);
   90 
   91 typedef void teardown_t(void);
   92 
   93 /** A simple test fixture comprising setup, teardown, and test */
   94 struct test_fixture {
   95         /** Will be run before the test to allocate and initialize variables */
   96         setup_t *setup;
   97 
   98         /** Will be run if setup succeeds */
   99         testcase_t *test;
  100 
  101         /** Cleans up test data whether or not the setup succeeded */
  102         teardown_t *teardown;
  103 };
  104 
  105 typedef struct test_fixture test_fixture_t;
  106 
  107 static int      xnb_get1pkt(struct xnb_pkt *pkt, size_t size, uint16_t flags);
  108 static int      xnb_unit_test_runner(test_fixture_t const tests[], int ntests,
  109                                      char *buffer, size_t buflen);
  110 
  111 static int __unused
  112 null_setup(void) { return 0; }
  113 
  114 static void __unused
  115 null_teardown(void) { }
  116 
  117 static setup_t setup_pvt_data;
  118 static teardown_t teardown_pvt_data;
  119 static testcase_t xnb_ring2pkt_emptyring;
  120 static testcase_t xnb_ring2pkt_1req;
  121 static testcase_t xnb_ring2pkt_2req;
  122 static testcase_t xnb_ring2pkt_3req;
  123 static testcase_t xnb_ring2pkt_extra;
  124 static testcase_t xnb_ring2pkt_partial;
  125 static testcase_t xnb_ring2pkt_wraps;
  126 static testcase_t xnb_txpkt2rsp_emptypkt;
  127 static testcase_t xnb_txpkt2rsp_1req;
  128 static testcase_t xnb_txpkt2rsp_extra;
  129 static testcase_t xnb_txpkt2rsp_long;
  130 static testcase_t xnb_txpkt2rsp_invalid;
  131 static testcase_t xnb_txpkt2rsp_error;
  132 static testcase_t xnb_txpkt2rsp_wraps;
  133 static testcase_t xnb_pkt2mbufc_empty;
  134 static testcase_t xnb_pkt2mbufc_short;
  135 static testcase_t xnb_pkt2mbufc_csum;
  136 static testcase_t xnb_pkt2mbufc_1cluster;
  137 static testcase_t xnb_pkt2mbufc_largecluster;
  138 static testcase_t xnb_pkt2mbufc_2cluster;
  139 static testcase_t xnb_txpkt2gnttab_empty;
  140 static testcase_t xnb_txpkt2gnttab_short;
  141 static testcase_t xnb_txpkt2gnttab_2req;
  142 static testcase_t xnb_txpkt2gnttab_2cluster;
  143 static testcase_t xnb_update_mbufc_short;
  144 static testcase_t xnb_update_mbufc_2req;
  145 static testcase_t xnb_update_mbufc_2cluster;
  146 static testcase_t xnb_mbufc2pkt_empty;
  147 static testcase_t xnb_mbufc2pkt_short;
  148 static testcase_t xnb_mbufc2pkt_1cluster;
  149 static testcase_t xnb_mbufc2pkt_2short;
  150 static testcase_t xnb_mbufc2pkt_long;
  151 static testcase_t xnb_mbufc2pkt_extra;
  152 static testcase_t xnb_mbufc2pkt_nospace;
  153 static testcase_t xnb_rxpkt2gnttab_empty;
  154 static testcase_t xnb_rxpkt2gnttab_short;
  155 static testcase_t xnb_rxpkt2gnttab_2req;
  156 static testcase_t xnb_rxpkt2rsp_empty;
  157 static testcase_t xnb_rxpkt2rsp_short;
  158 static testcase_t xnb_rxpkt2rsp_extra;
  159 static testcase_t xnb_rxpkt2rsp_2short;
  160 static testcase_t xnb_rxpkt2rsp_2slots;
  161 static testcase_t xnb_rxpkt2rsp_copyerror;
  162 static testcase_t xnb_sscanf_llu;
  163 static testcase_t xnb_sscanf_lld;
  164 static testcase_t xnb_sscanf_hhu;
  165 static testcase_t xnb_sscanf_hhd;
  166 static testcase_t xnb_sscanf_hhn;
  167 
  168 #if defined(INET) || defined(INET6)
  169 /* TODO: add test cases for xnb_add_mbuf_cksum for IPV6 tcp and udp */
  170 static testcase_t xnb_add_mbuf_cksum_arp;
  171 static testcase_t xnb_add_mbuf_cksum_tcp;
  172 static testcase_t xnb_add_mbuf_cksum_udp;
  173 static testcase_t xnb_add_mbuf_cksum_icmp;
  174 static testcase_t xnb_add_mbuf_cksum_tcp_swcksum;
  175 static void     xnb_fill_eh_and_ip(struct mbuf *m, uint16_t ip_len,
  176                                    uint16_t ip_id, uint16_t ip_p,
  177                                    uint16_t ip_off, uint16_t ip_sum);
  178 static void     xnb_fill_tcp(struct mbuf *m);
  179 #endif /* INET || INET6 */
  180 
  181 /** Private data used by unit tests */
  182 static struct {
  183         gnttab_copy_table       gnttab;
  184         netif_rx_back_ring_t    rxb;
  185         netif_rx_front_ring_t   rxf;
  186         netif_tx_back_ring_t    txb;
  187         netif_tx_front_ring_t   txf;
  188         struct ifnet*           ifp;
  189         netif_rx_sring_t*       rxs;
  190         netif_tx_sring_t*       txs;
  191 } xnb_unit_pvt;
  192 
  193 static inline void safe_m_freem(struct mbuf **ppMbuf) {
  194         if (*ppMbuf != NULL) {
  195                 m_freem(*ppMbuf);
  196                 *ppMbuf = NULL;
  197         }
  198 }
  199 
  200 /**
  201  * The unit test runner.  It will run every supplied test and return an
  202  * output message as a string
  203  * \param tests         An array of tests.  Every test will be attempted.
  204  * \param ntests        The length of tests
  205  * \param buffer        Return storage for the result string
  206  * \param buflen        The length of buffer
  207  * \return              The number of tests that failed
  208  */
  209 static int
  210 xnb_unit_test_runner(test_fixture_t const tests[], int ntests, char *buffer,
  211                      size_t buflen)
  212 {
  213         int i;
  214         int n_passes;
  215         int n_failures = 0;
  216 
  217         for (i = 0; i < ntests; i++) {
  218                 int error = tests[i].setup();
  219                 if (error != 0) {
  220                         SNCATF(buffer, buflen,
  221                             "Setup failed for test idx %d\n", i);
  222                         n_failures++;
  223                 } else {
  224                         size_t new_chars;
  225 
  226                         tests[i].test(buffer, buflen);
  227                         new_chars = strnlen(buffer, buflen);
  228                         buffer += new_chars;
  229                         buflen -= new_chars;
  230 
  231                         if (new_chars > 0) {
  232                                 n_failures++;
  233                         }
  234                 }
  235                 tests[i].teardown();
  236         }
  237 
  238         n_passes = ntests - n_failures;
  239         if (n_passes > 0) {
  240                 SNCATF(buffer, buflen, "%d Tests Passed\n", n_passes);
  241         }
  242         if (n_failures > 0) {
  243                 SNCATF(buffer, buflen, "%d Tests FAILED\n", n_failures);
  244         }
  245 
  246         return n_failures;
  247 }
  248 
  249 /** Number of unit tests.  Must match the length of the tests array below */
  250 #define TOTAL_TESTS     (53)
  251 /**
  252  * Max memory available for returning results.  400 chars/test should give
  253  * enough space for a five line error message for every test
  254  */
  255 #define TOTAL_BUFLEN    (400 * TOTAL_TESTS + 2)
  256 
  257 /**
  258  * Called from userspace by a sysctl.  Runs all internal unit tests, and
  259  * returns the results to userspace as a string
  260  * \param oidp  unused
  261  * \param arg1  pointer to an xnb_softc for a specific xnb device
  262  * \param arg2  unused
  263  * \param req   sysctl access structure
  264  * \return a string via the special SYSCTL_OUT macro.
  265  */
  266 
  267 static int
  268 xnb_unit_test_main(SYSCTL_HANDLER_ARGS) {
  269         test_fixture_t const tests[TOTAL_TESTS] = {
  270                 {setup_pvt_data, xnb_ring2pkt_emptyring, teardown_pvt_data},
  271                 {setup_pvt_data, xnb_ring2pkt_1req, teardown_pvt_data},
  272                 {setup_pvt_data, xnb_ring2pkt_2req, teardown_pvt_data},
  273                 {setup_pvt_data, xnb_ring2pkt_3req, teardown_pvt_data},
  274                 {setup_pvt_data, xnb_ring2pkt_extra, teardown_pvt_data},
  275                 {setup_pvt_data, xnb_ring2pkt_partial, teardown_pvt_data},
  276                 {setup_pvt_data, xnb_ring2pkt_wraps, teardown_pvt_data},
  277                 {setup_pvt_data, xnb_txpkt2rsp_emptypkt, teardown_pvt_data},
  278                 {setup_pvt_data, xnb_txpkt2rsp_1req, teardown_pvt_data},
  279                 {setup_pvt_data, xnb_txpkt2rsp_extra, teardown_pvt_data},
  280                 {setup_pvt_data, xnb_txpkt2rsp_long, teardown_pvt_data},
  281                 {setup_pvt_data, xnb_txpkt2rsp_invalid, teardown_pvt_data},
  282                 {setup_pvt_data, xnb_txpkt2rsp_error, teardown_pvt_data},
  283                 {setup_pvt_data, xnb_txpkt2rsp_wraps, teardown_pvt_data},
  284                 {setup_pvt_data, xnb_pkt2mbufc_empty, teardown_pvt_data},
  285                 {setup_pvt_data, xnb_pkt2mbufc_short, teardown_pvt_data},
  286                 {setup_pvt_data, xnb_pkt2mbufc_csum, teardown_pvt_data},
  287                 {setup_pvt_data, xnb_pkt2mbufc_1cluster, teardown_pvt_data},
  288                 {setup_pvt_data, xnb_pkt2mbufc_largecluster, teardown_pvt_data},
  289                 {setup_pvt_data, xnb_pkt2mbufc_2cluster, teardown_pvt_data},
  290                 {setup_pvt_data, xnb_txpkt2gnttab_empty, teardown_pvt_data},
  291                 {setup_pvt_data, xnb_txpkt2gnttab_short, teardown_pvt_data},
  292                 {setup_pvt_data, xnb_txpkt2gnttab_2req, teardown_pvt_data},
  293                 {setup_pvt_data, xnb_txpkt2gnttab_2cluster, teardown_pvt_data},
  294                 {setup_pvt_data, xnb_update_mbufc_short, teardown_pvt_data},
  295                 {setup_pvt_data, xnb_update_mbufc_2req, teardown_pvt_data},
  296                 {setup_pvt_data, xnb_update_mbufc_2cluster, teardown_pvt_data},
  297                 {setup_pvt_data, xnb_mbufc2pkt_empty, teardown_pvt_data},
  298                 {setup_pvt_data, xnb_mbufc2pkt_short, teardown_pvt_data},
  299                 {setup_pvt_data, xnb_mbufc2pkt_1cluster, teardown_pvt_data},
  300                 {setup_pvt_data, xnb_mbufc2pkt_2short, teardown_pvt_data},
  301                 {setup_pvt_data, xnb_mbufc2pkt_long, teardown_pvt_data},
  302                 {setup_pvt_data, xnb_mbufc2pkt_extra, teardown_pvt_data},
  303                 {setup_pvt_data, xnb_mbufc2pkt_nospace, teardown_pvt_data},
  304                 {setup_pvt_data, xnb_rxpkt2gnttab_empty, teardown_pvt_data},
  305                 {setup_pvt_data, xnb_rxpkt2gnttab_short, teardown_pvt_data},
  306                 {setup_pvt_data, xnb_rxpkt2gnttab_2req, teardown_pvt_data},
  307                 {setup_pvt_data, xnb_rxpkt2rsp_empty, teardown_pvt_data},
  308                 {setup_pvt_data, xnb_rxpkt2rsp_short, teardown_pvt_data},
  309                 {setup_pvt_data, xnb_rxpkt2rsp_extra, teardown_pvt_data},
  310                 {setup_pvt_data, xnb_rxpkt2rsp_2short, teardown_pvt_data},
  311                 {setup_pvt_data, xnb_rxpkt2rsp_2slots, teardown_pvt_data},
  312                 {setup_pvt_data, xnb_rxpkt2rsp_copyerror, teardown_pvt_data},
  313 #if defined(INET) || defined(INET6)
  314                 {null_setup, xnb_add_mbuf_cksum_arp, null_teardown},
  315                 {null_setup, xnb_add_mbuf_cksum_icmp, null_teardown},
  316                 {null_setup, xnb_add_mbuf_cksum_tcp, null_teardown},
  317                 {null_setup, xnb_add_mbuf_cksum_tcp_swcksum, null_teardown},
  318                 {null_setup, xnb_add_mbuf_cksum_udp, null_teardown},
  319 #endif
  320                 {null_setup, xnb_sscanf_hhd, null_teardown},
  321                 {null_setup, xnb_sscanf_hhu, null_teardown},
  322                 {null_setup, xnb_sscanf_lld, null_teardown},
  323                 {null_setup, xnb_sscanf_llu, null_teardown},
  324                 {null_setup, xnb_sscanf_hhn, null_teardown},
  325         };
  326         /**
  327          * results is static so that the data will persist after this function
  328          * returns.  The sysctl code expects us to return a constant string.
  329          * \todo: the static variable is not thread safe.  Put a mutex around
  330          * it.
  331          */
  332         static char results[TOTAL_BUFLEN];
  333 
  334         /* empty the result strings */
  335         results[0] = 0;
  336         xnb_unit_test_runner(tests, TOTAL_TESTS, results, TOTAL_BUFLEN);
  337 
  338         return (SYSCTL_OUT(req, results, strnlen(results, TOTAL_BUFLEN)));
  339 }
  340 
  341 static int
  342 setup_pvt_data(void)
  343 {
  344         int error = 0;
  345 
  346         bzero(xnb_unit_pvt.gnttab, sizeof(xnb_unit_pvt.gnttab));
  347 
  348         xnb_unit_pvt.txs = malloc(PAGE_SIZE, M_XENNETBACK, M_WAITOK|M_ZERO);
  349         if (xnb_unit_pvt.txs != NULL) {
  350                 SHARED_RING_INIT(xnb_unit_pvt.txs);
  351                 BACK_RING_INIT(&xnb_unit_pvt.txb, xnb_unit_pvt.txs, PAGE_SIZE);
  352                 FRONT_RING_INIT(&xnb_unit_pvt.txf, xnb_unit_pvt.txs, PAGE_SIZE);
  353         } else {
  354                 error = 1;
  355         }
  356 
  357         xnb_unit_pvt.ifp = if_alloc(IFT_ETHER);
  358         if (xnb_unit_pvt.ifp == NULL) {
  359                 error = 1;
  360         }
  361 
  362         xnb_unit_pvt.rxs = malloc(PAGE_SIZE, M_XENNETBACK, M_WAITOK|M_ZERO);
  363         if (xnb_unit_pvt.rxs != NULL) {
  364                 SHARED_RING_INIT(xnb_unit_pvt.rxs);
  365                 BACK_RING_INIT(&xnb_unit_pvt.rxb, xnb_unit_pvt.rxs, PAGE_SIZE);
  366                 FRONT_RING_INIT(&xnb_unit_pvt.rxf, xnb_unit_pvt.rxs, PAGE_SIZE);
  367         } else {
  368                 error = 1;
  369         }
  370 
  371         return error;
  372 }
  373 
  374 static void
  375 teardown_pvt_data(void)
  376 {
  377         if (xnb_unit_pvt.txs != NULL) {
  378                 free(xnb_unit_pvt.txs, M_XENNETBACK);
  379         }
  380         if (xnb_unit_pvt.rxs != NULL) {
  381                 free(xnb_unit_pvt.rxs, M_XENNETBACK);
  382         }
  383         if (xnb_unit_pvt.ifp != NULL) {
  384                 if_free(xnb_unit_pvt.ifp);
  385         }
  386 }
  387 
  388 /**
  389  * Verify that xnb_ring2pkt will not consume any requests from an empty ring
  390  */
  391 static void
  392 xnb_ring2pkt_emptyring(char *buffer, size_t buflen)
  393 {
  394         struct xnb_pkt pkt;
  395         int num_consumed;
  396 
  397         num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
  398                                     xnb_unit_pvt.txb.req_cons);
  399         XNB_ASSERT(num_consumed == 0);
  400 }
  401 
  402 /**
  403  * Verify that xnb_ring2pkt can convert a single request packet correctly
  404  */
  405 static void
  406 xnb_ring2pkt_1req(char *buffer, size_t buflen)
  407 {
  408         struct xnb_pkt pkt;
  409         int num_consumed;
  410         struct netif_tx_request *req;
  411 
  412         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  413             xnb_unit_pvt.txf.req_prod_pvt);
  414 
  415         req->flags = 0;
  416         req->size = 69; /* arbitrary number for test */
  417         xnb_unit_pvt.txf.req_prod_pvt++;
  418 
  419         RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
  420 
  421         num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
  422                                     xnb_unit_pvt.txb.req_cons);
  423         XNB_ASSERT(num_consumed == 1);
  424         XNB_ASSERT(pkt.size == 69);
  425         XNB_ASSERT(pkt.car_size == 69);
  426         XNB_ASSERT(pkt.flags == 0);
  427         XNB_ASSERT(xnb_pkt_is_valid(&pkt));
  428         XNB_ASSERT(pkt.list_len == 1);
  429         XNB_ASSERT(pkt.car == 0);
  430 }
  431 
  432 /**
  433  * Verify that xnb_ring2pkt can convert a two request packet correctly.
  434  * This tests handling of the MORE_DATA flag and cdr
  435  */
  436 static void
  437 xnb_ring2pkt_2req(char *buffer, size_t buflen)
  438 {
  439         struct xnb_pkt pkt;
  440         int num_consumed;
  441         struct netif_tx_request *req;
  442         RING_IDX start_idx = xnb_unit_pvt.txf.req_prod_pvt;
  443 
  444         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  445             xnb_unit_pvt.txf.req_prod_pvt);
  446         req->flags = NETTXF_more_data;
  447         req->size = 100;
  448         xnb_unit_pvt.txf.req_prod_pvt++;
  449 
  450         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  451             xnb_unit_pvt.txf.req_prod_pvt);
  452         req->flags = 0;
  453         req->size = 40;
  454         xnb_unit_pvt.txf.req_prod_pvt++;
  455 
  456         RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
  457 
  458         num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
  459                                     xnb_unit_pvt.txb.req_cons);
  460         XNB_ASSERT(num_consumed == 2);
  461         XNB_ASSERT(pkt.size == 100);
  462         XNB_ASSERT(pkt.car_size == 60);
  463         XNB_ASSERT(pkt.flags == 0);
  464         XNB_ASSERT(xnb_pkt_is_valid(&pkt));
  465         XNB_ASSERT(pkt.list_len == 2);
  466         XNB_ASSERT(pkt.car == start_idx);
  467         XNB_ASSERT(pkt.cdr == start_idx + 1);
  468 }
  469 
  470 /**
  471  * Verify that xnb_ring2pkt can convert a three request packet correctly
  472  */
  473 static void
  474 xnb_ring2pkt_3req(char *buffer, size_t buflen)
  475 {
  476         struct xnb_pkt pkt;
  477         int num_consumed;
  478         struct netif_tx_request *req;
  479         RING_IDX start_idx = xnb_unit_pvt.txf.req_prod_pvt;
  480 
  481         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  482             xnb_unit_pvt.txf.req_prod_pvt);
  483         req->flags = NETTXF_more_data;
  484         req->size = 200;
  485         xnb_unit_pvt.txf.req_prod_pvt++;
  486 
  487         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  488             xnb_unit_pvt.txf.req_prod_pvt);
  489         req->flags = NETTXF_more_data;
  490         req->size = 40;
  491         xnb_unit_pvt.txf.req_prod_pvt++;
  492 
  493         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  494             xnb_unit_pvt.txf.req_prod_pvt);
  495         req->flags = 0;
  496         req->size = 50;
  497         xnb_unit_pvt.txf.req_prod_pvt++;
  498 
  499         RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
  500 
  501         num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
  502                                     xnb_unit_pvt.txb.req_cons);
  503         XNB_ASSERT(num_consumed == 3);
  504         XNB_ASSERT(pkt.size == 200);
  505         XNB_ASSERT(pkt.car_size == 110);
  506         XNB_ASSERT(pkt.flags == 0);
  507         XNB_ASSERT(xnb_pkt_is_valid(&pkt));
  508         XNB_ASSERT(pkt.list_len == 3);
  509         XNB_ASSERT(pkt.car == start_idx);
  510         XNB_ASSERT(pkt.cdr == start_idx + 1);
  511         XNB_ASSERT(RING_GET_REQUEST(&xnb_unit_pvt.txb, pkt.cdr + 1) == req);
  512 }
  513 
  514 /**
  515  * Verify that xnb_ring2pkt can read extra inf
  516  */
  517 static void
  518 xnb_ring2pkt_extra(char *buffer, size_t buflen)
  519 {
  520         struct xnb_pkt pkt;
  521         int num_consumed;
  522         struct netif_tx_request *req;
  523         struct netif_extra_info *ext;
  524         RING_IDX start_idx = xnb_unit_pvt.txf.req_prod_pvt;
  525 
  526         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  527             xnb_unit_pvt.txf.req_prod_pvt);
  528         req->flags = NETTXF_extra_info | NETTXF_more_data;
  529         req->size = 150;
  530         xnb_unit_pvt.txf.req_prod_pvt++;
  531 
  532         ext = (struct netif_extra_info*) RING_GET_REQUEST(&xnb_unit_pvt.txf,
  533             xnb_unit_pvt.txf.req_prod_pvt);
  534         ext->flags = 0;
  535         ext->type = XEN_NETIF_EXTRA_TYPE_GSO;
  536         ext->u.gso.size = 250;
  537         ext->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
  538         ext->u.gso.features = 0;
  539         xnb_unit_pvt.txf.req_prod_pvt++;
  540 
  541         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  542             xnb_unit_pvt.txf.req_prod_pvt);
  543         req->flags = 0;
  544         req->size = 50;
  545         xnb_unit_pvt.txf.req_prod_pvt++;
  546 
  547         RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
  548 
  549         num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
  550                                     xnb_unit_pvt.txb.req_cons);
  551         XNB_ASSERT(num_consumed == 3);
  552         XNB_ASSERT(pkt.extra.flags == 0);
  553         XNB_ASSERT(pkt.extra.type == XEN_NETIF_EXTRA_TYPE_GSO);
  554         XNB_ASSERT(pkt.extra.u.gso.size == 250);
  555         XNB_ASSERT(pkt.extra.u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4);
  556         XNB_ASSERT(pkt.size == 150);
  557         XNB_ASSERT(pkt.car_size == 100);
  558         XNB_ASSERT(pkt.flags == NETTXF_extra_info);
  559         XNB_ASSERT(xnb_pkt_is_valid(&pkt));
  560         XNB_ASSERT(pkt.list_len == 2);
  561         XNB_ASSERT(pkt.car == start_idx);
  562         XNB_ASSERT(pkt.cdr == start_idx + 2);
  563         XNB_ASSERT(RING_GET_REQUEST(&xnb_unit_pvt.txb, pkt.cdr) == req);
  564 }
  565 
  566 /**
  567  * Verify that xnb_ring2pkt will consume no requests if the entire packet is
  568  * not yet in the ring
  569  */
  570 static void
  571 xnb_ring2pkt_partial(char *buffer, size_t buflen)
  572 {
  573         struct xnb_pkt pkt;
  574         int num_consumed;
  575         struct netif_tx_request *req;
  576 
  577         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  578             xnb_unit_pvt.txf.req_prod_pvt);
  579         req->flags = NETTXF_more_data;
  580         req->size = 150;
  581         xnb_unit_pvt.txf.req_prod_pvt++;
  582 
  583         RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
  584 
  585         num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
  586                                     xnb_unit_pvt.txb.req_cons);
  587         XNB_ASSERT(num_consumed == 0);
  588         XNB_ASSERT(! xnb_pkt_is_valid(&pkt));
  589 }
  590 
  591 /**
  592  * Verity that xnb_ring2pkt can read a packet whose requests wrap around
  593  * the end of the ring
  594  */
  595 static void
  596 xnb_ring2pkt_wraps(char *buffer, size_t buflen)
  597 {
  598         struct xnb_pkt pkt;
  599         int num_consumed;
  600         struct netif_tx_request *req;
  601         unsigned int rsize;
  602 
  603         /*
  604          * Manually tweak the ring indices to create a ring with no responses
  605          * and the next request slot at position 2 from the end
  606          */
  607         rsize = RING_SIZE(&xnb_unit_pvt.txf);
  608         xnb_unit_pvt.txf.req_prod_pvt = rsize - 2;
  609         xnb_unit_pvt.txf.rsp_cons = rsize - 2;
  610         xnb_unit_pvt.txs->req_prod = rsize - 2;
  611         xnb_unit_pvt.txs->req_event = rsize - 1;
  612         xnb_unit_pvt.txs->rsp_prod = rsize - 2;
  613         xnb_unit_pvt.txs->rsp_event = rsize - 1;
  614         xnb_unit_pvt.txb.rsp_prod_pvt = rsize - 2;
  615         xnb_unit_pvt.txb.req_cons = rsize - 2;
  616 
  617         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  618             xnb_unit_pvt.txf.req_prod_pvt);
  619         req->flags = NETTXF_more_data;
  620         req->size = 550;
  621         xnb_unit_pvt.txf.req_prod_pvt++;
  622 
  623         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  624             xnb_unit_pvt.txf.req_prod_pvt);
  625         req->flags = NETTXF_more_data;
  626         req->size = 100;
  627         xnb_unit_pvt.txf.req_prod_pvt++;
  628 
  629         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  630             xnb_unit_pvt.txf.req_prod_pvt);
  631         req->flags = 0;
  632         req->size = 50;
  633         xnb_unit_pvt.txf.req_prod_pvt++;
  634 
  635         RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
  636 
  637         num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
  638                                     xnb_unit_pvt.txb.req_cons);
  639         XNB_ASSERT(num_consumed == 3);
  640         XNB_ASSERT(xnb_pkt_is_valid(&pkt));
  641         XNB_ASSERT(pkt.list_len == 3);
  642         XNB_ASSERT(RING_GET_REQUEST(&xnb_unit_pvt.txb, pkt.cdr + 1) == req);
  643 }
  644 
  645 /**
  646  * xnb_txpkt2rsp should do nothing for an empty packet
  647  */
  648 static void
  649 xnb_txpkt2rsp_emptypkt(char *buffer, size_t buflen)
  650 {
  651         struct xnb_pkt pkt;
  652         netif_tx_back_ring_t txb_backup = xnb_unit_pvt.txb;
  653         netif_tx_sring_t txs_backup = *xnb_unit_pvt.txs;
  654         pkt.list_len = 0;
  655 
  656         /* must call xnb_ring2pkt just to intialize pkt */
  657         xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb, xnb_unit_pvt.txb.req_cons);
  658         xnb_txpkt2rsp(&pkt, &xnb_unit_pvt.txb, 0);
  659         XNB_ASSERT(
  660             memcmp(&txb_backup, &xnb_unit_pvt.txb, sizeof(txb_backup)) == 0);
  661         XNB_ASSERT(
  662             memcmp(&txs_backup, xnb_unit_pvt.txs, sizeof(txs_backup)) == 0);
  663 }
  664 
  665 /**
  666  * xnb_txpkt2rsp responding to one request
  667  */
  668 static void
  669 xnb_txpkt2rsp_1req(char *buffer, size_t buflen)
  670 {
  671         uint16_t num_consumed;
  672         struct xnb_pkt pkt;
  673         struct netif_tx_request *req;
  674         struct netif_tx_response *rsp;
  675 
  676         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  677             xnb_unit_pvt.txf.req_prod_pvt);
  678         req->size = 1000;
  679         req->flags = 0;
  680         xnb_unit_pvt.txf.req_prod_pvt++;
  681 
  682         RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
  683 
  684         num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
  685                                     xnb_unit_pvt.txb.req_cons);
  686         xnb_unit_pvt.txb.req_cons += num_consumed;
  687 
  688         xnb_txpkt2rsp(&pkt, &xnb_unit_pvt.txb, 0);
  689         rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb, xnb_unit_pvt.txf.rsp_cons);
  690 
  691         XNB_ASSERT(
  692             xnb_unit_pvt.txb.rsp_prod_pvt == xnb_unit_pvt.txs->req_prod);
  693         XNB_ASSERT(rsp->id == req->id);
  694         XNB_ASSERT(rsp->status == NETIF_RSP_OKAY);
  695 };
  696 
  697 /**
  698  * xnb_txpkt2rsp responding to 1 data request and 1 extra info
  699  */
  700 static void
  701 xnb_txpkt2rsp_extra(char *buffer, size_t buflen)
  702 {
  703         uint16_t num_consumed;
  704         struct xnb_pkt pkt;
  705         struct netif_tx_request *req;
  706         netif_extra_info_t *ext;
  707         struct netif_tx_response *rsp;
  708 
  709         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  710             xnb_unit_pvt.txf.req_prod_pvt);
  711         req->size = 1000;
  712         req->flags = NETTXF_extra_info;
  713         req->id = 69;
  714         xnb_unit_pvt.txf.req_prod_pvt++;
  715 
  716         ext = (netif_extra_info_t*) RING_GET_REQUEST(&xnb_unit_pvt.txf,
  717             xnb_unit_pvt.txf.req_prod_pvt);
  718         ext->type = XEN_NETIF_EXTRA_TYPE_GSO;
  719         ext->flags = 0;
  720         xnb_unit_pvt.txf.req_prod_pvt++;
  721 
  722         RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
  723 
  724         num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
  725                                     xnb_unit_pvt.txb.req_cons);
  726         xnb_unit_pvt.txb.req_cons += num_consumed;
  727 
  728         xnb_txpkt2rsp(&pkt, &xnb_unit_pvt.txb, 0);
  729 
  730         XNB_ASSERT(
  731             xnb_unit_pvt.txb.rsp_prod_pvt == xnb_unit_pvt.txs->req_prod);
  732 
  733         rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb, xnb_unit_pvt.txf.rsp_cons);
  734         XNB_ASSERT(rsp->id == req->id);
  735         XNB_ASSERT(rsp->status == NETIF_RSP_OKAY);
  736 
  737         rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb,
  738             xnb_unit_pvt.txf.rsp_cons + 1);
  739         XNB_ASSERT(rsp->status == NETIF_RSP_NULL);
  740 };
  741 
  742 /**
  743  * xnb_pkg2rsp responding to 3 data requests and 1 extra info
  744  */
  745 static void
  746 xnb_txpkt2rsp_long(char *buffer, size_t buflen)
  747 {
  748         uint16_t num_consumed;
  749         struct xnb_pkt pkt;
  750         struct netif_tx_request *req;
  751         netif_extra_info_t *ext;
  752         struct netif_tx_response *rsp;
  753 
  754         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  755             xnb_unit_pvt.txf.req_prod_pvt);
  756         req->size = 1000;
  757         req->flags = NETTXF_extra_info | NETTXF_more_data;
  758         req->id = 254;
  759         xnb_unit_pvt.txf.req_prod_pvt++;
  760 
  761         ext = (netif_extra_info_t*) RING_GET_REQUEST(&xnb_unit_pvt.txf,
  762             xnb_unit_pvt.txf.req_prod_pvt);
  763         ext->type = XEN_NETIF_EXTRA_TYPE_GSO;
  764         ext->flags = 0;
  765         xnb_unit_pvt.txf.req_prod_pvt++;
  766 
  767         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  768             xnb_unit_pvt.txf.req_prod_pvt);
  769         req->size = 300;
  770         req->flags = NETTXF_more_data;
  771         req->id = 1034;
  772         xnb_unit_pvt.txf.req_prod_pvt++;
  773 
  774         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  775             xnb_unit_pvt.txf.req_prod_pvt);
  776         req->size = 400;
  777         req->flags = 0;
  778         req->id = 34;
  779         xnb_unit_pvt.txf.req_prod_pvt++;
  780 
  781         RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
  782 
  783         num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
  784                                     xnb_unit_pvt.txb.req_cons);
  785         xnb_unit_pvt.txb.req_cons += num_consumed;
  786 
  787         xnb_txpkt2rsp(&pkt, &xnb_unit_pvt.txb, 0);
  788 
  789         XNB_ASSERT(
  790             xnb_unit_pvt.txb.rsp_prod_pvt == xnb_unit_pvt.txs->req_prod);
  791 
  792         rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb, xnb_unit_pvt.txf.rsp_cons);
  793         XNB_ASSERT(rsp->id ==
  794             RING_GET_REQUEST(&xnb_unit_pvt.txf, 0)->id);
  795         XNB_ASSERT(rsp->status == NETIF_RSP_OKAY);
  796 
  797         rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb,
  798             xnb_unit_pvt.txf.rsp_cons + 1);
  799         XNB_ASSERT(rsp->status == NETIF_RSP_NULL);
  800 
  801         rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb,
  802             xnb_unit_pvt.txf.rsp_cons + 2);
  803         XNB_ASSERT(rsp->id ==
  804             RING_GET_REQUEST(&xnb_unit_pvt.txf, 2)->id);
  805         XNB_ASSERT(rsp->status == NETIF_RSP_OKAY);
  806 
  807         rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb,
  808             xnb_unit_pvt.txf.rsp_cons + 3);
  809         XNB_ASSERT(rsp->id ==
  810             RING_GET_REQUEST(&xnb_unit_pvt.txf, 3)->id);
  811         XNB_ASSERT(rsp->status == NETIF_RSP_OKAY);
  812 }
  813 
  814 /**
  815  * xnb_txpkt2rsp responding to an invalid packet.
  816  * Note: this test will result in an error message being printed to the console
  817  * such as:
  818  * xnb(xnb_ring2pkt:1306): Unknown extra info type 255.  Discarding packet
  819  */
  820 static void
  821 xnb_txpkt2rsp_invalid(char *buffer, size_t buflen)
  822 {
  823         uint16_t num_consumed;
  824         struct xnb_pkt pkt;
  825         struct netif_tx_request *req;
  826         netif_extra_info_t *ext;
  827         struct netif_tx_response *rsp;
  828 
  829         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  830             xnb_unit_pvt.txf.req_prod_pvt);
  831         req->size = 1000;
  832         req->flags = NETTXF_extra_info;
  833         req->id = 69;
  834         xnb_unit_pvt.txf.req_prod_pvt++;
  835 
  836         ext = (netif_extra_info_t*) RING_GET_REQUEST(&xnb_unit_pvt.txf,
  837             xnb_unit_pvt.txf.req_prod_pvt);
  838         ext->type = 0xFF;       /* Invalid extra type */
  839         ext->flags = 0;
  840         xnb_unit_pvt.txf.req_prod_pvt++;
  841 
  842         RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
  843 
  844         num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
  845                                     xnb_unit_pvt.txb.req_cons);
  846         xnb_unit_pvt.txb.req_cons += num_consumed;
  847         XNB_ASSERT(! xnb_pkt_is_valid(&pkt));
  848 
  849         xnb_txpkt2rsp(&pkt, &xnb_unit_pvt.txb, 0);
  850 
  851         XNB_ASSERT(
  852             xnb_unit_pvt.txb.rsp_prod_pvt == xnb_unit_pvt.txs->req_prod);
  853 
  854         rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb, xnb_unit_pvt.txf.rsp_cons);
  855         XNB_ASSERT(rsp->id == req->id);
  856         XNB_ASSERT(rsp->status == NETIF_RSP_ERROR);
  857 
  858         rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb,
  859             xnb_unit_pvt.txf.rsp_cons + 1);
  860         XNB_ASSERT(rsp->status == NETIF_RSP_NULL);
  861 };
  862 
  863 /**
  864  * xnb_txpkt2rsp responding to one request which caused an error
  865  */
  866 static void
  867 xnb_txpkt2rsp_error(char *buffer, size_t buflen)
  868 {
  869         uint16_t num_consumed;
  870         struct xnb_pkt pkt;
  871         struct netif_tx_request *req;
  872         struct netif_tx_response *rsp;
  873 
  874         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  875             xnb_unit_pvt.txf.req_prod_pvt);
  876         req->size = 1000;
  877         req->flags = 0;
  878         xnb_unit_pvt.txf.req_prod_pvt++;
  879 
  880         RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
  881 
  882         num_consumed = xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb,
  883                                     xnb_unit_pvt.txb.req_cons);
  884         xnb_unit_pvt.txb.req_cons += num_consumed;
  885 
  886         xnb_txpkt2rsp(&pkt, &xnb_unit_pvt.txb, 1);
  887         rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb, xnb_unit_pvt.txf.rsp_cons);
  888 
  889         XNB_ASSERT(
  890             xnb_unit_pvt.txb.rsp_prod_pvt == xnb_unit_pvt.txs->req_prod);
  891         XNB_ASSERT(rsp->id == req->id);
  892         XNB_ASSERT(rsp->status == NETIF_RSP_ERROR);
  893 };
  894 
  895 /**
  896  * xnb_txpkt2rsp's responses wrap around the end of the ring
  897  */
  898 static void
  899 xnb_txpkt2rsp_wraps(char *buffer, size_t buflen)
  900 {
  901         struct xnb_pkt pkt;
  902         struct netif_tx_request *req;
  903         struct netif_tx_response *rsp;
  904         unsigned int rsize;
  905 
  906         /*
  907          * Manually tweak the ring indices to create a ring with no responses
  908          * and the next request slot at position 2 from the end
  909          */
  910         rsize = RING_SIZE(&xnb_unit_pvt.txf);
  911         xnb_unit_pvt.txf.req_prod_pvt = rsize - 2;
  912         xnb_unit_pvt.txf.rsp_cons = rsize - 2;
  913         xnb_unit_pvt.txs->req_prod = rsize - 2;
  914         xnb_unit_pvt.txs->req_event = rsize - 1;
  915         xnb_unit_pvt.txs->rsp_prod = rsize - 2;
  916         xnb_unit_pvt.txs->rsp_event = rsize - 1;
  917         xnb_unit_pvt.txb.rsp_prod_pvt = rsize - 2;
  918         xnb_unit_pvt.txb.req_cons = rsize - 2;
  919 
  920         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  921             xnb_unit_pvt.txf.req_prod_pvt);
  922         req->flags = NETTXF_more_data;
  923         req->size = 550;
  924         req->id = 1;
  925         xnb_unit_pvt.txf.req_prod_pvt++;
  926 
  927         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  928             xnb_unit_pvt.txf.req_prod_pvt);
  929         req->flags = NETTXF_more_data;
  930         req->size = 100;
  931         req->id = 2;
  932         xnb_unit_pvt.txf.req_prod_pvt++;
  933 
  934         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  935             xnb_unit_pvt.txf.req_prod_pvt);
  936         req->flags = 0;
  937         req->size = 50;
  938         req->id = 3;
  939         xnb_unit_pvt.txf.req_prod_pvt++;
  940 
  941         RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
  942 
  943         xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb, xnb_unit_pvt.txb.req_cons);
  944 
  945         xnb_txpkt2rsp(&pkt, &xnb_unit_pvt.txb, 0);
  946 
  947         XNB_ASSERT(
  948             xnb_unit_pvt.txb.rsp_prod_pvt == xnb_unit_pvt.txs->req_prod);
  949         rsp = RING_GET_RESPONSE(&xnb_unit_pvt.txb,
  950             xnb_unit_pvt.txf.rsp_cons + 2);
  951         XNB_ASSERT(rsp->id == req->id);
  952         XNB_ASSERT(rsp->status == NETIF_RSP_OKAY);
  953 }
  954 
  955 /**
  956  * Helper function used to setup pkt2mbufc tests
  957  * \param size     size in bytes of the single request to push to the ring
  958  * \param flags         optional flags to put in the netif request
  959  * \param[out] pkt the returned packet object
  960  * \return number of requests consumed from the ring
  961  */
  962 static int
  963 xnb_get1pkt(struct xnb_pkt *pkt, size_t size, uint16_t flags)
  964 {
  965         struct netif_tx_request *req;
  966 
  967         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
  968             xnb_unit_pvt.txf.req_prod_pvt);
  969         req->flags = flags;
  970         req->size = size;
  971         xnb_unit_pvt.txf.req_prod_pvt++;
  972 
  973         RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
  974 
  975         return xnb_ring2pkt(pkt, &xnb_unit_pvt.txb,
  976                                     xnb_unit_pvt.txb.req_cons);
  977 }
  978 
  979 /**
  980  * xnb_pkt2mbufc on an empty packet
  981  */
  982 static void
  983 xnb_pkt2mbufc_empty(char *buffer, size_t buflen)
  984 {
  985         struct xnb_pkt pkt;
  986         struct mbuf *pMbuf;
  987         pkt.list_len = 0;
  988 
  989         /* must call xnb_ring2pkt just to intialize pkt */
  990         xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb, xnb_unit_pvt.txb.req_cons);
  991         pkt.size = 0;
  992         pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
  993         safe_m_freem(&pMbuf);
  994 }
  995 
  996 /**
  997  * xnb_pkt2mbufc on short packet that can fit in an mbuf internal buffer
  998  */
  999 static void
 1000 xnb_pkt2mbufc_short(char *buffer, size_t buflen)
 1001 {
 1002         const size_t size = MINCLSIZE - 1;
 1003         struct xnb_pkt pkt;
 1004         struct mbuf *pMbuf;
 1005 
 1006         xnb_get1pkt(&pkt, size, 0);
 1007 
 1008         pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
 1009         XNB_ASSERT(M_TRAILINGSPACE(pMbuf) >= size);
 1010         safe_m_freem(&pMbuf);
 1011 }
 1012 
 1013 /**
 1014  * xnb_pkt2mbufc on short packet whose checksum was validated by the netfron
 1015  */
 1016 static void
 1017 xnb_pkt2mbufc_csum(char *buffer, size_t buflen)
 1018 {
 1019         const size_t size = MINCLSIZE - 1;
 1020         struct xnb_pkt pkt;
 1021         struct mbuf *pMbuf;
 1022 
 1023         xnb_get1pkt(&pkt, size, NETTXF_data_validated);
 1024 
 1025         pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
 1026         XNB_ASSERT(M_TRAILINGSPACE(pMbuf) >= size);
 1027         XNB_ASSERT(pMbuf->m_pkthdr.csum_flags & CSUM_IP_CHECKED);
 1028         XNB_ASSERT(pMbuf->m_pkthdr.csum_flags & CSUM_IP_VALID);
 1029         XNB_ASSERT(pMbuf->m_pkthdr.csum_flags & CSUM_DATA_VALID);
 1030         XNB_ASSERT(pMbuf->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR);
 1031         safe_m_freem(&pMbuf);
 1032 }
 1033 
 1034 /**
 1035  * xnb_pkt2mbufc on packet that can fit in one cluster
 1036  */
 1037 static void
 1038 xnb_pkt2mbufc_1cluster(char *buffer, size_t buflen)
 1039 {
 1040         const size_t size = MINCLSIZE;
 1041         struct xnb_pkt pkt;
 1042         struct mbuf *pMbuf;
 1043 
 1044         xnb_get1pkt(&pkt, size, 0);
 1045 
 1046         pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
 1047         XNB_ASSERT(M_TRAILINGSPACE(pMbuf) >= size);
 1048         safe_m_freem(&pMbuf);
 1049 }
 1050 
 1051 /**
 1052  * xnb_pkt2mbufc on packet that cannot fit in one regular cluster
 1053  */
 1054 static void
 1055 xnb_pkt2mbufc_largecluster(char *buffer, size_t buflen)
 1056 {
 1057         const size_t size = MCLBYTES + 1;
 1058         struct xnb_pkt pkt;
 1059         struct mbuf *pMbuf;
 1060 
 1061         xnb_get1pkt(&pkt, size, 0);
 1062 
 1063         pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
 1064         XNB_ASSERT(M_TRAILINGSPACE(pMbuf) >= size);
 1065         safe_m_freem(&pMbuf);
 1066 }
 1067 
 1068 /**
 1069  * xnb_pkt2mbufc on packet that cannot fit in one clusters
 1070  */
 1071 static void
 1072 xnb_pkt2mbufc_2cluster(char *buffer, size_t buflen)
 1073 {
 1074         const size_t size = 2 * MCLBYTES + 1;
 1075         size_t space = 0;
 1076         struct xnb_pkt pkt;
 1077         struct mbuf *pMbuf;
 1078         struct mbuf *m;
 1079 
 1080         xnb_get1pkt(&pkt, size, 0);
 1081 
 1082         pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
 1083 
 1084         for (m = pMbuf; m != NULL; m = m->m_next) {
 1085                 space += M_TRAILINGSPACE(m);
 1086         }
 1087         XNB_ASSERT(space >= size);
 1088         safe_m_freem(&pMbuf);
 1089 }
 1090 
 1091 /**
 1092  * xnb_txpkt2gnttab on an empty packet.  Should return empty gnttab
 1093  */
 1094 static void
 1095 xnb_txpkt2gnttab_empty(char *buffer, size_t buflen)
 1096 {
 1097         int n_entries;
 1098         struct xnb_pkt pkt;
 1099         struct mbuf *pMbuf;
 1100         pkt.list_len = 0;
 1101 
 1102         /* must call xnb_ring2pkt just to intialize pkt */
 1103         xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb, xnb_unit_pvt.txb.req_cons);
 1104         pkt.size = 0;
 1105         pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
 1106         n_entries = xnb_txpkt2gnttab(&pkt, pMbuf, xnb_unit_pvt.gnttab,
 1107             &xnb_unit_pvt.txb, DOMID_FIRST_RESERVED);
 1108         XNB_ASSERT(n_entries == 0);
 1109         safe_m_freem(&pMbuf);
 1110 }
 1111 
 1112 /**
 1113  * xnb_txpkt2gnttab on a short packet, that can fit in one mbuf internal buffer
 1114  * and has one request
 1115  */
 1116 static void
 1117 xnb_txpkt2gnttab_short(char *buffer, size_t buflen)
 1118 {
 1119         const size_t size = MINCLSIZE - 1;
 1120         int n_entries;
 1121         struct xnb_pkt pkt;
 1122         struct mbuf *pMbuf;
 1123 
 1124         struct netif_tx_request *req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
 1125             xnb_unit_pvt.txf.req_prod_pvt);
 1126         req->flags = 0;
 1127         req->size = size;
 1128         req->gref = 7;
 1129         req->offset = 17;
 1130         xnb_unit_pvt.txf.req_prod_pvt++;
 1131 
 1132         RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
 1133 
 1134         xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb, xnb_unit_pvt.txb.req_cons);
 1135 
 1136         pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
 1137         n_entries = xnb_txpkt2gnttab(&pkt, pMbuf, xnb_unit_pvt.gnttab,
 1138             &xnb_unit_pvt.txb, DOMID_FIRST_RESERVED);
 1139         XNB_ASSERT(n_entries == 1);
 1140         XNB_ASSERT(xnb_unit_pvt.gnttab[0].len == size);
 1141         /* flags should indicate gref's for source */
 1142         XNB_ASSERT(xnb_unit_pvt.gnttab[0].flags & GNTCOPY_source_gref);
 1143         XNB_ASSERT(xnb_unit_pvt.gnttab[0].source.offset == req->offset);
 1144         XNB_ASSERT(xnb_unit_pvt.gnttab[0].source.domid == DOMID_SELF);
 1145         XNB_ASSERT(xnb_unit_pvt.gnttab[0].dest.offset == virt_to_offset(
 1146               mtod(pMbuf, vm_offset_t)));
 1147         XNB_ASSERT(xnb_unit_pvt.gnttab[0].dest.u.gmfn ==
 1148                 virt_to_mfn(mtod(pMbuf, vm_offset_t)));
 1149         XNB_ASSERT(xnb_unit_pvt.gnttab[0].dest.domid == DOMID_FIRST_RESERVED);
 1150         safe_m_freem(&pMbuf);
 1151 }
 1152 
 1153 /**
 1154  * xnb_txpkt2gnttab on a packet with two requests, that can fit into a single
 1155  * mbuf cluster
 1156  */
 1157 static void
 1158 xnb_txpkt2gnttab_2req(char *buffer, size_t buflen)
 1159 {
 1160         int n_entries;
 1161         struct xnb_pkt pkt;
 1162         struct mbuf *pMbuf;
 1163 
 1164         struct netif_tx_request *req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
 1165             xnb_unit_pvt.txf.req_prod_pvt);
 1166         req->flags = NETTXF_more_data;
 1167         req->size = 1900;
 1168         req->gref = 7;
 1169         req->offset = 0;
 1170         xnb_unit_pvt.txf.req_prod_pvt++;
 1171 
 1172         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
 1173             xnb_unit_pvt.txf.req_prod_pvt);
 1174         req->flags = 0;
 1175         req->size = 500;
 1176         req->gref = 8;
 1177         req->offset = 0;
 1178         xnb_unit_pvt.txf.req_prod_pvt++;
 1179 
 1180         RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
 1181 
 1182         xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb, xnb_unit_pvt.txb.req_cons);
 1183 
 1184         pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
 1185         n_entries = xnb_txpkt2gnttab(&pkt, pMbuf, xnb_unit_pvt.gnttab,
 1186             &xnb_unit_pvt.txb, DOMID_FIRST_RESERVED);
 1187 
 1188         XNB_ASSERT(n_entries == 2);
 1189         XNB_ASSERT(xnb_unit_pvt.gnttab[0].len == 1400);
 1190         XNB_ASSERT(xnb_unit_pvt.gnttab[0].dest.offset == virt_to_offset(
 1191               mtod(pMbuf, vm_offset_t)));
 1192 
 1193         XNB_ASSERT(xnb_unit_pvt.gnttab[1].len == 500);
 1194         XNB_ASSERT(xnb_unit_pvt.gnttab[1].dest.offset == virt_to_offset(
 1195               mtod(pMbuf, vm_offset_t) + 1400));
 1196         safe_m_freem(&pMbuf);
 1197 }
 1198 
 1199 /**
 1200  * xnb_txpkt2gnttab on a single request that spans two mbuf clusters
 1201  */
 1202 static void
 1203 xnb_txpkt2gnttab_2cluster(char *buffer, size_t buflen)
 1204 {
 1205         int n_entries;
 1206         struct xnb_pkt pkt;
 1207         struct mbuf *pMbuf;
 1208         const uint16_t data_this_transaction = (MCLBYTES*2) + 1;
 1209 
 1210         struct netif_tx_request *req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
 1211             xnb_unit_pvt.txf.req_prod_pvt);
 1212         req->flags = 0;
 1213         req->size = data_this_transaction;
 1214         req->gref = 8;
 1215         req->offset = 0;
 1216         xnb_unit_pvt.txf.req_prod_pvt++;
 1217 
 1218         RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
 1219         xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb, xnb_unit_pvt.txb.req_cons);
 1220 
 1221         pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
 1222         XNB_ASSERT(pMbuf != NULL);
 1223         if (pMbuf == NULL)
 1224                 return;
 1225 
 1226         n_entries = xnb_txpkt2gnttab(&pkt, pMbuf, xnb_unit_pvt.gnttab,
 1227             &xnb_unit_pvt.txb, DOMID_FIRST_RESERVED);
 1228 
 1229         if (M_TRAILINGSPACE(pMbuf) == MCLBYTES) {
 1230                 /* there should be three mbufs and three gnttab entries */
 1231                 XNB_ASSERT(n_entries == 3);
 1232                 XNB_ASSERT(xnb_unit_pvt.gnttab[0].len == MCLBYTES);
 1233                 XNB_ASSERT(
 1234                     xnb_unit_pvt.gnttab[0].dest.offset == virt_to_offset(
 1235                       mtod(pMbuf, vm_offset_t)));
 1236                 XNB_ASSERT(xnb_unit_pvt.gnttab[0].source.offset == 0);
 1237 
 1238                 XNB_ASSERT(xnb_unit_pvt.gnttab[1].len == MCLBYTES);
 1239                 XNB_ASSERT(
 1240                     xnb_unit_pvt.gnttab[1].dest.offset == virt_to_offset(
 1241                       mtod(pMbuf->m_next, vm_offset_t)));
 1242                 XNB_ASSERT(xnb_unit_pvt.gnttab[1].source.offset == MCLBYTES);
 1243 
 1244                 XNB_ASSERT(xnb_unit_pvt.gnttab[2].len == 1);
 1245                 XNB_ASSERT(
 1246                     xnb_unit_pvt.gnttab[2].dest.offset == virt_to_offset(
 1247                       mtod(pMbuf->m_next, vm_offset_t)));
 1248                 XNB_ASSERT(xnb_unit_pvt.gnttab[2].source.offset == 2 *
 1249                             MCLBYTES);
 1250         } else if (M_TRAILINGSPACE(pMbuf) == 2 * MCLBYTES) {
 1251                 /* there should be two mbufs and two gnttab entries */
 1252                 XNB_ASSERT(n_entries == 2);
 1253                 XNB_ASSERT(xnb_unit_pvt.gnttab[0].len == 2 * MCLBYTES);
 1254                 XNB_ASSERT(
 1255                     xnb_unit_pvt.gnttab[0].dest.offset == virt_to_offset(
 1256                       mtod(pMbuf, vm_offset_t)));
 1257                 XNB_ASSERT(xnb_unit_pvt.gnttab[0].source.offset == 0);
 1258 
 1259                 XNB_ASSERT(xnb_unit_pvt.gnttab[1].len == 1);
 1260                 XNB_ASSERT(
 1261                     xnb_unit_pvt.gnttab[1].dest.offset == virt_to_offset(
 1262                       mtod(pMbuf->m_next, vm_offset_t)));
 1263                 XNB_ASSERT(
 1264                     xnb_unit_pvt.gnttab[1].source.offset == 2 * MCLBYTES);
 1265 
 1266         } else {
 1267                 /* should never get here */
 1268                 XNB_ASSERT(0);
 1269         }
 1270         m_freem(pMbuf);
 1271 }
 1272 
 1273 /**
 1274  * xnb_update_mbufc on a short packet that only has one gnttab entry
 1275  */
 1276 static void
 1277 xnb_update_mbufc_short(char *buffer, size_t buflen)
 1278 {
 1279         const size_t size = MINCLSIZE - 1;
 1280         int n_entries;
 1281         struct xnb_pkt pkt;
 1282         struct mbuf *pMbuf;
 1283 
 1284         struct netif_tx_request *req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
 1285             xnb_unit_pvt.txf.req_prod_pvt);
 1286         req->flags = 0;
 1287         req->size = size;
 1288         req->gref = 7;
 1289         req->offset = 17;
 1290         xnb_unit_pvt.txf.req_prod_pvt++;
 1291 
 1292         RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
 1293 
 1294         xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb, xnb_unit_pvt.txb.req_cons);
 1295 
 1296         pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
 1297         n_entries = xnb_txpkt2gnttab(&pkt, pMbuf, xnb_unit_pvt.gnttab,
 1298             &xnb_unit_pvt.txb, DOMID_FIRST_RESERVED);
 1299 
 1300         /* Update grant table's status fields as the hypervisor call would */
 1301         xnb_unit_pvt.gnttab[0].status = GNTST_okay;
 1302 
 1303         xnb_update_mbufc(pMbuf, xnb_unit_pvt.gnttab, n_entries);
 1304         XNB_ASSERT(pMbuf->m_len == size);
 1305         XNB_ASSERT(pMbuf->m_pkthdr.len == size);
 1306         safe_m_freem(&pMbuf);
 1307 }
 1308 
 1309 /**
 1310  * xnb_update_mbufc on a packet with two requests, that can fit into a single
 1311  * mbuf cluster
 1312  */
 1313 static void
 1314 xnb_update_mbufc_2req(char *buffer, size_t buflen)
 1315 {
 1316         int n_entries;
 1317         struct xnb_pkt pkt;
 1318         struct mbuf *pMbuf;
 1319 
 1320         struct netif_tx_request *req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
 1321             xnb_unit_pvt.txf.req_prod_pvt);
 1322         req->flags = NETTXF_more_data;
 1323         req->size = 1900;
 1324         req->gref = 7;
 1325         req->offset = 0;
 1326         xnb_unit_pvt.txf.req_prod_pvt++;
 1327 
 1328         req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
 1329             xnb_unit_pvt.txf.req_prod_pvt);
 1330         req->flags = 0;
 1331         req->size = 500;
 1332         req->gref = 8;
 1333         req->offset = 0;
 1334         xnb_unit_pvt.txf.req_prod_pvt++;
 1335 
 1336         RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
 1337 
 1338         xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb, xnb_unit_pvt.txb.req_cons);
 1339 
 1340         pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
 1341         n_entries = xnb_txpkt2gnttab(&pkt, pMbuf, xnb_unit_pvt.gnttab,
 1342             &xnb_unit_pvt.txb, DOMID_FIRST_RESERVED);
 1343 
 1344         /* Update grant table's status fields as the hypervisor call would */
 1345         xnb_unit_pvt.gnttab[0].status = GNTST_okay;
 1346         xnb_unit_pvt.gnttab[1].status = GNTST_okay;
 1347 
 1348         xnb_update_mbufc(pMbuf, xnb_unit_pvt.gnttab, n_entries);
 1349         XNB_ASSERT(n_entries == 2);
 1350         XNB_ASSERT(pMbuf->m_pkthdr.len == 1900);
 1351         XNB_ASSERT(pMbuf->m_len == 1900);
 1352 
 1353         safe_m_freem(&pMbuf);
 1354 }
 1355 
 1356 /**
 1357  * xnb_update_mbufc on a single request that spans two mbuf clusters
 1358  */
 1359 static void
 1360 xnb_update_mbufc_2cluster(char *buffer, size_t buflen)
 1361 {
 1362         int i;
 1363         int n_entries;
 1364         struct xnb_pkt pkt;
 1365         struct mbuf *pMbuf;
 1366         const uint16_t data_this_transaction = (MCLBYTES*2) + 1;
 1367 
 1368         struct netif_tx_request *req = RING_GET_REQUEST(&xnb_unit_pvt.txf,
 1369             xnb_unit_pvt.txf.req_prod_pvt);
 1370         req->flags = 0;
 1371         req->size = data_this_transaction;
 1372         req->gref = 8;
 1373         req->offset = 0;
 1374         xnb_unit_pvt.txf.req_prod_pvt++;
 1375 
 1376         RING_PUSH_REQUESTS(&xnb_unit_pvt.txf);
 1377         xnb_ring2pkt(&pkt, &xnb_unit_pvt.txb, xnb_unit_pvt.txb.req_cons);
 1378 
 1379         pMbuf = xnb_pkt2mbufc(&pkt, xnb_unit_pvt.ifp);
 1380         n_entries = xnb_txpkt2gnttab(&pkt, pMbuf, xnb_unit_pvt.gnttab,
 1381             &xnb_unit_pvt.txb, DOMID_FIRST_RESERVED);
 1382 
 1383         /* Update grant table's status fields */
 1384         for (i = 0; i < n_entries; i++) {
 1385                 xnb_unit_pvt.gnttab[0].status = GNTST_okay;
 1386         }
 1387         xnb_update_mbufc(pMbuf, xnb_unit_pvt.gnttab, n_entries);
 1388 
 1389         if (n_entries == 3) {
 1390                 /* there should be three mbufs and three gnttab entries */
 1391                 XNB_ASSERT(pMbuf->m_pkthdr.len == data_this_transaction);
 1392                 XNB_ASSERT(pMbuf->m_len == MCLBYTES);
 1393                 XNB_ASSERT(pMbuf->m_next->m_len == MCLBYTES);
 1394                 XNB_ASSERT(pMbuf->m_next->m_next->m_len == 1);
 1395         } else if (n_entries == 2) {
 1396                 /* there should be two mbufs and two gnttab entries */
 1397                 XNB_ASSERT(n_entries == 2);
 1398                 XNB_ASSERT(pMbuf->m_pkthdr.len == data_this_transaction);
 1399                 XNB_ASSERT(pMbuf->m_len == 2 * MCLBYTES);
 1400                 XNB_ASSERT(pMbuf->m_next->m_len == 1);
 1401         } else {
 1402                 /* should never get here */
 1403                 XNB_ASSERT(0);
 1404         }
 1405         safe_m_freem(&pMbuf);
 1406 }
 1407 
 1408 /** xnb_mbufc2pkt on an empty mbufc */
 1409 static void
 1410 xnb_mbufc2pkt_empty(char *buffer, size_t buflen) {
 1411         struct xnb_pkt pkt;
 1412         int free_slots = 64;
 1413         struct mbuf *mbuf;
 1414 
 1415         mbuf = m_get(M_WAITOK, MT_DATA);
 1416         /*
 1417          * note: it is illegal to set M_PKTHDR on a mbuf with no data.  Doing so
 1418          * will cause m_freem to segfault
 1419          */
 1420         XNB_ASSERT(mbuf->m_len == 0);
 1421 
 1422         xnb_mbufc2pkt(mbuf, &pkt, 0, free_slots);
 1423         XNB_ASSERT(! xnb_pkt_is_valid(&pkt));
 1424 
 1425         safe_m_freem(&mbuf);
 1426 }
 1427 
 1428 /** xnb_mbufc2pkt on a short mbufc */
 1429 static void
 1430 xnb_mbufc2pkt_short(char *buffer, size_t buflen) {
 1431         struct xnb_pkt pkt;
 1432         size_t size = 128;
 1433         int free_slots = 64;
 1434         RING_IDX start = 9;
 1435         struct mbuf *mbuf;
 1436 
 1437         mbuf = m_getm(NULL, size, M_WAITOK, MT_DATA);
 1438         mbuf->m_flags |= M_PKTHDR;
 1439         mbuf->m_pkthdr.len = size;
 1440         mbuf->m_len = size;
 1441 
 1442         xnb_mbufc2pkt(mbuf, &pkt, start, free_slots);
 1443         XNB_ASSERT(xnb_pkt_is_valid(&pkt));
 1444         XNB_ASSERT(pkt.size == size);
 1445         XNB_ASSERT(pkt.car_size == size);
 1446         XNB_ASSERT(! (pkt.flags &
 1447               (NETRXF_more_data | NETRXF_extra_info)));
 1448         XNB_ASSERT(pkt.list_len == 1);
 1449         XNB_ASSERT(pkt.car == start);
 1450 
 1451         safe_m_freem(&mbuf);
 1452 }
 1453 
 1454 /** xnb_mbufc2pkt on a single mbuf with an mbuf cluster */
 1455 static void
 1456 xnb_mbufc2pkt_1cluster(char *buffer, size_t buflen) {
 1457         struct xnb_pkt pkt;
 1458         size_t size = MCLBYTES;
 1459         int free_slots = 32;
 1460         RING_IDX start = 12;
 1461         struct mbuf *mbuf;
 1462 
 1463         mbuf = m_getm(NULL, size, M_WAITOK, MT_DATA);
 1464         mbuf->m_flags |= M_PKTHDR;
 1465         mbuf->m_pkthdr.len = size;
 1466         mbuf->m_len = size;
 1467 
 1468         xnb_mbufc2pkt(mbuf, &pkt, start, free_slots);
 1469         XNB_ASSERT(xnb_pkt_is_valid(&pkt));
 1470         XNB_ASSERT(pkt.size == size);
 1471         XNB_ASSERT(pkt.car_size == size);
 1472         XNB_ASSERT(! (pkt.flags &
 1473               (NETRXF_more_data | NETRXF_extra_info)));
 1474         XNB_ASSERT(pkt.list_len == 1);
 1475         XNB_ASSERT(pkt.car == start);
 1476 
 1477         safe_m_freem(&mbuf);
 1478 }
 1479 
 1480 /** xnb_mbufc2pkt on a two-mbuf chain with short data regions */
 1481 static void
 1482 xnb_mbufc2pkt_2short(char *buffer, size_t buflen) {
 1483         struct xnb_pkt pkt;
 1484         size_t size1 = MHLEN - 5;
 1485         size_t size2 = MHLEN - 15;
 1486         int free_slots = 32;
 1487         RING_IDX start = 14;
 1488         struct mbuf *mbufc, *mbufc2;
 1489 
 1490         mbufc = m_getm(NULL, size1, M_WAITOK, MT_DATA);
 1491         XNB_ASSERT(mbufc != NULL);
 1492         if (mbufc == NULL)
 1493                 return;
 1494         mbufc->m_flags |= M_PKTHDR;
 1495 
 1496         mbufc2 = m_getm(mbufc, size2, M_WAITOK, MT_DATA);
 1497         XNB_ASSERT(mbufc2 != NULL);
 1498         if (mbufc2 == NULL) {
 1499                 safe_m_freem(&mbufc);
 1500                 return;
 1501         }
 1502         mbufc2->m_pkthdr.len = size1 + size2;
 1503         mbufc2->m_len = size1;
 1504 
 1505         xnb_mbufc2pkt(mbufc2, &pkt, start, free_slots);
 1506         XNB_ASSERT(xnb_pkt_is_valid(&pkt));
 1507         XNB_ASSERT(pkt.size == size1 + size2);
 1508         XNB_ASSERT(pkt.car == start);
 1509         /*
 1510          * The second m_getm may allocate a new mbuf and append
 1511          * it to the chain, or it may simply extend the first mbuf.
 1512          */
 1513         if (mbufc2->m_next != NULL) {
 1514                 XNB_ASSERT(pkt.car_size == size1);
 1515                 XNB_ASSERT(pkt.list_len == 1);
 1516                 XNB_ASSERT(pkt.cdr == start + 1);
 1517         }
 1518 
 1519         safe_m_freem(&mbufc2);
 1520 }
 1521 
 1522 /** xnb_mbufc2pkt on a mbuf chain with >1 mbuf cluster */
 1523 static void
 1524 xnb_mbufc2pkt_long(char *buffer, size_t buflen) {
 1525         struct xnb_pkt pkt;
 1526         size_t size = 14 * MCLBYTES / 3;
 1527         size_t size_remaining;
 1528         int free_slots = 15;
 1529         RING_IDX start = 3;
 1530         struct mbuf *mbufc, *m;
 1531 
 1532         mbufc = m_getm(NULL, size, M_WAITOK, MT_DATA);
 1533         XNB_ASSERT(mbufc != NULL);
 1534         if (mbufc == NULL)
 1535                 return;
 1536         mbufc->m_flags |= M_PKTHDR;
 1537 
 1538         mbufc->m_pkthdr.len = size;
 1539         size_remaining = size;
 1540         for (m = mbufc; m != NULL; m = m->m_next) {
 1541                 m->m_len = MAX(M_TRAILINGSPACE(m), size_remaining);
 1542                 size_remaining -= m->m_len;
 1543         }
 1544 
 1545         xnb_mbufc2pkt(mbufc, &pkt, start, free_slots);
 1546         XNB_ASSERT(xnb_pkt_is_valid(&pkt));
 1547         XNB_ASSERT(pkt.size == size);
 1548         XNB_ASSERT(pkt.car == start);
 1549         XNB_ASSERT(pkt.car_size = mbufc->m_len);
 1550         /*
 1551          * There should be >1 response in the packet, and there is no
 1552          * extra info.
 1553          */
 1554         XNB_ASSERT(! (pkt.flags & NETRXF_extra_info));
 1555         XNB_ASSERT(pkt.cdr == pkt.car + 1);
 1556 
 1557         safe_m_freem(&mbufc);
 1558 }
 1559 
 1560 /** xnb_mbufc2pkt on a mbuf chain with >1 mbuf cluster and extra info */
 1561 static void
 1562 xnb_mbufc2pkt_extra(char *buffer, size_t buflen) {
 1563         struct xnb_pkt pkt;
 1564         size_t size = 14 * MCLBYTES / 3;
 1565         size_t size_remaining;
 1566         int free_slots = 15;
 1567         RING_IDX start = 3;
 1568         struct mbuf *mbufc, *m;
 1569 
 1570         mbufc = m_getm(NULL, size, M_WAITOK, MT_DATA);
 1571         XNB_ASSERT(mbufc != NULL);
 1572         if (mbufc == NULL)
 1573                 return;
 1574 
 1575         mbufc->m_flags |= M_PKTHDR;
 1576         mbufc->m_pkthdr.len = size;
 1577         mbufc->m_pkthdr.csum_flags |= CSUM_TSO;
 1578         mbufc->m_pkthdr.tso_segsz = TCP_MSS - 40;
 1579         size_remaining = size;
 1580         for (m = mbufc; m != NULL; m = m->m_next) {
 1581                 m->m_len = MAX(M_TRAILINGSPACE(m), size_remaining);
 1582                 size_remaining -= m->m_len;
 1583         }
 1584 
 1585         xnb_mbufc2pkt(mbufc, &pkt, start, free_slots);
 1586         XNB_ASSERT(xnb_pkt_is_valid(&pkt));
 1587         XNB_ASSERT(pkt.size == size);
 1588         XNB_ASSERT(pkt.car == start);
 1589         XNB_ASSERT(pkt.car_size = mbufc->m_len);
 1590         /* There should be >1 response in the packet, there is extra info */
 1591         XNB_ASSERT(pkt.flags & NETRXF_extra_info);
 1592         XNB_ASSERT(pkt.flags & NETRXF_data_validated);
 1593         XNB_ASSERT(pkt.cdr == pkt.car + 2);
 1594         XNB_ASSERT(pkt.extra.u.gso.size = mbufc->m_pkthdr.tso_segsz);
 1595         XNB_ASSERT(pkt.extra.type == XEN_NETIF_EXTRA_TYPE_GSO);
 1596         XNB_ASSERT(! (pkt.extra.flags & XEN_NETIF_EXTRA_FLAG_MORE));
 1597 
 1598         safe_m_freem(&mbufc);
 1599 }
 1600 
 1601 /** xnb_mbufc2pkt with insufficient space in the ring */
 1602 static void
 1603 xnb_mbufc2pkt_nospace(char *buffer, size_t buflen) {
 1604         struct xnb_pkt pkt;
 1605         size_t size = 14 * MCLBYTES / 3;
 1606         size_t size_remaining;
 1607         int free_slots = 2;
 1608         RING_IDX start = 3;
 1609         struct mbuf *mbufc, *m;
 1610         int error;
 1611 
 1612         mbufc = m_getm(NULL, size, M_WAITOK, MT_DATA);
 1613         XNB_ASSERT(mbufc != NULL);
 1614         if (mbufc == NULL)
 1615                 return;
 1616         mbufc->m_flags |= M_PKTHDR;
 1617 
 1618         mbufc->m_pkthdr.len = size;
 1619         size_remaining = size;
 1620         for (m = mbufc; m != NULL; m = m->m_next) {
 1621                 m->m_len = MAX(M_TRAILINGSPACE(m), size_remaining);
 1622                 size_remaining -= m->m_len;
 1623         }
 1624 
 1625         error = xnb_mbufc2pkt(mbufc, &pkt, start, free_slots);
 1626         XNB_ASSERT(error == EAGAIN);
 1627         XNB_ASSERT(! xnb_pkt_is_valid(&pkt));
 1628 
 1629         safe_m_freem(&mbufc);
 1630 }
 1631 
 1632 /**
 1633  * xnb_rxpkt2gnttab on an empty packet.  Should return empty gnttab
 1634  */
 1635 static void
 1636 xnb_rxpkt2gnttab_empty(char *buffer, size_t buflen)
 1637 {
 1638         struct xnb_pkt pkt;
 1639         int nr_entries;
 1640         int free_slots = 60;
 1641         struct mbuf *mbuf;
 1642 
 1643         mbuf = m_get(M_WAITOK, MT_DATA);
 1644 
 1645         xnb_mbufc2pkt(mbuf, &pkt, 0, free_slots);
 1646         nr_entries = xnb_rxpkt2gnttab(&pkt, mbuf, xnb_unit_pvt.gnttab,
 1647                         &xnb_unit_pvt.rxb, DOMID_FIRST_RESERVED);
 1648 
 1649         XNB_ASSERT(nr_entries == 0);
 1650 
 1651         safe_m_freem(&mbuf);
 1652 }
 1653 
 1654 /** xnb_rxpkt2gnttab on a short packet without extra data */
 1655 static void
 1656 xnb_rxpkt2gnttab_short(char *buffer, size_t buflen) {
 1657         struct xnb_pkt pkt;
 1658         int nr_entries;
 1659         size_t size = 128;
 1660         int free_slots = 60;
 1661         RING_IDX start = 9;
 1662         struct netif_rx_request *req;
 1663         struct mbuf *mbuf;
 1664 
 1665         mbuf = m_getm(NULL, size, M_WAITOK, MT_DATA);
 1666         mbuf->m_flags |= M_PKTHDR;
 1667         mbuf->m_pkthdr.len = size;
 1668         mbuf->m_len = size;
 1669 
 1670         xnb_mbufc2pkt(mbuf, &pkt, start, free_slots);
 1671         req = RING_GET_REQUEST(&xnb_unit_pvt.rxf,
 1672                                xnb_unit_pvt.txf.req_prod_pvt);
 1673         req->gref = 7;
 1674 
 1675         nr_entries = xnb_rxpkt2gnttab(&pkt, mbuf, xnb_unit_pvt.gnttab,
 1676                                       &xnb_unit_pvt.rxb, DOMID_FIRST_RESERVED);
 1677 
 1678         XNB_ASSERT(nr_entries == 1);
 1679         XNB_ASSERT(xnb_unit_pvt.gnttab[0].len == size);
 1680         /* flags should indicate gref's for dest */
 1681         XNB_ASSERT(xnb_unit_pvt.gnttab[0].flags & GNTCOPY_dest_gref);
 1682         XNB_ASSERT(xnb_unit_pvt.gnttab[0].dest.offset == 0);
 1683         XNB_ASSERT(xnb_unit_pvt.gnttab[0].source.domid == DOMID_SELF);
 1684         XNB_ASSERT(xnb_unit_pvt.gnttab[0].source.offset == virt_to_offset(
 1685                    mtod(mbuf, vm_offset_t)));
 1686         XNB_ASSERT(xnb_unit_pvt.gnttab[0].source.u.gmfn ==
 1687                    virt_to_mfn(mtod(mbuf, vm_offset_t)));
 1688         XNB_ASSERT(xnb_unit_pvt.gnttab[0].dest.domid == DOMID_FIRST_RESERVED);
 1689 
 1690         safe_m_freem(&mbuf);
 1691 }
 1692 
 1693 /**
 1694  * xnb_rxpkt2gnttab on a packet with two different mbufs in a single chai
 1695  */
 1696 static void
 1697 xnb_rxpkt2gnttab_2req(char *buffer, size_t buflen)
 1698 {
 1699         struct xnb_pkt pkt;
 1700         int nr_entries;
 1701         int i, num_mbufs;
 1702         size_t total_granted_size = 0;
 1703         size_t size = MJUMPAGESIZE + 1;
 1704         int free_slots = 60;
 1705         RING_IDX start = 11;
 1706         struct netif_rx_request *req;
 1707         struct mbuf *mbuf, *m;
 1708 
 1709         mbuf = m_getm(NULL, size, M_WAITOK, MT_DATA);
 1710         mbuf->m_flags |= M_PKTHDR;
 1711         mbuf->m_pkthdr.len = size;
 1712         mbuf->m_len = size;
 1713 
 1714         xnb_mbufc2pkt(mbuf, &pkt, start, free_slots);
 1715 
 1716         for (i = 0, m=mbuf; m != NULL; i++, m = m->m_next) {
 1717                 req = RING_GET_REQUEST(&xnb_unit_pvt.rxf,
 1718                     xnb_unit_pvt.txf.req_prod_pvt);
 1719                 req->gref = i;
 1720                 req->id = 5;
 1721         }
 1722         num_mbufs = i;
 1723 
 1724         nr_entries = xnb_rxpkt2gnttab(&pkt, mbuf, xnb_unit_pvt.gnttab,
 1725                         &xnb_unit_pvt.rxb, DOMID_FIRST_RESERVED);
 1726 
 1727         XNB_ASSERT(nr_entries >= num_mbufs);
 1728         for (i = 0; i < nr_entries; i++) {
 1729                 int end_offset = xnb_unit_pvt.gnttab[i].len +
 1730                         xnb_unit_pvt.gnttab[i].dest.offset;
 1731                 XNB_ASSERT(end_offset <= PAGE_SIZE);
 1732                 total_granted_size += xnb_unit_pvt.gnttab[i].len;
 1733         }
 1734         XNB_ASSERT(total_granted_size == size);
 1735 }
 1736 
 1737 /**
 1738  * xnb_rxpkt2rsp on an empty packet.  Shouldn't make any response
 1739  */
 1740 static void
 1741 xnb_rxpkt2rsp_empty(char *buffer, size_t buflen)
 1742 {
 1743         struct xnb_pkt pkt;
 1744         int nr_entries;
 1745         int nr_reqs;
 1746         int free_slots = 60;
 1747         netif_rx_back_ring_t rxb_backup = xnb_unit_pvt.rxb;
 1748         netif_rx_sring_t rxs_backup = *xnb_unit_pvt.rxs;
 1749         struct mbuf *mbuf;
 1750 
 1751         mbuf = m_get(M_WAITOK, MT_DATA);
 1752 
 1753         xnb_mbufc2pkt(mbuf, &pkt, 0, free_slots);
 1754         nr_entries = xnb_rxpkt2gnttab(&pkt, mbuf, xnb_unit_pvt.gnttab,
 1755                         &xnb_unit_pvt.rxb, DOMID_FIRST_RESERVED);
 1756 
 1757         nr_reqs = xnb_rxpkt2rsp(&pkt, xnb_unit_pvt.gnttab, nr_entries,
 1758             &xnb_unit_pvt.rxb);
 1759         XNB_ASSERT(nr_reqs == 0);
 1760         XNB_ASSERT(
 1761             memcmp(&rxb_backup, &xnb_unit_pvt.rxb, sizeof(rxb_backup)) == 0);
 1762         XNB_ASSERT(
 1763             memcmp(&rxs_backup, xnb_unit_pvt.rxs, sizeof(rxs_backup)) == 0);
 1764 
 1765         safe_m_freem(&mbuf);
 1766 }
 1767 
 1768 /**
 1769  * xnb_rxpkt2rsp on a short packet with no extras
 1770  */
 1771 static void
 1772 xnb_rxpkt2rsp_short(char *buffer, size_t buflen)
 1773 {
 1774         struct xnb_pkt pkt;
 1775         int nr_entries, nr_reqs;
 1776         size_t size = 128;
 1777         int free_slots = 60;
 1778         RING_IDX start = 5;
 1779         struct netif_rx_request *req;
 1780         struct netif_rx_response *rsp;
 1781         struct mbuf *mbuf;
 1782 
 1783         mbuf = m_getm(NULL, size, M_WAITOK, MT_DATA);
 1784         mbuf->m_flags |= M_PKTHDR;
 1785         mbuf->m_pkthdr.len = size;
 1786         mbuf->m_len = size;
 1787 
 1788         xnb_mbufc2pkt(mbuf, &pkt, start, free_slots);
 1789         req = RING_GET_REQUEST(&xnb_unit_pvt.rxf, start);
 1790         req->gref = 7;
 1791         xnb_unit_pvt.rxb.req_cons = start;
 1792         xnb_unit_pvt.rxb.rsp_prod_pvt = start;
 1793         xnb_unit_pvt.rxs->req_prod = start + 1;
 1794         xnb_unit_pvt.rxs->rsp_prod = start;
 1795 
 1796         nr_entries = xnb_rxpkt2gnttab(&pkt, mbuf, xnb_unit_pvt.gnttab,
 1797                         &xnb_unit_pvt.rxb, DOMID_FIRST_RESERVED);
 1798 
 1799         nr_reqs = xnb_rxpkt2rsp(&pkt, xnb_unit_pvt.gnttab, nr_entries,
 1800             &xnb_unit_pvt.rxb);
 1801 
 1802         XNB_ASSERT(nr_reqs == 1);
 1803         XNB_ASSERT(xnb_unit_pvt.rxb.rsp_prod_pvt == start + 1);
 1804         rsp = RING_GET_RESPONSE(&xnb_unit_pvt.rxb, start);
 1805         XNB_ASSERT(rsp->id == req->id);
 1806         XNB_ASSERT(rsp->offset == 0);
 1807         XNB_ASSERT((rsp->flags & (NETRXF_more_data | NETRXF_extra_info)) == 0);
 1808         XNB_ASSERT(rsp->status == size);
 1809 
 1810         safe_m_freem(&mbuf);
 1811 }
 1812 
 1813 /**
 1814  * xnb_rxpkt2rsp with extra data
 1815  */
 1816 static void
 1817 xnb_rxpkt2rsp_extra(char *buffer, size_t buflen)
 1818 {
 1819         struct xnb_pkt pkt;
 1820         int nr_entries, nr_reqs;
 1821         size_t size = 14;
 1822         int free_slots = 15;
 1823         RING_IDX start = 3;
 1824         uint16_t id = 49;
 1825         uint16_t gref = 65;
 1826         uint16_t mss = TCP_MSS - 40;
 1827         struct mbuf *mbufc;
 1828         struct netif_rx_request *req;
 1829         struct netif_rx_response *rsp;
 1830         struct netif_extra_info *ext;
 1831 
 1832         mbufc = m_getm(NULL, size, M_WAITOK, MT_DATA);
 1833         XNB_ASSERT(mbufc != NULL);
 1834         if (mbufc == NULL)
 1835                 return;
 1836 
 1837         mbufc->m_flags |= M_PKTHDR;
 1838         mbufc->m_pkthdr.len = size;
 1839         mbufc->m_pkthdr.csum_flags |= CSUM_TSO;
 1840         mbufc->m_pkthdr.tso_segsz = mss;
 1841         mbufc->m_len = size;
 1842 
 1843         xnb_mbufc2pkt(mbufc, &pkt, start, free_slots);
 1844         req = RING_GET_REQUEST(&xnb_unit_pvt.rxf, start);
 1845         req->id = id;
 1846         req->gref = gref;
 1847         req = RING_GET_REQUEST(&xnb_unit_pvt.rxf, start + 1);
 1848         req->id = id + 1;
 1849         req->gref = gref + 1;
 1850         xnb_unit_pvt.rxb.req_cons = start;
 1851         xnb_unit_pvt.rxb.rsp_prod_pvt = start;
 1852         xnb_unit_pvt.rxs->req_prod = start + 2;
 1853         xnb_unit_pvt.rxs->rsp_prod = start;
 1854 
 1855         nr_entries = xnb_rxpkt2gnttab(&pkt, mbufc, xnb_unit_pvt.gnttab,
 1856                         &xnb_unit_pvt.rxb, DOMID_FIRST_RESERVED);
 1857 
 1858         nr_reqs = xnb_rxpkt2rsp(&pkt, xnb_unit_pvt.gnttab, nr_entries,
 1859             &xnb_unit_pvt.rxb);
 1860 
 1861         XNB_ASSERT(nr_reqs == 2);
 1862         XNB_ASSERT(xnb_unit_pvt.rxb.rsp_prod_pvt == start + 2);
 1863         rsp = RING_GET_RESPONSE(&xnb_unit_pvt.rxb, start);
 1864         XNB_ASSERT(rsp->id == id);
 1865         XNB_ASSERT((rsp->flags & NETRXF_more_data) == 0);
 1866         XNB_ASSERT((rsp->flags & NETRXF_extra_info));
 1867         XNB_ASSERT((rsp->flags & NETRXF_data_validated));
 1868         XNB_ASSERT((rsp->flags & NETRXF_csum_blank));
 1869         XNB_ASSERT(rsp->status == size);
 1870 
 1871         ext = (struct netif_extra_info*)
 1872                 RING_GET_RESPONSE(&xnb_unit_pvt.rxb, start + 1);
 1873         XNB_ASSERT(ext->type == XEN_NETIF_EXTRA_TYPE_GSO);
 1874         XNB_ASSERT(! (ext->flags & XEN_NETIF_EXTRA_FLAG_MORE));
 1875         XNB_ASSERT(ext->u.gso.size == mss);
 1876         XNB_ASSERT(ext->u.gso.type == XEN_NETIF_EXTRA_TYPE_GSO);
 1877 
 1878         safe_m_freem(&mbufc);
 1879 }
 1880 
 1881 /**
 1882  * xnb_rxpkt2rsp on a packet with more than a pages's worth of data.  It should
 1883  * generate two response slot
 1884  */
 1885 static void
 1886 xnb_rxpkt2rsp_2slots(char *buffer, size_t buflen)
 1887 {
 1888         struct xnb_pkt pkt;
 1889         int nr_entries, nr_reqs;
 1890         size_t size = PAGE_SIZE + 100;
 1891         int free_slots = 3;
 1892         uint16_t id1 = 17;
 1893         uint16_t id2 = 37;
 1894         uint16_t gref1 = 24;
 1895         uint16_t gref2 = 34;
 1896         RING_IDX start = 15;
 1897         struct netif_rx_request *req;
 1898         struct netif_rx_response *rsp;
 1899         struct mbuf *mbuf;
 1900 
 1901         mbuf = m_getm(NULL, size, M_WAITOK, MT_DATA);
 1902         mbuf->m_flags |= M_PKTHDR;
 1903         mbuf->m_pkthdr.len = size;
 1904         if (mbuf->m_next != NULL) {
 1905                 size_t first_len = MIN(M_TRAILINGSPACE(mbuf), size);
 1906                 mbuf->m_len = first_len;
 1907                 mbuf->m_next->m_len = size - first_len;
 1908 
 1909         } else {
 1910                 mbuf->m_len = size;
 1911         }
 1912 
 1913         xnb_mbufc2pkt(mbuf, &pkt, start, free_slots);
 1914         req = RING_GET_REQUEST(&xnb_unit_pvt.rxf, start);
 1915         req->gref = gref1;
 1916         req->id = id1;
 1917         req = RING_GET_REQUEST(&xnb_unit_pvt.rxf, start + 1);
 1918         req->gref = gref2;
 1919         req->id = id2;
 1920         xnb_unit_pvt.rxb.req_cons = start;
 1921         xnb_unit_pvt.rxb.rsp_prod_pvt = start;
 1922         xnb_unit_pvt.rxs->req_prod = start + 2;
 1923         xnb_unit_pvt.rxs->rsp_prod = start;
 1924 
 1925         nr_entries = xnb_rxpkt2gnttab(&pkt, mbuf, xnb_unit_pvt.gnttab,
 1926                         &xnb_unit_pvt.rxb, DOMID_FIRST_RESERVED);
 1927 
 1928         nr_reqs = xnb_rxpkt2rsp(&pkt, xnb_unit_pvt.gnttab, nr_entries,
 1929             &xnb_unit_pvt.rxb);
 1930 
 1931         XNB_ASSERT(nr_reqs == 2);
 1932         XNB_ASSERT(xnb_unit_pvt.rxb.rsp_prod_pvt == start + 2);
 1933         rsp = RING_GET_RESPONSE(&xnb_unit_pvt.rxb, start);
 1934         XNB_ASSERT(rsp->id == id1);
 1935         XNB_ASSERT(rsp->offset == 0);
 1936         XNB_ASSERT((rsp->flags & NETRXF_extra_info) == 0);
 1937         XNB_ASSERT(rsp->flags & NETRXF_more_data);
 1938         XNB_ASSERT(rsp->status == PAGE_SIZE);
 1939 
 1940         rsp = RING_GET_RESPONSE(&xnb_unit_pvt.rxb, start + 1);
 1941         XNB_ASSERT(rsp->id == id2);
 1942         XNB_ASSERT(rsp->offset == 0);
 1943         XNB_ASSERT((rsp->flags & NETRXF_extra_info) == 0);
 1944         XNB_ASSERT(! (rsp->flags & NETRXF_more_data));
 1945         XNB_ASSERT(rsp->status == size - PAGE_SIZE);
 1946 
 1947         safe_m_freem(&mbuf);
 1948 }
 1949 
 1950 /** xnb_rxpkt2rsp on a grant table with two sub-page entries */
 1951 static void
 1952 xnb_rxpkt2rsp_2short(char *buffer, size_t buflen) {
 1953         struct xnb_pkt pkt;
 1954         int nr_reqs, nr_entries;
 1955         size_t size1 = MHLEN - 5;
 1956         size_t size2 = MHLEN - 15;
 1957         int free_slots = 32;
 1958         RING_IDX start = 14;
 1959         uint16_t id = 47;
 1960         uint16_t gref = 54;
 1961         struct netif_rx_request *req;
 1962         struct netif_rx_response *rsp;
 1963         struct mbuf *mbufc;
 1964 
 1965         mbufc = m_getm(NULL, size1, M_WAITOK, MT_DATA);
 1966         XNB_ASSERT(mbufc != NULL);
 1967         if (mbufc == NULL)
 1968                 return;
 1969         mbufc->m_flags |= M_PKTHDR;
 1970 
 1971         m_getm(mbufc, size2, M_WAITOK, MT_DATA);
 1972         XNB_ASSERT(mbufc->m_next != NULL);
 1973         mbufc->m_pkthdr.len = size1 + size2;
 1974         mbufc->m_len = size1;
 1975         mbufc->m_next->m_len = size2;
 1976 
 1977         xnb_mbufc2pkt(mbufc, &pkt, start, free_slots);
 1978 
 1979         req = RING_GET_REQUEST(&xnb_unit_pvt.rxf, start);
 1980         req->gref = gref;
 1981         req->id = id;
 1982         xnb_unit_pvt.rxb.req_cons = start;
 1983         xnb_unit_pvt.rxb.rsp_prod_pvt = start;
 1984         xnb_unit_pvt.rxs->req_prod = start + 1;
 1985         xnb_unit_pvt.rxs->rsp_prod = start;
 1986 
 1987         nr_entries = xnb_rxpkt2gnttab(&pkt, mbufc, xnb_unit_pvt.gnttab,
 1988                         &xnb_unit_pvt.rxb, DOMID_FIRST_RESERVED);
 1989 
 1990         nr_reqs = xnb_rxpkt2rsp(&pkt, xnb_unit_pvt.gnttab, nr_entries,
 1991             &xnb_unit_pvt.rxb);
 1992 
 1993         XNB_ASSERT(nr_entries == 2);
 1994         XNB_ASSERT(nr_reqs == 1);
 1995         rsp = RING_GET_RESPONSE(&xnb_unit_pvt.rxb, start);
 1996         XNB_ASSERT(rsp->id == id);
 1997         XNB_ASSERT(rsp->status == size1 + size2);
 1998         XNB_ASSERT(rsp->offset == 0);
 1999         XNB_ASSERT(! (rsp->flags & (NETRXF_more_data | NETRXF_extra_info)));
 2000 
 2001         safe_m_freem(&mbufc);
 2002 }
 2003 
 2004 /**
 2005  * xnb_rxpkt2rsp on a long packet with a hypervisor gnttab_copy error
 2006  * Note: this test will result in an error message being printed to the console
 2007  * such as:
 2008  * xnb(xnb_rxpkt2rsp:1720): Got error -1 for hypervisor gnttab_copy status
 2009  */
 2010 static void
 2011 xnb_rxpkt2rsp_copyerror(char *buffer, size_t buflen)
 2012 {
 2013         struct xnb_pkt pkt;
 2014         int nr_entries, nr_reqs;
 2015         int id = 7;
 2016         int gref = 42;
 2017         uint16_t canary = 6859;
 2018         size_t size = 7 * MCLBYTES;
 2019         int free_slots = 9;
 2020         RING_IDX start = 2;
 2021         struct netif_rx_request *req;
 2022         struct netif_rx_response *rsp;
 2023         struct mbuf *mbuf;
 2024 
 2025         mbuf = m_getm(NULL, size, M_WAITOK, MT_DATA);
 2026         mbuf->m_flags |= M_PKTHDR;
 2027         mbuf->m_pkthdr.len = size;
 2028         mbuf->m_len = size;
 2029 
 2030         xnb_mbufc2pkt(mbuf, &pkt, start, free_slots);
 2031         req = RING_GET_REQUEST(&xnb_unit_pvt.rxf, start);
 2032         req->gref = gref;
 2033         req->id = id;
 2034         xnb_unit_pvt.rxb.req_cons = start;
 2035         xnb_unit_pvt.rxb.rsp_prod_pvt = start;
 2036         xnb_unit_pvt.rxs->req_prod = start + 1;
 2037         xnb_unit_pvt.rxs->rsp_prod = start;
 2038         req = RING_GET_REQUEST(&xnb_unit_pvt.rxf, start + 1);
 2039         req->gref = canary;
 2040         req->id = canary;
 2041 
 2042         nr_entries = xnb_rxpkt2gnttab(&pkt, mbuf, xnb_unit_pvt.gnttab,
 2043                         &xnb_unit_pvt.rxb, DOMID_FIRST_RESERVED);
 2044         /* Inject the error*/
 2045         xnb_unit_pvt.gnttab[2].status = GNTST_general_error;
 2046 
 2047         nr_reqs = xnb_rxpkt2rsp(&pkt, xnb_unit_pvt.gnttab, nr_entries,
 2048             &xnb_unit_pvt.rxb);
 2049 
 2050         XNB_ASSERT(nr_reqs == 1);
 2051         XNB_ASSERT(xnb_unit_pvt.rxb.rsp_prod_pvt == start + 1);
 2052         rsp = RING_GET_RESPONSE(&xnb_unit_pvt.rxb, start);
 2053         XNB_ASSERT(rsp->id == id);
 2054         XNB_ASSERT(rsp->status == NETIF_RSP_ERROR);
 2055         req = RING_GET_REQUEST(&xnb_unit_pvt.rxf, start + 1);
 2056         XNB_ASSERT(req->gref == canary);
 2057         XNB_ASSERT(req->id == canary);
 2058 
 2059         safe_m_freem(&mbuf);
 2060 }
 2061 
 2062 #if defined(INET) || defined(INET6)
 2063 /**
 2064  * xnb_add_mbuf_cksum on an ARP request packet
 2065  */
 2066 static void
 2067 xnb_add_mbuf_cksum_arp(char *buffer, size_t buflen)
 2068 {
 2069         const size_t pkt_len = sizeof(struct ether_header) +
 2070                 sizeof(struct ether_arp);
 2071         struct mbuf *mbufc;
 2072         struct ether_header *eh;
 2073         struct ether_arp *ep;
 2074         unsigned char pkt_orig[pkt_len];
 2075 
 2076         mbufc = m_getm(NULL, pkt_len, M_WAITOK, MT_DATA);
 2077         /* Fill in an example arp request */
 2078         eh = mtod(mbufc, struct ether_header*);
 2079         eh->ether_dhost[0] = 0xff;
 2080         eh->ether_dhost[1] = 0xff;
 2081         eh->ether_dhost[2] = 0xff;
 2082         eh->ether_dhost[3] = 0xff;
 2083         eh->ether_dhost[4] = 0xff;
 2084         eh->ether_dhost[5] = 0xff;
 2085         eh->ether_shost[0] = 0x00;
 2086         eh->ether_shost[1] = 0x15;
 2087         eh->ether_shost[2] = 0x17;
 2088         eh->ether_shost[3] = 0xe9;
 2089         eh->ether_shost[4] = 0x30;
 2090         eh->ether_shost[5] = 0x68;
 2091         eh->ether_type = htons(ETHERTYPE_ARP);
 2092         ep = (struct ether_arp*)(eh + 1);
 2093         ep->ea_hdr.ar_hrd = htons(ARPHRD_ETHER);
 2094         ep->ea_hdr.ar_pro = htons(ETHERTYPE_IP);
 2095         ep->ea_hdr.ar_hln = 6;
 2096         ep->ea_hdr.ar_pln = 4;
 2097         ep->ea_hdr.ar_op = htons(ARPOP_REQUEST);
 2098         ep->arp_sha[0] = 0x00;
 2099         ep->arp_sha[1] = 0x15;
 2100         ep->arp_sha[2] = 0x17;
 2101         ep->arp_sha[3] = 0xe9;
 2102         ep->arp_sha[4] = 0x30;
 2103         ep->arp_sha[5] = 0x68;
 2104         ep->arp_spa[0] = 0xc0;
 2105         ep->arp_spa[1] = 0xa8;
 2106         ep->arp_spa[2] = 0x0a;
 2107         ep->arp_spa[3] = 0x04;
 2108         bzero(&(ep->arp_tha), ETHER_ADDR_LEN);
 2109         ep->arp_tpa[0] = 0xc0;
 2110         ep->arp_tpa[1] = 0xa8;
 2111         ep->arp_tpa[2] = 0x0a;
 2112         ep->arp_tpa[3] = 0x06;
 2113 
 2114         /* fill in the length field */
 2115         mbufc->m_len = pkt_len;
 2116         mbufc->m_pkthdr.len = pkt_len;
 2117         /* indicate that the netfront uses hw-assisted checksums */
 2118         mbufc->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID   |
 2119                                 CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
 2120 
 2121         /* Make a backup copy of the packet */
 2122         bcopy(mtod(mbufc, const void*), pkt_orig, pkt_len);
 2123 
 2124         /* Function under test */
 2125         xnb_add_mbuf_cksum(mbufc);
 2126 
 2127         /* Verify that the packet's data did not change */
 2128         XNB_ASSERT(bcmp(mtod(mbufc, const void*), pkt_orig, pkt_len) == 0);
 2129         m_freem(mbufc);
 2130 }
 2131 
 2132 /**
 2133  * Helper function that populates the ethernet header and IP header used by
 2134  * some of the xnb_add_mbuf_cksum unit tests.  m must already be allocated
 2135  * and must be large enough
 2136  */
 2137 static void
 2138 xnb_fill_eh_and_ip(struct mbuf *m, uint16_t ip_len, uint16_t ip_id,
 2139                    uint16_t ip_p, uint16_t ip_off, uint16_t ip_sum)
 2140 {
 2141         struct ether_header *eh;
 2142         struct ip *iph;
 2143 
 2144         eh = mtod(m, struct ether_header*);
 2145         eh->ether_dhost[0] = 0x00;
 2146         eh->ether_dhost[1] = 0x16;
 2147         eh->ether_dhost[2] = 0x3e;
 2148         eh->ether_dhost[3] = 0x23;
 2149         eh->ether_dhost[4] = 0x50;
 2150         eh->ether_dhost[5] = 0x0b;
 2151         eh->ether_shost[0] = 0x00;
 2152         eh->ether_shost[1] = 0x16;
 2153         eh->ether_shost[2] = 0x30;
 2154         eh->ether_shost[3] = 0x00;
 2155         eh->ether_shost[4] = 0x00;
 2156         eh->ether_shost[5] = 0x00;
 2157         eh->ether_type = htons(ETHERTYPE_IP);
 2158         iph = (struct ip*)(eh + 1);
 2159         iph->ip_hl = 0x5;       /* 5 dwords == 20 bytes */
 2160         iph->ip_v = 4;          /* IP v4 */
 2161         iph->ip_tos = 0;
 2162         iph->ip_len = htons(ip_len);
 2163         iph->ip_id = htons(ip_id);
 2164         iph->ip_off = htons(ip_off);
 2165         iph->ip_ttl = 64;
 2166         iph->ip_p = ip_p;
 2167         iph->ip_sum = htons(ip_sum);
 2168         iph->ip_src.s_addr = htonl(0xc0a80a04);
 2169         iph->ip_dst.s_addr = htonl(0xc0a80a05);
 2170 }
 2171 
 2172 /**
 2173  * xnb_add_mbuf_cksum on an ICMP packet, based on a tcpdump of an actual
 2174  * ICMP packet
 2175  */
 2176 static void
 2177 xnb_add_mbuf_cksum_icmp(char *buffer, size_t buflen)
 2178 {
 2179         const size_t icmp_len = 64;     /* set by ping(1) */
 2180         const size_t pkt_len = sizeof(struct ether_header) +
 2181                 sizeof(struct ip) + icmp_len;
 2182         struct mbuf *mbufc;
 2183         struct ether_header *eh;
 2184         struct ip *iph;
 2185         struct icmp *icmph;
 2186         unsigned char pkt_orig[icmp_len];
 2187         uint32_t *tv_field;
 2188         uint8_t *data_payload;
 2189         int i;
 2190         const uint16_t ICMP_CSUM = 0xaed7;
 2191         const uint16_t IP_CSUM = 0xe533;
 2192 
 2193         mbufc = m_getm(NULL, pkt_len, M_WAITOK, MT_DATA);
 2194         /* Fill in an example ICMP ping request */
 2195         eh = mtod(mbufc, struct ether_header*);
 2196         xnb_fill_eh_and_ip(mbufc, 84, 28, IPPROTO_ICMP, 0, 0);
 2197         iph = (struct ip*)(eh + 1);
 2198         icmph = (struct icmp*)(iph + 1);
 2199         icmph->icmp_type = ICMP_ECHO;
 2200         icmph->icmp_code = 0;
 2201         icmph->icmp_cksum = htons(ICMP_CSUM);
 2202         icmph->icmp_id = htons(31492);
 2203         icmph->icmp_seq = htons(0);
 2204         /*
 2205          * ping(1) uses bcopy to insert a native-endian timeval after icmp_seq.
 2206          * For this test, we will set the bytes individually for portability.
 2207          */
 2208         tv_field = (uint32_t*)(&(icmph->icmp_hun));
 2209         tv_field[0] = 0x4f02cfac;
 2210         tv_field[1] = 0x0007c46a;
 2211         /*
 2212          * Remainder of packet is an incrmenting 8 bit integer, starting with 8
 2213          */
 2214         data_payload = (uint8_t*)(&tv_field[2]);
 2215         for (i = 8; i < 37; i++) {
 2216                 *data_payload++ = i;
 2217         }
 2218 
 2219         /* fill in the length field */
 2220         mbufc->m_len = pkt_len;
 2221         mbufc->m_pkthdr.len = pkt_len;
 2222         /* indicate that the netfront uses hw-assisted checksums */
 2223         mbufc->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID   |
 2224                                 CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
 2225 
 2226         bcopy(mtod(mbufc, const void*), pkt_orig, icmp_len);
 2227         /* Function under test */
 2228         xnb_add_mbuf_cksum(mbufc);
 2229 
 2230         /* Check the IP checksum */
 2231         XNB_ASSERT(iph->ip_sum == htons(IP_CSUM));
 2232 
 2233         /* Check that the ICMP packet did not change */
 2234         XNB_ASSERT(bcmp(icmph, pkt_orig, icmp_len));
 2235         m_freem(mbufc);
 2236 }
 2237 
 2238 /**
 2239  * xnb_add_mbuf_cksum on a UDP packet, based on a tcpdump of an actual
 2240  * UDP packet
 2241  */
 2242 static void
 2243 xnb_add_mbuf_cksum_udp(char *buffer, size_t buflen)
 2244 {
 2245         const size_t udp_len = 16;
 2246         const size_t pkt_len = sizeof(struct ether_header) +
 2247                 sizeof(struct ip) + udp_len;
 2248         struct mbuf *mbufc;
 2249         struct ether_header *eh;
 2250         struct ip *iph;
 2251         struct udphdr *udp;
 2252         uint8_t *data_payload;
 2253         const uint16_t IP_CSUM = 0xe56b;
 2254         const uint16_t UDP_CSUM = 0xdde2;
 2255 
 2256         mbufc = m_getm(NULL, pkt_len, M_WAITOK, MT_DATA);
 2257         /* Fill in an example UDP packet made by 'uname | nc -u <host> 2222 */
 2258         eh = mtod(mbufc, struct ether_header*);
 2259         xnb_fill_eh_and_ip(mbufc, 36, 4, IPPROTO_UDP, 0, 0xbaad);
 2260         iph = (struct ip*)(eh + 1);
 2261         udp = (struct udphdr*)(iph + 1);
 2262         udp->uh_sport = htons(0x51ae);
 2263         udp->uh_dport = htons(0x08ae);
 2264         udp->uh_ulen = htons(udp_len);
 2265         udp->uh_sum = htons(0xbaad);  /* xnb_add_mbuf_cksum will fill this in */
 2266         data_payload = (uint8_t*)(udp + 1);
 2267         data_payload[0] = 'F';
 2268         data_payload[1] = 'r';
 2269         data_payload[2] = 'e';
 2270         data_payload[3] = 'e';
 2271         data_payload[4] = 'B';
 2272         data_payload[5] = 'S';
 2273         data_payload[6] = 'D';
 2274         data_payload[7] = '\n';
 2275 
 2276         /* fill in the length field */
 2277         mbufc->m_len = pkt_len;
 2278         mbufc->m_pkthdr.len = pkt_len;
 2279         /* indicate that the netfront uses hw-assisted checksums */
 2280         mbufc->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID   |
 2281                                 CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
 2282 
 2283         /* Function under test */
 2284         xnb_add_mbuf_cksum(mbufc);
 2285 
 2286         /* Check the checksums */
 2287         XNB_ASSERT(iph->ip_sum == htons(IP_CSUM));
 2288         XNB_ASSERT(udp->uh_sum == htons(UDP_CSUM));
 2289 
 2290         m_freem(mbufc);
 2291 }
 2292 
 2293 /**
 2294  * Helper function that populates a TCP packet used by all of the
 2295  * xnb_add_mbuf_cksum tcp unit tests.  m must already be allocated and must be
 2296  * large enough
 2297  */
 2298 static void
 2299 xnb_fill_tcp(struct mbuf *m)
 2300 {
 2301         struct ether_header *eh;
 2302         struct ip *iph;
 2303         struct tcphdr *tcp;
 2304         uint32_t *options;
 2305         uint8_t *data_payload;
 2306 
 2307         /* Fill in an example TCP packet made by 'uname | nc <host> 2222' */
 2308         eh = mtod(m, struct ether_header*);
 2309         xnb_fill_eh_and_ip(m, 60, 8, IPPROTO_TCP, IP_DF, 0);
 2310         iph = (struct ip*)(eh + 1);
 2311         tcp = (struct tcphdr*)(iph + 1);
 2312         tcp->th_sport = htons(0x9cd9);
 2313         tcp->th_dport = htons(2222);
 2314         tcp->th_seq = htonl(0x00f72b10);
 2315         tcp->th_ack = htonl(0x7f37ba6c);
 2316         tcp->th_x2 = 0;
 2317         tcp->th_off = 8;
 2318         tcp->th_flags = 0x18;
 2319         tcp->th_win = htons(0x410);
 2320         /* th_sum is incorrect; will be inserted by function under test */
 2321         tcp->th_sum = htons(0xbaad);
 2322         tcp->th_urp = htons(0);
 2323         /*
 2324          * The following 12 bytes of options encode:
 2325          * [nop, nop, TS val 33247 ecr 3457687679]
 2326          */
 2327         options = (uint32_t*)(tcp + 1);
 2328         options[0] = htonl(0x0101080a);
 2329         options[1] = htonl(0x000081df);
 2330         options[2] = htonl(0xce18207f);
 2331         data_payload = (uint8_t*)(&options[3]);
 2332         data_payload[0] = 'F';
 2333         data_payload[1] = 'r';
 2334         data_payload[2] = 'e';
 2335         data_payload[3] = 'e';
 2336         data_payload[4] = 'B';
 2337         data_payload[5] = 'S';
 2338         data_payload[6] = 'D';
 2339         data_payload[7] = '\n';
 2340 }
 2341 
 2342 /**
 2343  * xnb_add_mbuf_cksum on a TCP packet, based on a tcpdump of an actual TCP
 2344  * packet
 2345  */
 2346 static void
 2347 xnb_add_mbuf_cksum_tcp(char *buffer, size_t buflen)
 2348 {
 2349         const size_t payload_len = 8;
 2350         const size_t tcp_options_len = 12;
 2351         const size_t pkt_len = sizeof(struct ether_header) + sizeof(struct ip) +
 2352             sizeof(struct tcphdr) + tcp_options_len + payload_len;
 2353         struct mbuf *mbufc;
 2354         struct ether_header *eh;
 2355         struct ip *iph;
 2356         struct tcphdr *tcp;
 2357         const uint16_t IP_CSUM = 0xa55a;
 2358         const uint16_t TCP_CSUM = 0x2f64;
 2359 
 2360         mbufc = m_getm(NULL, pkt_len, M_WAITOK, MT_DATA);
 2361         /* Fill in an example TCP packet made by 'uname | nc <host> 2222' */
 2362         xnb_fill_tcp(mbufc);
 2363         eh = mtod(mbufc, struct ether_header*);
 2364         iph = (struct ip*)(eh + 1);
 2365         tcp = (struct tcphdr*)(iph + 1);
 2366 
 2367         /* fill in the length field */
 2368         mbufc->m_len = pkt_len;
 2369         mbufc->m_pkthdr.len = pkt_len;
 2370         /* indicate that the netfront uses hw-assisted checksums */
 2371         mbufc->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID   |
 2372                                 CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
 2373 
 2374         /* Function under test */
 2375         xnb_add_mbuf_cksum(mbufc);
 2376 
 2377         /* Check the checksums */
 2378         XNB_ASSERT(iph->ip_sum == htons(IP_CSUM));
 2379         XNB_ASSERT(tcp->th_sum == htons(TCP_CSUM));
 2380 
 2381         m_freem(mbufc);
 2382 }
 2383 
 2384 /**
 2385  * xnb_add_mbuf_cksum on a TCP packet that does not use HW assisted checksums
 2386  */
 2387 static void
 2388 xnb_add_mbuf_cksum_tcp_swcksum(char *buffer, size_t buflen)
 2389 {
 2390         const size_t payload_len = 8;
 2391         const size_t tcp_options_len = 12;
 2392         const size_t pkt_len = sizeof(struct ether_header) + sizeof(struct ip) +
 2393             sizeof(struct tcphdr) + tcp_options_len + payload_len;
 2394         struct mbuf *mbufc;
 2395         struct ether_header *eh;
 2396         struct ip *iph;
 2397         struct tcphdr *tcp;
 2398         /* Use deliberately bad checksums, and verify that they don't get */
 2399         /* corrected by xnb_add_mbuf_cksum */
 2400         const uint16_t IP_CSUM = 0xdead;
 2401         const uint16_t TCP_CSUM = 0xbeef;
 2402 
 2403         mbufc = m_getm(NULL, pkt_len, M_WAITOK, MT_DATA);
 2404         /* Fill in an example TCP packet made by 'uname | nc <host> 2222' */
 2405         xnb_fill_tcp(mbufc);
 2406         eh = mtod(mbufc, struct ether_header*);
 2407         iph = (struct ip*)(eh + 1);
 2408         iph->ip_sum = htons(IP_CSUM);
 2409         tcp = (struct tcphdr*)(iph + 1);
 2410         tcp->th_sum = htons(TCP_CSUM);
 2411 
 2412         /* fill in the length field */
 2413         mbufc->m_len = pkt_len;
 2414         mbufc->m_pkthdr.len = pkt_len;
 2415         /* indicate that the netfront does not use hw-assisted checksums */
 2416         mbufc->m_pkthdr.csum_flags = 0;
 2417 
 2418         /* Function under test */
 2419         xnb_add_mbuf_cksum(mbufc);
 2420 
 2421         /* Check that the checksums didn't change */
 2422         XNB_ASSERT(iph->ip_sum == htons(IP_CSUM));
 2423         XNB_ASSERT(tcp->th_sum == htons(TCP_CSUM));
 2424 
 2425         m_freem(mbufc);
 2426 }
 2427 #endif /* INET || INET6 */
 2428 
 2429 /**
 2430  * sscanf on unsigned chars
 2431  */
 2432 static void
 2433 xnb_sscanf_hhu(char *buffer, size_t buflen)
 2434 {
 2435         const char mystr[] = "137";
 2436         uint8_t dest[12];
 2437         int i;
 2438 
 2439         for (i = 0; i < 12; i++)
 2440                 dest[i] = 'X';
 2441 
 2442         XNB_ASSERT(sscanf(mystr, "%hhu", &dest[4]) == 1);
 2443         for (i = 0; i < 12; i++)
 2444                 XNB_ASSERT(dest[i] == (i == 4 ? 137 : 'X'));
 2445 }
 2446 
 2447 /**
 2448  * sscanf on signed chars
 2449  */
 2450 static void
 2451 xnb_sscanf_hhd(char *buffer, size_t buflen)
 2452 {
 2453         const char mystr[] = "-27";
 2454         int8_t dest[12];
 2455         int i;
 2456 
 2457         for (i = 0; i < 12; i++)
 2458                 dest[i] = 'X';
 2459 
 2460         XNB_ASSERT(sscanf(mystr, "%hhd", &dest[4]) == 1);
 2461         for (i = 0; i < 12; i++)
 2462                 XNB_ASSERT(dest[i] == (i == 4 ? -27 : 'X'));
 2463 }
 2464 
 2465 /**
 2466  * sscanf on signed long longs
 2467  */
 2468 static void
 2469 xnb_sscanf_lld(char *buffer, size_t buflen)
 2470 {
 2471         const char mystr[] = "-123456789012345";        /* about -2**47 */
 2472         long long dest[3];
 2473         int i;
 2474 
 2475         for (i = 0; i < 3; i++)
 2476                 dest[i] = (long long)0xdeadbeefdeadbeef;
 2477 
 2478         XNB_ASSERT(sscanf(mystr, "%lld", &dest[1]) == 1);
 2479         for (i = 0; i < 3; i++)
 2480                 XNB_ASSERT(dest[i] == (i != 1 ? (long long)0xdeadbeefdeadbeef :
 2481                     -123456789012345));
 2482 }
 2483 
 2484 /**
 2485  * sscanf on unsigned long longs
 2486  */
 2487 static void
 2488 xnb_sscanf_llu(char *buffer, size_t buflen)
 2489 {
 2490         const char mystr[] = "12802747070103273189";
 2491         unsigned long long dest[3];
 2492         int i;
 2493 
 2494         for (i = 0; i < 3; i++)
 2495                 dest[i] = (long long)0xdeadbeefdeadbeef;
 2496 
 2497         XNB_ASSERT(sscanf(mystr, "%llu", &dest[1]) == 1);
 2498         for (i = 0; i < 3; i++)
 2499                 XNB_ASSERT(dest[i] == (i != 1 ? (long long)0xdeadbeefdeadbeef :
 2500                     12802747070103273189ull));
 2501 }
 2502 
 2503 /**
 2504  * sscanf on unsigned short short n's
 2505  */
 2506 static void
 2507 xnb_sscanf_hhn(char *buffer, size_t buflen)
 2508 {
 2509         const char mystr[] =
 2510             "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
 2511             "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"
 2512             "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f";
 2513         unsigned char dest[12];
 2514         int i;
 2515 
 2516         for (i = 0; i < 12; i++)
 2517                 dest[i] = (unsigned char)'X';
 2518 
 2519         XNB_ASSERT(sscanf(mystr,
 2520             "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
 2521             "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"
 2522             "404142434445464748494a4b4c4d4e4f%hhn", &dest[4]) == 0);
 2523         for (i = 0; i < 12; i++)
 2524                 XNB_ASSERT(dest[i] == (i == 4 ? 160 : 'X'));
 2525 }

Cache object: 1258fc616e52177d5ce06687971d9c46


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.