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