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 2024 Oxide Computer Company
14#
15
16# This tests the behaviour of in.ndpd in conjunction with the creation and
17# deletion of IPv6 link local addresses in various combinations. It does this
18# using a VNIC on a simnet created just for the purpose. No special system
19# configuration is required, but the tests will restart the running in.ndpd
20# several times.
21
22SIMNET=ndpt_simnet0
23IF=ndpt_vnic0
24
25typeset -i comms=1
26typeset -i failures=0
27typeset -i zid=0
28
29function fatal {
30	print "$*" >&2
31	exit 1
32}
33
34function cleanup {
35	{
36		dladm delete-vnic $IF
37		dladm delete-simnet $SIMNET
38	} >/dev/null 2>&1
39}
40
41trap cleanup EXIT
42
43function init {
44	zid=$(zoneadm list -p | awk -F: -vz=`zonename` '$2 == z { print $1 }')
45	[[ -n "$zid" ]] || fatal "Cannot determine zone ID"
46	print "+ zone ID $zid"
47	print "+ creating simnet $SIMNET"
48	dladm create-simnet "$SIMNET" || \
49	    fatal "Could not create simnet $SIMNET"
50	print "+ creating VNIC $IF"
51	dladm create-vnic -l $SIMNET "$IF" || \
52	    fatal "Could not create vnic $IF"
53}
54
55function ndpid {
56	pgrep -x -z$zid in.ndpd || fatal "Could not find in.ndpd process"
57}
58
59function start {
60	print
61	print "************** $*"
62	print
63}
64
65function clean {
66	/usr/sbin/ipadm delete-if "$IF" 1>/dev/null 2>&1
67	restart_ndp
68
69	ifconfig "$IF" inet6 1>/dev/null 2>&1 && \
70	    fatal "$IF IPv6 interface exists"
71	mdb -p `ndpid` -e \
72	    'phyints::list struct phyint pi_next|::print struct phyint pi_name'\
73	    | egrep -s "$IF" && fatal "$IF exists in ndpd state after restart"
74
75	# Check that in.ndpd is running
76	ndpid >/dev/null
77}
78
79function ndpdump {
80	typeset cmd=
81	cmd+='phyints::list struct phyint pi_next '
82	cmd+='| ::print struct phyint '
83	cmd+='pi_name pi_ifaddr pi_autoconf pi_ipadm_aobjname'
84	mdb -e "$cmd" -p `ndpid` | sed -n "
85		/pi_name.*$IF/,/aobjname/ {
86			/name = /s/, '\\0'.*/.../
87			s/^/    /
88			p
89		}
90	"
91}
92
93function ndpac {
94	typeset cmd=
95	cmd+='phyints::list struct phyint pi_next '
96	cmd+='| ::printf "%s %s\n" struct phyint pi_name pi_autoconf'
97	mdb -p `ndpid` -e "$cmd" | awk "/$IF/ {print \$NF}"
98}
99
100function check_ac {
101	((comms)) || return
102
103	typeset ac=`ndpac`
104
105	[[ "$ac" == "$1" ]] && return
106	[[ -z "$ac" ]] && ac="<entry missing>"
107	print "FAIL: Expected autoconf $1, got $ac"
108	ndpdump >&2
109	((failures++))
110}
111
112function ipadm {
113	print "+ ipadm $*"
114	if ! /sbin/ipadm $*; then
115		print "FAIL: ipadm command unexpectedly failed"
116		((failures++))
117	fi
118}
119
120function restart_ndp {
121	disable_ndp
122	enable_ndp
123}
124
125function disable_ndp {
126	comms=0
127	svcadm disable -s ndp
128}
129
130function enable_ndp {
131	comms=1
132	svcadm enable -s ndp
133}
134
135function create_if {
136	ipadm create-if $IF
137	check_ac B_FALSE
138}
139
140function delete_if {
141	ipadm delete-if $IF
142	check_ac B_TRUE
143}
144
145function create_addr {
146	ipadm create-addr -T addrconf $IF/ll
147	check_ac B_TRUE
148}
149
150function delete_addr {
151	ipadm delete-addr $IF/ll
152	check_ac B_FALSE
153}
154
155init
156
157start "create-if, delete-if, repeat"
158clean
159for _ in {0..3}; do
160	create_if
161	delete_if
162done
163
164start "create/delete-addr with plumbed interface"
165clean
166create_if
167create_addr
168delete_addr
169delete_if
170
171start "create/delete_addr without plumbed interface"
172clean
173create_addr
174delete_addr
175delete_if
176
177start "create_addr, delete-addr, repeat"
178clean
179for _ in {0..3}; do
180	create_addr
181	delete_addr
182done
183
184start "create_addr, delete-if, create-if, create-addr"
185clean
186create_addr
187delete_if
188create_if
189create_addr
190
191start "run without ndp"
192clean
193disable_ndp
194create_addr
195delete_addr
196delete_if
197
198start "start without ndp, enable after create-if"
199clean
200disable_ndp
201create_if
202enable_ndp
203create_addr
204delete_addr
205delete_if
206enable_ndp
207
208start "start without ndp, enable after create-addr"
209clean
210disable_ndp
211create_if
212create_addr
213enable_ndp
214delete_addr
215delete_if
216
217start "start without ndp, enable after delete-addr"
218clean
219disable_ndp
220create_addr
221delete_addr
222enable_ndp
223delete_if
224
225start "restart ndp after create-if"
226clean
227create_if
228restart_ndp
229create_addr
230delete_addr
231delete_if
232
233start "restart ndp after create-addr"
234clean
235create_if
236create_addr
237restart_ndp
238delete_addr
239delete_if
240
241print
242if ((FAILURES)); then
243	print "$FAILURES failure(s) detected"
244	exit 1
245fi
246print "All tests passed"
247exit 0
248