Path: blob/master/tools/testing/selftests/drivers/net/ocelot/psfp.sh
26298 views
#!/bin/bash1# SPDX-License-Identifier: GPL-2.02# Copyright 2021-2022 NXP34# Note: On LS1028A, in lack of enough user ports, this setup requires patching5# the device tree to use the second CPU port as a user port67WAIT_TIME=18NUM_NETIFS=49STABLE_MAC_ADDRS=yes10NETIF_CREATE=no11lib_dir=$(dirname $0)/../../../net/forwarding12source $lib_dir/tc_common.sh13source $lib_dir/lib.sh14source $lib_dir/tsn_lib.sh1516UDS_ADDRESS_H1="/var/run/ptp4l_h1"17UDS_ADDRESS_SWP1="/var/run/ptp4l_swp1"1819# Tunables20NUM_PKTS=100021STREAM_VID=10022STREAM_PRIO=623# Use a conservative cycle of 10 ms to allow the test to still pass when the24# kernel has some extra overhead like lockdep etc25CYCLE_TIME_NS=1000000026# Create two Gate Control List entries, one OPEN and one CLOSE, of equal27# durations28GATE_DURATION_NS=$((${CYCLE_TIME_NS} / 2))29# Give 2/3 of the cycle time to user space and 1/3 to the kernel30FUDGE_FACTOR=$((${CYCLE_TIME_NS} / 3))31# Shift the isochron base time by half the gate time, so that packets are32# always received by swp1 close to the middle of the time slot, to minimize33# inaccuracies due to network sync34SHIFT_TIME_NS=$((${GATE_DURATION_NS} / 2))3536h1=${NETIFS[p1]}37swp1=${NETIFS[p2]}38swp2=${NETIFS[p3]}39h2=${NETIFS[p4]}4041H1_IPV4="192.0.2.1"42H2_IPV4="192.0.2.2"43H1_IPV6="2001:db8:1::1"44H2_IPV6="2001:db8:1::2"4546# Chain number exported by the ocelot driver for47# Per-Stream Filtering and Policing filters48PSFP()49{50echo 3000051}5253psfp_chain_create()54{55local if_name=$15657tc qdisc add dev $if_name clsact5859tc filter add dev $if_name ingress chain 0 pref 49152 flower \60skip_sw action goto chain $(PSFP)61}6263psfp_chain_destroy()64{65local if_name=$16667tc qdisc del dev $if_name clsact68}6970psfp_filter_check()71{72local expected=$173local packets=""74local drops=""75local stats=""7677stats=$(tc -j -s filter show dev ${swp1} ingress chain $(PSFP) pref 1)78packets=$(echo ${stats} | jq ".[1].options.actions[].stats.packets")79drops=$(echo ${stats} | jq ".[1].options.actions[].stats.drops")8081if ! [ "${packets}" = "${expected}" ]; then82printf "Expected filter to match on %d packets but matched on %d instead\n" \83"${expected}" "${packets}"84fi8586echo "Hardware filter reports ${drops} drops"87}8889h1_create()90{91simple_if_init $h1 $H1_IPV4/24 $H1_IPV6/6492}9394h1_destroy()95{96simple_if_fini $h1 $H1_IPV4/24 $H1_IPV6/6497}9899h2_create()100{101simple_if_init $h2 $H2_IPV4/24 $H2_IPV6/64102}103104h2_destroy()105{106simple_if_fini $h2 $H2_IPV4/24 $H2_IPV6/64107}108109switch_create()110{111local h2_mac_addr=$(mac_get $h2)112113ip link set ${swp1} up114ip link set ${swp2} up115116ip link add br0 type bridge vlan_filtering 1117ip link set ${swp1} master br0118ip link set ${swp2} master br0119ip link set br0 up120121bridge vlan add dev ${swp2} vid ${STREAM_VID}122bridge vlan add dev ${swp1} vid ${STREAM_VID}123# PSFP on Ocelot requires the filter to also be added to the bridge124# FDB, and not be removed125bridge fdb add dev ${swp2} \126${h2_mac_addr} vlan ${STREAM_VID} static master127128psfp_chain_create ${swp1}129130tc filter add dev ${swp1} ingress chain $(PSFP) pref 1 \131protocol 802.1Q flower skip_sw \132dst_mac ${h2_mac_addr} vlan_id ${STREAM_VID} \133action gate base-time 0.000000000 \134sched-entry OPEN ${GATE_DURATION_NS} -1 -1 \135sched-entry CLOSE ${GATE_DURATION_NS} -1 -1136}137138switch_destroy()139{140psfp_chain_destroy ${swp1}141ip link del br0142}143144txtime_setup()145{146local if_name=$1147148tc qdisc add dev ${if_name} clsact149# Classify PTP on TC 7 and isochron on TC 6150tc filter add dev ${if_name} egress protocol 0x88f7 \151flower action skbedit priority 7152tc filter add dev ${if_name} egress protocol 802.1Q \153flower vlan_ethtype 0xdead action skbedit priority 6154tc qdisc add dev ${if_name} handle 100: parent root mqprio num_tc 8 \155queues 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7 \156map 0 1 2 3 4 5 6 7 \157hw 1158# Set up TC 6 for SO_TXTIME. tc-mqprio queues count from 1.159tc qdisc replace dev ${if_name} parent 100:$((${STREAM_PRIO} + 1)) etf \160clockid CLOCK_TAI offload delta ${FUDGE_FACTOR}161}162163txtime_cleanup()164{165local if_name=$1166167tc qdisc del dev ${if_name} root168tc qdisc del dev ${if_name} clsact169}170171setup_prepare()172{173vrf_prepare174175h1_create176h2_create177switch_create178179txtime_setup ${h1}180181# Set up swp1 as a master PHC for h1, synchronized to the local182# CLOCK_REALTIME.183phc2sys_start ${UDS_ADDRESS_SWP1}184185# Assumption true for LS1028A: h1 and h2 use the same PHC. So by186# synchronizing h1 to swp1 via PTP, h2 is also implicitly synchronized187# to swp1 (and both to CLOCK_REALTIME).188ptp4l_start ${h1} true ${UDS_ADDRESS_H1}189ptp4l_start ${swp1} false ${UDS_ADDRESS_SWP1}190191# Make sure there are no filter matches at the beginning of the test192psfp_filter_check 0193}194195cleanup()196{197pre_cleanup198199ptp4l_stop ${swp1}200ptp4l_stop ${h1}201phc2sys_stop202isochron_recv_stop203204txtime_cleanup ${h1}205206h2_destroy207h1_destroy208switch_destroy209210vrf_cleanup211}212213debug_incorrectly_dropped_packets()214{215local isochron_dat=$1216local dropped_seqids217local seqid218219echo "Packets incorrectly dropped:"220221dropped_seqids=$(isochron report \222--input-file "${isochron_dat}" \223--printf-format "%u RX hw %T\n" \224--printf-args "qR" | \225grep 'RX hw 0.000000000' | \226awk '{print $1}')227228for seqid in ${dropped_seqids}; do229isochron report \230--input-file "${isochron_dat}" \231--start ${seqid} --stop ${seqid} \232--printf-format "seqid %u scheduled for %T, HW TX timestamp %T\n" \233--printf-args "qST"234done235}236237debug_incorrectly_received_packets()238{239local isochron_dat=$1240241echo "Packets incorrectly received:"242243isochron report \244--input-file "${isochron_dat}" \245--printf-format "seqid %u scheduled for %T, HW TX timestamp %T, HW RX timestamp %T\n" \246--printf-args "qSTR" |247grep -v 'HW RX timestamp 0.000000000'248}249250run_test()251{252local base_time=$1253local expected=$2254local test_name=$3255local debug=$4256local isochron_dat="$(mktemp)"257local extra_args=""258local received259260isochron_do \261"${h1}" \262"${h2}" \263"${UDS_ADDRESS_H1}" \264"" \265"${base_time}" \266"${CYCLE_TIME_NS}" \267"${SHIFT_TIME_NS}" \268"${GATE_DURATION_NS}" \269"${NUM_PKTS}" \270"${STREAM_VID}" \271"${STREAM_PRIO}" \272"" \273"${isochron_dat}"274275received=$(isochron_report_num_received "${isochron_dat}")276if [ "${received}" = "${expected}" ]; then277RET=0278else279RET=1280echo "Expected isochron to receive ${expected} packets but received ${received}"281fi282283log_test "${test_name}"284285if [ "$RET" = "1" ]; then286${debug} "${isochron_dat}"287fi288289rm ${isochron_dat} 2> /dev/null290}291292test_gate_in_band()293{294# Send packets in-band with the OPEN gate entry295run_test 0.000000000 ${NUM_PKTS} "In band" \296debug_incorrectly_dropped_packets297298psfp_filter_check ${NUM_PKTS}299}300301test_gate_out_of_band()302{303# Send packets in-band with the CLOSE gate entry304run_test 0.005000000 0 "Out of band" \305debug_incorrectly_received_packets306307psfp_filter_check $((2 * ${NUM_PKTS}))308}309310trap cleanup EXIT311312ALL_TESTS="313test_gate_in_band314test_gate_out_of_band315"316317setup_prepare318setup_wait319320tests_run321322exit $EXIT_STATUS323324325