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 } 2537