aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/net/ioam6.sh
blob: a2b9fad5a9a6523fddb42b5c74d20fc0bd90b363 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0+
#
# Author: Justin Iurman <justin.iurman@uliege.be>
#
# This script evaluates the IOAM insertion for IPv6 by checking the IOAM data
# consistency directly inside packets on the receiver side. Tests are divided
# into three categories: OUTPUT (evaluates the IOAM processing by the sender),
# INPUT (evaluates the IOAM processing by a receiver) and GLOBAL (evaluates
# wider use cases that do not fall into the other two categories). Both OUTPUT
# and INPUT tests only use a two-node topology (alpha and beta), while GLOBAL
# tests use the entire three-node topology (alpha, beta, gamma). Each test is
# documented inside its own handler in the code below.
#
# An IOAM domain is configured from Alpha to Gamma but not on the reverse path.
# When either Beta or Gamma is the destination (depending on the test category),
# Alpha adds an IOAM option (Pre-allocated Trace) inside a Hop-by-hop.
#
#
#            +-------------------+            +-------------------+
#            |                   |            |                   |
#            |    Alpha netns    |            |    Gamma netns    |
#            |                   |            |                   |
#            |  +-------------+  |            |  +-------------+  |
#            |  |    veth0    |  |            |  |    veth0    |  |
#            |  |  db01::2/64 |  |            |  |  db02::2/64 |  |
#            |  +-------------+  |            |  +-------------+  |
#            |         .         |            |         .         |
#            +-------------------+            +-------------------+
#                      .                                .
#                      .                                .
#                      .                                .
#            +----------------------------------------------------+
#            |         .                                .         |
#            |  +-------------+                  +-------------+  |
#            |  |    veth0    |                  |    veth1    |  |
#            |  |  db01::1/64 | ................ |  db02::1/64 |  |
#            |  +-------------+                  +-------------+  |
#            |                                                    |
#            |                      Beta netns                    |
#            |                                                    |
#            +----------------------------------------------------+
#
#
#
#        =============================================================
#        |                Alpha - IOAM configuration                 |
#        +===========================================================+
#        | Node ID             | 1                                   |
#        +-----------------------------------------------------------+
#        | Node Wide ID        | 11111111                            |
#        +-----------------------------------------------------------+
#        | Ingress ID          | 0xffff (default value)              |
#        +-----------------------------------------------------------+
#        | Ingress Wide ID     | 0xffffffff (default value)          |
#        +-----------------------------------------------------------+
#        | Egress ID           | 101                                 |
#        +-----------------------------------------------------------+
#        | Egress Wide ID      | 101101                              |
#        +-----------------------------------------------------------+
#        | Namespace Data      | 0xdeadbee0                          |
#        +-----------------------------------------------------------+
#        | Namespace Wide Data | 0xcafec0caf00dc0de                  |
#        +-----------------------------------------------------------+
#        | Schema ID           | 777                                 |
#        +-----------------------------------------------------------+
#        | Schema Data         | something that will be 4n-aligned   |
#        +-----------------------------------------------------------+
#
#
#        =============================================================
#        |                 Beta - IOAM configuration                 |
#        +===========================================================+
#        | Node ID             | 2                                   |
#        +-----------------------------------------------------------+
#        | Node Wide ID        | 22222222                            |
#        +-----------------------------------------------------------+
#        | Ingress ID          | 201                                 |
#        +-----------------------------------------------------------+
#        | Ingress Wide ID     | 201201                              |
#        +-----------------------------------------------------------+
#        | Egress ID           | 202                                 |
#        +-----------------------------------------------------------+
#        | Egress Wide ID      | 202202                              |
#        +-----------------------------------------------------------+
#        | Namespace Data      | 0xdeadbee1                          |
#        +-----------------------------------------------------------+
#        | Namespace Wide Data | 0xcafec0caf11dc0de                  |
#        +-----------------------------------------------------------+
#        | Schema ID           | 666                                 |
#        +-----------------------------------------------------------+
#        | Schema Data         | Hello there -Obi                    |
#        +-----------------------------------------------------------+
#
#
#        =============================================================
#        |                Gamma - IOAM configuration                 |
#        +===========================================================+
#        | Node ID             | 3                                   |
#        +-----------------------------------------------------------+
#        | Node Wide ID        | 33333333                            |
#        +-----------------------------------------------------------+
#        | Ingress ID          | 301                                 |
#        +-----------------------------------------------------------+
#        | Ingress Wide ID     | 301301                              |
#        +-----------------------------------------------------------+
#        | Egress ID           | 0xffff (default value)              |
#        +-----------------------------------------------------------+
#        | Egress Wide ID      | 0xffffffff (default value)          |
#        +-----------------------------------------------------------+
#        | Namespace Data      | 0xdeadbee2                          |
#        +-----------------------------------------------------------+
#        | Namespace Wide Data | 0xcafec0caf22dc0de                  |
#        +-----------------------------------------------------------+
#        | Schema ID           | 0xffffff (= None)                   |
#        +-----------------------------------------------------------+
#        | Schema Data         |                                     |
#        +-----------------------------------------------------------+


