1 /* $NetBSD: t_cop.c,v 1.4 2014/07/13 21:35:33 alnsn Exp $ */ 2 3 /*- 4 * Copyright (c) 2013-2014 Alexander Nasonov. 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 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __RCSID("$NetBSD: t_cop.c,v 1.4 2014/07/13 21:35:33 alnsn Exp $"); 34 35 #include <atf-c.h> 36 #include <stdint.h> 37 #include <string.h> 38 39 #define __BPF_PRIVATE 40 #include <net/bpf.h> 41 #include <net/bpfjit.h> 42 43 static uint32_t retA(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 44 static uint32_t retBL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 45 static uint32_t retWL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 46 static uint32_t retNF(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 47 static uint32_t setARG(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 48 49 static const bpf_copfunc_t copfuncs[] = { 50 &retA, 51 &retBL, 52 &retWL, 53 &retNF, 54 &setARG 55 }; 56 57 static const bpf_ctx_t ctx = { 58 .copfuncs = copfuncs, 59 .nfuncs = sizeof(copfuncs) / sizeof(copfuncs[0]), 60 .extwords = 0 61 }; 62 63 static uint32_t 64 retA(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A) 65 { 66 67 return A; 68 } 69 70 static uint32_t 71 retBL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A) 72 { 73 74 return args->buflen; 75 } 76 77 static uint32_t 78 retWL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A) 79 { 80 81 return args->wirelen; 82 } 83 84 static uint32_t 85 retNF(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A) 86 { 87 88 return bc->nfuncs; 89 } 90 91 /* 92 * COP function with a side effect. 93 */ 94 static uint32_t 95 setARG(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A) 96 { 97 bool *arg = (bool *)args->arg; 98 bool old = *arg; 99 100 *arg = true; 101 return old; 102 } 103 104 ATF_TC(libbpfjit_cop_no_ctx); 105 ATF_TC_HEAD(libbpfjit_cop_no_ctx, tc) 106 { 107 atf_tc_set_md_var(tc, "descr", "Test that bpf program with BPF_COP " 108 "instruction isn't valid without a context"); 109 } 110 111 ATF_TC_BODY(libbpfjit_cop_no_ctx, tc) 112 { 113 static struct bpf_insn insns[] = { 114 BPF_STMT(BPF_MISC+BPF_COP, 0), 115 BPF_STMT(BPF_RET+BPF_K, 7) 116 }; 117 118 bpfjit_func_t code; 119 120 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 121 122 ATF_CHECK(!bpf_validate(insns, insn_count)); 123 124 code = bpfjit_generate_code(NULL, insns, insn_count); 125 ATF_CHECK(code == NULL); 126 } 127 128 ATF_TC(libbpfjit_cop_ret_A); 129 ATF_TC_HEAD(libbpfjit_cop_ret_A, tc) 130 { 131 atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 132 "that returns a content of the A register"); 133 } 134 135 ATF_TC_BODY(libbpfjit_cop_ret_A, tc) 136 { 137 static struct bpf_insn insns[] = { 138 BPF_STMT(BPF_LD+BPF_IMM, 13), 139 BPF_STMT(BPF_MISC+BPF_COP, 0), // retA 140 BPF_STMT(BPF_RET+BPF_A, 0) 141 }; 142 143 bpfjit_func_t code; 144 uint8_t pkt[1] = { 0 }; 145 bpf_args_t args = { 146 .pkt = pkt, 147 .buflen = sizeof(pkt), 148 .wirelen = sizeof(pkt), 149 }; 150 151 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 152 153 code = bpfjit_generate_code(&ctx, insns, insn_count); 154 ATF_REQUIRE(code != NULL); 155 156 ATF_CHECK(code(&ctx, &args) == 13); 157 158 bpfjit_free_code(code); 159 } 160 161 ATF_TC(libbpfjit_cop_ret_buflen); 162 ATF_TC_HEAD(libbpfjit_cop_ret_buflen, tc) 163 { 164 atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 165 "that returns the buflen argument"); 166 } 167 168 ATF_TC_BODY(libbpfjit_cop_ret_buflen, tc) 169 { 170 static struct bpf_insn insns[] = { 171 BPF_STMT(BPF_LD+BPF_IMM, 13), 172 BPF_STMT(BPF_MISC+BPF_COP, 1), // retBL 173 BPF_STMT(BPF_RET+BPF_A, 0) 174 }; 175 176 bpfjit_func_t code; 177 uint8_t pkt[1] = { 0 }; 178 bpf_args_t args = { 179 .pkt = pkt, 180 .buflen = sizeof(pkt), 181 .wirelen = sizeof(pkt) 182 }; 183 184 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 185 186 code = bpfjit_generate_code(&ctx, insns, insn_count); 187 ATF_REQUIRE(code != NULL); 188 189 ATF_CHECK(code(&ctx, &args) == sizeof(pkt)); 190 191 bpfjit_free_code(code); 192 } 193 194 ATF_TC(libbpfjit_cop_ret_wirelen); 195 ATF_TC_HEAD(libbpfjit_cop_ret_wirelen, tc) 196 { 197 atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 198 "that returns the wirelen argument"); 199 } 200 201 ATF_TC_BODY(libbpfjit_cop_ret_wirelen, tc) 202 { 203 static struct bpf_insn insns[] = { 204 BPF_STMT(BPF_LD+BPF_IMM, 13), 205 BPF_STMT(BPF_MISC+BPF_COP, 2), // retWL 206 BPF_STMT(BPF_RET+BPF_A, 0) 207 }; 208 209 bpfjit_func_t code; 210 uint8_t pkt[1] = { 0 }; 211 bpf_args_t args = { 212 .pkt = pkt, 213 .buflen = sizeof(pkt), 214 .wirelen = sizeof(pkt) 215 }; 216 217 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 218 219 code = bpfjit_generate_code(&ctx, insns, insn_count); 220 ATF_REQUIRE(code != NULL); 221 222 ATF_CHECK(code(&ctx, &args) == sizeof(pkt)); 223 224 bpfjit_free_code(code); 225 } 226 227 ATF_TC(libbpfjit_cop_ret_nfuncs); 228 ATF_TC_HEAD(libbpfjit_cop_ret_nfuncs, tc) 229 { 230 atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 231 "that returns nfuncs member of the context argument"); 232 } 233 234 ATF_TC_BODY(libbpfjit_cop_ret_nfuncs, tc) 235 { 236 static struct bpf_insn insns[] = { 237 BPF_STMT(BPF_LD+BPF_IMM, 13), 238 BPF_STMT(BPF_MISC+BPF_COP, 3), // retNF 239 BPF_STMT(BPF_RET+BPF_A, 0) 240 }; 241 242 bpfjit_func_t code; 243 uint8_t pkt[1] = { 0 }; 244 bpf_args_t args = { 245 .pkt = pkt, 246 .buflen = sizeof(pkt), 247 .wirelen = sizeof(pkt) 248 }; 249 250 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 251 252 code = bpfjit_generate_code(&ctx, insns, insn_count); 253 ATF_REQUIRE(code != NULL); 254 255 ATF_CHECK(code(&ctx, &args) == ctx.nfuncs); 256 257 bpfjit_free_code(code); 258 } 259 260 ATF_TC(libbpfjit_cop_side_effect); 261 ATF_TC_HEAD(libbpfjit_cop_side_effect, tc) 262 { 263 atf_tc_set_md_var(tc, "descr", 264 "Test that ABC optimization doesn't skip BPF_COP call"); 265 } 266 267 ATF_TC_BODY(libbpfjit_cop_side_effect, tc) 268 { 269 static struct bpf_insn insns[] = { 270 BPF_STMT(BPF_LD+BPF_IMM, 13), 271 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0), 272 BPF_STMT(BPF_MISC+BPF_COP, 4), // setARG 273 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 99999), 274 BPF_STMT(BPF_RET+BPF_A, 0) 275 }; 276 277 bpfjit_func_t code; 278 bool arg = false; 279 uint8_t pkt[1] = { 0 }; 280 bpf_args_t args = { 281 .pkt = pkt, 282 .buflen = sizeof(pkt), 283 .wirelen = sizeof(pkt), 284 .mem = NULL, 285 .arg = &arg 286 }; 287 288 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 289 290 code = bpfjit_generate_code(&ctx, insns, insn_count); 291 ATF_REQUIRE(code != NULL); 292 293 ATF_CHECK(code(&ctx, &args) == 0); 294 ATF_CHECK(arg == true); 295 296 bpfjit_free_code(code); 297 } 298 299 ATF_TC(libbpfjit_cop_copx); 300 ATF_TC_HEAD(libbpfjit_cop_copx, tc) 301 { 302 atf_tc_set_md_var(tc, "descr", 303 "Test BPF_COP call followed by BPF_COPX call"); 304 } 305 306 ATF_TC_BODY(libbpfjit_cop_copx, tc) 307 { 308 static struct bpf_insn insns[] = { 309 BPF_STMT(BPF_LD+BPF_IMM, 1), /* A <- 1 */ 310 BPF_STMT(BPF_MISC+BPF_COP, 0), /* retA */ 311 BPF_STMT(BPF_MISC+BPF_TAX, 0), /* X <- A */ 312 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0), /* A = P[0] */ 313 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1), /* A = A + X */ 314 BPF_STMT(BPF_MISC+BPF_TAX, 0), /* X <- A */ 315 BPF_STMT(BPF_MISC+BPF_COPX, 0), /* retNF */ 316 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1), /* A = A + X */ 317 BPF_STMT(BPF_RET+BPF_A, 0) 318 }; 319 320 bpfjit_func_t code; 321 uint8_t pkt[1] = { 2 }; 322 bpf_args_t args = { 323 .pkt = pkt, 324 .buflen = sizeof(pkt), 325 .wirelen = sizeof(pkt), 326 }; 327 328 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 329 330 code = bpfjit_generate_code(&ctx, insns, insn_count); 331 ATF_REQUIRE(code != NULL); 332 333 ATF_CHECK(code(&ctx, &args) == 3 + ctx.nfuncs); 334 335 bpfjit_free_code(code); 336 } 337 338 ATF_TC(libbpfjit_cop_invalid_index); 339 ATF_TC_HEAD(libbpfjit_cop_invalid_index, tc) 340 { 341 atf_tc_set_md_var(tc, "descr", 342 "Test that out-of-range coprocessor function fails validation"); 343 } 344 345 ATF_TC_BODY(libbpfjit_cop_invalid_index, tc) 346 { 347 static struct bpf_insn insns[] = { 348 BPF_STMT(BPF_LD+BPF_IMM, 13), 349 BPF_STMT(BPF_MISC+BPF_COP, 6), // invalid index 350 BPF_STMT(BPF_RET+BPF_K, 27) 351 }; 352 353 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 354 355 ATF_CHECK(bpfjit_generate_code(&ctx, insns, insn_count) == NULL); 356 } 357 358 ATF_TC(libbpfjit_copx_no_ctx); 359 ATF_TC_HEAD(libbpfjit_copx_no_ctx, tc) 360 { 361 atf_tc_set_md_var(tc, "descr", "Test that bpf program with BPF_COPX " 362 "instruction isn't valid without a context"); 363 } 364 365 ATF_TC_BODY(libbpfjit_copx_no_ctx, tc) 366 { 367 static struct bpf_insn insns[] = { 368 BPF_STMT(BPF_MISC+BPF_COP, 0), 369 BPF_STMT(BPF_RET+BPF_K, 7) 370 }; 371 372 bpfjit_func_t code; 373 374 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 375 376 ATF_CHECK(!bpf_validate(insns, insn_count)); 377 378 code = bpfjit_generate_code(NULL, insns, insn_count); 379 ATF_CHECK(code == NULL); 380 } 381 382 ATF_TC(libbpfjit_copx_ret_A); 383 ATF_TC_HEAD(libbpfjit_copx_ret_A, tc) 384 { 385 atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 386 "that returns a content of the A register"); 387 } 388 389 ATF_TC_BODY(libbpfjit_copx_ret_A, tc) 390 { 391 static struct bpf_insn insns[] = { 392 BPF_STMT(BPF_LD+BPF_IMM, 13), 393 BPF_STMT(BPF_LDX+BPF_IMM, 0), // retA 394 BPF_STMT(BPF_MISC+BPF_COPX, 0), 395 BPF_STMT(BPF_RET+BPF_A, 0) 396 }; 397 398 bpfjit_func_t code; 399 uint8_t pkt[1] = { 0 }; 400 bpf_args_t args = { 401 .pkt = pkt, 402 .buflen = sizeof(pkt), 403 .wirelen = sizeof(pkt), 404 }; 405 406 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 407 408 code = bpfjit_generate_code(&ctx, insns, insn_count); 409 ATF_REQUIRE(code != NULL); 410 411 ATF_CHECK(code(&ctx, &args) == 13); 412 413 bpfjit_free_code(code); 414 } 415 416 ATF_TC(libbpfjit_copx_ret_buflen); 417 ATF_TC_HEAD(libbpfjit_copx_ret_buflen, tc) 418 { 419 atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 420 "that returns the buflen argument"); 421 } 422 423 ATF_TC_BODY(libbpfjit_copx_ret_buflen, tc) 424 { 425 static struct bpf_insn insns[] = { 426 BPF_STMT(BPF_LD+BPF_IMM, 13), 427 BPF_STMT(BPF_LDX+BPF_IMM, 1), // retBL 428 BPF_STMT(BPF_MISC+BPF_COPX, 0), 429 BPF_STMT(BPF_RET+BPF_A, 0) 430 }; 431 432 bpfjit_func_t code; 433 uint8_t pkt[1] = { 0 }; 434 bpf_args_t args = { 435 .pkt = pkt, 436 .buflen = sizeof(pkt), 437 .wirelen = sizeof(pkt) 438 }; 439 440 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 441 442 code = bpfjit_generate_code(&ctx, insns, insn_count); 443 ATF_REQUIRE(code != NULL); 444 445 ATF_CHECK(code(&ctx, &args) == sizeof(pkt)); 446 447 bpfjit_free_code(code); 448 } 449 450 ATF_TC(libbpfjit_copx_ret_wirelen); 451 ATF_TC_HEAD(libbpfjit_copx_ret_wirelen, tc) 452 { 453 atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 454 "that returns the wirelen argument"); 455 } 456 457 ATF_TC_BODY(libbpfjit_copx_ret_wirelen, tc) 458 { 459 static struct bpf_insn insns[] = { 460 BPF_STMT(BPF_LDX+BPF_IMM, 2), // retWL 461 BPF_STMT(BPF_LD+BPF_IMM, 13), 462 BPF_STMT(BPF_MISC+BPF_COPX, 0), 463 BPF_STMT(BPF_RET+BPF_A, 0) 464 }; 465 466 bpfjit_func_t code; 467 uint8_t pkt[1] = { 0 }; 468 bpf_args_t args = { 469 .pkt = pkt, 470 .buflen = sizeof(pkt), 471 .wirelen = sizeof(pkt) 472 }; 473 474 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 475 476 code = bpfjit_generate_code(&ctx, insns, insn_count); 477 ATF_REQUIRE(code != NULL); 478 479 ATF_CHECK(code(&ctx, &args) == sizeof(pkt)); 480 481 bpfjit_free_code(code); 482 } 483 484 ATF_TC(libbpfjit_copx_ret_nfuncs); 485 ATF_TC_HEAD(libbpfjit_copx_ret_nfuncs, tc) 486 { 487 atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 488 "that returns nfuncs member of the context argument"); 489 } 490 491 ATF_TC_BODY(libbpfjit_copx_ret_nfuncs, tc) 492 { 493 static struct bpf_insn insns[] = { 494 BPF_STMT(BPF_LD+BPF_IMM, 13), 495 BPF_STMT(BPF_LDX+BPF_IMM, 3), // retNF 496 BPF_STMT(BPF_MISC+BPF_COPX, 0), 497 BPF_STMT(BPF_RET+BPF_A, 0) 498 }; 499 500 bpfjit_func_t code; 501 uint8_t pkt[1] = { 0 }; 502 bpf_args_t args = { 503 .pkt = pkt, 504 .buflen = sizeof(pkt), 505 .wirelen = sizeof(pkt) 506 }; 507 508 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 509 510 code = bpfjit_generate_code(&ctx, insns, insn_count); 511 ATF_REQUIRE(code != NULL); 512 513 ATF_CHECK(code(&ctx, &args) == ctx.nfuncs); 514 515 bpfjit_free_code(code); 516 } 517 518 ATF_TC(libbpfjit_copx_side_effect); 519 ATF_TC_HEAD(libbpfjit_copx_side_effect, tc) 520 { 521 atf_tc_set_md_var(tc, "descr", 522 "Test that ABC optimization doesn't skip BPF_COPX call"); 523 } 524 525 ATF_TC_BODY(libbpfjit_copx_side_effect, tc) 526 { 527 static struct bpf_insn insns[] = { 528 BPF_STMT(BPF_LD+BPF_IMM, 13), 529 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0), 530 BPF_STMT(BPF_LDX+BPF_IMM, 4), // setARG 531 BPF_STMT(BPF_MISC+BPF_COPX, 0), 532 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 99999), 533 BPF_STMT(BPF_RET+BPF_A, 0) 534 }; 535 536 bpfjit_func_t code; 537 bool arg = false; 538 uint8_t pkt[1] = { 0 }; 539 bpf_args_t args = { 540 .pkt = pkt, 541 .buflen = sizeof(pkt), 542 .wirelen = sizeof(pkt), 543 .mem = NULL, 544 .arg = &arg 545 }; 546 547 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 548 549 code = bpfjit_generate_code(&ctx, insns, insn_count); 550 ATF_REQUIRE(code != NULL); 551 552 ATF_CHECK(code(&ctx, &args) == 0); 553 ATF_CHECK(arg == true); 554 555 bpfjit_free_code(code); 556 } 557 558 ATF_TC(libbpfjit_copx_cop); 559 ATF_TC_HEAD(libbpfjit_copx_cop, tc) 560 { 561 atf_tc_set_md_var(tc, "descr", 562 "Test BPF_COPX call followed by BPF_COP call"); 563 } 564 565 ATF_TC_BODY(libbpfjit_copx_cop, tc) 566 { 567 static struct bpf_insn insns[] = { 568 BPF_STMT(BPF_LDX+BPF_IMM, 2), /* X <- 2 */ 569 BPF_STMT(BPF_MISC+BPF_COPX, 0), /* retWL */ 570 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1), /* A = A + X */ 571 BPF_STMT(BPF_MISC+BPF_TAX, 0), /* X <- A */ 572 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0), /* A = P[0] */ 573 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1), /* A = A + X */ 574 BPF_STMT(BPF_MISC+BPF_TAX, 0), /* X <- A */ 575 BPF_STMT(BPF_MISC+BPF_COP, 3), /* retNF */ 576 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1), /* A = A + X */ 577 BPF_STMT(BPF_RET+BPF_A, 0) 578 }; 579 580 bpfjit_func_t code; 581 uint8_t pkt[1] = { 2 }; 582 bpf_args_t args = { 583 .pkt = pkt, 584 .buflen = sizeof(pkt), 585 .wirelen = sizeof(pkt), 586 }; 587 588 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 589 590 code = bpfjit_generate_code(&ctx, insns, insn_count); 591 ATF_REQUIRE(code != NULL); 592 593 ATF_CHECK(code(&ctx, &args) == 5 + ctx.nfuncs); 594 595 bpfjit_free_code(code); 596 } 597 598 ATF_TC(libbpfjit_copx_invalid_index); 599 ATF_TC_HEAD(libbpfjit_copx_invalid_index, tc) 600 { 601 atf_tc_set_md_var(tc, "descr", 602 "Test that out-of-range BPF_COPX call fails at runtime"); 603 } 604 605 ATF_TC_BODY(libbpfjit_copx_invalid_index, tc) 606 { 607 static struct bpf_insn insns[] = { 608 BPF_STMT(BPF_LDX+BPF_IMM, 5), // invalid index 609 BPF_STMT(BPF_MISC+BPF_COPX, 0), 610 BPF_STMT(BPF_RET+BPF_K, 27) 611 }; 612 613 bpfjit_func_t code; 614 uint8_t pkt[1] = { 0 }; 615 bpf_args_t args = { 616 .pkt = pkt, 617 .buflen = sizeof(pkt), 618 .wirelen = sizeof(pkt) 619 }; 620 621 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 622 623 code = bpfjit_generate_code(&ctx, insns, insn_count); 624 ATF_REQUIRE(code != NULL); 625 626 ATF_CHECK(code(&ctx, &args) == 0); 627 628 bpfjit_free_code(code); 629 } 630 631 ATF_TP_ADD_TCS(tp) 632 { 633 634 /* 635 * For every new test please also add a similar test 636 * to ../../net/bpfjit/t_cop.c 637 */ 638 ATF_TP_ADD_TC(tp, libbpfjit_cop_no_ctx); 639 ATF_TP_ADD_TC(tp, libbpfjit_cop_ret_A); 640 ATF_TP_ADD_TC(tp, libbpfjit_cop_ret_buflen); 641 ATF_TP_ADD_TC(tp, libbpfjit_cop_ret_wirelen); 642 ATF_TP_ADD_TC(tp, libbpfjit_cop_ret_nfuncs); 643 ATF_TP_ADD_TC(tp, libbpfjit_cop_side_effect); 644 ATF_TP_ADD_TC(tp, libbpfjit_cop_copx); 645 ATF_TP_ADD_TC(tp, libbpfjit_cop_invalid_index); 646 647 ATF_TP_ADD_TC(tp, libbpfjit_copx_no_ctx); 648 ATF_TP_ADD_TC(tp, libbpfjit_copx_ret_A); 649 ATF_TP_ADD_TC(tp, libbpfjit_copx_ret_buflen); 650 ATF_TP_ADD_TC(tp, libbpfjit_copx_ret_wirelen); 651 ATF_TP_ADD_TC(tp, libbpfjit_copx_ret_nfuncs); 652 ATF_TP_ADD_TC(tp, libbpfjit_copx_side_effect); 653 ATF_TP_ADD_TC(tp, libbpfjit_copx_cop); 654 ATF_TP_ADD_TC(tp, libbpfjit_copx_invalid_index); 655 656 return atf_no_error(); 657 } 658