Back to home page

OSCL-LXR

 
 

    


0001 #!/bin/bash
0002 # SPDX-License-Identifier: GPL-2.0
0003 
0004 # +------------------+
0005 # | H1 (v$h1)        |
0006 # | 2001:db8:1::2/64 |
0007 # | 198.51.100.2/28  |
0008 # |         $h1 +    |
0009 # +-------------|----+
0010 #               |
0011 # +-------------|-------------------------------+
0012 # | SW1         |                               |
0013 # |        $rp1 +                               |
0014 # | 198.51.100.1/28                             |
0015 # | 2001:db8:1::1/64                            |
0016 # |                                             |
0017 # | 2001:db8:2::1/64           2001:db8:3::1/64 |
0018 # | 198.51.100.17/28           198.51.100.33/28 |
0019 # |         $rp2 +                     $rp3 +   |
0020 # +--------------|--------------------------|---+
0021 #                |                          |
0022 #                |                          |
0023 # +--------------|---+       +--------------|---+
0024 # | H2 (v$h2)    |   |       | H3 (v$h3)    |   |
0025 # |          $h2 +   |       |          $h3 +   |
0026 # | 198.51.100.18/28 |       | 198.51.100.34/28 |
0027 # | 2001:db8:2::2/64 |       | 2001:db8:3::2/64 |
0028 # +------------------+       +------------------+
0029 #
0030 
0031 ALL_TESTS="mcast_v4 mcast_v6 rpf_v4 rpf_v6 unres_v4 unres_v6"
0032 NUM_NETIFS=6
0033 source lib.sh
0034 source tc_common.sh
0035 
0036 require_command $MCD
0037 require_command $MC_CLI
0038 table_name=selftests
0039 
0040 h1_create()
0041 {
0042         simple_if_init $h1 198.51.100.2/28 2001:db8:1::2/64
0043 
0044         ip route add 198.51.100.16/28 vrf v$h1 nexthop via 198.51.100.1
0045         ip route add 198.51.100.32/28 vrf v$h1 nexthop via 198.51.100.1
0046 
0047         ip route add 2001:db8:2::/64 vrf v$h1 nexthop via 2001:db8:1::1
0048         ip route add 2001:db8:3::/64 vrf v$h1 nexthop via 2001:db8:1::1
0049 
0050         tc qdisc add dev $h1 ingress
0051 }
0052 
0053 h1_destroy()
0054 {
0055         tc qdisc del dev $h1 ingress
0056 
0057         ip route del 2001:db8:3::/64 vrf v$h1
0058         ip route del 2001:db8:2::/64 vrf v$h1
0059 
0060         ip route del 198.51.100.32/28 vrf v$h1
0061         ip route del 198.51.100.16/28 vrf v$h1
0062 
0063         simple_if_fini $h1 198.51.100.2/28 2001:db8:1::2/64
0064 }
0065 
0066 h2_create()
0067 {
0068         simple_if_init $h2 198.51.100.18/28 2001:db8:2::2/64
0069 
0070         ip route add 198.51.100.0/28 vrf v$h2 nexthop via 198.51.100.17
0071         ip route add 198.51.100.32/28 vrf v$h2 nexthop via 198.51.100.17
0072 
0073         ip route add 2001:db8:1::/64 vrf v$h2 nexthop via 2001:db8:2::1
0074         ip route add 2001:db8:3::/64 vrf v$h2 nexthop via 2001:db8:2::1
0075 
0076         tc qdisc add dev $h2 ingress
0077 }
0078 
0079 h2_destroy()
0080 {
0081         tc qdisc del dev $h2 ingress
0082 
0083         ip route del 2001:db8:3::/64 vrf v$h2
0084         ip route del 2001:db8:1::/64 vrf v$h2
0085 
0086         ip route del 198.51.100.32/28 vrf v$h2
0087         ip route del 198.51.100.0/28 vrf v$h2
0088 
0089         simple_if_fini $h2 198.51.100.18/28 2001:db8:2::2/64
0090 }
0091 
0092 h3_create()
0093 {
0094         simple_if_init $h3 198.51.100.34/28 2001:db8:3::2/64
0095 
0096         ip route add 198.51.100.0/28 vrf v$h3 nexthop via 198.51.100.33
0097         ip route add 198.51.100.16/28 vrf v$h3 nexthop via 198.51.100.33
0098 
0099         ip route add 2001:db8:1::/64 vrf v$h3 nexthop via 2001:db8:3::1
0100         ip route add 2001:db8:2::/64 vrf v$h3 nexthop via 2001:db8:3::1
0101 
0102         tc qdisc add dev $h3 ingress
0103 }
0104 
0105 h3_destroy()
0106 {
0107         tc qdisc del dev $h3 ingress
0108 
0109         ip route del 2001:db8:2::/64 vrf v$h3
0110         ip route del 2001:db8:1::/64 vrf v$h3
0111 
0112         ip route del 198.51.100.16/28 vrf v$h3
0113         ip route del 198.51.100.0/28 vrf v$h3
0114 
0115         simple_if_fini $h3 198.51.100.34/28 2001:db8:3::2/64
0116 }
0117 
0118 router_create()
0119 {
0120         ip link set dev $rp1 up
0121         ip link set dev $rp2 up
0122         ip link set dev $rp3 up
0123 
0124         ip address add 198.51.100.1/28 dev $rp1
0125         ip address add 198.51.100.17/28 dev $rp2
0126         ip address add 198.51.100.33/28 dev $rp3
0127 
0128         ip address add 2001:db8:1::1/64 dev $rp1
0129         ip address add 2001:db8:2::1/64 dev $rp2
0130         ip address add 2001:db8:3::1/64 dev $rp3
0131 
0132         tc qdisc add dev $rp3 ingress
0133 }
0134 
0135 router_destroy()
0136 {
0137         tc qdisc del dev $rp3 ingress
0138 
0139         ip address del 2001:db8:3::1/64 dev $rp3
0140         ip address del 2001:db8:2::1/64 dev $rp2
0141         ip address del 2001:db8:1::1/64 dev $rp1
0142 
0143         ip address del 198.51.100.33/28 dev $rp3
0144         ip address del 198.51.100.17/28 dev $rp2
0145         ip address del 198.51.100.1/28 dev $rp1
0146 
0147         ip link set dev $rp3 down
0148         ip link set dev $rp2 down
0149         ip link set dev $rp1 down
0150 }
0151 
0152 start_mcd()
0153 {
0154         SMCROUTEDIR="$(mktemp -d)"
0155 
0156         for ((i = 1; i <= $NUM_NETIFS; ++i)); do
0157                 echo "phyint ${NETIFS[p$i]} enable" >> \
0158                         $SMCROUTEDIR/$table_name.conf
0159         done
0160 
0161         $MCD -N -I $table_name -f $SMCROUTEDIR/$table_name.conf \
0162                 -P $SMCROUTEDIR/$table_name.pid
0163 }
0164 
0165 kill_mcd()
0166 {
0167         pkill $MCD
0168         rm -rf $SMCROUTEDIR
0169 }
0170 
0171 setup_prepare()
0172 {
0173         h1=${NETIFS[p1]}
0174         rp1=${NETIFS[p2]}
0175 
0176         rp2=${NETIFS[p3]}
0177         h2=${NETIFS[p4]}
0178 
0179         rp3=${NETIFS[p5]}
0180         h3=${NETIFS[p6]}
0181 
0182         start_mcd
0183 
0184         vrf_prepare
0185 
0186         h1_create
0187         h2_create
0188         h3_create
0189 
0190         router_create
0191 
0192         forwarding_enable
0193 }
0194 
0195 cleanup()
0196 {
0197         pre_cleanup
0198 
0199         forwarding_restore
0200 
0201         router_destroy
0202 
0203         h3_destroy
0204         h2_destroy
0205         h1_destroy
0206 
0207         vrf_cleanup
0208 
0209         kill_mcd
0210 }
0211 
0212 create_mcast_sg()
0213 {
0214         local if_name=$1; shift
0215         local s_addr=$1; shift
0216         local mcast=$1; shift
0217         local dest_ifs=${@}
0218 
0219         $MC_CLI -I $table_name add $if_name $s_addr $mcast $dest_ifs
0220 }
0221 
0222 delete_mcast_sg()
0223 {
0224         local if_name=$1; shift
0225         local s_addr=$1; shift
0226         local mcast=$1; shift
0227         local dest_ifs=${@}
0228 
0229         $MC_CLI -I $table_name remove $if_name $s_addr $mcast $dest_ifs
0230 }
0231 
0232 mcast_v4()
0233 {
0234         # Add two interfaces to an MC group, send a packet to the MC group and
0235         # verify packets are received on both. Then delete the route and verify
0236         # packets are no longer received.
0237 
0238         RET=0
0239 
0240         tc filter add dev $h2 ingress protocol ip pref 1 handle 122 flower \
0241                 dst_ip 225.1.2.3 action drop
0242         tc filter add dev $h3 ingress protocol ip pref 1 handle 133 flower \
0243                 dst_ip 225.1.2.3 action drop
0244 
0245         create_mcast_sg $rp1 198.51.100.2 225.1.2.3 $rp2 $rp3
0246 
0247         # Send frames with the corresponding L2 destination address.
0248         $MZ $h1 -c 5 -p 128 -t udp -a 00:11:22:33:44:55 -b 01:00:5e:01:02:03 \
0249                 -A 198.51.100.2 -B 225.1.2.3 -q
0250 
0251         tc_check_packets "dev $h2 ingress" 122 5
0252         check_err $? "Multicast not received on first host"
0253         tc_check_packets "dev $h3 ingress" 133 5
0254         check_err $? "Multicast not received on second host"
0255 
0256         delete_mcast_sg $rp1 198.51.100.2 225.1.2.3 $rp2 $rp3
0257 
0258         $MZ $h1 -c 5 -p 128 -t udp -a 00:11:22:33:44:55 -b 01:00:5e:01:02:03 \
0259                 -A 198.51.100.2 -B 225.1.2.3 -q
0260 
0261         tc_check_packets "dev $h2 ingress" 122 5
0262         check_err $? "Multicast received on host although deleted"
0263         tc_check_packets "dev $h3 ingress" 133 5
0264         check_err $? "Multicast received on second host although deleted"
0265 
0266         tc filter del dev $h3 ingress protocol ip pref 1 handle 133 flower
0267         tc filter del dev $h2 ingress protocol ip pref 1 handle 122 flower
0268 
0269         log_test "mcast IPv4"
0270 }
0271 
0272 mcast_v6()
0273 {
0274         # Add two interfaces to an MC group, send a packet to the MC group and
0275         # verify packets are received on both. Then delete the route and verify
0276         # packets are no longer received.
0277 
0278         RET=0
0279 
0280         tc filter add dev $h2 ingress protocol ipv6 pref 1 handle 122 flower \
0281                 dst_ip ff0e::3 action drop
0282         tc filter add dev $h3 ingress protocol ipv6 pref 1 handle 133 flower \
0283                 dst_ip ff0e::3 action drop
0284 
0285         create_mcast_sg $rp1 2001:db8:1::2 ff0e::3 $rp2 $rp3
0286 
0287         # Send frames with the corresponding L2 destination address.
0288         $MZ $h1 -6 -c 5 -p 128 -t udp -a 00:11:22:33:44:55 \
0289                 -b 33:33:00:00:00:03 -A 2001:db8:1::2 -B ff0e::3 -q
0290 
0291         tc_check_packets "dev $h2 ingress" 122 5
0292         check_err $? "Multicast not received on first host"
0293         tc_check_packets "dev $h3 ingress" 133 5
0294         check_err $? "Multicast not received on second host"
0295 
0296         delete_mcast_sg $rp1 2001:db8:1::2 ff0e::3 $rp2 $rp3
0297 
0298         $MZ $h1 -6 -c 5 -p 128 -t udp -a 00:11:22:33:44:55 \
0299                 -b 33:33:00:00:00:03 -A 2001:db8:1::2 -B ff0e::3 -q
0300 
0301         tc_check_packets "dev $h2 ingress" 122 5
0302         check_err $? "Multicast received on first host although deleted"
0303         tc_check_packets "dev $h3 ingress" 133 5
0304         check_err $? "Multicast received on second host although deleted"
0305 
0306         tc filter del dev $h3 ingress protocol ipv6 pref 1 handle 133 flower
0307         tc filter del dev $h2 ingress protocol ipv6 pref 1 handle 122 flower
0308 
0309         log_test "mcast IPv6"
0310 }
0311 
0312 rpf_v4()
0313 {
0314         # Add a multicast route from first router port to the other two. Send
0315         # matching packets and test that both hosts receive them. Then, send
0316         # the same packets via the third router port and test that they do not
0317         # reach any host due to RPF check. A filter with 'skip_hw' is added to
0318         # test that devices capable of multicast routing offload trap those
0319         # packets. The filter is essentialy a NOP in other scenarios.
0320 
0321         RET=0
0322 
0323         tc filter add dev $h1 ingress protocol ip pref 1 handle 1 flower \
0324                 dst_ip 225.1.2.3 ip_proto udp dst_port 12345 action drop
0325         tc filter add dev $h2 ingress protocol ip pref 1 handle 1 flower \
0326                 dst_ip 225.1.2.3 ip_proto udp dst_port 12345 action drop
0327         tc filter add dev $h3 ingress protocol ip pref 1 handle 1 flower \
0328                 dst_ip 225.1.2.3 ip_proto udp dst_port 12345 action drop
0329         tc filter add dev $rp3 ingress protocol ip pref 1 handle 1 flower \
0330                 skip_hw dst_ip 225.1.2.3 ip_proto udp dst_port 12345 action pass
0331 
0332         create_mcast_sg $rp1 198.51.100.2 225.1.2.3 $rp2 $rp3
0333 
0334         $MZ $h1 -c 5 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \
0335                 -a 00:11:22:33:44:55 -b 01:00:5e:01:02:03 \
0336                 -A 198.51.100.2 -B 225.1.2.3 -q
0337 
0338         tc_check_packets "dev $h2 ingress" 1 5
0339         check_err $? "Multicast not received on first host"
0340         tc_check_packets "dev $h3 ingress" 1 5
0341         check_err $? "Multicast not received on second host"
0342 
0343         $MZ $h3 -c 5 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \
0344                 -a 00:11:22:33:44:55 -b 01:00:5e:01:02:03 \
0345                 -A 198.51.100.2 -B 225.1.2.3 -q
0346 
0347         tc_check_packets "dev $h1 ingress" 1 0
0348         check_err $? "Multicast received on first host when should not"
0349         tc_check_packets "dev $h2 ingress" 1 5
0350         check_err $? "Multicast received on second host when should not"
0351         tc_check_packets "dev $rp3 ingress" 1 5
0352         check_err $? "Packets not trapped due to RPF check"
0353 
0354         delete_mcast_sg $rp1 198.51.100.2 225.1.2.3 $rp2 $rp3
0355 
0356         tc filter del dev $rp3 ingress protocol ip pref 1 handle 1 flower
0357         tc filter del dev $h3 ingress protocol ip pref 1 handle 1 flower
0358         tc filter del dev $h2 ingress protocol ip pref 1 handle 1 flower
0359         tc filter del dev $h1 ingress protocol ip pref 1 handle 1 flower
0360 
0361         log_test "RPF IPv4"
0362 }
0363 
0364 rpf_v6()
0365 {
0366         RET=0
0367 
0368         tc filter add dev $h1 ingress protocol ipv6 pref 1 handle 1 flower \
0369                 dst_ip ff0e::3 ip_proto udp dst_port 12345 action drop
0370         tc filter add dev $h2 ingress protocol ipv6 pref 1 handle 1 flower \
0371                 dst_ip ff0e::3 ip_proto udp dst_port 12345 action drop
0372         tc filter add dev $h3 ingress protocol ipv6 pref 1 handle 1 flower \
0373                 dst_ip ff0e::3 ip_proto udp dst_port 12345 action drop
0374         tc filter add dev $rp3 ingress protocol ipv6 pref 1 handle 1 flower \
0375                 skip_hw dst_ip ff0e::3 ip_proto udp dst_port 12345 action pass
0376 
0377         create_mcast_sg $rp1 2001:db8:1::2 ff0e::3 $rp2 $rp3
0378 
0379         $MZ $h1 -6 -c 5 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \
0380                 -a 00:11:22:33:44:55 -b 33:33:00:00:00:03 \
0381                 -A 2001:db8:1::2 -B ff0e::3 -q
0382 
0383         tc_check_packets "dev $h2 ingress" 1 5
0384         check_err $? "Multicast not received on first host"
0385         tc_check_packets "dev $h3 ingress" 1 5
0386         check_err $? "Multicast not received on second host"
0387 
0388         $MZ $h3 -6 -c 5 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \
0389                 -a 00:11:22:33:44:55 -b 33:33:00:00:00:03 \
0390                 -A 2001:db8:1::2 -B ff0e::3 -q
0391 
0392         tc_check_packets "dev $h1 ingress" 1 0
0393         check_err $? "Multicast received on first host when should not"
0394         tc_check_packets "dev $h2 ingress" 1 5
0395         check_err $? "Multicast received on second host when should not"
0396         tc_check_packets "dev $rp3 ingress" 1 5
0397         check_err $? "Packets not trapped due to RPF check"
0398 
0399         delete_mcast_sg $rp1 2001:db8:1::2 ff0e::3 $rp2 $rp3
0400 
0401         tc filter del dev $rp3 ingress protocol ipv6 pref 1 handle 1 flower
0402         tc filter del dev $h3 ingress protocol ipv6 pref 1 handle 1 flower
0403         tc filter del dev $h2 ingress protocol ipv6 pref 1 handle 1 flower
0404         tc filter del dev $h1 ingress protocol ipv6 pref 1 handle 1 flower
0405 
0406         log_test "RPF IPv6"
0407 }
0408 
0409 unres_v4()
0410 {
0411         # Send a multicast packet not corresponding to an installed route,
0412         # causing the kernel to queue the packet for resolution and emit an
0413         # IGMPMSG_NOCACHE notification. smcrouted will react to this
0414         # notification by consulting its (*, G) list and installing an (S, G)
0415         # route, which will be used to forward the queued packet.
0416 
0417         RET=0
0418 
0419         tc filter add dev $h2 ingress protocol ip pref 1 handle 1 flower \
0420                 dst_ip 225.1.2.3 ip_proto udp dst_port 12345 action drop
0421         tc filter add dev $h3 ingress protocol ip pref 1 handle 1 flower \
0422                 dst_ip 225.1.2.3 ip_proto udp dst_port 12345 action drop
0423 
0424         # Forwarding should fail before installing a matching (*, G).
0425         $MZ $h1 -c 1 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \
0426                 -a 00:11:22:33:44:55 -b 01:00:5e:01:02:03 \
0427                 -A 198.51.100.2 -B 225.1.2.3 -q
0428 
0429         tc_check_packets "dev $h2 ingress" 1 0
0430         check_err $? "Multicast received on first host when should not"
0431         tc_check_packets "dev $h3 ingress" 1 0
0432         check_err $? "Multicast received on second host when should not"
0433 
0434         # Create (*, G). Will not be installed in the kernel.
0435         create_mcast_sg $rp1 0.0.0.0 225.1.2.3 $rp2 $rp3
0436 
0437         $MZ $h1 -c 1 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \
0438                 -a 00:11:22:33:44:55 -b 01:00:5e:01:02:03 \
0439                 -A 198.51.100.2 -B 225.1.2.3 -q
0440 
0441         tc_check_packets "dev $h2 ingress" 1 1
0442         check_err $? "Multicast not received on first host"
0443         tc_check_packets "dev $h3 ingress" 1 1
0444         check_err $? "Multicast not received on second host"
0445 
0446         delete_mcast_sg $rp1 0.0.0.0 225.1.2.3 $rp2 $rp3
0447 
0448         tc filter del dev $h3 ingress protocol ip pref 1 handle 1 flower
0449         tc filter del dev $h2 ingress protocol ip pref 1 handle 1 flower
0450 
0451         log_test "Unresolved queue IPv4"
0452 }
0453 
0454 unres_v6()
0455 {
0456         # Send a multicast packet not corresponding to an installed route,
0457         # causing the kernel to queue the packet for resolution and emit an
0458         # MRT6MSG_NOCACHE notification. smcrouted will react to this
0459         # notification by consulting its (*, G) list and installing an (S, G)
0460         # route, which will be used to forward the queued packet.
0461 
0462         RET=0
0463 
0464         tc filter add dev $h2 ingress protocol ipv6 pref 1 handle 1 flower \
0465                 dst_ip ff0e::3 ip_proto udp dst_port 12345 action drop
0466         tc filter add dev $h3 ingress protocol ipv6 pref 1 handle 1 flower \
0467                 dst_ip ff0e::3 ip_proto udp dst_port 12345 action drop
0468 
0469         # Forwarding should fail before installing a matching (*, G).
0470         $MZ $h1 -6 -c 1 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \
0471                 -a 00:11:22:33:44:55 -b 33:33:00:00:00:03 \
0472                 -A 2001:db8:1::2 -B ff0e::3 -q
0473 
0474         tc_check_packets "dev $h2 ingress" 1 0
0475         check_err $? "Multicast received on first host when should not"
0476         tc_check_packets "dev $h3 ingress" 1 0
0477         check_err $? "Multicast received on second host when should not"
0478 
0479         # Create (*, G). Will not be installed in the kernel.
0480         create_mcast_sg $rp1 :: ff0e::3 $rp2 $rp3
0481 
0482         $MZ $h1 -6 -c 1 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \
0483                 -a 00:11:22:33:44:55 -b 33:33:00:00:00:03 \
0484                 -A 2001:db8:1::2 -B ff0e::3 -q
0485 
0486         tc_check_packets "dev $h2 ingress" 1 1
0487         check_err $? "Multicast not received on first host"
0488         tc_check_packets "dev $h3 ingress" 1 1
0489         check_err $? "Multicast not received on second host"
0490 
0491         delete_mcast_sg $rp1 :: ff0e::3 $rp2 $rp3
0492 
0493         tc filter del dev $h3 ingress protocol ipv6 pref 1 handle 1 flower
0494         tc filter del dev $h2 ingress protocol ipv6 pref 1 handle 1 flower
0495 
0496         log_test "Unresolved queue IPv6"
0497 }
0498 
0499 trap cleanup EXIT
0500 
0501 setup_prepare
0502 setup_wait
0503 
0504 tests_run
0505 
0506 exit $EXIT_STATUS