################################################################################
#                                                                              #
# WARNING: Be careful if you modify the block below - it MUST be kept          #
#          synchronized with configurations inside ioam6_parser.c and always   #
#          reflect the same.                                                   #
#                                                                              #
################################################################################

ALPHA=(
	1					# ID
	11111111				# Wide ID
	0xffff					# Ingress ID
	0xffffffff				# Ingress Wide ID
	101					# Egress ID
	101101					# Egress Wide ID
	0xdeadbee0				# Namespace Data
	0xcafec0caf00dc0de			# Namespace Wide Data
	777					# Schema ID (0xffffff = None)
	"something that will be 4n-aligned"	# Schema Data
)

BETA=(
	2
	22222222
	201
	201201
	202
	202202
	0xdeadbee1
	0xcafec0caf11dc0de
	666
	"Hello there -Obi"
)

GAMMA=(
	3
	33333333
	301
	301301
	0xffff
	0xffffffff
	0xdeadbee2
	0xcafec0caf22dc0de
	0xffffff
	""
)

TESTS_OUTPUT="
	out_undef_ns
	out_no_room
	out_bits
	out_full_supp_trace
"

TESTS_INPUT="
	in_undef_ns
	in_no_room
	in_oflag
	in_bits
	in_full_supp_trace
"

TESTS_GLOBAL="
	fwd_full_supp_trace
"


################################################################################
#                                                                              #
#                                   LIBRARY                                    #
#                                                                              #
################################################################################

check_kernel_compatibility()
{
  ip netns add ioam-tmp-node
  ip link add name veth0 netns ioam-tmp-node type veth \
         peer name veth1 netns ioam-tmp-node

  ip -netns ioam-tmp-node link set veth0 up
  ip -netns ioam-tmp-node link set veth1 up

  ip -netns ioam-tmp-node ioam namespace add 0
  ns_ad=$?

  ip -netns ioam-tmp-node ioam namespace show | grep -q "namespace 0"
  ns_sh=$?

  if [[ $ns_ad != 0 || $ns_sh != 0 ]]
  then
    echo "SKIP: kernel version probably too old, missing ioam support"
    ip link del veth0 2>/dev/null || true
    ip netns del ioam-tmp-node || true
    exit 1
  fi

  ip -netns ioam-tmp-node route add db02::/64 encap ioam6 mode inline \
         trace prealloc type 0x800000 ns 0 size 4 dev veth0
  tr_ad=$?

  ip -netns ioam-tmp-node -6 route | grep -q "encap ioam6"
  tr_sh=$?

  if [[ $tr_ad != 0 || $tr_sh != 0 ]]
  then
    echo "SKIP: cannot attach an ioam trace to a route, did you compile" \
         "without CONFIG_IPV6_IOAM6_LWTUNNEL?"
    ip link del veth0 2>/dev/null || true
    ip netns del ioam-tmp-node || true
    exit 1
  fi

  ip link del veth0 2>/dev/null || true
  ip netns del ioam-tmp-node || true

  lsmod | grep -q "ip6_tunnel"
  ip6tnl_loaded=$?

  if [ $ip6tnl_loaded = 0 ]
  then
    encap_tests=0
  else
    modprobe ip6_tunnel &>/dev/null
    lsmod | grep -q "ip6_tunnel"
    encap_tests=$?

    if [ $encap_tests != 0 ]
    then
      ip a | grep -q "ip6tnl0"
      encap_tests=$?

      if [ $encap_tests != 0 ]
      then
        echo "Note: ip6_tunnel not found neither as a module nor inside the" \
             "kernel, tests that require it (encap mode) will be omitted"
      fi
    fi
  fi
}

