#!/bin/bash # SPDX-License-Identifier: GPL-2.0 ALL_TESTS=" manual_with_verification_h1_to_h2 manual_with_verification_h2_to_h1 manual_without_verification_h1_to_h2 manual_without_verification_h2_to_h1 manual_failed_verification_h1_to_h2 manual_failed_verification_h2_to_h1 lldp " NUM_NETIFS=2 REQUIRE_MZ=no PREEMPTIBLE_PRIO=0 source lib.sh traffic_test() { local if=$1; shift local src=$1; shift local num_pkts=10000 local before= local after= local delta= if [ ${has_pmac_stats[$if]} = false ]; then src="aggregate" fi before=$(ethtool_std_stats_get $if "eth-mac" "FramesTransmittedOK" $src) $MZ $if -q -c $num_pkts -p 64 -b bcast -t ip -R $PREEMPTIBLE_PRIO after=$(ethtool_std_stats_get $if "eth-mac" "FramesTransmittedOK" $src) delta=$((after - before)) # Allow an extra 1% tolerance for random packets sent by the stack [ $delta -ge $num_pkts ] && [ $delta -le $((num_pkts + 100)) ] } manual_with_verification() { local tx=$1; shift local rx=$1; shift RET=0 # It isn't completely clear from IEEE 802.3-2018 Figure 99-5: Transmit # Processing state diagram whether the "send_r" variable (send response # to verification frame) should be taken into consideration while the # MAC Merge TX direction is disabled. That being said, at least the # NXP ENETC does not, and requires tx-enabled on in order to respond to # the link partner's verification frames. ethtool --set-mm $rx tx-enabled on ethtool --set-mm $tx verify-enabled on tx-enabled on # Wait for verification to finish sleep 1 ethtool --json --show-mm $tx | jq -r '.[]."verify-status"' | \ grep -q 'SUCCEEDED' check_err "$?" "Verification did not succeed" ethtool --json --show-mm $tx | jq -r '.[]."tx-active"' | grep -q 'true' check_err "$?" "pMAC TX is not active" traffic_test $tx "pmac" check_err "$?" "Traffic did not get sent through $tx's pMAC" ethtool --set-mm $tx verify-enabled off tx-enabled off ethtool --set-mm $rx tx-enabled off log_test "Manual configuration with verification: $tx to $rx" } manual_with_verification_h1_to_h2() { manual_with_verification $h1 $h2 } manual_with_verification_h2_to_h1() { manual_with_verification $h2 $h1 } manual_without_verification() { local tx=$1; shift local rx=$1; shift RET=0 ethtool --set-mm $tx verify-enabled off tx-enabled on ethtool --json --show-mm $tx | jq -r '.[]."verify-status"' | \ grep -q 'DISABLED' check_err "$?" "Verification is not disabled" ethtool --json --show-mm $tx | jq -r '.[]."tx-active"' | grep -q 'true' check_err "$?" "pMAC TX is not active" traffic_test $tx "pmac" check_err "$?" "Traffic did not get sent through $tx's pMAC" ethtool --set-mm $tx verify-enabled off tx-enabled off log_test "Manual configuration without verification: $tx to $rx" } manual_without_verification_h1_to_h2() { manual_without_verification $h1 $h2 } manual_without_verification_h2_to_h1() { manual_without_verification $h2 $h1 } manual_failed_verification() { local tx=$1; shift local rx=$1; shift RET=0 ethtool --set-mm $rx pmac-enabled off ethtool --set-mm $tx verify-enabled on tx-enabled on # Wait for verification to time out sleep 1 ethtool --json --show-mm $tx | jq -r '.[]."verify-status"' | \ grep -q 'SUCCEEDED' check_fail "$?" "Verification succeeded when it shouldn't have" ethtool --json --show-mm $tx | jq -r '.[]."tx-active"' | grep -q 'true' check_fail "$?" "pMAC TX is active when it shouldn't have" traffic_test $tx "emac" check_err "$?" "Traffic did not get sent through $tx's eMAC" ethtool --set-mm $tx verify-enabled off tx-enabled off ethtool --set-mm $rx pmac-enabled on log_test "Manual configuration with failed verification: $tx to $rx" } manual_failed_verification_h1_to_h2() { manual_failed_verification $h1 $h2 } manual_failed_verification_h2_to_h1() { manual_failed_verification $h2 $h1 } smallest_supported_add_frag_size() { local iface=$1 local rx_min_frag_size= rx_min_frag_size=$(ethtool --json --show-mm $iface | \ jq '.[]."rx-min-frag-size"') if [ $rx_min_frag_size -le 60 ]; then echo 0 elif [ $rx_min_frag_size -le 124 ]; then echo 1 elif [ $rx_min_frag_size -le 188 ]; then echo 2 elif [ $rx_min_frag_size -le 252 ]; then echo 3 else echo "$iface: RX min frag size $rx_min_frag_size cannot be advertised over LLDP" exit 1 fi } expected_add_frag_size() { local iface=$1 local requested=$2 local min=$(smallest_supported_add_frag_size $iface) [ $requested -le $min ] && echo $min || echo $requested } lldp_change_add_frag_size() { local add_frag_size=$1 local pattern= lldptool -T -i $h1 -V addEthCaps addFragSize=$add_frag_size >/dev/null # Wait for TLVs to be received sleep 2 pattern=$(printf "Additional fragment size: %d" \ $(expected_add_frag_size $h1 $add_frag_size)) lldptool -i $h2 -t -n -V addEthCaps | grep -q "$pattern" } lldp() { RET=0 systemctl start lldpad # Configure the interfaces to receive and transmit LLDPDUs lldptool -L -i $h1 adminStatus=rxtx >/dev/null lldptool -L -i $h2 adminStatus=rxtx >/dev/null # Enable the transmission of Additional Ethernet Capabilities TLV lldptool -T -i $h1 -V addEthCaps enableTx=yes >/dev/null lldptool -T -i $h2 -V addEthCaps enableTx=yes >/dev/null # Wait for TLVs to be received sleep 2 lldptool -i $h1 -t -n -V addEthCaps | \ grep -q "Preemption capability active" check_err "$?" "$h1 pMAC TX is not active" lldptool -i $h2 -t -n -V addEthCaps | \ grep -q "Preemption capability active" check_err "$?" "$h2 pMAC TX is not active" lldp_change_add_frag_size 3 check_err "$?" "addFragSize 3" lldp_change_add_frag_size 2 check_err "$?" "addFragSize 2" lldp_change_add_frag_size 1 check_err "$?" "addFragSize 1" lldp_change_add_frag_size 0 check_err "$?" "addFragSize 0" traffic_test $h1 "pmac" check_err "$?" "Traffic did not get sent through $h1's pMAC" traffic_test $h2 "pmac" check_err "$?" "Traffic did not get sent through $h2's pMAC" systemctl stop lldpad log_test "LLDP" } h1_create() { ip link set dev $h1 up tc qdisc add dev $h1 root mqprio num_tc 4 map 0 1 2 3 \ queues 1@0 1@1 1@2 1@3 \ fp P E E E \ hw 1 ethtool --set-mm $h1 pmac-enabled on tx-enabled off verify-enabled off } h2_create() { ip link set dev $h2 up ethtool --set-mm $h2 pmac-enabled on tx-enabled off verify-enabled off tc qdisc add dev $h2 root mqprio num_tc 4 map 0 1 2 3 \ queues 1@0 1@1 1@2 1@3 \ fp P E E E \ hw 1 } h1_destroy() { ethtool --set-mm $h1 pmac-enabled off tx-enabled off verify-enabled off tc qdisc del dev $h1 root ip link set dev $h1 down } h2_destroy() { tc qdisc del dev $h2 root ethtool --set-mm $h2 pmac-enabled off tx-enabled off verify-enabled off ip link set dev $h2 down } setup_prepare() { h1=${NETIFS[p1]} h2=${NETIFS[p2]} h1_create h2_create } cleanup() { pre_cleanup h2_destroy h1_destroy } check_ethtool_mm_support check_tc_fp_support require_command lldptool bail_on_lldpad "autoconfigure the MAC Merge layer" "configure it manually" for netif in ${NETIFS[@]}; do ethtool --show-mm $netif 2>&1 &> /dev/null if [[ $? -ne 0 ]]; then echo "SKIP: $netif does not support MAC Merge" exit $ksft_skip fi if check_ethtool_pmac_std_stats_support $netif eth-mac; then has_pmac_stats[$netif]=true else has_pmac_stats[$netif]=false echo "$netif does not report pMAC statistics, falling back to aggregate" fi done trap cleanup EXIT setup_prepare setup_wait tests_run exit $EXIT_STATUS