xref: /linux/tools/testing/selftests/net/ioam6_parser.c (revision c34e9ab9a612ee8b18273398ef75c207b01f516d)
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