cleanup()
{
  ip link del ioam-veth-alpha 2>/dev/null || true
  ip link del ioam-veth-gamma 2>/dev/null || true

  ip netns del ioam-node-alpha || true
  ip netns del ioam-node-beta || true
  ip netns del ioam-node-gamma || true

  if [ $ip6tnl_loaded != 0 ]
  then
    modprobe -r ip6_tunnel 2>/dev/null || true
  fi
}

setup()
{
  ip netns add ioam-node-alpha
  ip netns add ioam-node-beta
  ip netns add ioam-node-gamma

  ip link add name ioam-veth-alpha netns ioam-node-alpha type veth \
         peer name ioam-veth-betaL netns ioam-node-beta
  ip link add name ioam-veth-betaR netns ioam-node-beta type veth \
         peer name ioam-veth-gamma netns ioam-node-gamma

  ip -netns ioam-node-alpha link set ioam-veth-alpha name veth0
  ip -netns ioam-node-beta link set ioam-veth-betaL name veth0
  ip -netns ioam-node-beta link set ioam-veth-betaR name veth1
  ip -netns ioam-node-gamma link set ioam-veth-gamma name veth0

  ip -netns ioam-node-alpha addr add db01::2/64 dev veth0
  ip -netns ioam-node-alpha link set veth0 up
  ip -netns ioam-node-alpha link set lo up
  ip -netns ioam-node-alpha route add db02::/64 via db01::1 dev veth0
  ip -netns ioam-node-alpha route del db01::/64
  ip -netns ioam-node-alpha route add db01::/64 dev veth0

  ip -netns ioam-node-beta addr add db01::1/64 dev veth0
  ip -netns ioam-node-beta addr add db02::1/64 dev veth1
  ip -netns ioam-node-beta link set veth0 up
  ip -netns ioam-node-beta link set veth1 up
  ip -netns ioam-node-beta link set lo up

  ip -netns ioam-node-gamma addr add db02::2/64 dev veth0
  ip -netns ioam-node-gamma link set veth0 up
  ip -netns ioam-node-gamma link set lo up
  ip -netns ioam-node-gamma route add db01::/64 via db02::1 dev veth0

  # - IOAM config -
  ip netns exec ioam-node-alpha sysctl -wq net.ipv6.ioam6_id=${ALPHA[0]}
  ip netns exec ioam-node-alpha sysctl -wq net.ipv6.ioam6_id_wide=${ALPHA[1]}
  ip netns exec ioam-node-alpha sysctl -wq net.ipv6.conf.veth0.ioam6_id=${ALPHA[4]}
  ip netns exec ioam-node-alpha sysctl -wq net.ipv6.conf.veth0.ioam6_id_wide=${ALPHA[5]}
  ip -netns ioam-node-alpha ioam namespace add 123 data ${ALPHA[6]} wide ${ALPHA[7]}
  ip -netns ioam-node-alpha ioam schema add ${ALPHA[8]} "${ALPHA[9]}"
  ip -netns ioam-node-alpha ioam namespace set 123 schema ${ALPHA[8]}

  ip netns exec ioam-node-beta sysctl -wq net.ipv6.conf.all.forwarding=1
  ip netns exec ioam-node-beta sysctl -wq net.ipv6.ioam6_id=${BETA[0]}
  ip netns exec ioam-node-beta sysctl -wq net.ipv6.ioam6_id_wide=${BETA[1]}
  ip netns exec ioam-node-beta sysctl -wq net.ipv6.conf.veth0.ioam6_enabled=1
  ip netns exec ioam-node-beta sysctl -wq net.ipv6.conf.veth0.ioam6_id=${BETA[2]}
  ip netns exec ioam-node-beta sysctl -wq net.ipv6.conf.veth0.ioam6_id_wide=${BETA[3]}
  ip netns exec ioam-node-beta sysctl -wq net.ipv6.conf.veth1.ioam6_id=${BETA[4]}
  ip netns exec ioam-node-beta sysctl -wq net.ipv6.conf.veth1.ioam6_id_wide=${BETA[5]}
  ip -netns ioam-node-beta ioam namespace add 123 data ${BETA[6]} wide ${BETA[7]}
  ip -netns ioam-node-beta ioam schema add ${BETA[8]} "${BETA[9]}"
  ip -netns ioam-node-beta ioam namespace set 123 schema ${BETA[8]}

  ip netns exec ioam-node-gamma sysctl -wq net.ipv6.ioam6_id=${GAMMA[0]}
  ip netns exec ioam-node-gamma sysctl -wq net.ipv6.ioam6_id_wide=${GAMMA[1]}
  ip netns exec ioam-node-gamma sysctl -wq net.ipv6.conf.veth0.ioam6_enabled=1
  ip netns exec ioam-node-gamma sysctl -wq net.ipv6.conf.veth0.ioam6_id=${GAMMA[2]}
  ip netns exec ioam-node-gamma sysctl -wq net.ipv6.conf.veth0.ioam6_id_wide=${GAMMA[3]}
  ip -netns ioam-node-gamma ioam namespace add 123 data ${GAMMA[6]} wide ${GAMMA[7]}

  sleep 1

  ip netns exec ioam-node-alpha ping6 -c 5 -W 1 db02::2 &>/dev/null
  if [ $? != 0 ]
  then
    echo "Setup FAILED"
    cleanup &>/dev/null
    exit 0
  fi
}

