1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Author: Justin Iurman (justin.iurman@uliege.be) 4 * 5 * IOAM tester for IPv6, see ioam6.sh for details on each test case. 6 */ 7 #include <arpa/inet.h> 8 #include <errno.h> 9 #include <limits.h> 10 #include <linux/const.h> 11 #include <linux/if_ether.h> 12 #include <linux/ioam6.h> 13 #include <linux/ipv6.h> 14 #include <stdbool.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include <unistd.h> 18 19 struct ioam_config { 20 __u32 id; 21 __u64 wide; 22 __u16 ingr_id; 23 __u16 egr_id; 24 __u32 ingr_wide; 25 __u32 egr_wide; 26 __u32 ns_data; 27 __u64 ns_wide; 28 __u32 sc_id; 29 __u8 hlim; 30 char *sc_data; 31 }; 32 33 /* 34 * Be careful if you modify structs below - everything MUST be kept synchronized 35 * with configurations inside ioam6.sh and always reflect the same. 36 */ 37 38 static struct ioam_config node1 = { 39 .id = 1, 40 .wide = 11111111, 41 .ingr_id = 0xffff, /* default value */ 42 .egr_id = 101, 43 .ingr_wide = 0xffffffff, /* default value */ 44 .egr_wide = 101101, 45 .ns_data = 0xdeadbeef, 46 .ns_wide = 0xcafec0caf00dc0de, 47 .sc_id = 777, 48 .sc_data = "something that will be 4n-aligned", 49 .hlim = 64, 50 }; 51 52 static struct ioam_config node2 = { 53 .id = 2, 54 .wide = 22222222, 55 .ingr_id = 201, 56 .egr_id = 202, 57 .ingr_wide = 201201, 58 .egr_wide = 202202, 59 .ns_data = 0xffffffff, /* default value */ 60 .ns_wide = 0xffffffffffffffff, /* default value */ 61 .sc_id = 0xffffff, /* default value */ 62 .sc_data = NULL, 63 .hlim = 63, 64 }; 65 66 enum { 67 /********** 68 * OUTPUT * 69 **********/ 70 __TEST_OUT_MIN, 71 72 TEST_OUT_UNDEF_NS, 73 TEST_OUT_NO_ROOM, 74 TEST_OUT_NO_ROOM_OSS, 75 TEST_OUT_BIT0, 76 TEST_OUT_BIT1, 77 TEST_OUT_BIT2, 78 TEST_OUT_BIT3, 79 TEST_OUT_BIT4, 80 TEST_OUT_BIT5, 81 TEST_OUT_BIT6, 82 TEST_OUT_BIT7, 83 TEST_OUT_BIT8, 84 TEST_OUT_BIT9, 85 TEST_OUT_BIT10, 86 TEST_OUT_BIT11, 87 TEST_OUT_BIT22, 88 TEST_OUT_SIZE4, 89 TEST_OUT_SIZE8, 90 TEST_OUT_SIZE12, 91 TEST_OUT_SIZE16, 92 TEST_OUT_SIZE20, 93 TEST_OUT_SIZE24, 94 TEST_OUT_SIZE28, 95 TEST_OUT_SIZE32, 96 TEST_OUT_SIZE36, 97 TEST_OUT_SIZE40, 98 TEST_OUT_SIZE44, 99 TEST_OUT_SIZE48, 100 TEST_OUT_SIZE52, 101 TEST_OUT_SIZE56, 102 TEST_OUT_SIZE60, 103 TEST_OUT_SIZE64, 104 TEST_OUT_SIZE68, 105 TEST_OUT_SIZE72, 106 TEST_OUT_SIZE76, 107 TEST_OUT_SIZE80, 108 TEST_OUT_SIZE84, 109 TEST_OUT_SIZE88, 110 TEST_OUT_SIZE92, 111 TEST_OUT_SIZE96, 112 TEST_OUT_SIZE100, 113 TEST_OUT_SIZE104, 114 TEST_OUT_SIZE108, 115 TEST_OUT_SIZE112, 116 TEST_OUT_SIZE116, 117 TEST_OUT_SIZE120, 118 TEST_OUT_SIZE124, 119 TEST_OUT_SIZE128, 120 TEST_OUT_SIZE132, 121 TEST_OUT_SIZE136, 122 TEST_OUT_SIZE140, 123 TEST_OUT_SIZE144, 124 TEST_OUT_SIZE148, 125 TEST_OUT_SIZE152, 126 TEST_OUT_SIZE156, 127 TEST_OUT_SIZE160, 128 TEST_OUT_SIZE164, 129 TEST_OUT_SIZE168, 130 TEST_OUT_SIZE172, 131 TEST_OUT_SIZE176, 132 TEST_OUT_SIZE180, 133 TEST_OUT_SIZE184, 134 TEST_OUT_SIZE188, 135 TEST_OUT_SIZE192, 136 TEST_OUT_SIZE196, 137 TEST_OUT_SIZE200, 138 TEST_OUT_SIZE204, 139 TEST_OUT_SIZE208, 140 TEST_OUT_SIZE212, 141 TEST_OUT_SIZE216, 142 TEST_OUT_SIZE220, 143 TEST_OUT_SIZE224, 144 TEST_OUT_SIZE228, 145 TEST_OUT_SIZE232, 146 TEST_OUT_SIZE236, 147 TEST_OUT_SIZE240, 148 TEST_OUT_SIZE244, 149 TEST_OUT_FULL_SUPP_TRACE, 150 151 __TEST_OUT_MAX, 152 153 /********* 154 * INPUT * 155 *********/ 156 __TEST_IN_MIN, 157 158 TEST_IN_UNDEF_NS, 159 TEST_IN_NO_ROOM, 160 TEST_IN_NO_ROOM_OSS, 161 TEST_IN_DISABLED, 162 TEST_IN_OFLAG, 163 TEST_IN_BIT0, 164 TEST_IN_BIT1, 165 TEST_IN_BIT2, 166 TEST_IN_BIT3, 167 TEST_IN_BIT4, 168 TEST_IN_BIT5, 169 TEST_IN_BIT6, 170 TEST_IN_BIT7, 171 TEST_IN_BIT8, 172 TEST_IN_BIT9, 173 TEST_IN_BIT10, 174 TEST_IN_BIT11, 175 TEST_IN_BIT22, 176 TEST_IN_SIZE4, 177 TEST_IN_SIZE8, 178 TEST_IN_SIZE12, 179 TEST_IN_SIZE16, 180 TEST_IN_SIZE20, 181 TEST_IN_SIZE24, 182 TEST_IN_SIZE28, 183 TEST_IN_SIZE32, 184 TEST_IN_SIZE36, 185 TEST_IN_SIZE40, 186 TEST_IN_SIZE44, 187 TEST_IN_SIZE48, 188 TEST_IN_SIZE52, 189 TEST_IN_SIZE56, 190 TEST_IN_SIZE60, 191 TEST_IN_SIZE64, 192 TEST_IN_SIZE68, 193 TEST_IN_SIZE72, 194 TEST_IN_SIZE76, 195 TEST_IN_SIZE80, 196 TEST_IN_SIZE84, 197 TEST_IN_SIZE88, 198 TEST_IN_SIZE92, 199 TEST_IN_SIZE96, 200 TEST_IN_SIZE100, 201 TEST_IN_SIZE104, 202 TEST_IN_SIZE108, 203 TEST_IN_SIZE112, 204 TEST_IN_SIZE116, 205 TEST_IN_SIZE120, 206 TEST_IN_SIZE124, 207 TEST_IN_SIZE128, 208 TEST_IN_SIZE132, 209 TEST_IN_SIZE136, 210 TEST_IN_SIZE140, 211 TEST_IN_SIZE144, 212 TEST_IN_SIZE148, 213 TEST_IN_SIZE152, 214 TEST_IN_SIZE156, 215 TEST_IN_SIZE160, 216 TEST_IN_SIZE164, 217 TEST_IN_SIZE168, 218 TEST_IN_SIZE172, 219 TEST_IN_SIZE176, 220 TEST_IN_SIZE180, 221 TEST_IN_SIZE184, 222 TEST_IN_SIZE188, 223 TEST_IN_SIZE192, 224 TEST_IN_SIZE196, 225 TEST_IN_SIZE200, 226 TEST_IN_SIZE204, 227 TEST_IN_SIZE208, 228 TEST_IN_SIZE212, 229 TEST_IN_SIZE216, 230 TEST_IN_SIZE220, 231 TEST_IN_SIZE224, 232 TEST_IN_SIZE228, 233 TEST_IN_SIZE232, 234 TEST_IN_SIZE236, 235 TEST_IN_SIZE240, 236 TEST_IN_SIZE244, 237 TEST_IN_FULL_SUPP_TRACE, 238 239 __TEST_IN_MAX, 240 241 __TEST_MAX, 242 }; 243 244 static int check_header(int tid, struct ioam6_trace_hdr *trace, 245 __u32 trace_type, __u8 trace_size, __u16 ioam_ns) 246 { 247 if (__be16_to_cpu(trace->namespace_id) != ioam_ns || 248 __be32_to_cpu(trace->type_be32) != (trace_type << 8)) 249 return 1; 250 251 switch (tid) { 252 case TEST_OUT_UNDEF_NS: 253 case TEST_IN_UNDEF_NS: 254 case TEST_IN_DISABLED: 255 return trace->overflow == 1 || 256 trace->nodelen != 1 || 257 trace->remlen != 1; 258 259 case TEST_OUT_NO_ROOM: 260 case TEST_IN_NO_ROOM: 261 case TEST_IN_OFLAG: 262 return trace->overflow == 0 || 263 trace->nodelen != 2 || 264 trace->remlen != 1; 265 266 case TEST_OUT_NO_ROOM_OSS: 267 return trace->overflow == 0 || 268 trace->nodelen != 0 || 269 trace->remlen != 1; 270 271 case TEST_IN_NO_ROOM_OSS: 272 case TEST_OUT_BIT22: 273 case TEST_IN_BIT22: 274 return trace->overflow == 1 || 275 trace->nodelen != 0 || 276 trace->remlen != 0; 277 278 case TEST_OUT_BIT0: 279 case TEST_IN_BIT0: 280 case TEST_OUT_BIT1: 281 case TEST_IN_BIT1: 282 case TEST_OUT_BIT2: 283 case TEST_IN_BIT2: 284 case TEST_OUT_BIT3: 285 case TEST_IN_BIT3: 286 case TEST_OUT_BIT4: 287 case TEST_IN_BIT4: 288 case TEST_OUT_BIT5: 289 case TEST_IN_BIT5: 290 case TEST_OUT_BIT6: 291 case TEST_IN_BIT6: 292 case TEST_OUT_BIT7: 293 case TEST_IN_BIT7: 294 case TEST_OUT_BIT11: 295 case TEST_IN_BIT11: 296 return trace->overflow == 1 || 297 trace->nodelen != 1 || 298 trace->remlen != 0; 299 300 case TEST_OUT_BIT8: 301 case TEST_IN_BIT8: 302 case TEST_OUT_BIT9: 303 case TEST_IN_BIT9: 304 case TEST_OUT_BIT10: 305 case TEST_IN_BIT10: 306 return trace->overflow == 1 || 307 trace->nodelen != 2 || 308 trace->remlen != 0; 309 310 case TEST_OUT_SIZE4: 311 case TEST_OUT_SIZE8: 312 case TEST_OUT_SIZE12: 313 case TEST_OUT_SIZE16: 314 case TEST_OUT_SIZE20: 315 case TEST_OUT_SIZE24: 316 case TEST_OUT_SIZE28: 317 case TEST_OUT_SIZE32: 318 case TEST_OUT_SIZE36: 319 case TEST_OUT_SIZE40: 320 case TEST_OUT_SIZE44: 321 case TEST_OUT_SIZE48: 322 case TEST_OUT_SIZE52: 323 case TEST_OUT_SIZE56: 324 case TEST_OUT_SIZE60: 325 case TEST_OUT_SIZE64: 326 case TEST_OUT_SIZE68: 327 case TEST_OUT_SIZE72: 328 case TEST_OUT_SIZE76: 329 case TEST_OUT_SIZE80: 330 case TEST_OUT_SIZE84: 331 case TEST_OUT_SIZE88: 332 case TEST_OUT_SIZE92: 333 case TEST_OUT_SIZE96: 334 case TEST_OUT_SIZE100: 335 case TEST_OUT_SIZE104: 336 case TEST_OUT_SIZE108: 337 case TEST_OUT_SIZE112: 338 case TEST_OUT_SIZE116: 339 case TEST_OUT_SIZE120: 340 case TEST_OUT_SIZE124: 341 case TEST_OUT_SIZE128: 342 case TEST_OUT_SIZE132: 343 case TEST_OUT_SIZE136: 344 case TEST_OUT_SIZE140: 345 case TEST_OUT_SIZE144: 346 case TEST_OUT_SIZE148: 347 case TEST_OUT_SIZE152: 348 case TEST_OUT_SIZE156: 349 case TEST_OUT_SIZE160: 350 case TEST_OUT_SIZE164: 351 case TEST_OUT_SIZE168: 352 case TEST_OUT_SIZE172: 353 case TEST_OUT_SIZE176: 354 case TEST_OUT_SIZE180: 355 case TEST_OUT_SIZE184: 356 case TEST_OUT_SIZE188: 357 case TEST_OUT_SIZE192: 358 case TEST_OUT_SIZE196: 359 case TEST_OUT_SIZE200: 360 case TEST_OUT_SIZE204: 361 case TEST_OUT_SIZE208: 362 case TEST_OUT_SIZE212: 363 case TEST_OUT_SIZE216: 364 case TEST_OUT_SIZE220: 365 case TEST_OUT_SIZE224: 366 case TEST_OUT_SIZE228: 367 case TEST_OUT_SIZE232: 368 case TEST_OUT_SIZE236: 369 case TEST_OUT_SIZE240: 370 case TEST_OUT_SIZE244: 371 return trace->overflow == 1 || 372 trace->nodelen != 1 || 373 trace->remlen != trace_size / 4; 374 375 case TEST_IN_SIZE4: 376 case TEST_IN_SIZE8: 377 case TEST_IN_SIZE12: 378 case TEST_IN_SIZE16: 379 case TEST_IN_SIZE20: 380 case TEST_IN_SIZE24: 381 case TEST_IN_SIZE28: 382 case TEST_IN_SIZE32: 383 case TEST_IN_SIZE36: 384 case TEST_IN_SIZE40: 385 case TEST_IN_SIZE44: 386 case TEST_IN_SIZE48: 387 case TEST_IN_SIZE52: 388 case TEST_IN_SIZE56: 389 case TEST_IN_SIZE60: 390 case TEST_IN_SIZE64: 391 case TEST_IN_SIZE68: 392 case TEST_IN_SIZE72: 393 case TEST_IN_SIZE76: 394 case TEST_IN_SIZE80: 395 case TEST_IN_SIZE84: 396 case TEST_IN_SIZE88: 397 case TEST_IN_SIZE92: 398 case TEST_IN_SIZE96: 399 case TEST_IN_SIZE100: 400 case TEST_IN_SIZE104: 401 case TEST_IN_SIZE108: 402 case TEST_IN_SIZE112: 403 case TEST_IN_SIZE116: 404 case TEST_IN_SIZE120: 405 case TEST_IN_SIZE124: 406 case TEST_IN_SIZE128: 407 case TEST_IN_SIZE132: 408 case TEST_IN_SIZE136: 409 case TEST_IN_SIZE140: 410 case TEST_IN_SIZE144: 411 case TEST_IN_SIZE148: 412 case TEST_IN_SIZE152: 413 case TEST_IN_SIZE156: 414 case TEST_IN_SIZE160: 415 case TEST_IN_SIZE164: 416 case TEST_IN_SIZE168: 417 case TEST_IN_SIZE172: 418 case TEST_IN_SIZE176: 419 case TEST_IN_SIZE180: 420 case TEST_IN_SIZE184: 421 case TEST_IN_SIZE188: 422 case TEST_IN_SIZE192: 423 case TEST_IN_SIZE196: 424 case TEST_IN_SIZE200: 425 case TEST_IN_SIZE204: 426 case TEST_IN_SIZE208: 427 case TEST_IN_SIZE212: 428 case TEST_IN_SIZE216: 429 case TEST_IN_SIZE220: 430 case TEST_IN_SIZE224: 431 case TEST_IN_SIZE228: 432 case TEST_IN_SIZE232: 433 case TEST_IN_SIZE236: 434 case TEST_IN_SIZE240: 435 case TEST_IN_SIZE244: 436 return trace->overflow == 1 || 437 trace->nodelen != 1 || 438 trace->remlen != (trace_size / 4) - trace->nodelen; 439 440 case TEST_OUT_FULL_SUPP_TRACE: 441 case TEST_IN_FULL_SUPP_TRACE: 442 return trace->overflow == 1 || 443 trace->nodelen != 15 || 444 trace->remlen != 0; 445 446 default: 447 break; 448 } 449 450 return 1; 451 } 452 453 static int check_data(struct ioam6_trace_hdr *trace, __u8 trace_size, 454 const struct ioam_config cnf, bool is_output) 455 { 456 unsigned int len, i; 457 __u8 aligned; 458 __u64 raw64; 459 __u32 raw32; 460 __u8 *p; 461 462 if (trace->type.bit12 | trace->type.bit13 | trace->type.bit14 | 463 trace->type.bit15 | trace->type.bit16 | trace->type.bit17 | 464 trace->type.bit18 | trace->type.bit19 | trace->type.bit20 | 465 trace->type.bit21 | trace->type.bit23) 466 return 1; 467 468 for (i = 0; i < trace->remlen * 4; i++) { 469 if (trace->data[i] != 0) 470 return 1; 471 } 472 473 if (trace->remlen * 4 == trace_size) 474 return 0; 475 476 p = trace->data + trace->remlen * 4; 477 478 if (trace->type.bit0) { 479 raw32 = __be32_to_cpu(*((__u32 *)p)); 480 if (cnf.hlim != (raw32 >> 24) || cnf.id != (raw32 & 0xffffff)) 481 return 1; 482 p += sizeof(__u32); 483 } 484 485 if (trace->type.bit1) { 486 raw32 = __be32_to_cpu(*((__u32 *)p)); 487 if (cnf.ingr_id != (raw32 >> 16) || 488 cnf.egr_id != (raw32 & 0xffff)) 489 return 1; 490 p += sizeof(__u32); 491 } 492 493 if (trace->type.bit2) { 494 raw32 = __be32_to_cpu(*((__u32 *)p)); 495 if ((is_output && raw32 != 0xffffffff) || 496 (!is_output && (raw32 == 0 || raw32 == 0xffffffff))) 497 return 1; 498 p += sizeof(__u32); 499 } 500 501 if (trace->type.bit3) { 502 raw32 = __be32_to_cpu(*((__u32 *)p)); 503 if ((is_output && raw32 != 0xffffffff) || 504 (!is_output && (raw32 == 0 || raw32 == 0xffffffff))) 505 return 1; 506 p += sizeof(__u32); 507 } 508 509 if (trace->type.bit4) { 510 if (__be32_to_cpu(*((__u32 *)p)) != 0xffffffff) 511 return 1; 512 p += sizeof(__u32); 513 } 514 515 if (trace->type.bit5) { 516 if (__be32_to_cpu(*((__u32 *)p)) != cnf.ns_data) 517 return 1; 518 p += sizeof(__u32); 519 } 520 521 if (trace->type.bit6) { 522 if (__be32_to_cpu(*((__u32 *)p)) == 0xffffffff) 523 return 1; 524 p += sizeof(__u32); 525 } 526 527 if (trace->type.bit7) { 528 if (__be32_to_cpu(*((__u32 *)p)) != 0xffffffff) 529 return 1; 530 p += sizeof(__u32); 531 } 532 533 if (trace->type.bit8) { 534 raw64 = __be64_to_cpu(*((__u64 *)p)); 535 if (cnf.hlim != (raw64 >> 56) || 536 cnf.wide != (raw64 & 0xffffffffffffff)) 537 return 1; 538 p += sizeof(__u64); 539 } 540 541 if (trace->type.bit9) { 542 if (__be32_to_cpu(*((__u32 *)p)) != cnf.ingr_wide) 543 return 1; 544 p += sizeof(__u32); 545 546 if (__be32_to_cpu(*((__u32 *)p)) != cnf.egr_wide) 547 return 1; 548 p += sizeof(__u32); 549 } 550 551 if (trace->type.bit10) { 552 if (__be64_to_cpu(*((__u64 *)p)) != cnf.ns_wide) 553 return 1; 554 p += sizeof(__u64); 555 } 556 557 if (trace->type.bit11) { 558 if (__be32_to_cpu(*((__u32 *)p)) != 0xffffffff) 559 return 1; 560 p += sizeof(__u32); 561 } 562 563 if (trace->type.bit22) { 564 len = cnf.sc_data ? strlen(cnf.sc_data) : 0; 565 aligned = cnf.sc_data ? __ALIGN_KERNEL(len, 4) : 0; 566 567 raw32 = __be32_to_cpu(*((__u32 *)p)); 568 if (aligned != (raw32 >> 24) * 4 || 569 cnf.sc_id != (raw32 & 0xffffff)) 570 return 1; 571 p += sizeof(__u32); 572 573 if (cnf.sc_data) { 574 if (strncmp((char *)p, cnf.sc_data, len)) 575 return 1; 576 577 p += len; 578 aligned -= len; 579 580 while (aligned--) { 581 if (*p != '\0') 582 return 1; 583 p += sizeof(__u8); 584 } 585 } 586 } 587 588 return 0; 589 } 590 591 static int check_ioam_trace(int tid, struct ioam6_trace_hdr *trace, 592 __u32 trace_type, __u8 trace_size, __u16 ioam_ns) 593 { 594 if (check_header(tid, trace, trace_type, trace_size, ioam_ns)) 595 return 1; 596 597 if (tid > __TEST_OUT_MIN && tid < __TEST_OUT_MAX) 598 return check_data(trace, trace_size, node1, true); 599 600 if (tid > __TEST_IN_MIN && tid < __TEST_IN_MAX) 601 return check_data(trace, trace_size, node2, false); 602 603 return 1; 604 } 605 606 static int str2id(const char *tname) 607 { 608 if (!strcmp("output_undef_ns", tname)) 609 return TEST_OUT_UNDEF_NS; 610 if (!strcmp("output_no_room", tname)) 611 return TEST_OUT_NO_ROOM; 612 if (!strcmp("output_no_room_oss", tname)) 613 return TEST_OUT_NO_ROOM_OSS; 614 if (!strcmp("output_bit0", tname)) 615 return TEST_OUT_BIT0; 616 if (!strcmp("output_bit1", tname)) 617 return TEST_OUT_BIT1; 618 if (!strcmp("output_bit2", tname)) 619 return TEST_OUT_BIT2; 620 if (!strcmp("output_bit3", tname)) 621 return TEST_OUT_BIT3; 622 if (!strcmp("output_bit4", tname)) 623 return TEST_OUT_BIT4; 624 if (!strcmp("output_bit5", tname)) 625 return TEST_OUT_BIT5; 626 if (!strcmp("output_bit6", tname)) 627 return TEST_OUT_BIT6; 628 if (!strcmp("output_bit7", tname)) 629 return TEST_OUT_BIT7; 630 if (!strcmp("output_bit8", tname)) 631 return TEST_OUT_BIT8; 632 if (!strcmp("output_bit9", tname)) 633 return TEST_OUT_BIT9; 634 if (!strcmp("output_bit10", tname)) 635 return TEST_OUT_BIT10; 636 if (!strcmp("output_bit11", tname)) 637 return TEST_OUT_BIT11; 638 if (!strcmp("output_bit22", tname)) 639 return TEST_OUT_BIT22; 640 if (!strcmp("output_size4", tname)) 641 return TEST_OUT_SIZE4; 642 if (!strcmp("output_size8", tname)) 643 return TEST_OUT_SIZE8; 644 if (!strcmp("output_size12", tname)) 645 return TEST_OUT_SIZE12; 646 if (!strcmp("output_size16", tname)) 647 return TEST_OUT_SIZE16; 648 if (!strcmp("output_size20", tname)) 649 return TEST_OUT_SIZE20; 650 if (!strcmp("output_size24", tname)) 651 return TEST_OUT_SIZE24; 652 if (!strcmp("output_size28", tname)) 653 return TEST_OUT_SIZE28; 654 if (!strcmp("output_size32", tname)) 655 return TEST_OUT_SIZE32; 656 if (!strcmp("output_size36", tname)) 657 return TEST_OUT_SIZE36; 658 if (!strcmp("output_size40", tname)) 659 return TEST_OUT_SIZE40; 660 if (!strcmp("output_size44", tname)) 661 return TEST_OUT_SIZE44; 662 if (!strcmp("output_size48", tname)) 663 return TEST_OUT_SIZE48; 664 if (!strcmp("output_size52", tname)) 665 return TEST_OUT_SIZE52; 666 if (!strcmp("output_size56", tname)) 667 return TEST_OUT_SIZE56; 668 if (!strcmp("output_size60", tname)) 669 return TEST_OUT_SIZE60; 670 if (!strcmp("output_size64", tname)) 671 return TEST_OUT_SIZE64; 672 if (!strcmp("output_size68", tname)) 673 return TEST_OUT_SIZE68; 674 if (!strcmp("output_size72", tname)) 675 return TEST_OUT_SIZE72; 676 if (!strcmp("output_size76", tname)) 677 return TEST_OUT_SIZE76; 678 if (!strcmp("output_size80", tname)) 679 return TEST_OUT_SIZE80; 680 if (!strcmp("output_size84", tname)) 681 return TEST_OUT_SIZE84; 682 if (!strcmp("output_size88", tname)) 683 return TEST_OUT_SIZE88; 684 if (!strcmp("output_size92", tname)) 685 return TEST_OUT_SIZE92; 686 if (!strcmp("output_size96", tname)) 687 return TEST_OUT_SIZE96; 688 if (!strcmp("output_size100", tname)) 689 return TEST_OUT_SIZE100; 690 if (!strcmp("output_size104", tname)) 691 return TEST_OUT_SIZE104; 692 if (!strcmp("output_size108", tname)) 693 return TEST_OUT_SIZE108; 694 if (!strcmp("output_size112", tname)) 695 return TEST_OUT_SIZE112; 696 if (!strcmp("output_size116", tname)) 697 return TEST_OUT_SIZE116; 698 if (!strcmp("output_size120", tname)) 699 return TEST_OUT_SIZE120; 700 if (!strcmp("output_size124", tname)) 701 return TEST_OUT_SIZE124; 702 if (!strcmp("output_size128", tname)) 703 return TEST_OUT_SIZE128; 704 if (!strcmp("output_size132", tname)) 705 return TEST_OUT_SIZE132; 706 if (!strcmp("output_size136", tname)) 707 return TEST_OUT_SIZE136; 708 if (!strcmp("output_size140", tname)) 709 return TEST_OUT_SIZE140; 710 if (!strcmp("output_size144", tname)) 711 return TEST_OUT_SIZE144; 712 if (!strcmp("output_size148", tname)) 713 return TEST_OUT_SIZE148; 714 if (!strcmp("output_size152", tname)) 715 return TEST_OUT_SIZE152; 716 if (!strcmp("output_size156", tname)) 717 return TEST_OUT_SIZE156; 718 if (!strcmp("output_size160", tname)) 719 return TEST_OUT_SIZE160; 720 if (!strcmp("output_size164", tname)) 721 return TEST_OUT_SIZE164; 722 if (!strcmp("output_size168", tname)) 723 return TEST_OUT_SIZE168; 724 if (!strcmp("output_size172", tname)) 725 return TEST_OUT_SIZE172; 726 if (!strcmp("output_size176", tname)) 727 return TEST_OUT_SIZE176; 728 if (!strcmp("output_size180", tname)) 729 return TEST_OUT_SIZE180; 730 if (!strcmp("output_size184", tname)) 731 return TEST_OUT_SIZE184; 732 if (!strcmp("output_size188", tname)) 733 return TEST_OUT_SIZE188; 734 if (!strcmp("output_size192", tname)) 735 return TEST_OUT_SIZE192; 736 if (!strcmp("output_size196", tname)) 737 return TEST_OUT_SIZE196; 738 if (!strcmp("output_size200", tname)) 739 return TEST_OUT_SIZE200; 740 if (!strcmp("output_size204", tname)) 741 return TEST_OUT_SIZE204; 742 if (!strcmp("output_size208", tname)) 743 return TEST_OUT_SIZE208; 744 if (!strcmp("output_size212", tname)) 745 return TEST_OUT_SIZE212; 746 if (!strcmp("output_size216", tname)) 747 return TEST_OUT_SIZE216; 748 if (!strcmp("output_size220", tname)) 749 return TEST_OUT_SIZE220; 750 if (!strcmp("output_size224", tname)) 751 return TEST_OUT_SIZE224; 752 if (!strcmp("output_size228", tname)) 753 return TEST_OUT_SIZE228; 754 if (!strcmp("output_size232", tname)) 755 return TEST_OUT_SIZE232; 756 if (!strcmp("output_size236", tname)) 757 return TEST_OUT_SIZE236; 758 if (!strcmp("output_size240", tname)) 759 return TEST_OUT_SIZE240; 760 if (!strcmp("output_size244", tname)) 761 return TEST_OUT_SIZE244; 762 if (!strcmp("output_full_supp_trace", tname)) 763 return TEST_OUT_FULL_SUPP_TRACE; 764 if (!strcmp("input_undef_ns", tname)) 765 return TEST_IN_UNDEF_NS; 766 if (!strcmp("input_no_room", tname)) 767 return TEST_IN_NO_ROOM; 768 if (!strcmp("input_no_room_oss", tname)) 769 return TEST_IN_NO_ROOM_OSS; 770 if (!strcmp("input_disabled", tname)) 771 return TEST_IN_DISABLED; 772 if (!strcmp("input_oflag", tname)) 773 return TEST_IN_OFLAG; 774 if (!strcmp("input_bit0", tname)) 775 return TEST_IN_BIT0; 776 if (!strcmp("input_bit1", tname)) 777 return TEST_IN_BIT1; 778 if (!strcmp("input_bit2", tname)) 779 return TEST_IN_BIT2; 780 if (!strcmp("input_bit3", tname)) 781 return TEST_IN_BIT3; 782 if (!strcmp("input_bit4", tname)) 783 return TEST_IN_BIT4; 784 if (!strcmp("input_bit5", tname)) 785 return TEST_IN_BIT5; 786 if (!strcmp("input_bit6", tname)) 787 return TEST_IN_BIT6; 788 if (!strcmp("input_bit7", tname)) 789 return TEST_IN_BIT7; 790 if (!strcmp("input_bit8", tname)) 791 return TEST_IN_BIT8; 792 if (!strcmp("input_bit9", tname)) 793 return TEST_IN_BIT9; 794 if (!strcmp("input_bit10", tname)) 795 return TEST_IN_BIT10; 796 if (!strcmp("input_bit11", tname)) 797 return TEST_IN_BIT11; 798 if (!strcmp("input_bit22", tname)) 799 return TEST_IN_BIT22; 800 if (!strcmp("input_size4", tname)) 801 return TEST_IN_SIZE4; 802 if (!strcmp("input_size8", tname)) 803 return TEST_IN_SIZE8; 804 if (!strcmp("input_size12", tname)) 805 return TEST_IN_SIZE12; 806 if (!strcmp("input_size16", tname)) 807 return TEST_IN_SIZE16; 808 if (!strcmp("input_size20", tname)) 809 return TEST_IN_SIZE20; 810 if (!strcmp("input_size24", tname)) 811 return TEST_IN_SIZE24; 812 if (!strcmp("input_size28", tname)) 813 return TEST_IN_SIZE28; 814 if (!strcmp("input_size32", tname)) 815 return TEST_IN_SIZE32; 816 if (!strcmp("input_size36", tname)) 817 return TEST_IN_SIZE36; 818 if (!strcmp("input_size40", tname)) 819 return TEST_IN_SIZE40; 820 if (!strcmp("input_size44", tname)) 821 return TEST_IN_SIZE44; 822 if (!strcmp("input_size48", tname)) 823 return TEST_IN_SIZE48; 824 if (!strcmp("input_size52", tname)) 825 return TEST_IN_SIZE52; 826 if (!strcmp("input_size56", tname)) 827 return TEST_IN_SIZE56; 828 if (!strcmp("input_size60", tname)) 829 return TEST_IN_SIZE60; 830 if (!strcmp("input_size64", tname)) 831 return TEST_IN_SIZE64; 832 if (!strcmp("input_size68", tname)) 833 return TEST_IN_SIZE68; 834 if (!strcmp("input_size72", tname)) 835 return TEST_IN_SIZE72; 836 if (!strcmp("input_size76", tname)) 837 return TEST_IN_SIZE76; 838 if (!strcmp("input_size80", tname)) 839 return TEST_IN_SIZE80; 840 if (!strcmp("input_size84", tname)) 841 return TEST_IN_SIZE84; 842 if (!strcmp("input_size88", tname)) 843 return TEST_IN_SIZE88; 844 if (!strcmp("input_size92", tname)) 845 return TEST_IN_SIZE92; 846 if (!strcmp("input_size96", tname)) 847 return TEST_IN_SIZE96; 848 if (!strcmp("input_size100", tname)) 849 return TEST_IN_SIZE100; 850 if (!strcmp("input_size104", tname)) 851 return TEST_IN_SIZE104; 852 if (!strcmp("input_size108", tname)) 853 return TEST_IN_SIZE108; 854 if (!strcmp("input_size112", tname)) 855 return TEST_IN_SIZE112; 856 if (!strcmp("input_size116", tname)) 857 return TEST_IN_SIZE116; 858 if (!strcmp("input_size120", tname)) 859 return TEST_IN_SIZE120; 860 if (!strcmp("input_size124", tname)) 861 return TEST_IN_SIZE124; 862 if (!strcmp("input_size128", tname)) 863 return TEST_IN_SIZE128; 864 if (!strcmp("input_size132", tname)) 865 return TEST_IN_SIZE132; 866 if (!strcmp("input_size136", tname)) 867 return TEST_IN_SIZE136; 868 if (!strcmp("input_size140", tname)) 869 return TEST_IN_SIZE140; 870 if (!strcmp("input_size144", tname)) 871 return TEST_IN_SIZE144; 872 if (!strcmp("input_size148", tname)) 873 return TEST_IN_SIZE148; 874 if (!strcmp("input_size152", tname)) 875 return TEST_IN_SIZE152; 876 if (!strcmp("input_size156", tname)) 877 return TEST_IN_SIZE156; 878 if (!strcmp("input_size160", tname)) 879 return TEST_IN_SIZE160; 880 if (!strcmp("input_size164", tname)) 881 return TEST_IN_SIZE164; 882 if (!strcmp("input_size168", tname)) 883 return TEST_IN_SIZE168; 884 if (!strcmp("input_size172", tname)) 885 return TEST_IN_SIZE172; 886 if (!strcmp("input_size176", tname)) 887 return TEST_IN_SIZE176; 888 if (!strcmp("input_size180", tname)) 889 return TEST_IN_SIZE180; 890 if (!strcmp("input_size184", tname)) 891 return TEST_IN_SIZE184; 892 if (!strcmp("input_size188", tname)) 893 return TEST_IN_SIZE188; 894 if (!strcmp("input_size192", tname)) 895 return TEST_IN_SIZE192; 896 if (!strcmp("input_size196", tname)) 897 return TEST_IN_SIZE196; 898 if (!strcmp("input_size200", tname)) 899 return TEST_IN_SIZE200; 900 if (!strcmp("input_size204", tname)) 901 return TEST_IN_SIZE204; 902 if (!strcmp("input_size208", tname)) 903 return TEST_IN_SIZE208; 904 if (!strcmp("input_size212", tname)) 905 return TEST_IN_SIZE212; 906 if (!strcmp("input_size216", tname)) 907 return TEST_IN_SIZE216; 908 if (!strcmp("input_size220", tname)) 909 return TEST_IN_SIZE220; 910 if (!strcmp("input_size224", tname)) 911 return TEST_IN_SIZE224; 912 if (!strcmp("input_size228", tname)) 913 return TEST_IN_SIZE228; 914 if (!strcmp("input_size232", tname)) 915 return TEST_IN_SIZE232; 916 if (!strcmp("input_size236", tname)) 917 return TEST_IN_SIZE236; 918 if (!strcmp("input_size240", tname)) 919 return TEST_IN_SIZE240; 920 if (!strcmp("input_size244", tname)) 921 return TEST_IN_SIZE244; 922 if (!strcmp("input_full_supp_trace", tname)) 923 return TEST_IN_FULL_SUPP_TRACE; 924 925 return -1; 926 } 927 928 static int ipv6_addr_equal(const struct in6_addr *a1, const struct in6_addr *a2) 929 { 930 return ((a1->s6_addr32[0] ^ a2->s6_addr32[0]) | 931 (a1->s6_addr32[1] ^ a2->s6_addr32[1]) | 932 (a1->s6_addr32[2] ^ a2->s6_addr32[2]) | 933 (a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0; 934 } 935 936 static int get_u32(__u32 *val, const char *arg, int base) 937 { 938 unsigned long res; 939 char *ptr; 940 941 if (!arg || !*arg) 942 return -1; 943 res = strtoul(arg, &ptr, base); 944 945 if (!ptr || ptr == arg || *ptr) 946 return -1; 947 948 if (res == ULONG_MAX && errno == ERANGE) 949 return -1; 950 951 if (res > 0xFFFFFFFFUL) 952 return -1; 953 954 *val = res; 955 return 0; 956 } 957 958 static int get_u16(__u16 *val, const char *arg, int base) 959 { 960 unsigned long res; 961 char *ptr; 962 963 if (!arg || !*arg) 964 return -1; 965 res = strtoul(arg, &ptr, base); 966 967 if (!ptr || ptr == arg || *ptr) 968 return -1; 969 970 if (res == ULONG_MAX && errno == ERANGE) 971 return -1; 972 973 if (res > 0xFFFFUL) 974 return -1; 975 976 *val = res; 977 return 0; 978 } 979 980 static int get_u8(__u8 *val, const char *arg, int base) 981 { 982 unsigned long res; 983 char *ptr; 984 985 if (!arg || !*arg) 986 return -1; 987 res = strtoul(arg, &ptr, base); 988 989 if (!ptr || ptr == arg || *ptr) 990 return -1; 991 992 if (res == ULONG_MAX && errno == ERANGE) 993 return -1; 994 995 if (res > 0xFFUL) 996 return -1; 997 998 *val = res; 999 return 0; 1000 } 1001 1002 int main(int argc, char **argv) 1003 { 1004 __u8 buffer[512], *ptr, nexthdr, tr_size; 1005 struct ioam6_trace_hdr *trace; 1006 unsigned int hoplen, ret = 1; 1007 struct ipv6_hopopt_hdr *hbh; 1008 int fd, size, testname_id; 1009 struct in6_addr src, dst; 1010 struct ioam6_hdr *ioam6; 1011 struct timeval timeout; 1012 struct ipv6hdr *ipv6; 1013 __u32 tr_type; 1014 __u16 ioam_ns; 1015 1016 if (argc != 9) 1017 goto out; 1018 1019 testname_id = str2id(argv[2]); 1020 1021 if (testname_id < 0 || 1022 inet_pton(AF_INET6, argv[3], &src) != 1 || 1023 inet_pton(AF_INET6, argv[4], &dst) != 1 || 1024 get_u32(&tr_type, argv[5], 16) || 1025 get_u8(&tr_size, argv[6], 0) || 1026 get_u16(&ioam_ns, argv[7], 0)) 1027 goto out; 1028 1029 nexthdr = (!strcmp(argv[8], "encap") ? IPPROTO_IPV6 : IPPROTO_ICMPV6); 1030 1031 hoplen = sizeof(*hbh); 1032 hoplen += 2; // 2-byte padding for alignment 1033 hoplen += sizeof(*ioam6); // IOAM option header 1034 hoplen += sizeof(*trace); // IOAM trace header 1035 hoplen += tr_size; // IOAM trace size 1036 hoplen += (tr_size % 8); // optional padding 1037 1038 fd = socket(AF_PACKET, SOCK_DGRAM, __cpu_to_be16(ETH_P_IPV6)); 1039 if (fd < 0) 1040 goto out; 1041 1042 if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, 1043 argv[1], strlen(argv[1]))) 1044 goto close; 1045 1046 timeout.tv_sec = 1; 1047 timeout.tv_usec = 0; 1048 if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, 1049 (const char *)&timeout, sizeof(timeout))) 1050 goto close; 1051 recv: 1052 size = recv(fd, buffer, sizeof(buffer), 0); 1053 if (size <= 0) 1054 goto close; 1055 1056 ipv6 = (struct ipv6hdr *)buffer; 1057 1058 /* Skip packets that do not have the expected src/dst address or that 1059 * do not have a Hop-by-hop. 1060 */ 1061 if (!ipv6_addr_equal(&ipv6->saddr, &src) || 1062 !ipv6_addr_equal(&ipv6->daddr, &dst) || 1063 ipv6->nexthdr != IPPROTO_HOPOPTS) 1064 goto recv; 1065 1066 /* Check Hbh's Next Header and Size. */ 1067 hbh = (struct ipv6_hopopt_hdr *)(buffer + sizeof(*ipv6)); 1068 if (hbh->nexthdr != nexthdr || hbh->hdrlen != (hoplen >> 3) - 1) 1069 goto close; 1070 1071 /* Check we have a 2-byte padding for alignment. */ 1072 ptr = (__u8 *)hbh + sizeof(*hbh); 1073 if (ptr[0] != IPV6_TLV_PADN && ptr[1] != 0) 1074 goto close; 1075 1076 /* Check we now have the IOAM option. */ 1077 ptr += 2; 1078 if (ptr[0] != IPV6_TLV_IOAM) 1079 goto close; 1080 1081 /* Check its size and the IOAM option type. */ 1082 ioam6 = (struct ioam6_hdr *)ptr; 1083 if (ioam6->opt_len != sizeof(*ioam6) - 2 + sizeof(*trace) + tr_size || 1084 ioam6->type != IOAM6_TYPE_PREALLOC) 1085 goto close; 1086 1087 trace = (struct ioam6_trace_hdr *)(ptr + sizeof(*ioam6)); 1088 1089 /* Check the trailing 4-byte padding (potentially). */ 1090 ptr = (__u8 *)trace + sizeof(*trace) + tr_size; 1091 if (tr_size % 8 && ptr[0] != IPV6_TLV_PADN && ptr[1] != 2 && 1092 ptr[2] != 0 && ptr[3] != 0) 1093 goto close; 1094 1095 /* Check the IOAM header and data. */ 1096 ret = check_ioam_trace(testname_id, trace, tr_type, tr_size, ioam_ns); 1097 close: 1098 close(fd); 1099 out: 1100 return ret; 1101 } 1102