1#!/usr/bin/ksh
2#
3# This file and its contents are supplied under the terms of the
4# Common Development and Distribution License ("CDDL"), version 1.0.
5# You may only use this file in accordance with the terms of version
6# 1.0 of the CDDL.
7#
8# A full copy of the text of the CDDL should have accompanied this
9# source.  A copy of the CDDL is also available via the Internet at
10# http://www.illumos.org/license/CDDL.
11
12#
13# Copyright 2019 Joyent, Inc.
14# Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
15#
16
17#
18# Functions shared across the network tests.
19#
20
21DEBUG=0
22
23function dbg
24{
25	typeset msg="$*"
26	if (($DEBUG == 1)); then
27		echo "DBG [$nt_tname]: $msg"
28	fi
29}
30
31function fail
32{
33	typeset msg="$*"
34	echo "FAIL [$nt_tname]: $msg" >&2
35	exit 1
36}
37
38function maybe_fail
39{
40	typeset msg=$1
41
42	if ((BAIL == 1)); then
43		fail "$msg"
44	else
45		dbg "$msg"
46		return 1
47	fi
48}
49
50function zone_exists
51{
52	typeset name=$1
53
54	if (($# != 1)); then
55		fail "$0: incorrect number of args provided"
56	fi
57
58	dbg "checking for existence of zone: $name"
59	if zoneadm -z $name list > /dev/null 2>&1; then
60		dbg "found zone: $name"
61		return 0
62	else
63		dbg "zone not found: $name"
64		return 1
65	fi
66}
67
68function zone_running
69{
70	typeset name=$1
71	typeset state=$(zoneadm -z $name list -p | awk -F: '{ print $3 }')
72	typeset err="zone $name is not running"
73
74	if (($# != 1)); then
75		fail "$0: incorrect number of args provided"
76	fi
77
78	dbg "check if zone $name is running"
79	dbg "state of zone $name: $state"
80	if [[ "$state" == "running" ]]; then
81		dbg "zone $name is running"
82		return 0
83	fi
84
85	maybe_fail "$err"
86}
87
88function simnet_exists
89{
90	typeset name=$1
91
92	if (($# != 1)); then
93		fail "$0: incorrect number of args provided"
94	fi
95
96	if dladm show-simnet $name > /dev/null 2>&1; then
97		dbg "simnet $name found"
98		return 0
99	else
100		dbg "simnet $name not found"
101		return 1
102	fi
103}
104
105function create_simnet
106{
107	typeset name=$1
108	typeset err="failed to create simnet $name"
109
110	if (($# != 1)); then
111		fail "$0: incorrect number of args provided"
112	fi
113
114	dbg "creating simnet $name"
115	if simnet_exists $name; then
116		dbg "simnet $name already exists"
117		maybe_fail "$err"
118		return 1
119	fi
120
121	if dladm create-simnet > /dev/null $name; then
122		dbg "created simnet $name"
123		return 0
124	fi
125
126	maybe_fail "$err"
127}
128
129function delete_simnet
130{
131	typeset name=$1
132	typeset err="failed to delete simnet $name"
133
134	if (($# != 1)); then
135		fail "$0: incorrect number of args provided"
136	fi
137
138	dbg "deleting simnet $name"
139	if ! simnet_exists $name; then
140		dbg "simnet $name doesn't exist"
141		return 1
142	fi
143
144	if dladm delete-simnet $name; then
145		dbg "simnet $name deleted"
146		return 0
147	fi
148
149	maybe_fail "$err"
150}
151
152function link_simnets
153{
154	typeset sim1=$1
155	typeset sim2=$2
156	typeset err="failed to link simnet $sim1 to $sim2"
157
158	if (($# != 2)); then
159		fail "$0: incorrect number of args provided"
160	fi
161
162	dbg "linking simnet $sim1 to $sim2"
163	if dladm modify-simnet -p $sim2 $sim1 > /dev/null; then
164		dbg "linked simnet $sim1 to $sim2"
165		return 0
166	fi
167
168	maybe_fail "$err"
169}
170
171function vnic_exists
172{
173	typeset name=$1
174	typeset vid=$2
175	typeset over=$3
176	typeset zone=$4
177
178	if (($# != 4)); then
179		fail "$0: incorrect number of args provided"
180	fi
181
182	if dladm show-vnic $name > /dev/null 2>&1; then
183		typeset avid=$(dladm show-vnic -p -o vid $name)
184		typeset aover=$(dladm show-vnic -p -o over $name)
185		typeset azone=$(dladm show-linkprop -cp zone -o value $name)
186		if (($avid == $vid)) && [ $aover == $over ] && \
187			   [ $azone == $zone ]
188		then
189			return 0
190		else
191			return 1
192		fi
193	else
194		return 1
195	fi
196}
197
198function create_vnic
199{
200	typeset name=$1
201	typeset over=$2
202	typeset vid=$3
203	typeset zone=$4
204	typeset r=1
205	typeset vid_opt=""
206	typeset vnic_info="$name, vid: $vid, over: $over, zone: $zone"
207	typeset err="failed to create VNIC: $vnic_info"
208
209	if (($# != 4)); then
210		fail "$0: incorrect number of args provided"
211	fi
212
213	if ((vid != 0)); then
214		vid_opt="-v $vid"
215	fi
216
217	dbg "creating VNIC: $vnic_info"
218	if dladm create-vnic -l $over $vid_opt $name > /dev/null 2>&1 && \
219	    dladm set-linkprop -t -p zone=$zone $name > /dev/null 2>&1
220	then
221		dbg "created VNIC: $vnic_info"
222		return 0
223	fi
224
225	maybe_fail "$err"
226}
227
228function delete_vnic
229{
230	typeset name=$1
231	typeset vid=$2
232	typeset zone=$3
233	typeset vnic_info="$name, vid: $vid, zone: $zone"
234	typeset err1="failed to assign VNIC $name from $zone to GZ"
235	typeset err2="failed to delete VNIC: $vnic_info"
236
237	if (($# != 3)); then
238		fail "$0: incorrect number of args provided"
239	fi
240
241	dbg "assigning VNIC $name from $zone to GZ"
242	if ! dladm set-linkprop -t -p zone=global $name; then
243		maybe_fail "$err1"
244		return 1
245	fi
246
247	dbg "deleting VNIC: $vnic_info"
248	if dladm delete-vnic $name > /dev/null; then
249		dbg "deleted VNIC: $vnic_info"
250		return 0
251	fi
252
253	maybe_fail "$err2"
254}
255
256function create_addr
257{
258	typeset zone=$1
259	typeset vnic=$2
260	typeset ip=$3
261	typeset ipname=${vnic}/v4
262
263	if (($# != 3)); then
264		fail "$0: incorrect number of args provided"
265	fi
266
267	if zlogin $zone ipadm create-addr -t -T static -a $ip \
268		  $ipname > /dev/null
269	then
270		dbg "created addr $ipname ($ip) in zone $zone"
271		return 0
272	fi
273
274	maybe_fail "failed to create addr $ipname ($ip) in zone $zone"
275}
276
277function create_addr6
278{
279	typeset zone=$1
280	typeset vnic=$2
281	typeset ip=$3
282	typeset ll_name=${vnic}/v6
283	typeset uni_name=${vnic}/v6add
284	typeset err1="failed to create link-local addr $ll_name in zone $zone"
285	typeset err2="failed to create unicast addr $uni_name in zone $zone"
286
287	if (($# != 3)); then
288		fail "$0: incorrect number of args provided"
289	fi
290
291	if zlogin $zone ipadm create-addr -t -T addrconf $ll_name; then
292		dbg "created link-local addr $ll_name in zone $zone"
293	else
294		maybe_fail "$err1"
295		return 1
296	fi
297
298	if zlogin $zone ipadm create-addr -t -T static -a $ip/64 $uni_name; then
299		dbg "created unicast addr $uni_name in zone $zone"
300	else
301		maybe_fail "$err2"
302	fi
303}
304
305function delete_addr
306{
307	typeset zone=$1
308	typeset ifname=$2
309	typeset version=$3
310	typeset ipname=$ifname/$version
311
312	if (($# != 3)); then
313		fail "$0: incorrect number of args provided"
314	fi
315
316	if zlogin $zone ipadm show-addr $ipname > /dev/null 2>&1; then
317		if zlogin $zone ipadm delete-addr $ipname > /dev/null; then
318			dbg "deleted addr $ipname in zone $zone"
319		else
320			maybe_fail "failed to delete addr $ipname in zone $zone"
321			return 1
322		fi
323	else
324		dbg "addr $ipname doesn't exist in zone $zone"
325	fi
326
327	if [[ "v6" == "$version" ]]; then
328		typeset ipname=$ifname/v6add
329		typeset err="failed to delete addr $ipname in zone $zone"
330
331		if zlogin $zone ipadm show-addr $ipname > /dev/null 2>&1; then
332			if zlogin $zone ipadm delete-addr $ipname > /dev/null
333			then
334				dbg "deleted addr $ipname in zone $zone"
335			else
336				maybe_fail "$err"
337			fi
338		else
339			dbg "addr $ipname doesn't exist in zone $zone"
340		fi
341	fi
342}
343
344function delete_if
345{
346	typeset zone=$1
347	typeset ifname=$2
348	typeset err="failed to delete interface $ifname in zone $zone"
349
350	if (($# != 2)); then
351		fail "$0: incorrect number of args provided"
352	fi
353
354	if zlogin $zone ipadm show-if $ifname > /dev/null 2>&1; then
355		if zlogin $zone ipadm delete-if $ifname > /dev/null; then
356			dbg "deleted interface $ifname in zone $zone"
357		else
358			maybe_fail "$err"
359		fi
360	else
361		dbg "interface $ifname doesn't exist in zone $zone"
362	fi
363}
364
365function ip_fwd_enable
366{
367	typeset zone=$1
368
369	if (($# != 1)); then
370		fail "$0: incorrect number of args provided"
371	fi
372
373	if zlogin $zone routeadm -p ipv4-forwarding | \
374			egrep 'current=enabled' > /dev/null
375	then
376		dbg "IPv4 forwarding already enabled for $zone"
377	else
378		if zlogin $zone routeadm -ue ipv4-forwarding; then
379			dbg "enabled IPv4 forwarding for $zone"
380		else
381			maybe_fail "failed to enable IPv4 forwarding for $zone"
382			return 1
383		fi
384	fi
385
386	if zlogin $zone routeadm -p ipv6-forwarding | \
387			egrep 'current=enabled' > /dev/null
388	then
389		dbg "IPv6 forwarding already enabled for $zone"
390	else
391		if zlogin $zone routeadm -ue ipv6-forwarding; then
392			dbg "enabled IPv6 forwarding for $zone"
393		else
394			maybe_fail "failed to enable IPv6 forwarding for $zone"
395		fi
396	fi
397}
398
399function ip_fwd_disable
400{
401	typeset zone=$1
402
403	if (($# != 1)); then
404		fail "$0: incorrect number of args provided"
405	fi
406
407	if zlogin $zone routeadm -p ipv4-forwarding | \
408			egrep 'current=disabled' > /dev/null
409	then
410		dbg "IPv4 forwarding already disabled for $zone"
411	else
412		if zlogin $zone routeadm -ud ipv4-forwarding; then
413			dbg "disabled IPv4 forwarding in $zone"
414		else
415			maybe_fail "failed to disable IPv4 forwarding in $zone"
416			return 1
417		fi
418	fi
419
420	if zlogin $zone routeadm -p ipv6-forwarding | \
421			egrep 'current=disabled' > /dev/null
422	then
423		dbg "IPv6 forwarding already disabled for $zone"
424	else
425		if zlogin $zone routeadm -ud ipv6-forwarding; then
426			dbg "disabled IPv6 forwarding in $zone"
427		else
428			maybe_fail "failed to disable IPv6 forwarding in $zone"
429		fi
430	fi
431}
432
433function add_route
434{
435	typeset zone=$1
436	typeset dest=$2
437	typeset net=$3
438	typeset gateway=$4
439
440	if (($# != 4)); then
441		fail "$0: incorrect number of args provided"
442	fi
443
444	if zlogin $zone route -n add $net $gateway > /dev/null; then
445		dbg "added route $gateway => $net to $zone"
446		return 0
447	fi
448
449	maybe_fail "failed to add route $gateway => $net to $zone"
450}
451
452function add_route6
453{
454	typeset zone=$1
455	typeset dest=$2
456	typeset net=$3
457	typeset gateway=$4
458
459	if (($# != 4)); then
460		fail "$0: incorrect number of args provided"
461	fi
462
463	if zlogin $zone route -n add -inet6 $net $gateway > /dev/null
464	then
465		dbg "added route $gateway => $net to $zone"
466		return 0
467	fi
468
469	maybe_fail "failed to add route $gateway => $net to $zone"
470}
471
472function rm_route
473{
474	typeset zone=$1
475	typeset dest=$2
476	typeset net=$3
477	typeset gateway=$4
478	typeset gw=$(zlogin $zone route -n get $dest | \
479			     grep gateway | awk '{ print $2 }')
480	typeset err="failed to remove route $gateway => $net from $zone"
481
482	if (($# != 4)); then
483		fail "$0: incorrect number of args provided"
484	fi
485
486	if [[ "$gw" == "$gateway" ]]; then
487		if zlogin $zone route -n delete $net $gateway > /dev/null
488		then
489			dbg "removed route $gateway => $net from $zone"
490		else
491			maybe_fail "$err"
492		fi
493	else
494		dbg "$zone already lacked route $gateway => $net"
495	fi
496}
497
498function rm_route6
499{
500	typeset zone=$1
501	typeset dest=$2
502	typeset net=$3
503	typeset gateway=$4
504	typeset gw=$(zlogin $zone route -n get -inet6 $dest | \
505			     grep gateway | awk '{ print $2 }')
506	typeset err="failed to remove route $gateway => $net from $zone"
507
508	if (($# != 4)); then
509		fail "$0: incorrect number of args provided"
510	fi
511
512	if [[ "$gw" == "$gateway" ]]; then
513		if zlogin $zone route -n delete -inet6 $net $gateway > /dev/null
514		then
515			dbg "removed route $gateway => $net from $zone"
516		else
517			maybe_fail "$err"
518		fi
519	else
520		dbg "$zone already lacked route $gateway => $net"
521	fi
522}
523
524function set_linkprop
525{
526	typeset link=$1
527	typeset prop=$2
528	typeset val=$3
529	typeset err="failed to set $link prop: $prop=$val"
530
531	if (($# != 3)); then
532		fail "$0: incorrect number of args provided"
533	fi
534
535	dbg "attempt to set $link prop: $prop=$val"
536	if dladm set-linkprop -p $prop=$val $link; then
537		dbg "set $link prop: $prop=$val"
538		return 0
539	fi
540
541	maybe_fail "$err"
542}
543
544function ping
545{
546	typeset zone=$1
547	typeset src=$2
548	typeset dst=$3
549	typeset info="$src -> $dst"
550
551	if (($# != 3)); then
552		fail "$0: incorrect number of args provided"
553	fi
554
555	dbg "ping: $info"
556	if zlogin $zone ping $dst > /dev/null 2>&1; then
557		dbg "successful ping: $info"
558		return 0
559	fi
560
561	maybe_fail "could not ping: $info"
562}
563
564function ping_udp
565{
566	typeset client=$1
567	typeset client_ip=$2
568	typeset server_ip=$3
569	typeset size=$4
570	typeset num=$5
571	typeset info="$client_ip -> $server_ip (size: $size)"
572
573	if (($# != 5)); then
574		fail "$0: incorrect number of args provided"
575	fi
576
577	dbg "UDP ping: $info"
578	if zlogin $client ping -ns -U $server_ip $size $num > /dev/null; then
579		dbg "UDP ping passed: $info"
580		return 0
581	fi
582
583	maybe_fail "UDP ping failed: $info"
584}
585
586function start_server
587{
588	typeset zone=$1
589	typeset type=$2
590	typeset ip=$3
591	typeset port=$4
592	typeset ofile=$5
593
594	if (($# != 5)); then
595		fail "$0: incorrect number of args provided"
596	fi
597
598	dbg "start server $rfile"
599	zlogin $zone \
600	       /usr/bin/socat -u ${type}-LISTEN:$port,bind=[$ip],reuseaddr \
601	       CREATE:$ofile &
602	listener_ppid=$!
603	dbg "listener PPID: $listener_ppid, zone $zone"
604}
605
606function wait_for_pid
607{
608	typeset pid=$1
609	typeset seconds=$2
610	typeset s=0
611
612	if (($# != 2)); then
613		fail "$0: incorrect number of args provided"
614	fi
615
616	while true; do
617		if kill -0 $pid > /dev/null 2>&1; then
618			if ((seconds == s)); then
619				maybe_fail "timed out waiting for pid $pid"
620				return 1
621			fi
622			dbg "waiting for pid $pid"
623			sleep 1
624			((s++))
625		else
626			return 0
627		fi
628	done
629}
630