log_test_passed()
{
  local desc=$1
  printf "TEST: %-60s  [ OK ]\n" "${desc}"
}

log_test_failed()
{
  local desc=$1
  printf "TEST: %-60s  [FAIL]\n" "${desc}"
}

log_results()
{
  echo "- Tests passed: ${npassed}"
  echo "- Tests failed: ${nfailed}"
}

run_test()
{
  local name=$1
  local desc=$2
  local node_src=$3
  local node_dst=$4
  local ip6_src=$5
  local ip6_dst=$6
  local if_dst=$7
  local trace_type=$8
  local ioam_ns=$9

  ip netns exec $node_dst ./ioam6_parser $if_dst $name $ip6_src $ip6_dst \
         $trace_type $ioam_ns &
  local spid=$!
  sleep 0.1

  ip netns exec $node_src ping6 -t 64 -c 1 -W 1 $ip6_dst &>/dev/null
  if [ $? != 0 ]
  then
    nfailed=$((nfailed+1))
    log_test_failed "${desc}"
    kill -2 $spid &>/dev/null
  else
    wait $spid
    if [ $? = 0 ]
    then
      npassed=$((npassed+1))
      log_test_passed "${desc}"
    else
      nfailed=$((nfailed+1))
      log_test_failed "${desc}"
    fi
  fi
}

run()
{
  echo
  printf "%0.s-" {1..74}
  echo
  echo "OUTPUT tests"
  printf "%0.s-" {1..74}
  echo

  # set OUTPUT settings
  ip netns exec ioam-node-beta sysctl -wq net.ipv6.conf.veth0.ioam6_enabled=0

  for t in $TESTS_OUTPUT
  do
    $t "inline"
    [ $encap_tests = 0 ] && $t "encap"
  done

  # clean OUTPUT settings
  ip netns exec ioam-node-beta sysctl -wq net.ipv6.conf.veth0.ioam6_enabled=1
  ip -netns ioam-node-alpha route change db01::/64 dev veth0


  echo
  printf "%0.s-" {1..74}
  echo
  echo "INPUT tests"
  printf "%0.s-" {1..74}
  echo

  # set INPUT settings
  ip -netns ioam-node-alpha ioam namespace del 123

  for t in $TESTS_INPUT
  do
    $t "inline"
    [ $encap_tests = 0 ] && $t "encap"
  done

  # clean INPUT settings
  ip -netns ioam-node-alpha ioam namespace add 123 \
         data ${ALPHA[6]} wide ${ALPHA[7]}
  ip -netns ioam-node-alpha ioam namespace set 123 schema ${ALPHA[8]}
  ip -netns ioam-node-alpha route change db01::/64 dev veth0

  echo
  printf "%0.s-" {1..74}
  echo
  echo "GLOBAL tests"
  printf "%0.s-" {1..74}
  echo

  for t in $TESTS_GLOBAL
  do
    $t "inline"
    [ $encap_tests = 0 ] && $t "encap"
  done

  echo
  log_results
}

