test_tunnel.sh 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  1. #!/bin/bash
  2. # SPDX-License-Identifier: GPL-2.0
  3. # End-to-end eBPF tunnel test suite
  4. # The script tests BPF network tunnel implementation.
  5. #
  6. # Topology:
  7. # ---------
  8. # root namespace | at_ns0 namespace
  9. # |
  10. # ----------- | -----------
  11. # | tnl dev | | | tnl dev | (overlay network)
  12. # ----------- | -----------
  13. # metadata-mode | native-mode
  14. # with bpf |
  15. # |
  16. # ---------- | ----------
  17. # | veth1 | --------- | veth0 | (underlay network)
  18. # ---------- peer ----------
  19. #
  20. #
  21. # Device Configuration
  22. # --------------------
  23. # Root namespace with metadata-mode tunnel + BPF
  24. # Device names and addresses:
  25. # veth1 IP: 172.16.1.200, IPv6: 00::22 (underlay)
  26. # tunnel dev <type>11, ex: gre11, IPv4: 10.1.1.200, IPv6: 1::22 (overlay)
  27. #
  28. # Namespace at_ns0 with native tunnel
  29. # Device names and addresses:
  30. # veth0 IPv4: 172.16.1.100, IPv6: 00::11 (underlay)
  31. # tunnel dev <type>00, ex: gre00, IPv4: 10.1.1.100, IPv6: 1::11 (overlay)
  32. #
  33. #
  34. # End-to-end ping packet flow
  35. # ---------------------------
  36. # Most of the tests start by namespace creation, device configuration,
  37. # then ping the underlay and overlay network. When doing 'ping 10.1.1.100'
  38. # from root namespace, the following operations happen:
  39. # 1) Route lookup shows 10.1.1.100/24 belongs to tnl dev, fwd to tnl dev.
  40. # 2) Tnl device's egress BPF program is triggered and set the tunnel metadata,
  41. # with remote_ip=172.16.1.100 and others.
  42. # 3) Outer tunnel header is prepended and route the packet to veth1's egress
  43. # 4) veth0's ingress queue receive the tunneled packet at namespace at_ns0
  44. # 5) Tunnel protocol handler, ex: vxlan_rcv, decap the packet
  45. # 6) Forward the packet to the overlay tnl dev
  46. BPF_FILE="test_tunnel_kern.bpf.o"
  47. BPF_PIN_TUNNEL_DIR="/sys/fs/bpf/tc/tunnel"
  48. PING_ARG="-c 3 -w 10 -q"
  49. ret=0
  50. GREEN='\033[0;92m'
  51. RED='\033[0;31m'
  52. NC='\033[0m' # No Color
  53. config_device()
  54. {
  55. ip netns add at_ns0
  56. ip link add veth0 type veth peer name veth1
  57. ip link set veth0 netns at_ns0
  58. ip netns exec at_ns0 ip addr add 172.16.1.100/24 dev veth0
  59. ip netns exec at_ns0 ip link set dev veth0 up
  60. ip link set dev veth1 up mtu 1500
  61. ip addr add dev veth1 172.16.1.200/24
  62. }
  63. add_gre_tunnel()
  64. {
  65. tun_key=
  66. if [ -n "$1" ]; then
  67. tun_key="key $1"
  68. fi
  69. # at_ns0 namespace
  70. ip netns exec at_ns0 \
  71. ip link add dev $DEV_NS type $TYPE seq $tun_key \
  72. local 172.16.1.100 remote 172.16.1.200
  73. ip netns exec at_ns0 ip link set dev $DEV_NS up
  74. ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24
  75. # root namespace
  76. ip link add dev $DEV type $TYPE $tun_key external
  77. ip link set dev $DEV up
  78. ip addr add dev $DEV 10.1.1.200/24
  79. }
  80. add_ip6gretap_tunnel()
  81. {
  82. # assign ipv6 address
  83. ip netns exec at_ns0 ip addr add ::11/96 dev veth0
  84. ip netns exec at_ns0 ip link set dev veth0 up
  85. ip addr add dev veth1 ::22/96
  86. ip link set dev veth1 up
  87. # at_ns0 namespace
  88. ip netns exec at_ns0 \
  89. ip link add dev $DEV_NS type $TYPE seq flowlabel 0xbcdef key 2 \
  90. local ::11 remote ::22
  91. ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24
  92. ip netns exec at_ns0 ip addr add dev $DEV_NS fc80::100/96
  93. ip netns exec at_ns0 ip link set dev $DEV_NS up
  94. # root namespace
  95. ip link add dev $DEV type $TYPE external
  96. ip addr add dev $DEV 10.1.1.200/24
  97. ip addr add dev $DEV fc80::200/24
  98. ip link set dev $DEV up
  99. }
  100. add_erspan_tunnel()
  101. {
  102. # at_ns0 namespace
  103. if [ "$1" == "v1" ]; then
  104. ip netns exec at_ns0 \
  105. ip link add dev $DEV_NS type $TYPE seq key 2 \
  106. local 172.16.1.100 remote 172.16.1.200 \
  107. erspan_ver 1 erspan 123
  108. else
  109. ip netns exec at_ns0 \
  110. ip link add dev $DEV_NS type $TYPE seq key 2 \
  111. local 172.16.1.100 remote 172.16.1.200 \
  112. erspan_ver 2 erspan_dir egress erspan_hwid 3
  113. fi
  114. ip netns exec at_ns0 ip link set dev $DEV_NS up
  115. ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24
  116. # root namespace
  117. ip link add dev $DEV type $TYPE external
  118. ip link set dev $DEV up
  119. ip addr add dev $DEV 10.1.1.200/24
  120. }
  121. add_ip6erspan_tunnel()
  122. {
  123. # assign ipv6 address
  124. ip netns exec at_ns0 ip addr add ::11/96 dev veth0
  125. ip netns exec at_ns0 ip link set dev veth0 up
  126. ip addr add dev veth1 ::22/96
  127. ip link set dev veth1 up
  128. # at_ns0 namespace
  129. if [ "$1" == "v1" ]; then
  130. ip netns exec at_ns0 \
  131. ip link add dev $DEV_NS type $TYPE seq key 2 \
  132. local ::11 remote ::22 \
  133. erspan_ver 1 erspan 123
  134. else
  135. ip netns exec at_ns0 \
  136. ip link add dev $DEV_NS type $TYPE seq key 2 \
  137. local ::11 remote ::22 \
  138. erspan_ver 2 erspan_dir egress erspan_hwid 7
  139. fi
  140. ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24
  141. ip netns exec at_ns0 ip link set dev $DEV_NS up
  142. # root namespace
  143. ip link add dev $DEV type $TYPE external
  144. ip addr add dev $DEV 10.1.1.200/24
  145. ip link set dev $DEV up
  146. }
  147. add_geneve_tunnel()
  148. {
  149. # at_ns0 namespace
  150. ip netns exec at_ns0 \
  151. ip link add dev $DEV_NS type $TYPE \
  152. id 2 dstport 6081 remote 172.16.1.200
  153. ip netns exec at_ns0 ip link set dev $DEV_NS up
  154. ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24
  155. # root namespace
  156. ip link add dev $DEV type $TYPE dstport 6081 external
  157. ip link set dev $DEV up
  158. ip addr add dev $DEV 10.1.1.200/24
  159. }
  160. add_ip6geneve_tunnel()
  161. {
  162. ip netns exec at_ns0 ip addr add ::11/96 dev veth0
  163. ip netns exec at_ns0 ip link set dev veth0 up
  164. ip addr add dev veth1 ::22/96
  165. ip link set dev veth1 up
  166. # at_ns0 namespace
  167. ip netns exec at_ns0 \
  168. ip link add dev $DEV_NS type $TYPE id 22 \
  169. remote ::22 # geneve has no local option
  170. ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24
  171. ip netns exec at_ns0 ip link set dev $DEV_NS up
  172. # root namespace
  173. ip link add dev $DEV type $TYPE external
  174. ip addr add dev $DEV 10.1.1.200/24
  175. ip link set dev $DEV up
  176. }
  177. add_ipip_tunnel()
  178. {
  179. # at_ns0 namespace
  180. ip netns exec at_ns0 \
  181. ip link add dev $DEV_NS type $TYPE \
  182. local 172.16.1.100 remote 172.16.1.200
  183. ip netns exec at_ns0 ip link set dev $DEV_NS up
  184. ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24
  185. # root namespace
  186. ip link add dev $DEV type $TYPE external
  187. ip link set dev $DEV up
  188. ip addr add dev $DEV 10.1.1.200/24
  189. }
  190. add_ip6tnl_tunnel()
  191. {
  192. ip netns exec at_ns0 ip addr add ::11/96 dev veth0
  193. ip netns exec at_ns0 ip link set dev veth0 up
  194. ip addr add dev veth1 ::22/96
  195. ip link set dev veth1 up
  196. # at_ns0 namespace
  197. ip netns exec at_ns0 \
  198. ip link add dev $DEV_NS type $TYPE \
  199. local ::11 remote ::22
  200. ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24
  201. ip netns exec at_ns0 ip addr add dev $DEV_NS 1::11/96
  202. ip netns exec at_ns0 ip link set dev $DEV_NS up
  203. # root namespace
  204. ip link add dev $DEV type $TYPE external
  205. ip addr add dev $DEV 10.1.1.200/24
  206. ip addr add dev $DEV 1::22/96
  207. ip link set dev $DEV up
  208. }
  209. test_gre()
  210. {
  211. TYPE=gretap
  212. DEV_NS=gretap00
  213. DEV=gretap11
  214. ret=0
  215. check $TYPE
  216. config_device
  217. add_gre_tunnel 2
  218. attach_bpf $DEV gre_set_tunnel gre_get_tunnel
  219. ping $PING_ARG 10.1.1.100
  220. check_err $?
  221. ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
  222. check_err $?
  223. cleanup
  224. if [ $ret -ne 0 ]; then
  225. echo -e ${RED}"FAIL: $TYPE"${NC}
  226. return 1
  227. fi
  228. echo -e ${GREEN}"PASS: $TYPE"${NC}
  229. }
  230. test_gre_no_tunnel_key()
  231. {
  232. TYPE=gre
  233. DEV_NS=gre00
  234. DEV=gre11
  235. ret=0
  236. check $TYPE
  237. config_device
  238. add_gre_tunnel
  239. attach_bpf $DEV gre_set_tunnel_no_key gre_get_tunnel
  240. ping $PING_ARG 10.1.1.100
  241. check_err $?
  242. ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
  243. check_err $?
  244. cleanup
  245. if [ $ret -ne 0 ]; then
  246. echo -e ${RED}"FAIL: $TYPE"${NC}
  247. return 1
  248. fi
  249. echo -e ${GREEN}"PASS: $TYPE"${NC}
  250. }
  251. test_ip6gre()
  252. {
  253. TYPE=ip6gre
  254. DEV_NS=ip6gre00
  255. DEV=ip6gre11
  256. ret=0
  257. check $TYPE
  258. config_device
  259. # reuse the ip6gretap function
  260. add_ip6gretap_tunnel
  261. attach_bpf $DEV ip6gretap_set_tunnel ip6gretap_get_tunnel
  262. # underlay
  263. ping6 $PING_ARG ::11
  264. # overlay: ipv4 over ipv6
  265. ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
  266. ping $PING_ARG 10.1.1.100
  267. check_err $?
  268. # overlay: ipv6 over ipv6
  269. ip netns exec at_ns0 ping6 $PING_ARG fc80::200
  270. check_err $?
  271. cleanup
  272. if [ $ret -ne 0 ]; then
  273. echo -e ${RED}"FAIL: $TYPE"${NC}
  274. return 1
  275. fi
  276. echo -e ${GREEN}"PASS: $TYPE"${NC}
  277. }
  278. test_ip6gretap()
  279. {
  280. TYPE=ip6gretap
  281. DEV_NS=ip6gretap00
  282. DEV=ip6gretap11
  283. ret=0
  284. check $TYPE
  285. config_device
  286. add_ip6gretap_tunnel
  287. attach_bpf $DEV ip6gretap_set_tunnel ip6gretap_get_tunnel
  288. # underlay
  289. ping6 $PING_ARG ::11
  290. # overlay: ipv4 over ipv6
  291. ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
  292. ping $PING_ARG 10.1.1.100
  293. check_err $?
  294. # overlay: ipv6 over ipv6
  295. ip netns exec at_ns0 ping6 $PING_ARG fc80::200
  296. check_err $?
  297. cleanup
  298. if [ $ret -ne 0 ]; then
  299. echo -e ${RED}"FAIL: $TYPE"${NC}
  300. return 1
  301. fi
  302. echo -e ${GREEN}"PASS: $TYPE"${NC}
  303. }
  304. test_erspan()
  305. {
  306. TYPE=erspan
  307. DEV_NS=erspan00
  308. DEV=erspan11
  309. ret=0
  310. check $TYPE
  311. config_device
  312. add_erspan_tunnel $1
  313. attach_bpf $DEV erspan_set_tunnel erspan_get_tunnel
  314. ping $PING_ARG 10.1.1.100
  315. check_err $?
  316. ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
  317. check_err $?
  318. cleanup
  319. if [ $ret -ne 0 ]; then
  320. echo -e ${RED}"FAIL: $TYPE"${NC}
  321. return 1
  322. fi
  323. echo -e ${GREEN}"PASS: $TYPE"${NC}
  324. }
  325. test_ip6erspan()
  326. {
  327. TYPE=ip6erspan
  328. DEV_NS=ip6erspan00
  329. DEV=ip6erspan11
  330. ret=0
  331. check $TYPE
  332. config_device
  333. add_ip6erspan_tunnel $1
  334. attach_bpf $DEV ip4ip6erspan_set_tunnel ip4ip6erspan_get_tunnel
  335. ping6 $PING_ARG ::11
  336. ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
  337. check_err $?
  338. cleanup
  339. if [ $ret -ne 0 ]; then
  340. echo -e ${RED}"FAIL: $TYPE"${NC}
  341. return 1
  342. fi
  343. echo -e ${GREEN}"PASS: $TYPE"${NC}
  344. }
  345. test_geneve()
  346. {
  347. TYPE=geneve
  348. DEV_NS=geneve00
  349. DEV=geneve11
  350. ret=0
  351. check $TYPE
  352. config_device
  353. add_geneve_tunnel
  354. attach_bpf $DEV geneve_set_tunnel geneve_get_tunnel
  355. ping $PING_ARG 10.1.1.100
  356. check_err $?
  357. ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
  358. check_err $?
  359. cleanup
  360. if [ $ret -ne 0 ]; then
  361. echo -e ${RED}"FAIL: $TYPE"${NC}
  362. return 1
  363. fi
  364. echo -e ${GREEN}"PASS: $TYPE"${NC}
  365. }
  366. test_ip6geneve()
  367. {
  368. TYPE=geneve
  369. DEV_NS=ip6geneve00
  370. DEV=ip6geneve11
  371. ret=0
  372. check $TYPE
  373. config_device
  374. add_ip6geneve_tunnel
  375. attach_bpf $DEV ip6geneve_set_tunnel ip6geneve_get_tunnel
  376. ping $PING_ARG 10.1.1.100
  377. check_err $?
  378. ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
  379. check_err $?
  380. cleanup
  381. if [ $ret -ne 0 ]; then
  382. echo -e ${RED}"FAIL: ip6$TYPE"${NC}
  383. return 1
  384. fi
  385. echo -e ${GREEN}"PASS: ip6$TYPE"${NC}
  386. }
  387. test_ipip()
  388. {
  389. TYPE=ipip
  390. DEV_NS=ipip00
  391. DEV=ipip11
  392. ret=0
  393. check $TYPE
  394. config_device
  395. add_ipip_tunnel
  396. ip link set dev veth1 mtu 1500
  397. attach_bpf $DEV ipip_set_tunnel ipip_get_tunnel
  398. ping $PING_ARG 10.1.1.100
  399. check_err $?
  400. ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
  401. check_err $?
  402. cleanup
  403. if [ $ret -ne 0 ]; then
  404. echo -e ${RED}"FAIL: $TYPE"${NC}
  405. return 1
  406. fi
  407. echo -e ${GREEN}"PASS: $TYPE"${NC}
  408. }
  409. test_ipip6()
  410. {
  411. TYPE=ip6tnl
  412. DEV_NS=ipip6tnl00
  413. DEV=ipip6tnl11
  414. ret=0
  415. check $TYPE
  416. config_device
  417. add_ip6tnl_tunnel
  418. ip link set dev veth1 mtu 1500
  419. attach_bpf $DEV ipip6_set_tunnel ipip6_get_tunnel
  420. # underlay
  421. ping6 $PING_ARG ::11
  422. # ip4 over ip6
  423. ping $PING_ARG 10.1.1.100
  424. check_err $?
  425. ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
  426. check_err $?
  427. cleanup
  428. if [ $ret -ne 0 ]; then
  429. echo -e ${RED}"FAIL: $TYPE"${NC}
  430. return 1
  431. fi
  432. echo -e ${GREEN}"PASS: $TYPE"${NC}
  433. }
  434. test_ip6ip6()
  435. {
  436. TYPE=ip6tnl
  437. DEV_NS=ip6ip6tnl00
  438. DEV=ip6ip6tnl11
  439. ret=0
  440. check $TYPE
  441. config_device
  442. add_ip6tnl_tunnel
  443. ip link set dev veth1 mtu 1500
  444. attach_bpf $DEV ip6ip6_set_tunnel ip6ip6_get_tunnel
  445. # underlay
  446. ping6 $PING_ARG ::11
  447. # ip6 over ip6
  448. ping6 $PING_ARG 1::11
  449. check_err $?
  450. ip netns exec at_ns0 ping6 $PING_ARG 1::22
  451. check_err $?
  452. cleanup
  453. if [ $ret -ne 0 ]; then
  454. echo -e ${RED}"FAIL: ip6$TYPE"${NC}
  455. return 1
  456. fi
  457. echo -e ${GREEN}"PASS: ip6$TYPE"${NC}
  458. }
  459. attach_bpf()
  460. {
  461. DEV=$1
  462. SET=$2
  463. GET=$3
  464. mkdir -p ${BPF_PIN_TUNNEL_DIR}
  465. bpftool prog loadall ${BPF_FILE} ${BPF_PIN_TUNNEL_DIR}/
  466. tc qdisc add dev $DEV clsact
  467. tc filter add dev $DEV egress bpf da object-pinned ${BPF_PIN_TUNNEL_DIR}/$SET
  468. tc filter add dev $DEV ingress bpf da object-pinned ${BPF_PIN_TUNNEL_DIR}/$GET
  469. }
  470. cleanup()
  471. {
  472. rm -rf ${BPF_PIN_TUNNEL_DIR}
  473. ip netns delete at_ns0 2> /dev/null
  474. ip link del veth1 2> /dev/null
  475. ip link del ipip11 2> /dev/null
  476. ip link del ipip6tnl11 2> /dev/null
  477. ip link del ip6ip6tnl11 2> /dev/null
  478. ip link del gretap11 2> /dev/null
  479. ip link del gre11 2> /dev/null
  480. ip link del ip6gre11 2> /dev/null
  481. ip link del ip6gretap11 2> /dev/null
  482. ip link del geneve11 2> /dev/null
  483. ip link del ip6geneve11 2> /dev/null
  484. ip link del erspan11 2> /dev/null
  485. ip link del ip6erspan11 2> /dev/null
  486. }
  487. cleanup_exit()
  488. {
  489. echo "CATCH SIGKILL or SIGINT, cleanup and exit"
  490. cleanup
  491. exit 0
  492. }
  493. check()
  494. {
  495. ip link help 2>&1 | grep -q "\s$1\s"
  496. if [ $? -ne 0 ];then
  497. echo "SKIP $1: iproute2 not support"
  498. cleanup
  499. return 1
  500. fi
  501. }
  502. enable_debug()
  503. {
  504. echo 'file ip_gre.c +p' > /sys/kernel/debug/dynamic_debug/control
  505. echo 'file ip6_gre.c +p' > /sys/kernel/debug/dynamic_debug/control
  506. echo 'file geneve.c +p' > /sys/kernel/debug/dynamic_debug/control
  507. echo 'file ipip.c +p' > /sys/kernel/debug/dynamic_debug/control
  508. }
  509. check_err()
  510. {
  511. if [ $ret -eq 0 ]; then
  512. ret=$1
  513. fi
  514. }
  515. bpf_tunnel_test()
  516. {
  517. local errors=0
  518. echo "Testing GRE tunnel..."
  519. test_gre
  520. errors=$(( $errors + $? ))
  521. echo "Testing GRE tunnel (without tunnel keys)..."
  522. test_gre_no_tunnel_key
  523. errors=$(( $errors + $? ))
  524. echo "Testing IP6GRE tunnel..."
  525. test_ip6gre
  526. errors=$(( $errors + $? ))
  527. echo "Testing IP6GRETAP tunnel..."
  528. test_ip6gretap
  529. errors=$(( $errors + $? ))
  530. echo "Testing ERSPAN tunnel..."
  531. test_erspan v2
  532. errors=$(( $errors + $? ))
  533. echo "Testing IP6ERSPAN tunnel..."
  534. test_ip6erspan v2
  535. errors=$(( $errors + $? ))
  536. echo "Testing GENEVE tunnel..."
  537. test_geneve
  538. errors=$(( $errors + $? ))
  539. echo "Testing IP6GENEVE tunnel..."
  540. test_ip6geneve
  541. errors=$(( $errors + $? ))
  542. echo "Testing IPIP tunnel..."
  543. test_ipip
  544. errors=$(( $errors + $? ))
  545. echo "Testing IPIP6 tunnel..."
  546. test_ipip6
  547. errors=$(( $errors + $? ))
  548. echo "Testing IP6IP6 tunnel..."
  549. test_ip6ip6
  550. errors=$(( $errors + $? ))
  551. return $errors
  552. }
  553. trap cleanup 0 3 6
  554. trap cleanup_exit 2 9
  555. cleanup
  556. bpf_tunnel_test
  557. if [ $? -ne 0 ]; then
  558. echo -e "$(basename $0): ${RED}FAIL${NC}"
  559. exit 1
  560. fi
  561. echo -e "$(basename $0): ${GREEN}PASS${NC}"
  562. exit 0