t_ndp.sh revision 1.11 1 # $NetBSD: t_ndp.sh,v 1.11 2016/05/20 06:48:52 ozaki-r Exp $
2 #
3 # Copyright (c) 2015 The NetBSD Foundation, Inc.
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 # 1. Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 #
15 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 # POSSIBILITY OF SUCH DAMAGE.
26 #
27
28 inetserver="rump_server -lrumpnet -lrumpnet_net -lrumpnet_netinet"
29 inetserver="$inetserver -lrumpnet_netinet6 -lrumpnet_shmif"
30 HIJACKING="env LD_PRELOAD=/usr/lib/librumphijack.so RUMPHIJACK=sysctl=yes"
31
32 SOCKSRC=unix://commsock1
33 SOCKDST=unix://commsock2
34 IP6SRC=fc00::1
35 IP6DST=fc00::2
36
37 DEBUG=true
38 TIMEOUT=1
39
40 atf_test_case cache_expiration cleanup
41 atf_test_case command cleanup
42 atf_test_case cache_overwriting cleanup
43 atf_test_case neighborgcthresh cleanup
44 atf_test_case link_activation cleanup
45
46 cache_expiration_head()
47 {
48 atf_set "descr" "Tests for NDP cache expiration"
49 atf_set "require.progs" "rump_server"
50 }
51
52 command_head()
53 {
54 atf_set "descr" "Tests for commands of ndp(8)"
55 atf_set "require.progs" "rump_server"
56 }
57
58 cache_overwriting_head()
59 {
60 atf_set "descr" "Tests for behavior of overwriting NDP caches"
61 atf_set "require.progs" "rump_server"
62 }
63
64 neighborgcthresh_head()
65 {
66 atf_set "descr" "Tests for GC of neighbor caches"
67 atf_set "require.progs" "rump_server"
68 }
69
70 link_activation_head()
71 {
72 atf_set "descr" "Tests for activating a new MAC address"
73 atf_set "require.progs" "rump_server"
74 }
75
76 setup_dst_server()
77 {
78 local assign_ip=$1
79
80 export RUMP_SERVER=$SOCKDST
81 atf_check -s exit:0 rump.ifconfig shmif0 create
82 atf_check -s exit:0 rump.ifconfig shmif0 linkstr bus1
83 if [ "$assign_ip" != no ]; then
84 atf_check -s exit:0 rump.ifconfig shmif0 inet6 $IP6DST
85 fi
86 atf_check -s exit:0 rump.ifconfig shmif0 up
87 atf_check -s exit:0 rump.ifconfig -w 10
88
89 $DEBUG && rump.ifconfig shmif0
90 $DEBUG && rump.ndp -n -a
91 }
92
93 setup_src_server()
94 {
95 $DEBUG && ulimit -c unlimited
96 export RUMP_SERVER=$SOCKSRC
97
98 # Setup an interface
99 atf_check -s exit:0 rump.ifconfig shmif0 create
100 atf_check -s exit:0 rump.ifconfig shmif0 linkstr bus1
101 atf_check -s exit:0 rump.ifconfig shmif0 inet6 $IP6SRC
102 atf_check -s exit:0 rump.ifconfig shmif0 up
103 atf_check -s exit:0 rump.ifconfig -w 10
104
105 # Sanity check
106 $DEBUG && rump.ifconfig shmif0
107 $DEBUG && rump.ndp -n -a
108 atf_check -s exit:0 -o ignore rump.ndp -n $IP6SRC
109 atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n $IP6DST
110 }
111
112 get_timeout()
113 {
114 local timeout=$(env RUMP_SERVER=$SOCKSRC rump.ndp -n $IP6DST |grep $IP6DST|awk '{print $4;}')
115 timeout=${timeout%s}
116 echo $timeout
117 }
118
119 cache_expiration_body()
120 {
121 atf_check -s exit:0 ${inetserver} $SOCKSRC
122 atf_check -s exit:0 ${inetserver} $SOCKDST
123
124 setup_dst_server
125 setup_src_server
126
127 #
128 # Check if a cache is expired expectedly
129 #
130 export RUMP_SERVER=$SOCKSRC
131 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST
132
133 $DEBUG && rump.ndp -n -a
134 atf_check -s exit:0 -o match:'permanent' rump.ndp -n $IP6SRC
135 # Should be cached
136 atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n $IP6DST
137
138 timeout=$(get_timeout $IP6DST)
139
140 atf_check -s exit:0 sleep $(($timeout + 1))
141
142 $DEBUG && rump.ndp -n -a
143 atf_check -s exit:0 -o match:'permanent' rump.ndp -n $IP6SRC
144 # Expired but remains until GC sweaps it (1 day)
145 atf_check -s exit:0 -o match:'(1d0h0m|23h59m)' rump.ndp -n $IP6DST
146 }
147
148 ifdown_dst_server()
149 {
150 export RUMP_SERVER=$SOCKDST
151 atf_check -s exit:0 rump.ifconfig shmif0 down
152 export RUMP_SERVER=$SOCKSRC
153 }
154
155 command_body()
156 {
157 atf_check -s exit:0 ${inetserver} $SOCKSRC
158 atf_check -s exit:0 ${inetserver} $SOCKDST
159
160 setup_dst_server
161 setup_src_server
162
163 export RUMP_SERVER=$SOCKSRC
164
165 # We can delete the entry for the interface's IP address
166 atf_check -s exit:0 -o match:"$IP6SRC" rump.ndp -d $IP6SRC
167
168 # Add and delete a static entry
169 $DEBUG && rump.ndp -n -a
170 atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10
171 $DEBUG && rump.ndp -n -a
172 atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::10
173 atf_check -s exit:0 -o match:'deleted' rump.ndp -d fc00::10
174 $DEBUG && rump.ndp -n -a
175 atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n fc00::10
176
177 # Add multiple entries via a file (XXX not implemented)
178 #cat - > ./list <<-EOF
179 #fc00::11 b2:a0:20:00:00:11
180 #fc00::12 b2:a0:20:00:00:12
181 #fc00::13 b2:a0:20:00:00:13
182 #fc00::14 b2:a0:20:00:00:14
183 #fc00::15 b2:a0:20:00:00:15
184 #EOF
185 #$DEBUG && rump.ndp -n -a
186 #atf_check -s exit:0 -o ignore rump.ndp -f ./list
187 #$DEBUG && rump.ndp -n -a
188
189 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST
190 atf_check -s exit:0 -o ignore rump.ndp -s fc00::11 b2:a0:20:00:00:11
191 atf_check -s exit:0 -o ignore rump.ndp -s fc00::12 b2:a0:20:00:00:12
192
193 atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n $IP6DST
194 atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::11
195 atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::12
196
197 # Test ndp -a
198 atf_check -s exit:0 -o match:'fc00::11' rump.ndp -n -a
199 atf_check -s exit:0 -o match:'fc00::12' rump.ndp -n -a
200
201 # Ensure no packet upsets the src server
202 ifdown_dst_server
203
204 # Flush all entries (-c)
205 $DEBUG && rump.ndp -n -a
206 atf_check -s exit:0 -o ignore rump.ndp -c
207 atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n $IP6SRC
208 atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n $IP6DST
209 # Only the static caches are not deleted
210 atf_check -s exit:0 -o ignore -e ignore rump.ndp -n fc00::11
211 atf_check -s exit:0 -o ignore -e ignore rump.ndp -n fc00::12
212
213 $DEBUG && rump.ndp -n -a
214 atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp
215 rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp
216 $DEBUG && rump.ndp -n -a
217 atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n fc00::10
218
219 return 0
220 }
221
222 cache_overwriting_body()
223 {
224 atf_check -s exit:0 ${inetserver} $SOCKSRC
225 atf_check -s exit:0 ${inetserver} $SOCKDST
226
227 setup_dst_server
228 setup_src_server
229
230 export RUMP_SERVER=$SOCKSRC
231
232 # Cannot overwrite a permanent cache
233 atf_check -s not-exit:0 -e ignore rump.ndp -s $IP6SRC b2:a0:20:00:00:ff
234 $DEBUG && rump.ndp -n -a
235
236 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST
237 $DEBUG && rump.ndp -n -a
238 # Can overwrite a dynamic cache
239 atf_check -s exit:0 -o ignore rump.ndp -s $IP6DST b2:a0:20:00:00:00
240 $DEBUG && rump.ndp -n -a
241 atf_check -s exit:0 -o match:'permanent' rump.ndp -n $IP6DST
242
243 # Test temp option (XXX it doesn't work; expire time isn't set)
244 #atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp
245 #$DEBUG && rump.ndp -n -a
246 #atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n fc00::10
247 # Cannot overwrite a temp cache
248 #atf_check -s not-exit:0 -e ignore rump.ndp -s fc00::10 b2:a0:20:00:00:ff
249 #$DEBUG && rump.ndp -n -a
250
251 return 0
252 }
253
254 get_n_caches()
255 {
256
257 echo $(rump.ndp -a -n |grep -v -e Neighbor -e permanent |wc -l)
258 }
259
260 neighborgcthresh_body()
261 {
262
263 atf_check -s exit:0 ${inetserver} $SOCKSRC
264 atf_check -s exit:0 ${inetserver} $SOCKDST
265
266 setup_dst_server no
267 setup_src_server
268
269 export RUMP_SERVER=$SOCKDST
270 for i in $(seq 0 9); do
271 atf_check -s exit:0 rump.ifconfig shmif0 inet6 ${IP6DST}$i
272 done
273
274 export RUMP_SERVER=$SOCKSRC
275
276 # ping to 3 destinations
277 $DEBUG && rump.ndp -n -a
278 for i in $(seq 0 2); do
279 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \
280 ${IP6DST}$i
281 done
282 $DEBUG && rump.ndp -n -a
283
284 # 3 caches should be created
285 atf_check_equal $(get_n_caches) 3
286
287 # ping to additional 3 destinations
288 for i in $(seq 3 5); do
289 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \
290 ${IP6DST}$i
291 done
292 $DEBUG && rump.ndp -n -a
293
294 # 6 caches should be created in total
295 atf_check_equal $(get_n_caches) 6
296
297 # Limit the number of neighbor caches to 5
298 atf_check -s exit:0 -o ignore rump.sysctl -w \
299 net.inet6.ip6.neighborgcthresh=5
300
301 # ping to additional 4 destinations
302 for i in $(seq 6 9); do
303 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \
304 ${IP6DST}$i
305 done
306
307 # More than 5 caches should be created in total, but exceeded caches
308 # should be GC-ed
309 if [ "$(get_n_caches)" -gt 5 ]; then
310 atf_fail "Neighbor caches are not GC-ed"
311 fi
312
313 return 0
314 }
315
316 make_pkt_str_na()
317 {
318 local ip=$1
319 local mac=$2
320 local pkt=
321 pkt="$mac > 33:33:00:00:00:01, ethertype IPv6 (0x86dd), length 86:"
322 pkt="$pkt $ip > ff02::1: ICMP6, neighbor advertisement"
323 echo $pkt
324 }
325
326 extract_new_packets()
327 {
328 local old=./old
329
330 if [ ! -f $old ]; then
331 old=/dev/null
332 fi
333
334 shmif_dumpbus -p - bus1 2>/dev/null| \
335 tcpdump -n -e -r - 2>/dev/null > ./new
336 diff -u $old ./new |grep '^+' |cut -d '+' -f 2 > ./diff
337 mv -f ./new ./old
338 cat ./diff
339 }
340
341 link_activation_body()
342 {
343 local linklocal=
344
345 atf_check -s exit:0 ${inetserver} $SOCKSRC
346 atf_check -s exit:0 ${inetserver} $SOCKDST
347
348 setup_dst_server
349 setup_src_server
350
351 # flush old packets
352 extract_new_packets > ./out
353
354 export RUMP_SERVER=$SOCKSRC
355
356 atf_check -s exit:0 -o ignore rump.ifconfig shmif0 link \
357 b2:a1:00:00:00:01
358
359 atf_check -s exit:0 sleep 1
360 extract_new_packets > ./out
361 $DEBUG && cat ./out
362
363 linklocal=$(rump.ifconfig shmif0 |awk '/fe80/ {print $2;}' |awk -F % '{print $1;}')
364 $DEBUG && echo $linklocal
365
366 pkt=$(make_pkt_str_na $linklocal b2:a1:00:00:00:01)
367 atf_check -s not-exit:0 -x "cat ./out |grep -q '$pkt'"
368
369 atf_check -s exit:0 -o ignore rump.ifconfig shmif0 link \
370 b2:a1:00:00:00:02 active
371
372 atf_check -s exit:0 sleep 1
373 extract_new_packets > ./out
374 $DEBUG && cat ./out
375
376 linklocal=$(rump.ifconfig shmif0 |awk '/fe80/ {print $2;}' |awk -F % '{print $1;}')
377 $DEBUG && echo $linklocal
378
379 pkt=$(make_pkt_str_na $linklocal b2:a1:00:00:00:02)
380 atf_check -s exit:0 -x "cat ./out |grep -q '$pkt'"
381 }
382
383 cleanup()
384 {
385 env RUMP_SERVER=$SOCKSRC rump.halt
386 env RUMP_SERVER=$SOCKDST rump.halt
387 }
388
389 dump_src()
390 {
391 export RUMP_SERVER=$SOCKSRC
392 rump.netstat -nr
393 rump.ndp -n -a
394 rump.ifconfig
395 $HIJACKING dmesg
396 }
397
398 dump_dst()
399 {
400 export RUMP_SERVER=$SOCKDST
401 rump.netstat -nr
402 rump.ndp -n -a
403 rump.ifconfig
404 $HIJACKING dmesg
405 }
406
407 dump()
408 {
409 dump_src
410 dump_dst
411 shmif_dumpbus -p - bus1 2>/dev/null| tcpdump -n -e -r -
412 $DEBUG && gdb -ex bt /usr/bin/rump_server rump_server.core
413 $DEBUG && gdb -ex bt /usr/sbin/rump.ndp rump.ndp.core
414 }
415
416 cache_expiration_cleanup()
417 {
418 $DEBUG && dump
419 cleanup
420 }
421
422 command_cleanup()
423 {
424 $DEBUG && dump
425 cleanup
426 }
427
428 cache_overwriting_cleanup()
429 {
430 $DEBUG && dump
431 cleanup
432 }
433
434 neighborgcthresh_cleanup()
435 {
436 $DEBUG && dump
437 cleanup
438 }
439
440 link_activation_cleanup()
441 {
442 $DEBUG && dump
443 cleanup
444 }
445
446 atf_init_test_cases()
447 {
448 atf_add_test_case cache_expiration
449 atf_add_test_case command
450 atf_add_test_case cache_overwriting
451 atf_add_test_case neighborgcthresh
452 atf_add_test_case link_activation
453 }
454