1 // SPDX-License-Identifier: GPL-2.0+
5 * IOAM tester for IPv6, see ioam6.sh for details on each test case.
10 #include <linux/const.h>
11 #include <linux/if_ether.h>
12 #include <linux/ioam6.h>
13 #include <linux/ipv6.h>
34 * Be careful if you modify structs below - everything MUST be kept synchronized
35 * with configurations inside ioam6.sh and always reflect the same.
38 static struct ioam_config node1 = {
41 .ingr_id = 0xffff, /* default value */
43 .ingr_wide = 0xffffffff, /* default value */
45 .ns_data = 0xdeadbeef,
46 .ns_wide = 0xcafec0caf00dc0de,
48 .sc_data = "something that will be 4n-aligned",
52 static struct ioam_config node2 = {
59 .ns_data = 0xffffffff, /* default value */
60 .ns_wide = 0xffffffffffffffff, /* default value */
61 .sc_id = 0xffffff, /* default value */
149 TEST_OUT_FULL_SUPP_TRACE,
237 TEST_IN_FULL_SUPP_TRACE,
244 static int check_header(int tid, struct ioam6_trace_hdr *trace,
245 __u32 trace_type, __u8 trace_size, __u16 ioam_ns)
247 if (__be16_to_cpu(trace->namespace_id) != ioam_ns ||
248 __be32_to_cpu(trace->type_be32) != (trace_type << 8))
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 ||
259 case TEST_OUT_NO_ROOM:
260 case TEST_IN_NO_ROOM:
262 return trace->overflow == 0 ||
263 trace->nodelen != 2 ||
266 case TEST_OUT_NO_ROOM_OSS:
267 return trace->overflow == 0 ||
268 trace->nodelen != 0 ||
271 case TEST_IN_NO_ROOM_OSS:
274 return trace->overflow == 1 ||
275 trace->nodelen != 0 ||
296 return trace->overflow == 1 ||
297 trace->nodelen != 1 ||
306 return trace->overflow == 1 ||
307 trace->nodelen != 2 ||
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;
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;
440 case TEST_OUT_FULL_SUPP_TRACE:
441 case TEST_IN_FULL_SUPP_TRACE:
442 return trace->overflow == 1 ||
443 trace->nodelen != 15 ||
453 static int check_data(struct ioam6_trace_hdr *trace, __u8 trace_size,
454 const struct ioam_config cnf, bool is_output)
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)
468 for (i = 0; i < trace->remlen * 4; i++) {
469 if (trace->data[i] != 0)
473 if (trace->remlen * 4 == trace_size)
476 p = trace->data + trace->remlen * 4;
478 if (trace->type.bit0) {
479 raw32 = __be32_to_cpu(*((__u32 *)p));
480 if (cnf.hlim != (raw32 >> 24) || cnf.id != (raw32 & 0xffffff))
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))
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)))
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)))
509 if (trace->type.bit4) {
510 if (__be32_to_cpu(*((__u32 *)p)) != 0xffffffff)
515 if (trace->type.bit5) {
516 if (__be32_to_cpu(*((__u32 *)p)) != cnf.ns_data)
521 if (trace->type.bit6) {
522 if (__be32_to_cpu(*((__u32 *)p)) == 0xffffffff)
527 if (trace->type.bit7) {
528 if (__be32_to_cpu(*((__u32 *)p)) != 0xffffffff)
533 if (trace->type.bit8) {
534 raw64 = __be64_to_cpu(*((__u64 *)p));
535 if (cnf.hlim != (raw64 >> 56) ||
536 cnf.wide != (raw64 & 0xffffffffffffff))
541 if (trace->type.bit9) {
542 if (__be32_to_cpu(*((__u32 *)p)) != cnf.ingr_wide)
546 if (__be32_to_cpu(*((__u32 *)p)) != cnf.egr_wide)
551 if (trace->type.bit10) {
552 if (__be64_to_cpu(*((__u64 *)p)) != cnf.ns_wide)
557 if (trace->type.bit11) {
558 if (__be32_to_cpu(*((__u32 *)p)) != 0xffffffff)
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;
567 raw32 = __be32_to_cpu(*((__u32 *)p));
568 if (aligned != (raw32 >> 24) * 4 ||
569 cnf.sc_id != (raw32 & 0xffffff))
574 if (strncmp((char *)p, cnf.sc_data, len))
591 static int check_ioam_trace(int tid, struct ioam6_trace_hdr *trace,
592 __u32 trace_type, __u8 trace_size, __u16 ioam_ns)
594 if (check_header(tid, trace, trace_type, trace_size, ioam_ns))
597 if (tid > __TEST_OUT_MIN && tid < __TEST_OUT_MAX)
598 return check_data(trace, trace_size, node1, true);
600 if (tid > __TEST_IN_MIN && tid < __TEST_IN_MAX)
601 return check_data(trace, trace_size, node2, false);
606 static int str2id(const char *tname)
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))
776 if (!strcmp("input_bit1", tname))
778 if (!strcmp("input_bit2", tname))
780 if (!strcmp("input_bit3", tname))
782 if (!strcmp("input_bit4", tname))
784 if (!strcmp("input_bit5", tname))
786 if (!strcmp("input_bit6", tname))
788 if (!strcmp("input_bit7", tname))
790 if (!strcmp("input_bit8", tname))
792 if (!strcmp("input_bit9", tname))
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;
928 static int ipv6_addr_equal(const struct in6_addr *a1, const struct in6_addr *a2)
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;
936 static int get_u32(__u32 *val, const char *arg, int base)
943 res = strtoul(arg, &ptr, base);
945 if (!ptr || ptr == arg || *ptr)
948 if (res == ULONG_MAX && errno == ERANGE)
951 if (res > 0xFFFFFFFFUL)
958 static int get_u16(__u16 *val, const char *arg, int base)
965 res = strtoul(arg, &ptr, base);
967 if (!ptr || ptr == arg || *ptr)
970 if (res == ULONG_MAX && errno == ERANGE)
980 static int get_u8(__u8 *val, const char *arg, int base)
987 res = strtoul(arg, &ptr, base);
989 if (!ptr || ptr == arg || *ptr)
992 if (res == ULONG_MAX && errno == ERANGE)
1002 int main(int argc, char **argv)
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;
1019 testname_id = str2id(argv[2]);
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))
1029 nexthdr = (!strcmp(argv[8], "encap") ? IPPROTO_IPV6 : IPPROTO_ICMPV6);
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
1038 fd = socket(AF_PACKET, SOCK_DGRAM, __cpu_to_be16(ETH_P_IPV6));
1042 if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
1043 argv[1], strlen(argv[1])))
1047 timeout.tv_usec = 0;
1048 if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
1049 (const char *)&timeout, sizeof(timeout)))
1052 size = recv(fd, buffer, sizeof(buffer), 0);
1056 ipv6 = (struct ipv6hdr *)buffer;
1058 /* Skip packets that do not have the expected src/dst address or that
1059 * do not have a Hop-by-hop.
1061 if (!ipv6_addr_equal(&ipv6->saddr, &src) ||
1062 !ipv6_addr_equal(&ipv6->daddr, &dst) ||
1063 ipv6->nexthdr != IPPROTO_HOPOPTS)
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)
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)
1076 /* Check we now have the IOAM option. */
1078 if (ptr[0] != IPV6_TLV_IOAM)
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)
1087 trace = (struct ioam6_trace_hdr *)(ptr + sizeof(*ioam6));
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)
1095 /* Check the IOAM header and data. */
1096 ret = check_ioam_trace(testname_id, trace, tr_type, tr_size, ioam_ns);