bit2type=(
  0x800000 0x400000 0x200000 0x100000 0x080000 0x040000 0x020000 0x010000
  0x008000 0x004000 0x002000 0x001000 0x000800 0x000400 0x000200 0x000100
  0x000080 0x000040 0x000020 0x000010 0x000008 0x000004 0x000002
)
bit2size=( 4 4 4 4 4 4 4 4 8 8 8 4 4 4 4 4 4 4 4 4 4 4 4 )


################################################################################
#                                                                              #
#                              OUTPUT tests                                    #
#                                                                              #
#   Two nodes (sender/receiver), IOAM disabled on ingress for the receiver.    #
################################################################################

out_undef_ns()
{
  ##############################################################################
  # Make sure that the encap node won't fill the trace if the chosen IOAM      #
  # namespace is not configured locally.                                       #
  ##############################################################################
  local desc="Unknown IOAM namespace"

  [ "$1" = "encap" ] && mode="$1 tundst db01::1" || mode="$1"
  [ "$1" = "encap" ] && ip -netns ioam-node-beta link set ip6tnl0 up

  ip -netns ioam-node-alpha route change db01::/64 encap ioam6 mode $mode \
         trace prealloc type 0x800000 ns 0 size 4 dev veth0

  run_test ${FUNCNAME[0]} "${desc} ($1 mode)" ioam-node-alpha ioam-node-beta \
         db01::2 db01::1 veth0 0x800000 0

  [ "$1" = "encap" ] && ip -netns ioam-node-beta link set ip6tnl0 down
}

out_no_room()
{
  ##############################################################################
  # Make sure that the encap node won't fill the trace and will set the        #
  # Overflow flag since there is no room enough for its data.                  #
  ##############################################################################
  local desc="Missing trace room"

  [ "$1" = "encap" ] && mode="$1 tundst db01::1" || mode="$1"
  [ "$1" = "encap" ] && ip -netns ioam-node-beta link set ip6tnl0 up

  ip -netns ioam-node-alpha route change db01::/64 encap ioam6 mode $mode \
         trace prealloc type 0xc00000 ns 123 size 4 dev veth0

  run_test ${FUNCNAME[0]} "${desc} ($1 mode)" ioam-node-alpha ioam-node-beta \
         db01::2 db01::1 veth0 0xc00000 123

  [ "$1" = "encap" ] && ip -netns ioam-node-beta link set ip6tnl0 down
}

