t_ndp.sh revision 1.9 1 # $NetBSD: t_ndp.sh,v 1.9 2016/02/29 09:35:16 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 # Add and delete a static entry
166 $DEBUG && rump.ndp -n -a
167 atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10
168 $DEBUG && rump.ndp -n -a
169 atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::10
170 atf_check -s exit:0 -o match:'deleted' rump.ndp -d fc00::10
171 $DEBUG && rump.ndp -n -a
172 atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n fc00::10
173
174 # Add multiple entries via a file (XXX not implemented)
175 #cat - > ./list <<-EOF
176 #fc00::11 b2:a0:20:00:00:11
177 #fc00::12 b2:a0:20:00:00:12
178 #fc00::13 b2:a0:20:00:00:13
179 #fc00::14 b2:a0:20:00:00:14
180 #fc00::15 b2:a0:20:00:00:15
181 #EOF
182 #$DEBUG && rump.ndp -n -a
183 #atf_check -s exit:0 -o ignore rump.ndp -f ./list
184 #$DEBUG && rump.ndp -n -a
185
186 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST
187 atf_check -s exit:0 -o ignore rump.ndp -s fc00::11 b2:a0:20:00:00:11
188 atf_check -s exit:0 -o ignore rump.ndp -s fc00::12 b2:a0:20:00:00:12
189
190 atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n $IP6DST
191 atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::11
192 atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::12
193
194 # Test ndp -a
195 atf_check -s exit:0 -o match:'fc00::11' rump.ndp -n -a
196 atf_check -s exit:0 -o match:'fc00::12' rump.ndp -n -a
197
198 # Ensure no packet upsets the src server
199 ifdown_dst_server
200
201 # Flush all entries (-c)
202 $DEBUG && rump.ndp -n -a
203 atf_check -s exit:0 -o ignore rump.ndp -c
204 atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n $IP6DST
205 # Only the static caches are not deleted
206 atf_check -s exit:0 -o ignore -e ignore rump.ndp -n fc00::11
207 atf_check -s exit:0 -o ignore -e ignore rump.ndp -n fc00::12
208
209 # Test temp option (XXX it doesn't work; expire time isn't set)
210 $DEBUG && rump.ndp -n -a
211 #atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp
212 rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp
213 $DEBUG && rump.ndp -n -a
214 #atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n fc00::10
215
216 return 0
217 }
218
219 cache_overwriting_body()
220 {
221 atf_check -s exit:0 ${inetserver} $SOCKSRC
222 atf_check -s exit:0 ${inetserver} $SOCKDST
223
224 setup_dst_server
225 setup_src_server
226
227 export RUMP_SERVER=$SOCKSRC
228
229 # Cannot overwrite a permanent cache
230 atf_check -s not-exit:0 -e ignore rump.ndp -s $IP6SRC b2:a0:20:00:00:ff
231 $DEBUG && rump.ndp -n -a
232
233 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST
234 $DEBUG && rump.ndp -n -a
235 # Can overwrite a dynamic cache
236 atf_check -s exit:0 -o ignore rump.ndp -s $IP6DST b2:a0:20:00:00:00
237 $DEBUG && rump.ndp -n -a
238 atf_check -s exit:0 -o match:'permanent' rump.ndp -n $IP6DST
239
240 # Test temp option (XXX it doesn't work; expire time isn't set)
241 #atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp
242 #$DEBUG && rump.ndp -n -a
243 #atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n fc00::10
244 # Cannot overwrite a temp cache
245 #atf_check -s not-exit:0 -e ignore rump.ndp -s fc00::10 b2:a0:20:00:00:ff
246 #$DEBUG && rump.ndp -n -a
247
248 return 0
249 }
250
251 get_n_caches()
252 {
253
254 echo $(rump.ndp -a -n |grep -v -e Neighbor -e permanent |wc -l)
255 }
256
257 neighborgcthresh_body()
258 {
259
260 atf_check -s exit:0 ${inetserver} $SOCKSRC
261 atf_check -s exit:0 ${inetserver} $SOCKDST
262
263 setup_dst_server no
264 setup_src_server
265
266 export RUMP_SERVER=$SOCKDST
267 for i in $(seq 0 9); do
268 atf_check -s exit:0 rump.ifconfig shmif0 inet6 ${IP6DST}$i
269 done
270
271 export RUMP_SERVER=$SOCKSRC
272
273 # ping to 3 destinations
274 $DEBUG && rump.ndp -n -a
275 for i in $(seq 0 2); do
276 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \
277 ${IP6DST}$i
278 done
279 $DEBUG && rump.ndp -n -a
280
281 # 3 caches should be created
282 atf_check_equal $(get_n_caches) 3
283
284 # ping to additional 3 destinations
285 for i in $(seq 3 5); do
286 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \
287 ${IP6DST}$i
288 done
289 $DEBUG && rump.ndp -n -a
290
291 # 6 caches should be created in total
292 atf_check_equal $(get_n_caches) 6
293
294 # Limit the number of neighbor caches to 5
295 atf_check -s exit:0 -o ignore rump.sysctl -w \
296 net.inet6.ip6.neighborgcthresh=5
297
298 # ping to additional 4 destinations
299 for i in $(seq 6 9); do
300 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \
301 ${IP6DST}$i
302 done
303
304 # More than 5 caches should be created in total, but exceeded caches
305 # should be GC-ed
306 if [ "$(get_n_caches)" -gt 5 ]; then
307 atf_fail "Neighbor caches are not GC-ed"
308 fi
309
310 return 0
311 }
312
313 make_pkt_str_na()
314 {
315 local ip=$1
316 local mac=$2
317 local pkt=
318 pkt="$mac > 33:33:00:00:00:01, ethertype IPv6 (0x86dd), length 86:"
319 pkt="$pkt $ip > ff02::1: ICMP6, neighbor advertisement"
320 echo $pkt
321 }
322
323 extract_new_packets()
324 {
325 local old=./old
326
327 if [ ! -f $old ]; then
328 old=/dev/null
329 fi
330
331 shmif_dumpbus -p - bus1 2>/dev/null| \
332 tcpdump -n -e -r - 2>/dev/null > ./new
333 diff -u $old ./new |grep '^+' |cut -d '+' -f 2 > ./diff
334 mv -f ./new ./old
335 cat ./diff
336 }
337
338 link_activation_body()
339 {
340 local linklocal=
341
342 atf_check -s exit:0 ${inetserver} $SOCKSRC
343 atf_check -s exit:0 ${inetserver} $SOCKDST
344
345 setup_dst_server
346 setup_src_server
347
348 # flush old packets
349 extract_new_packets > ./out
350
351 export RUMP_SERVER=$SOCKSRC
352
353 atf_check -s exit:0 -o ignore rump.ifconfig shmif0 link \
354 b2:a1:00:00:00:01
355
356 atf_check -s exit:0 sleep 1
357 extract_new_packets > ./out
358 $DEBUG && cat ./out
359
360 linklocal=$(rump.ifconfig shmif0 |awk '/fe80/ {print $2;}' |awk -F % '{print $1;}')
361 $DEBUG && echo $linklocal
362
363 pkt=$(make_pkt_str_na $linklocal b2:a1:00:00:00:01)
364 atf_check -s not-exit:0 -x "cat ./out |grep -q '$pkt'"
365
366 atf_check -s exit:0 -o ignore rump.ifconfig shmif0 link \
367 b2:a1:00:00:00:02 active
368
369 atf_check -s exit:0 sleep 1
370 extract_new_packets > ./out
371 $DEBUG && cat ./out
372
373 linklocal=$(rump.ifconfig shmif0 |awk '/fe80/ {print $2;}' |awk -F % '{print $1;}')
374 $DEBUG && echo $linklocal
375
376 pkt=$(make_pkt_str_na $linklocal b2:a1:00:00:00:02)
377 atf_check -s exit:0 -x "cat ./out |grep -q '$pkt'"
378 }
379
380 cleanup()
381 {
382 env RUMP_SERVER=$SOCKSRC rump.halt
383 env RUMP_SERVER=$SOCKDST rump.halt
384 }
385
386 dump_src()
387 {
388 export RUMP_SERVER=$SOCKSRC
389 rump.netstat -nr
390 rump.ndp -n -a
391 rump.ifconfig
392 $HIJACKING dmesg
393 }
394
395 dump_dst()
396 {
397 export RUMP_SERVER=$SOCKDST
398 rump.netstat -nr
399 rump.ndp -n -a
400 rump.ifconfig
401 $HIJACKING dmesg
402 }
403
404 dump()
405 {
406 dump_src
407 dump_dst
408 shmif_dumpbus -p - bus1 2>/dev/null| tcpdump -n -e -r -
409 $DEBUG && gdb -ex bt /usr/bin/rump_server rump_server.core
410 $DEBUG && gdb -ex bt /usr/sbin/rump.ndp rump.ndp.core
411 }
412
413 cache_expiration_cleanup()
414 {
415 $DEBUG && dump
416 cleanup
417 }
418
419 command_cleanup()
420 {
421 $DEBUG && dump
422 cleanup
423 }
424
425 cache_overwriting_cleanup()
426 {
427 $DEBUG && dump
428 cleanup
429 }
430
431 neighborgcthresh_cleanup()
432 {
433 $DEBUG && dump
434 cleanup
435 }
436
437 link_activation_cleanup()
438 {
439 $DEBUG && dump
440 cleanup
441 }
442
443 atf_init_test_cases()
444 {
445 atf_add_test_case cache_expiration
446 atf_add_test_case command
447 atf_add_test_case cache_overwriting
448 atf_add_test_case neighborgcthresh
449 atf_add_test_case link_activation
450 }
451