Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
   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
  19struct 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
  38static 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
  52static 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
  66enum {
  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
 244static 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
 453static 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
 591static 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
 606static 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
 928static 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
 936static 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
 958static 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
 980static 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
1002int 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;
1051recv:
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);
1097close:
1098	close(fd);
1099out:
1100	return ret;
1101}