out_bits()
{
  ##############################################################################
  # Make sure that, for each trace type bit, the encap node will either:       #
  #  (i)  fill the trace with its data when it is a supported bit              #
  #  (ii) not fill the trace with its data when it is an unsupported bit       #
  ##############################################################################
  local desc="Trace type with bit <n> only"

  local tmp=${bit2size[22]}
  bit2size[22]=$(( $tmp + ${#ALPHA[9]} + ((4 - (${#ALPHA[9]} % 4)) % 4) ))

  [ "$1" = "encap" ] && mode="$1 tundst db01::1" || mode="$1"
  [ "$1" = "encap" ] && ip -netns ioam-node-beta link set ip6tnl0 up

  for i in {0..22}
  do
    ip -netns ioam-node-alpha route change db01::/64 encap ioam6 mode $mode \
           trace prealloc type ${bit2type[$i]} ns 123 size ${bit2size[$i]} \
           dev veth0 &>/dev/null

    local cmd_res=$?
    local descr="${desc/<n>/$i}"

    if [[ $i -ge 12 && $i -le 21 ]]
    then
      if [ $cmd_res != 0 ]
      then
        npassed=$((npassed+1))
        log_test_passed "$descr"
      else
        nfailed=$((nfailed+1))
        log_test_failed "$descr"
      fi
    else
	run_test "out_bit$i" "$descr ($1 mode)" ioam-node-alpha \
           ioam-node-beta db01::2 db01::1 veth0 ${bit2type[$i]} 123
    fi
  done

  [ "$1" = "encap" ] && ip -netns ioam-node-beta link set ip6tnl0 down

  bit2size[22]=$tmp
}

out_full_supp_trace()
{
  ##############################################################################
  # Make sure that the encap node will correctly fill a full trace. Be careful,#
  # "full trace" here does NOT mean all bits (only supported ones).            #
  ##############################################################################
  local desc="Full supported trace"

  [ "$1" = "encap" ] && mode="$1 tundst db01::1" || mode="$1"
  [ "$1" = "encap" ] && ip -netns ioam-node-beta link set ip6tnl0 up

  ip -netns ioam-node-alpha route change db01::/64 encap ioam6 mode $mode \
         trace prealloc type 0xfff002 ns 123 size 100 dev veth0

  run_test ${FUNCNAME[0]} "${desc} ($1 mode)" ioam-node-alpha ioam-node-beta \
         db01::2 db01::1 veth0 0xfff002 123

  [ "$1" = "encap" ] && ip -netns ioam-node-beta link set ip6tnl0 down
}


################################################################################
#                                                                              #
#                               INPUT tests                                    #
#                                                                              #
#     Two nodes (sender/receiver), the sender MUST NOT fill the trace upon     #
#     insertion -> the IOAM namespace configured on the sender is removed      #
#     and is used in the inserted trace to force the sender not to fill it.    #
################################################################################

in_undef_ns()
{
  ##############################################################################
  # Make sure that the receiving node won't fill the trace if the related IOAM #
  # namespace is not configured locally.                                       #
  ##############################################################################
  local desc="Unknown IOAM namespace"

  [ "$1" = "encap" ] && mode="$1 tundst db01::1" || mode="$1"
  [ "$1" = "encap" ] && ip -netns ioam-node-beta link set ip6tnl0 up

  ip -netns ioam-node-alpha route change db01::/64 encap ioam6 mode $mode \
         trace prealloc type 0x800000 ns 0 size 4 dev veth0

  run_test ${FUNCNAME[0]} "${desc} ($1 mode)" ioam-node-alpha ioam-node-beta \
         db01::2 db01::1 veth0 0x800000 0

  [ "$1" = "encap" ] && ip -netns ioam-node-beta link set ip6tnl0 down
}

in_no_room()
{
  ##############################################################################
  # Make sure that the receiving node won't fill the trace and will set the    #
  # Overflow flag if there is no room enough for its data.                     #
  ##############################################################################
  local desc="Missing trace room"

  [ "$1" = "encap" ] && mode="$1 tundst db01::1" || mode="$1"
  [ "$1" = "encap" ] && ip -netns ioam-node-beta link set ip6tnl0 up

  ip -netns ioam-node-alpha route change db01::/64 encap ioam6 mode $mode \
         trace prealloc type 0xc00000 ns 123 size 4 dev veth0

  run_test ${FUNCNAME[0]} "${desc} ($1 mode)" ioam-node-alpha ioam-node-beta \
         db01::2 db01::1 veth0 0xc00000 123

  [ "$1" = "encap" ] && ip -netns ioam-node-beta link set ip6tnl0 down
}

in_bits()
{
  ##############################################################################
  # Make sure that, for each trace type bit, the receiving node will either:   #
  #  (i)  fill the trace with its data when it is a supported bit              #
  #  (ii) not fill the trace with its data when it is an unsupported bit       #
  ##############################################################################
  local desc="Trace type with bit <n> only"

  local tmp=${bit2size[22]}
  bit2size[22]=$(( $tmp + ${#BETA[9]} + ((4 - (${#BETA[9]} % 4)) % 4) ))

  [ "$1" = "encap" ] && mode="$1 tundst db01::1" || mode="$1"
  [ "$1" = "encap" ] && ip -netns ioam-node-beta link set ip6tnl0 up

  for i in {0..11} {22..22}
  do
    ip -netns ioam-node-alpha route change db01::/64 encap ioam6 mode $mode \
           trace prealloc type ${bit2type[$i]} ns 123 size ${bit2size[$i]} \
           dev veth0

    run_test "in_bit$i" "${desc/<n>/$i} ($1 mode)" ioam-node-alpha \
           ioam-node-beta db01::2 db01::1 veth0 ${bit2type[$i]} 123
  done

  [ "$1" = "encap" ] && ip -netns ioam-node-beta link set ip6tnl0 down

  bit2size[22]=$tmp
}

in_oflag()
{
  ##############################################################################
  # Make sure that the receiving node won't fill the trace since the Overflow  #
  # flag is set.                                                               #
  ##############################################################################
  local desc="Overflow flag is set"

  # Exception:
  #   Here, we need the sender to set the Overflow flag. For that, we will add
  #   back the IOAM namespace that was previously configured on the sender.
  ip -netns ioam-node-alpha ioam namespace add 123

  [ "$1" = "encap" ] && mode="$1 tundst db01::1" || mode="$1"
  [ "$1" = "encap" ] && ip -netns ioam-node-beta link set ip6tnl0 up

  ip -netns ioam-node-alpha route change db01::/64 encap ioam6 mode $mode \
         trace prealloc type 0xc00000 ns 123 size 4 dev veth0

  run_test ${FUNCNAME[0]} "${desc} ($1 mode)" ioam-node-alpha ioam-node-beta \
         db01::2 db01::1 veth0 0xc00000 123

  [ "$1" = "encap" ] && ip -netns ioam-node-beta link set ip6tnl0 down

  # And we clean the exception for this test to get things back to normal for
  # other INPUT tests
  ip -netns ioam-node-alpha ioam namespace del 123
}

in_full_supp_trace()
{
  ##############################################################################
  # Make sure that the receiving node will correctly fill a full trace. Be     #
  # careful, "full trace" here does NOT mean all bits (only supported ones).   #
  ##############################################################################
  local desc="Full supported trace"

  [ "$1" = "encap" ] && mode="$1 tundst db01::1" || mode="$1"
  [ "$1" = "encap" ] && ip -netns ioam-node-beta link set ip6tnl0 up

  ip -netns ioam-node-alpha route change db01::/64 encap ioam6 mode $mode \
         trace prealloc type 0xfff002 ns 123 size 80 dev veth0

  run_test ${FUNCNAME[0]} "${desc} ($1 mode)" ioam-node-alpha ioam-node-beta \
         db01::2 db01::1 veth0 0xfff002 123

  [ "$1" = "encap" ] && ip -netns ioam-node-beta link set ip6tnl0 down
}


################################################################################
#                                                                              #
#                              GLOBAL tests                                    #
#                                                                              #
#   Three nodes (sender/router/receiver), IOAM fully enabled on every node.    #
################################################################################

fwd_full_supp_trace()
{
  ##############################################################################
  # Make sure that all three nodes correctly filled the full supported trace   #
  # by checking that the trace data is consistent with the predefined config.  #
  ##############################################################################
  local desc="Forward - Full supported trace"

  [ "$1" = "encap" ] && mode="$1 tundst db02::2" || mode="$1"
  [ "$1" = "encap" ] && ip -netns ioam-node-gamma link set ip6tnl0 up

  ip -netns ioam-node-alpha route change db02::/64 encap ioam6 mode $mode \
         trace prealloc type 0xfff002 ns 123 size 244 via db01::1 dev veth0

  run_test ${FUNCNAME[0]} "${desc} ($1 mode)" ioam-node-alpha ioam-node-gamma \
         db01::2 db02::2 veth0 0xfff002 123

  [ "$1" = "encap" ] && ip -netns ioam-node-gamma link set ip6tnl0 down
}


################################################################################
#                                                                              #
#                                     MAIN                                     #
#                                                                              #
################################################################################

npassed=0
nfailed=0

if [ "$(id -u)" -ne 0 ]
then
  echo "SKIP: Need root privileges"
  exit 1
fi

if [ ! -x "$(command -v ip)" ]
then
  echo "SKIP: Could not run test without ip tool"
  exit 1
fi

ip ioam &>/dev/null
if [ $? = 1 ]
then
  echo "SKIP: iproute2 too old, missing ioam command"
  exit 1
fi

check_kernel_compatibility

cleanup &>/dev/null
setup
run
cleanup &>/dev/null