Back to home page

OSCL-LXR

 
 

    


0001 #!/bin/bash
0002 # SPDX-License-Identifier: GPL-2.0
0003 
0004 # This test sends one stream of traffic from H1 through a TBF shaper, to a RED
0005 # within TBF shaper on $swp3. The two shapers have the same configuration, and
0006 # thus the resulting stream should fill all available bandwidth on the latter
0007 # shaper. A second stream is sent from H2 also via $swp3, and used to inject
0008 # additional traffic. Since all available bandwidth is taken, this traffic has
0009 # to go to backlog.
0010 #
0011 # +--------------------------+                     +--------------------------+
0012 # | H1                       |                     | H2                       |
0013 # |     + $h1                |                     |     + $h2                |
0014 # |     | 192.0.2.1/28       |                     |     | 192.0.2.2/28       |
0015 # |     | TBF 10Mbps         |                     |     |                    |
0016 # +-----|--------------------+                     +-----|--------------------+
0017 #       |                                                |
0018 # +-----|------------------------------------------------|--------------------+
0019 # | SW  |                                                |                    |
0020 # |  +--|------------------------------------------------|----------------+   |
0021 # |  |  + $swp1                                          + $swp2          |   |
0022 # |  |                               BR                                   |   |
0023 # |  |                                                                    |   |
0024 # |  |                                + $swp3                             |   |
0025 # |  |                                | TBF 10Mbps / RED                  |   |
0026 # |  +--------------------------------|-----------------------------------+   |
0027 # |                                   |                                       |
0028 # +-----------------------------------|---------------------------------------+
0029 #                                     |
0030 #                               +-----|--------------------+
0031 #                               | H3  |                    |
0032 #                               |     + $h1                |
0033 #                               |       192.0.2.3/28       |
0034 #                               |                          |
0035 #                               +--------------------------+
0036 
0037 ALL_TESTS="
0038         ping_ipv4
0039         ecn_test
0040         ecn_nodrop_test
0041         red_test
0042         red_qevent_test
0043         ecn_qevent_test
0044 "
0045 
0046 NUM_NETIFS=6
0047 CHECK_TC="yes"
0048 source lib.sh
0049 
0050 BACKLOG=30000
0051 PKTSZ=1400
0052 
0053 h1_create()
0054 {
0055         simple_if_init $h1 192.0.2.1/28
0056         mtu_set $h1 10000
0057         tc qdisc replace dev $h1 root handle 1: tbf \
0058            rate 10Mbit burst 10K limit 1M
0059 }
0060 
0061 h1_destroy()
0062 {
0063         tc qdisc del dev $h1 root
0064         mtu_restore $h1
0065         simple_if_fini $h1 192.0.2.1/28
0066 }
0067 
0068 h2_create()
0069 {
0070         simple_if_init $h2 192.0.2.2/28
0071         mtu_set $h2 10000
0072 }
0073 
0074 h2_destroy()
0075 {
0076         mtu_restore $h2
0077         simple_if_fini $h2 192.0.2.2/28
0078 }
0079 
0080 h3_create()
0081 {
0082         simple_if_init $h3 192.0.2.3/28
0083         mtu_set $h3 10000
0084 }
0085 
0086 h3_destroy()
0087 {
0088         mtu_restore $h3
0089         simple_if_fini $h3 192.0.2.3/28
0090 }
0091 
0092 switch_create()
0093 {
0094         ip link add dev br up type bridge
0095         ip link set dev $swp1 up master br
0096         ip link set dev $swp2 up master br
0097         ip link set dev $swp3 up master br
0098 
0099         mtu_set $swp1 10000
0100         mtu_set $swp2 10000
0101         mtu_set $swp3 10000
0102 
0103         tc qdisc replace dev $swp3 root handle 1: tbf \
0104            rate 10Mbit burst 10K limit 1M
0105         ip link add name _drop_test up type dummy
0106 }
0107 
0108 switch_destroy()
0109 {
0110         ip link del dev _drop_test
0111         tc qdisc del dev $swp3 root
0112 
0113         mtu_restore $h3
0114         mtu_restore $h2
0115         mtu_restore $h1
0116 
0117         ip link set dev $swp3 down nomaster
0118         ip link set dev $swp2 down nomaster
0119         ip link set dev $swp1 down nomaster
0120         ip link del dev br
0121 }
0122 
0123 setup_prepare()
0124 {
0125         h1=${NETIFS[p1]}
0126         swp1=${NETIFS[p2]}
0127 
0128         h2=${NETIFS[p3]}
0129         swp2=${NETIFS[p4]}
0130 
0131         swp3=${NETIFS[p5]}
0132         h3=${NETIFS[p6]}
0133 
0134         h3_mac=$(mac_get $h3)
0135 
0136         vrf_prepare
0137 
0138         h1_create
0139         h2_create
0140         h3_create
0141         switch_create
0142 }
0143 
0144 cleanup()
0145 {
0146         pre_cleanup
0147 
0148         switch_destroy
0149         h3_destroy
0150         h2_destroy
0151         h1_destroy
0152 
0153         vrf_cleanup
0154 }
0155 
0156 ping_ipv4()
0157 {
0158         ping_test $h1 192.0.2.3 " from host 1"
0159         ping_test $h2 192.0.2.3 " from host 2"
0160 }
0161 
0162 get_qdisc_backlog()
0163 {
0164         qdisc_stats_get $swp3 11: .backlog
0165 }
0166 
0167 get_nmarked()
0168 {
0169         qdisc_stats_get $swp3 11: .marked
0170 }
0171 
0172 get_qdisc_npackets()
0173 {
0174         qdisc_stats_get $swp3 11: .packets
0175 }
0176 
0177 get_nmirrored()
0178 {
0179         link_stats_get _drop_test tx packets
0180 }
0181 
0182 send_packets()
0183 {
0184         local proto=$1; shift
0185         local pkts=$1; shift
0186 
0187         $MZ $h2 -p $PKTSZ -a own -b $h3_mac -A 192.0.2.2 -B 192.0.2.3 -t $proto -q -c $pkts "$@"
0188 }
0189 
0190 # This sends traffic in an attempt to build a backlog of $size. Returns 0 on
0191 # success. After 10 failed attempts it bails out and returns 1. It dumps the
0192 # backlog size to stdout.
0193 build_backlog()
0194 {
0195         local size=$1; shift
0196         local proto=$1; shift
0197 
0198         local i=0
0199 
0200         while :; do
0201                 local cur=$(get_qdisc_backlog)
0202                 local diff=$((size - cur))
0203                 local pkts=$(((diff + PKTSZ - 1) / PKTSZ))
0204 
0205                 if ((cur >= size)); then
0206                         echo $cur
0207                         return 0
0208                 elif ((i++ > 10)); then
0209                         echo $cur
0210                         return 1
0211                 fi
0212 
0213                 send_packets $proto $pkts "$@"
0214                 sleep 1
0215         done
0216 }
0217 
0218 check_marking()
0219 {
0220         local cond=$1; shift
0221 
0222         local npackets_0=$(get_qdisc_npackets)
0223         local nmarked_0=$(get_nmarked)
0224         sleep 5
0225         local npackets_1=$(get_qdisc_npackets)
0226         local nmarked_1=$(get_nmarked)
0227 
0228         local nmarked_d=$((nmarked_1 - nmarked_0))
0229         local npackets_d=$((npackets_1 - npackets_0))
0230         local pct=$((100 * nmarked_d / npackets_d))
0231 
0232         echo $pct
0233         ((pct $cond))
0234 }
0235 
0236 check_mirroring()
0237 {
0238         local cond=$1; shift
0239 
0240         local npackets_0=$(get_qdisc_npackets)
0241         local nmirrored_0=$(get_nmirrored)
0242         sleep 5
0243         local npackets_1=$(get_qdisc_npackets)
0244         local nmirrored_1=$(get_nmirrored)
0245 
0246         local nmirrored_d=$((nmirrored_1 - nmirrored_0))
0247         local npackets_d=$((npackets_1 - npackets_0))
0248         local pct=$((100 * nmirrored_d / npackets_d))
0249 
0250         echo $pct
0251         ((pct $cond))
0252 }
0253 
0254 ecn_test_common()
0255 {
0256         local name=$1; shift
0257         local limit=$1; shift
0258         local backlog
0259         local pct
0260 
0261         # Build the below-the-limit backlog using UDP. We could use TCP just
0262         # fine, but this way we get a proof that UDP is accepted when queue
0263         # length is below the limit. The main stream is using TCP, and if the
0264         # limit is misconfigured, we would see this traffic being ECN marked.
0265         RET=0
0266         backlog=$(build_backlog $((2 * limit / 3)) udp)
0267         check_err $? "Could not build the requested backlog"
0268         pct=$(check_marking "== 0")
0269         check_err $? "backlog $backlog / $limit Got $pct% marked packets, expected == 0."
0270         log_test "$name backlog < limit"
0271 
0272         # Now push TCP, because non-TCP traffic would be early-dropped after the
0273         # backlog crosses the limit, and we want to make sure that the backlog
0274         # is above the limit.
0275         RET=0
0276         backlog=$(build_backlog $((3 * limit / 2)) tcp tos=0x01)
0277         check_err $? "Could not build the requested backlog"
0278         pct=$(check_marking ">= 95")
0279         check_err $? "backlog $backlog / $limit Got $pct% marked packets, expected >= 95."
0280         log_test "$name backlog > limit"
0281 }
0282 
0283 do_ecn_test()
0284 {
0285         local limit=$1; shift
0286         local name=ECN
0287 
0288         $MZ $h1 -p $PKTSZ -A 192.0.2.1 -B 192.0.2.3 -c 0 \
0289                 -a own -b $h3_mac -t tcp -q tos=0x01 &
0290         sleep 1
0291 
0292         ecn_test_common "$name" $limit
0293 
0294         # Up there we saw that UDP gets accepted when backlog is below the
0295         # limit. Now that it is above, it should all get dropped, and backlog
0296         # building should fail.
0297         RET=0
0298         build_backlog $((2 * limit)) udp >/dev/null
0299         check_fail $? "UDP traffic went into backlog instead of being early-dropped"
0300         log_test "$name backlog > limit: UDP early-dropped"
0301 
0302         stop_traffic
0303         sleep 1
0304 }
0305 
0306 do_ecn_nodrop_test()
0307 {
0308         local limit=$1; shift
0309         local name="ECN nodrop"
0310 
0311         $MZ $h1 -p $PKTSZ -A 192.0.2.1 -B 192.0.2.3 -c 0 \
0312                 -a own -b $h3_mac -t tcp -q tos=0x01 &
0313         sleep 1
0314 
0315         ecn_test_common "$name" $limit
0316 
0317         # Up there we saw that UDP gets accepted when backlog is below the
0318         # limit. Now that it is above, in nodrop mode, make sure it goes to
0319         # backlog as well.
0320         RET=0
0321         build_backlog $((2 * limit)) udp >/dev/null
0322         check_err $? "UDP traffic was early-dropped instead of getting into backlog"
0323         log_test "$name backlog > limit: UDP not dropped"
0324 
0325         stop_traffic
0326         sleep 1
0327 }
0328 
0329 do_red_test()
0330 {
0331         local limit=$1; shift
0332         local backlog
0333         local pct
0334 
0335         # Use ECN-capable TCP to verify there's no marking even though the queue
0336         # is above limit.
0337         $MZ $h1 -p $PKTSZ -A 192.0.2.1 -B 192.0.2.3 -c 0 \
0338                 -a own -b $h3_mac -t tcp -q tos=0x01 &
0339 
0340         # Pushing below the queue limit should work.
0341         RET=0
0342         backlog=$(build_backlog $((2 * limit / 3)) tcp tos=0x01)
0343         check_err $? "Could not build the requested backlog"
0344         pct=$(check_marking "== 0")
0345         check_err $? "backlog $backlog / $limit Got $pct% marked packets, expected == 0."
0346         log_test "RED backlog < limit"
0347 
0348         # Pushing above should not.
0349         RET=0
0350         backlog=$(build_backlog $((3 * limit / 2)) tcp tos=0x01)
0351         check_fail $? "Traffic went into backlog instead of being early-dropped"
0352         pct=$(check_marking "== 0")
0353         check_err $? "backlog $backlog / $limit Got $pct% marked packets, expected == 0."
0354         log_test "RED backlog > limit"
0355 
0356         stop_traffic
0357         sleep 1
0358 }
0359 
0360 do_red_qevent_test()
0361 {
0362         local limit=$1; shift
0363         local backlog
0364         local base
0365         local now
0366         local pct
0367 
0368         RET=0
0369 
0370         $MZ $h1 -p $PKTSZ -A 192.0.2.1 -B 192.0.2.3 -c 0 \
0371                 -a own -b $h3_mac -t udp -q &
0372         sleep 1
0373 
0374         tc filter add block 10 pref 1234 handle 102 matchall skip_hw \
0375            action mirred egress mirror dev _drop_test
0376 
0377         # Push to the queue until it's at the limit. The configured limit is
0378         # rounded by the qdisc, so this is the best we can do to get to the real
0379         # limit.
0380         build_backlog $((3 * limit / 2)) udp >/dev/null
0381 
0382         base=$(get_nmirrored)
0383         send_packets udp 100
0384         sleep 1
0385         now=$(get_nmirrored)
0386         ((now >= base + 100))
0387         check_err $? "Dropped packets not observed: 100 expected, $((now - base)) seen"
0388 
0389         tc filter del block 10 pref 1234 handle 102 matchall
0390 
0391         base=$(get_nmirrored)
0392         send_packets udp 100
0393         sleep 1
0394         now=$(get_nmirrored)
0395         ((now == base))
0396         check_err $? "Dropped packets still observed: 0 expected, $((now - base)) seen"
0397 
0398         log_test "RED early_dropped packets mirrored"
0399 
0400         stop_traffic
0401         sleep 1
0402 }
0403 
0404 do_ecn_qevent_test()
0405 {
0406         local limit=$1; shift
0407         local name=ECN
0408 
0409         RET=0
0410 
0411         $MZ $h1 -p $PKTSZ -A 192.0.2.1 -B 192.0.2.3 -c 0 \
0412                 -a own -b $h3_mac -t tcp -q tos=0x01 &
0413         sleep 1
0414 
0415         tc filter add block 10 pref 1234 handle 102 matchall skip_hw \
0416            action mirred egress mirror dev _drop_test
0417 
0418         backlog=$(build_backlog $((2 * limit / 3)) tcp tos=0x01)
0419         check_err $? "Could not build the requested backlog"
0420         pct=$(check_mirroring "== 0")
0421         check_err $? "backlog $backlog / $limit Got $pct% mirrored packets, expected == 0."
0422 
0423         backlog=$(build_backlog $((3 * limit / 2)) tcp tos=0x01)
0424         check_err $? "Could not build the requested backlog"
0425         pct=$(check_mirroring ">= 95")
0426         check_err $? "backlog $backlog / $limit Got $pct% mirrored packets, expected >= 95."
0427 
0428         tc filter del block 10 pref 1234 handle 102 matchall
0429 
0430         log_test "ECN marked packets mirrored"
0431 
0432         stop_traffic
0433         sleep 1
0434 }
0435 
0436 install_qdisc()
0437 {
0438         local -a args=("$@")
0439 
0440         tc qdisc replace dev $swp3 parent 1:1 handle 11: red \
0441            limit 1M avpkt $PKTSZ probability 1 \
0442            min $BACKLOG max $((BACKLOG + 1)) burst 38 "${args[@]}"
0443         sleep 1
0444 }
0445 
0446 uninstall_qdisc()
0447 {
0448         tc qdisc del dev $swp3 parent 1:1
0449 }
0450 
0451 ecn_test()
0452 {
0453         install_qdisc ecn
0454         do_ecn_test $BACKLOG
0455         uninstall_qdisc
0456 }
0457 
0458 ecn_nodrop_test()
0459 {
0460         install_qdisc ecn nodrop
0461         do_ecn_nodrop_test $BACKLOG
0462         uninstall_qdisc
0463 }
0464 
0465 red_test()
0466 {
0467         install_qdisc
0468         do_red_test $BACKLOG
0469         uninstall_qdisc
0470 }
0471 
0472 red_qevent_test()
0473 {
0474         install_qdisc qevent early_drop block 10
0475         do_red_qevent_test $BACKLOG
0476         uninstall_qdisc
0477 }
0478 
0479 ecn_qevent_test()
0480 {
0481         install_qdisc ecn qevent mark block 10
0482         do_ecn_qevent_test $BACKLOG
0483         uninstall_qdisc
0484 }
0485 
0486 trap cleanup EXIT
0487 
0488 setup_prepare
0489 setup_wait
0490 
0491 tests_run
0492 
0493 exit $EXIT_STATUS