Back to home page

OSCL-LXR

 
 

    


0001 #!/bin/bash
0002 # SPDX-License-Identifier: GPL-2.0
0003 # Copyright 2021-2022 NXP
0004 
0005 # Note: On LS1028A, in lack of enough user ports, this setup requires patching
0006 # the device tree to use the second CPU port as a user port
0007 
0008 WAIT_TIME=1
0009 NUM_NETIFS=4
0010 STABLE_MAC_ADDRS=yes
0011 NETIF_CREATE=no
0012 lib_dir=$(dirname $0)/../../../net/forwarding
0013 source $lib_dir/tc_common.sh
0014 source $lib_dir/lib.sh
0015 source $lib_dir/tsn_lib.sh
0016 
0017 UDS_ADDRESS_H1="/var/run/ptp4l_h1"
0018 UDS_ADDRESS_SWP1="/var/run/ptp4l_swp1"
0019 
0020 # Tunables
0021 NUM_PKTS=1000
0022 STREAM_VID=100
0023 STREAM_PRIO=6
0024 # Use a conservative cycle of 10 ms to allow the test to still pass when the
0025 # kernel has some extra overhead like lockdep etc
0026 CYCLE_TIME_NS=10000000
0027 # Create two Gate Control List entries, one OPEN and one CLOSE, of equal
0028 # durations
0029 GATE_DURATION_NS=$((${CYCLE_TIME_NS} / 2))
0030 # Give 2/3 of the cycle time to user space and 1/3 to the kernel
0031 FUDGE_FACTOR=$((${CYCLE_TIME_NS} / 3))
0032 # Shift the isochron base time by half the gate time, so that packets are
0033 # always received by swp1 close to the middle of the time slot, to minimize
0034 # inaccuracies due to network sync
0035 SHIFT_TIME_NS=$((${GATE_DURATION_NS} / 2))
0036 
0037 h1=${NETIFS[p1]}
0038 swp1=${NETIFS[p2]}
0039 swp2=${NETIFS[p3]}
0040 h2=${NETIFS[p4]}
0041 
0042 H1_IPV4="192.0.2.1"
0043 H2_IPV4="192.0.2.2"
0044 H1_IPV6="2001:db8:1::1"
0045 H2_IPV6="2001:db8:1::2"
0046 
0047 # Chain number exported by the ocelot driver for
0048 # Per-Stream Filtering and Policing filters
0049 PSFP()
0050 {
0051         echo 30000
0052 }
0053 
0054 psfp_chain_create()
0055 {
0056         local if_name=$1
0057 
0058         tc qdisc add dev $if_name clsact
0059 
0060         tc filter add dev $if_name ingress chain 0 pref 49152 flower \
0061                 skip_sw action goto chain $(PSFP)
0062 }
0063 
0064 psfp_chain_destroy()
0065 {
0066         local if_name=$1
0067 
0068         tc qdisc del dev $if_name clsact
0069 }
0070 
0071 psfp_filter_check()
0072 {
0073         local expected=$1
0074         local packets=""
0075         local drops=""
0076         local stats=""
0077 
0078         stats=$(tc -j -s filter show dev ${swp1} ingress chain $(PSFP) pref 1)
0079         packets=$(echo ${stats} | jq ".[1].options.actions[].stats.packets")
0080         drops=$(echo ${stats} | jq ".[1].options.actions[].stats.drops")
0081 
0082         if ! [ "${packets}" = "${expected}" ]; then
0083                 printf "Expected filter to match on %d packets but matched on %d instead\n" \
0084                         "${expected}" "${packets}"
0085         fi
0086 
0087         echo "Hardware filter reports ${drops} drops"
0088 }
0089 
0090 h1_create()
0091 {
0092         simple_if_init $h1 $H1_IPV4/24 $H1_IPV6/64
0093 }
0094 
0095 h1_destroy()
0096 {
0097         simple_if_fini $h1 $H1_IPV4/24 $H1_IPV6/64
0098 }
0099 
0100 h2_create()
0101 {
0102         simple_if_init $h2 $H2_IPV4/24 $H2_IPV6/64
0103 }
0104 
0105 h2_destroy()
0106 {
0107         simple_if_fini $h2 $H2_IPV4/24 $H2_IPV6/64
0108 }
0109 
0110 switch_create()
0111 {
0112         local h2_mac_addr=$(mac_get $h2)
0113 
0114         ip link set ${swp1} up
0115         ip link set ${swp2} up
0116 
0117         ip link add br0 type bridge vlan_filtering 1
0118         ip link set ${swp1} master br0
0119         ip link set ${swp2} master br0
0120         ip link set br0 up
0121 
0122         bridge vlan add dev ${swp2} vid ${STREAM_VID}
0123         bridge vlan add dev ${swp1} vid ${STREAM_VID}
0124         # PSFP on Ocelot requires the filter to also be added to the bridge
0125         # FDB, and not be removed
0126         bridge fdb add dev ${swp2} \
0127                 ${h2_mac_addr} vlan ${STREAM_VID} static master
0128 
0129         psfp_chain_create ${swp1}
0130 
0131         tc filter add dev ${swp1} ingress chain $(PSFP) pref 1 \
0132                 protocol 802.1Q flower skip_sw \
0133                 dst_mac ${h2_mac_addr} vlan_id ${STREAM_VID} \
0134                 action gate base-time 0.000000000 \
0135                 sched-entry OPEN  ${GATE_DURATION_NS} -1 -1 \
0136                 sched-entry CLOSE ${GATE_DURATION_NS} -1 -1
0137 }
0138 
0139 switch_destroy()
0140 {
0141         psfp_chain_destroy ${swp1}
0142         ip link del br0
0143 }
0144 
0145 txtime_setup()
0146 {
0147         local if_name=$1
0148 
0149         tc qdisc add dev ${if_name} clsact
0150         # Classify PTP on TC 7 and isochron on TC 6
0151         tc filter add dev ${if_name} egress protocol 0x88f7 \
0152                 flower action skbedit priority 7
0153         tc filter add dev ${if_name} egress protocol 802.1Q \
0154                 flower vlan_ethtype 0xdead action skbedit priority 6
0155         tc qdisc add dev ${if_name} handle 100: parent root mqprio num_tc 8 \
0156                 queues 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7 \
0157                 map 0 1 2 3 4 5 6 7 \
0158                 hw 1
0159         # Set up TC 6 for SO_TXTIME. tc-mqprio queues count from 1.
0160         tc qdisc replace dev ${if_name} parent 100:$((${STREAM_PRIO} + 1)) etf \
0161                 clockid CLOCK_TAI offload delta ${FUDGE_FACTOR}
0162 }
0163 
0164 txtime_cleanup()
0165 {
0166         local if_name=$1
0167 
0168         tc qdisc del dev ${if_name} root
0169         tc qdisc del dev ${if_name} clsact
0170 }
0171 
0172 setup_prepare()
0173 {
0174         vrf_prepare
0175 
0176         h1_create
0177         h2_create
0178         switch_create
0179 
0180         txtime_setup ${h1}
0181 
0182         # Set up swp1 as a master PHC for h1, synchronized to the local
0183         # CLOCK_REALTIME.
0184         phc2sys_start ${swp1} ${UDS_ADDRESS_SWP1}
0185 
0186         # Assumption true for LS1028A: h1 and h2 use the same PHC. So by
0187         # synchronizing h1 to swp1 via PTP, h2 is also implicitly synchronized
0188         # to swp1 (and both to CLOCK_REALTIME).
0189         ptp4l_start ${h1} true ${UDS_ADDRESS_H1}
0190         ptp4l_start ${swp1} false ${UDS_ADDRESS_SWP1}
0191 
0192         # Make sure there are no filter matches at the beginning of the test
0193         psfp_filter_check 0
0194 }
0195 
0196 cleanup()
0197 {
0198         pre_cleanup
0199 
0200         ptp4l_stop ${swp1}
0201         ptp4l_stop ${h1}
0202         phc2sys_stop
0203         isochron_recv_stop
0204 
0205         txtime_cleanup ${h1}
0206 
0207         h2_destroy
0208         h1_destroy
0209         switch_destroy
0210 
0211         vrf_cleanup
0212 }
0213 
0214 debug_incorrectly_dropped_packets()
0215 {
0216         local isochron_dat=$1
0217         local dropped_seqids
0218         local seqid
0219 
0220         echo "Packets incorrectly dropped:"
0221 
0222         dropped_seqids=$(isochron report \
0223                 --input-file "${isochron_dat}" \
0224                 --printf-format "%u RX hw %T\n" \
0225                 --printf-args "qR" | \
0226                 grep 'RX hw 0.000000000' | \
0227                 awk '{print $1}')
0228 
0229         for seqid in ${dropped_seqids}; do
0230                 isochron report \
0231                         --input-file "${isochron_dat}" \
0232                         --start ${seqid} --stop ${seqid} \
0233                         --printf-format "seqid %u scheduled for %T, HW TX timestamp %T\n" \
0234                         --printf-args "qST"
0235         done
0236 }
0237 
0238 debug_incorrectly_received_packets()
0239 {
0240         local isochron_dat=$1
0241 
0242         echo "Packets incorrectly received:"
0243 
0244         isochron report \
0245                 --input-file "${isochron_dat}" \
0246                 --printf-format "seqid %u scheduled for %T, HW TX timestamp %T, HW RX timestamp %T\n" \
0247                 --printf-args "qSTR" |
0248                 grep -v 'HW RX timestamp 0.000000000'
0249 }
0250 
0251 run_test()
0252 {
0253         local base_time=$1
0254         local expected=$2
0255         local test_name=$3
0256         local debug=$4
0257         local isochron_dat="$(mktemp)"
0258         local extra_args=""
0259         local received
0260 
0261         isochron_do \
0262                 "${h1}" \
0263                 "${h2}" \
0264                 "${UDS_ADDRESS_H1}" \
0265                 "" \
0266                 "${base_time}" \
0267                 "${CYCLE_TIME_NS}" \
0268                 "${SHIFT_TIME_NS}" \
0269                 "${NUM_PKTS}" \
0270                 "${STREAM_VID}" \
0271                 "${STREAM_PRIO}" \
0272                 "" \
0273                 "${isochron_dat}"
0274 
0275         # Count all received packets by looking at the non-zero RX timestamps
0276         received=$(isochron report \
0277                 --input-file "${isochron_dat}" \
0278                 --printf-format "%u\n" --printf-args "R" | \
0279                 grep -w -v '0' | wc -l)
0280 
0281         if [ "${received}" = "${expected}" ]; then
0282                 RET=0
0283         else
0284                 RET=1
0285                 echo "Expected isochron to receive ${expected} packets but received ${received}"
0286         fi
0287 
0288         log_test "${test_name}"
0289 
0290         if [ "$RET" = "1" ]; then
0291                 ${debug} "${isochron_dat}"
0292         fi
0293 
0294         rm ${isochron_dat} 2> /dev/null
0295 }
0296 
0297 test_gate_in_band()
0298 {
0299         # Send packets in-band with the OPEN gate entry
0300         run_test 0.000000000 ${NUM_PKTS} "In band" \
0301                 debug_incorrectly_dropped_packets
0302 
0303         psfp_filter_check ${NUM_PKTS}
0304 }
0305 
0306 test_gate_out_of_band()
0307 {
0308         # Send packets in-band with the CLOSE gate entry
0309         run_test 0.005000000 0 "Out of band" \
0310                 debug_incorrectly_received_packets
0311 
0312         psfp_filter_check $((2 * ${NUM_PKTS}))
0313 }
0314 
0315 trap cleanup EXIT
0316 
0317 ALL_TESTS="
0318         test_gate_in_band
0319         test_gate_out_of_band
0320 "
0321 
0322 setup_prepare
0323 setup_wait
0324 
0325 tests_run
0326 
0327 exit $EXIT_STATUS