~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/net/forwarding/sch_red.sh

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #!/bin/bash
  2 # SPDX-License-Identifier: GPL-2.0
  3 
  4 # This test sends one stream of traffic from H1 through a TBF shaper, to a RED
  5 # within TBF shaper on $swp3. The two shapers have the same configuration, and
  6 # thus the resulting stream should fill all available bandwidth on the latter
  7 # shaper. A second stream is sent from H2 also via $swp3, and used to inject
  8 # additional traffic. Since all available bandwidth is taken, this traffic has
  9 # to go to backlog.
 10 #
 11 # +--------------------------+                     +--------------------------+
 12 # | H1                       |                     | H2                       |
 13 # |     + $h1                |                     |     + $h2                |
 14 # |     | 192.0.2.1/28       |                     |     | 192.0.2.2/28       |
 15 # |     | TBF 10Mbps         |                     |     |                    |
 16 # +-----|--------------------+                     +-----|--------------------+
 17 #       |                                                |
 18 # +-----|------------------------------------------------|--------------------+
 19 # | SW  |                                                |                    |
 20 # |  +--|------------------------------------------------|----------------+   |
 21 # |  |  + $swp1                                          + $swp2          |   |
 22 # |  |                               BR                                   |   |
 23 # |  |                                                                    |   |
 24 # |  |                                + $swp3                             |   |
 25 # |  |                                | TBF 10Mbps / RED                  |   |
 26 # |  +--------------------------------|-----------------------------------+   |
 27 # |                                   |                                       |
 28 # +-----------------------------------|---------------------------------------+
 29 #                                     |
 30 #                               +-----|--------------------+
 31 #                               | H3  |                    |
 32 #                               |     + $h1                |
 33 #                               |       192.0.2.3/28       |
 34 #                               |                          |
 35 #                               +--------------------------+
 36 
 37 ALL_TESTS="
 38         ping_ipv4
 39         ecn_test
 40         ecn_nodrop_test
 41         red_test
 42         red_qevent_test
 43         ecn_qevent_test
 44 "
 45 
 46 NUM_NETIFS=6
 47 CHECK_TC="yes"
 48 source lib.sh
 49 
 50 BACKLOG=30000
 51 PKTSZ=1400
 52 
 53 h1_create()
 54 {
 55         simple_if_init $h1 192.0.2.1/28
 56         mtu_set $h1 10000
 57         tc qdisc replace dev $h1 root handle 1: tbf \
 58            rate 10Mbit burst 10K limit 1M
 59 }
 60 
 61 h1_destroy()
 62 {
 63         tc qdisc del dev $h1 root
 64         mtu_restore $h1
 65         simple_if_fini $h1 192.0.2.1/28
 66 }
 67 
 68 h2_create()
 69 {
 70         simple_if_init $h2 192.0.2.2/28
 71         mtu_set $h2 10000
 72 }
 73 
 74 h2_destroy()
 75 {
 76         mtu_restore $h2
 77         simple_if_fini $h2 192.0.2.2/28
 78 }
 79 
 80 h3_create()
 81 {
 82         simple_if_init $h3 192.0.2.3/28
 83         mtu_set $h3 10000
 84 }
 85 
 86 h3_destroy()
 87 {
 88         mtu_restore $h3
 89         simple_if_fini $h3 192.0.2.3/28
 90 }
 91 
 92 switch_create()
 93 {
 94         ip link add dev br up type bridge
 95         ip link set dev $swp1 up master br
 96         ip link set dev $swp2 up master br
 97         ip link set dev $swp3 up master br
 98 
 99         mtu_set $swp1 10000
100         mtu_set $swp2 10000
101         mtu_set $swp3 10000
102 
103         tc qdisc replace dev $swp3 root handle 1: tbf \
104            rate 10Mbit burst 10K limit 1M
105         ip link add name _drop_test up type dummy
106 }
107 
108 switch_destroy()
109 {
110         ip link del dev _drop_test
111         tc qdisc del dev $swp3 root
112 
113         mtu_restore $h3
114         mtu_restore $h2
115         mtu_restore $h1
116 
117         ip link set dev $swp3 down nomaster
118         ip link set dev $swp2 down nomaster
119         ip link set dev $swp1 down nomaster
120         ip link del dev br
121 }
122 
123 setup_prepare()
124 {
125         h1=${NETIFS[p1]}
126         swp1=${NETIFS[p2]}
127 
128         h2=${NETIFS[p3]}
129         swp2=${NETIFS[p4]}
130 
131         swp3=${NETIFS[p5]}
132         h3=${NETIFS[p6]}
133 
134         h3_mac=$(mac_get $h3)
135 
136         vrf_prepare
137 
138         h1_create
139         h2_create
140         h3_create
141         switch_create
142 }
143 
144 cleanup()
145 {
146         pre_cleanup
147 
148         switch_destroy
149         h3_destroy
150         h2_destroy
151         h1_destroy
152 
153         vrf_cleanup
154 }
155 
156 ping_ipv4()
157 {
158         ping_test $h1 192.0.2.3 " from host 1"
159         ping_test $h2 192.0.2.3 " from host 2"
160 }
161 
162 get_qdisc_backlog()
163 {
164         qdisc_stats_get $swp3 11: .backlog
165 }
166 
167 get_nmarked()
168 {
169         qdisc_stats_get $swp3 11: .marked
170 }
171 
172 get_qdisc_npackets()
173 {
174         qdisc_stats_get $swp3 11: .packets
175 }
176 
177 get_nmirrored()
178 {
179         link_stats_get _drop_test tx packets
180 }
181 
182 send_packets()
183 {
184         local proto=$1; shift
185         local pkts=$1; shift
186 
187         $MZ $h2 -p $PKTSZ -a own -b $h3_mac -A 192.0.2.2 -B 192.0.2.3 -t $proto -q -c $pkts "$@"
188 }
189 
190 # This sends traffic in an attempt to build a backlog of $size. Returns 0 on
191 # success. After 10 failed attempts it bails out and returns 1. It dumps the
192 # backlog size to stdout.
193 build_backlog()
194 {
195         local size=$1; shift
196         local proto=$1; shift
197 
198         local i=0
199 
200         while :; do
201                 local cur=$(get_qdisc_backlog)
202                 local diff=$((size - cur))
203                 local pkts=$(((diff + PKTSZ - 1) / PKTSZ))
204 
205                 if ((cur >= size)); then
206                         echo $cur
207                         return 0
208                 elif ((i++ > 10)); then
209                         echo $cur
210                         return 1
211                 fi
212 
213                 send_packets $proto $pkts "$@"
214                 sleep 1
215         done
216 }
217 
218 check_marking()
219 {
220         local cond=$1; shift
221 
222         local npackets_0=$(get_qdisc_npackets)
223         local nmarked_0=$(get_nmarked)
224         sleep 5
225         local npackets_1=$(get_qdisc_npackets)
226         local nmarked_1=$(get_nmarked)
227 
228         local nmarked_d=$((nmarked_1 - nmarked_0))
229         local npackets_d=$((npackets_1 - npackets_0))
230         local pct=$((100 * nmarked_d / npackets_d))
231 
232         echo $pct
233         ((pct $cond))
234 }
235 
236 check_mirroring()
237 {
238         local cond=$1; shift
239 
240         local npackets_0=$(get_qdisc_npackets)
241         local nmirrored_0=$(get_nmirrored)
242         sleep 5
243         local npackets_1=$(get_qdisc_npackets)
244         local nmirrored_1=$(get_nmirrored)
245 
246         local nmirrored_d=$((nmirrored_1 - nmirrored_0))
247         local npackets_d=$((npackets_1 - npackets_0))
248         local pct=$((100 * nmirrored_d / npackets_d))
249 
250         echo $pct
251         ((pct $cond))
252 }
253 
254 ecn_test_common()
255 {
256         local name=$1; shift
257         local limit=$1; shift
258         local backlog
259         local pct
260 
261         # Build the below-the-limit backlog using UDP. We could use TCP just
262         # fine, but this way we get a proof that UDP is accepted when queue
263         # length is below the limit. The main stream is using TCP, and if the
264         # limit is misconfigured, we would see this traffic being ECN marked.
265         RET=0
266         backlog=$(build_backlog $((2 * limit / 3)) udp)
267         check_err $? "Could not build the requested backlog"
268         pct=$(check_marking "== 0")
269         check_err $? "backlog $backlog / $limit Got $pct% marked packets, expected == 0."
270         log_test "$name backlog < limit"
271 
272         # Now push TCP, because non-TCP traffic would be early-dropped after the
273         # backlog crosses the limit, and we want to make sure that the backlog
274         # is above the limit.
275         RET=0
276         backlog=$(build_backlog $((3 * limit / 2)) tcp tos=0x01)
277         check_err $? "Could not build the requested backlog"
278         pct=$(check_marking ">= 95")
279         check_err $? "backlog $backlog / $limit Got $pct% marked packets, expected >= 95."
280         log_test "$name backlog > limit"
281 }
282 
283 do_ecn_test()
284 {
285         local limit=$1; shift
286         local name=ECN
287 
288         $MZ $h1 -p $PKTSZ -A 192.0.2.1 -B 192.0.2.3 -c 0 \
289                 -a own -b $h3_mac -t tcp -q tos=0x01 &
290         sleep 1
291 
292         ecn_test_common "$name" $limit
293 
294         # Up there we saw that UDP gets accepted when backlog is below the
295         # limit. Now that it is above, it should all get dropped, and backlog
296         # building should fail.
297         RET=0
298         build_backlog $((2 * limit)) udp >/dev/null
299         check_fail $? "UDP traffic went into backlog instead of being early-dropped"
300         log_test "$name backlog > limit: UDP early-dropped"
301 
302         stop_traffic
303         sleep 1
304 }
305 
306 do_ecn_nodrop_test()
307 {
308         local limit=$1; shift
309         local name="ECN nodrop"
310 
311         $MZ $h1 -p $PKTSZ -A 192.0.2.1 -B 192.0.2.3 -c 0 \
312                 -a own -b $h3_mac -t tcp -q tos=0x01 &
313         sleep 1
314 
315         ecn_test_common "$name" $limit
316 
317         # Up there we saw that UDP gets accepted when backlog is below the
318         # limit. Now that it is above, in nodrop mode, make sure it goes to
319         # backlog as well.
320         RET=0
321         build_backlog $((2 * limit)) udp >/dev/null
322         check_err $? "UDP traffic was early-dropped instead of getting into backlog"
323         log_test "$name backlog > limit: UDP not dropped"
324 
325         stop_traffic
326         sleep 1
327 }
328 
329 do_red_test()
330 {
331         local limit=$1; shift
332         local backlog
333         local pct
334 
335         # Use ECN-capable TCP to verify there's no marking even though the queue
336         # is above limit.
337         $MZ $h1 -p $PKTSZ -A 192.0.2.1 -B 192.0.2.3 -c 0 \
338                 -a own -b $h3_mac -t tcp -q tos=0x01 &
339 
340         # Pushing below the queue limit should work.
341         RET=0
342         backlog=$(build_backlog $((2 * limit / 3)) tcp tos=0x01)
343         check_err $? "Could not build the requested backlog"
344         pct=$(check_marking "== 0")
345         check_err $? "backlog $backlog / $limit Got $pct% marked packets, expected == 0."
346         log_test "RED backlog < limit"
347 
348         # Pushing above should not.
349         RET=0
350         backlog=$(build_backlog $((3 * limit / 2)) tcp tos=0x01)
351         check_fail $? "Traffic went into backlog instead of being early-dropped"
352         pct=$(check_marking "== 0")
353         check_err $? "backlog $backlog / $limit Got $pct% marked packets, expected == 0."
354         log_test "RED backlog > limit"
355 
356         stop_traffic
357         sleep 1
358 }
359 
360 do_red_qevent_test()
361 {
362         local limit=$1; shift
363         local backlog
364         local base
365         local now
366         local pct
367 
368         RET=0
369 
370         $MZ $h1 -p $PKTSZ -A 192.0.2.1 -B 192.0.2.3 -c 0 \
371                 -a own -b $h3_mac -t udp -q &
372         sleep 1
373 
374         tc filter add block 10 pref 1234 handle 102 matchall skip_hw \
375            action mirred egress mirror dev _drop_test
376 
377         # Push to the queue until it's at the limit. The configured limit is
378         # rounded by the qdisc, so this is the best we can do to get to the real
379         # limit.
380         build_backlog $((3 * limit / 2)) udp >/dev/null
381 
382         base=$(get_nmirrored)
383         send_packets udp 100
384         sleep 1
385         now=$(get_nmirrored)
386         ((now >= base + 100))
387         check_err $? "Dropped packets not observed: 100 expected, $((now - base)) seen"
388 
389         tc filter del block 10 pref 1234 handle 102 matchall
390 
391         base=$(get_nmirrored)
392         send_packets udp 100
393         sleep 1
394         now=$(get_nmirrored)
395         ((now == base))
396         check_err $? "Dropped packets still observed: 0 expected, $((now - base)) seen"
397 
398         log_test "RED early_dropped packets mirrored"
399 
400         stop_traffic
401         sleep 1
402 }
403 
404 do_ecn_qevent_test()
405 {
406         local limit=$1; shift
407         local name=ECN
408 
409         RET=0
410 
411         $MZ $h1 -p $PKTSZ -A 192.0.2.1 -B 192.0.2.3 -c 0 \
412                 -a own -b $h3_mac -t tcp -q tos=0x01 &
413         sleep 1
414 
415         tc filter add block 10 pref 1234 handle 102 matchall skip_hw \
416            action mirred egress mirror dev _drop_test
417 
418         backlog=$(build_backlog $((2 * limit / 3)) tcp tos=0x01)
419         check_err $? "Could not build the requested backlog"
420         pct=$(check_mirroring "== 0")
421         check_err $? "backlog $backlog / $limit Got $pct% mirrored packets, expected == 0."
422 
423         backlog=$(build_backlog $((3 * limit / 2)) tcp tos=0x01)
424         check_err $? "Could not build the requested backlog"
425         pct=$(check_mirroring ">= 95")
426         check_err $? "backlog $backlog / $limit Got $pct% mirrored packets, expected >= 95."
427 
428         tc filter del block 10 pref 1234 handle 102 matchall
429 
430         log_test "ECN marked packets mirrored"
431 
432         stop_traffic
433         sleep 1
434 }
435 
436 install_qdisc()
437 {
438         local -a args=("$@")
439 
440         tc qdisc replace dev $swp3 parent 1:1 handle 11: red \
441            limit 1M avpkt $PKTSZ probability 1 \
442            min $BACKLOG max $((BACKLOG + 1)) burst 38 "${args[@]}"
443         sleep 1
444 }
445 
446 uninstall_qdisc()
447 {
448         tc qdisc del dev $swp3 parent 1:1
449 }
450 
451 ecn_test()
452 {
453         install_qdisc ecn
454         xfail_on_slow do_ecn_test $BACKLOG
455         uninstall_qdisc
456 }
457 
458 ecn_nodrop_test()
459 {
460         install_qdisc ecn nodrop
461         xfail_on_slow do_ecn_nodrop_test $BACKLOG
462         uninstall_qdisc
463 }
464 
465 red_test()
466 {
467         install_qdisc
468         xfail_on_slow do_red_test $BACKLOG
469         uninstall_qdisc
470 }
471 
472 red_qevent_test()
473 {
474         install_qdisc qevent early_drop block 10
475         xfail_on_slow do_red_qevent_test $BACKLOG
476         uninstall_qdisc
477 }
478 
479 ecn_qevent_test()
480 {
481         install_qdisc ecn qevent mark block 10
482         xfail_on_slow do_ecn_qevent_test $BACKLOG
483         uninstall_qdisc
484 }
485 
486 trap cleanup EXIT
487 
488 setup_prepare
489 setup_wait
490 
491 tests_run
492 
493 exit $EXIT_STATUS

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php