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 43static uint32_t retA(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 44static uint32_t retBL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 45static uint32_t retWL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 46static uint32_t retNF(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 47static uint32_t setARG(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 48 49static const bpf_copfunc_t copfuncs[] = { 50 &retA, 51 &retBL, 52 &retWL, 53 &retNF, 54 &setARG 55}; 56 57static const bpf_ctx_t ctx = { 58 .copfuncs = copfuncs, 59 .nfuncs = sizeof(copfuncs) / sizeof(copfuncs[0]), 60 .extwords = 0 61}; 62 63static uint32_t 64retA(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A) 65{ 66 67 return A; 68} 69 70static uint32_t 71retBL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A) 72{ 73 74 return args->buflen; 75} 76 77static uint32_t 78retWL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A) 79{ 80 81 return args->wirelen; 82} 83 84static uint32_t 85retNF(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 */ 94static uint32_t 95setARG(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 104ATF_TC(libbpfjit_cop_no_ctx); 105ATF_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 111ATF_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 128ATF_TC(libbpfjit_cop_ret_A); 129ATF_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 135ATF_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 161ATF_TC(libbpfjit_cop_ret_buflen); 162ATF_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 168ATF_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 194ATF_TC(libbpfjit_cop_ret_wirelen); 195ATF_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 201ATF_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 227ATF_TC(libbpfjit_cop_ret_nfuncs); 228ATF_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 234ATF_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 260ATF_TC(libbpfjit_cop_side_effect); 261ATF_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 267ATF_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 299ATF_TC(libbpfjit_cop_copx); 300ATF_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 306ATF_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 338ATF_TC(libbpfjit_cop_invalid_index); 339ATF_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 345ATF_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 358ATF_TC(libbpfjit_copx_no_ctx); 359ATF_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 365ATF_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 382ATF_TC(libbpfjit_copx_ret_A); 383ATF_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 389ATF_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 416ATF_TC(libbpfjit_copx_ret_buflen); 417ATF_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 423ATF_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 450ATF_TC(libbpfjit_copx_ret_wirelen); 451ATF_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 457ATF_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 484ATF_TC(libbpfjit_copx_ret_nfuncs); 485ATF_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 491ATF_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 518ATF_TC(libbpfjit_copx_side_effect); 519ATF_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 525ATF_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 558ATF_TC(libbpfjit_copx_cop); 559ATF_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 565ATF_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 598ATF_TC(libbpfjit_copx_invalid_index); 599ATF_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 605ATF_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 631ATF_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