1 // SPDX-License-Identifier: GPL-2.0+
3 * Author: Justin Iurman (justin.iurman@uliege.be)
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
);