Merge branch 'netdevsim-add-ethtool-coalesce-and-ring-settings'
Antonio Cardace says: ==================== netdevsim: add ethtool coalesce and ring settings Output of ethtool-ring.sh and ethtool-coalesce.sh selftests: # ./ethtool-ring.sh PASSED all 4 checks # ./ethtool-coalesce.sh PASSED all 22 checks # ./ethtool-pause.sh PASSED all 7 checks ==================== Link: https://lore.kernel.org/r/20201118204522.5660-1-acardace@redhat.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
2ed03e5a84
|
@ -13,9 +13,9 @@ nsim_get_pause_stats(struct net_device *dev,
|
|||
{
|
||||
struct netdevsim *ns = netdev_priv(dev);
|
||||
|
||||
if (ns->ethtool.report_stats_rx)
|
||||
if (ns->ethtool.pauseparam.report_stats_rx)
|
||||
pause_stats->rx_pause_frames = 1;
|
||||
if (ns->ethtool.report_stats_tx)
|
||||
if (ns->ethtool.pauseparam.report_stats_tx)
|
||||
pause_stats->tx_pause_frames = 2;
|
||||
}
|
||||
|
||||
|
@ -25,8 +25,8 @@ nsim_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *pause)
|
|||
struct netdevsim *ns = netdev_priv(dev);
|
||||
|
||||
pause->autoneg = 0; /* We don't support ksettings, so can't pretend */
|
||||
pause->rx_pause = ns->ethtool.rx;
|
||||
pause->tx_pause = ns->ethtool.tx;
|
||||
pause->rx_pause = ns->ethtool.pauseparam.rx;
|
||||
pause->tx_pause = ns->ethtool.pauseparam.tx;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -37,28 +37,88 @@ nsim_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *pause)
|
|||
if (pause->autoneg)
|
||||
return -EINVAL;
|
||||
|
||||
ns->ethtool.rx = pause->rx_pause;
|
||||
ns->ethtool.tx = pause->tx_pause;
|
||||
ns->ethtool.pauseparam.rx = pause->rx_pause;
|
||||
ns->ethtool.pauseparam.tx = pause->tx_pause;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nsim_get_coalesce(struct net_device *dev,
|
||||
struct ethtool_coalesce *coal)
|
||||
{
|
||||
struct netdevsim *ns = netdev_priv(dev);
|
||||
|
||||
memcpy(coal, &ns->ethtool.coalesce, sizeof(ns->ethtool.coalesce));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nsim_set_coalesce(struct net_device *dev,
|
||||
struct ethtool_coalesce *coal)
|
||||
{
|
||||
struct netdevsim *ns = netdev_priv(dev);
|
||||
|
||||
memcpy(&ns->ethtool.coalesce, coal, sizeof(ns->ethtool.coalesce));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nsim_get_ringparam(struct net_device *dev,
|
||||
struct ethtool_ringparam *ring)
|
||||
{
|
||||
struct netdevsim *ns = netdev_priv(dev);
|
||||
|
||||
memcpy(ring, &ns->ethtool.ring, sizeof(ns->ethtool.ring));
|
||||
}
|
||||
|
||||
static int nsim_set_ringparam(struct net_device *dev,
|
||||
struct ethtool_ringparam *ring)
|
||||
{
|
||||
struct netdevsim *ns = netdev_priv(dev);
|
||||
|
||||
memcpy(&ns->ethtool.ring, ring, sizeof(ns->ethtool.ring));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ethtool_ops nsim_ethtool_ops = {
|
||||
.get_pause_stats = nsim_get_pause_stats,
|
||||
.get_pauseparam = nsim_get_pauseparam,
|
||||
.set_pauseparam = nsim_set_pauseparam,
|
||||
.supported_coalesce_params = ETHTOOL_COALESCE_ALL_PARAMS,
|
||||
.get_pause_stats = nsim_get_pause_stats,
|
||||
.get_pauseparam = nsim_get_pauseparam,
|
||||
.set_pauseparam = nsim_set_pauseparam,
|
||||
.set_coalesce = nsim_set_coalesce,
|
||||
.get_coalesce = nsim_get_coalesce,
|
||||
.get_ringparam = nsim_get_ringparam,
|
||||
.set_ringparam = nsim_set_ringparam,
|
||||
};
|
||||
|
||||
static void nsim_ethtool_ring_init(struct netdevsim *ns)
|
||||
{
|
||||
ns->ethtool.ring.rx_max_pending = 4096;
|
||||
ns->ethtool.ring.rx_jumbo_max_pending = 4096;
|
||||
ns->ethtool.ring.rx_mini_max_pending = 4096;
|
||||
ns->ethtool.ring.tx_max_pending = 4096;
|
||||
}
|
||||
|
||||
void nsim_ethtool_init(struct netdevsim *ns)
|
||||
{
|
||||
struct dentry *ethtool, *dir;
|
||||
|
||||
ns->netdev->ethtool_ops = &nsim_ethtool_ops;
|
||||
|
||||
nsim_ethtool_ring_init(ns);
|
||||
|
||||
ethtool = debugfs_create_dir("ethtool", ns->nsim_dev_port->ddir);
|
||||
|
||||
dir = debugfs_create_dir("pause", ethtool);
|
||||
debugfs_create_bool("report_stats_rx", 0600, dir,
|
||||
&ns->ethtool.report_stats_rx);
|
||||
&ns->ethtool.pauseparam.report_stats_rx);
|
||||
debugfs_create_bool("report_stats_tx", 0600, dir,
|
||||
&ns->ethtool.report_stats_tx);
|
||||
&ns->ethtool.pauseparam.report_stats_tx);
|
||||
|
||||
dir = debugfs_create_dir("ring", ethtool);
|
||||
debugfs_create_u32("rx_max_pending", 0600, dir,
|
||||
&ns->ethtool.ring.rx_max_pending);
|
||||
debugfs_create_u32("rx_jumbo_max_pending", 0600, dir,
|
||||
&ns->ethtool.ring.rx_jumbo_max_pending);
|
||||
debugfs_create_u32("rx_mini_max_pending", 0600, dir,
|
||||
&ns->ethtool.ring.rx_mini_max_pending);
|
||||
debugfs_create_u32("tx_max_pending", 0600, dir,
|
||||
&ns->ethtool.ring.tx_max_pending);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
@ -51,13 +52,19 @@ struct nsim_ipsec {
|
|||
u32 ok;
|
||||
};
|
||||
|
||||
struct nsim_ethtool {
|
||||
struct nsim_ethtool_pauseparam {
|
||||
bool rx;
|
||||
bool tx;
|
||||
bool report_stats_rx;
|
||||
bool report_stats_tx;
|
||||
};
|
||||
|
||||
struct nsim_ethtool {
|
||||
struct nsim_ethtool_pauseparam pauseparam;
|
||||
struct ethtool_coalesce coalesce;
|
||||
struct ethtool_ringparam ring;
|
||||
};
|
||||
|
||||
struct netdevsim {
|
||||
struct net_device *netdev;
|
||||
struct nsim_dev *nsim_dev;
|
||||
|
|
|
@ -215,6 +215,7 @@ bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32,
|
|||
#define ETHTOOL_COALESCE_TX_USECS_HIGH BIT(19)
|
||||
#define ETHTOOL_COALESCE_TX_MAX_FRAMES_HIGH BIT(20)
|
||||
#define ETHTOOL_COALESCE_RATE_SAMPLE_INTERVAL BIT(21)
|
||||
#define ETHTOOL_COALESCE_ALL_PARAMS GENMASK(21, 0)
|
||||
|
||||
#define ETHTOOL_COALESCE_USECS \
|
||||
(ETHTOOL_COALESCE_RX_USECS | ETHTOOL_COALESCE_TX_USECS)
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
source ethtool-common.sh
|
||||
|
||||
function get_value {
|
||||
local query="${SETTINGS_MAP[$1]}"
|
||||
|
||||
echo $(ethtool -c $NSIM_NETDEV | \
|
||||
awk -F':' -v pattern="$query:" '$0 ~ pattern {gsub(/[ \t]/, "", $2); print $2}')
|
||||
}
|
||||
|
||||
function update_current_settings {
|
||||
for key in ${!SETTINGS_MAP[@]}; do
|
||||
CURRENT_SETTINGS[$key]=$(get_value $key)
|
||||
done
|
||||
echo ${CURRENT_SETTINGS[@]}
|
||||
}
|
||||
|
||||
if ! ethtool -h | grep -q coalesce; then
|
||||
echo "SKIP: No --coalesce support in ethtool"
|
||||
exit 4
|
||||
fi
|
||||
|
||||
NSIM_NETDEV=$(make_netdev)
|
||||
|
||||
set -o pipefail
|
||||
|
||||
declare -A SETTINGS_MAP=(
|
||||
["rx-frames-low"]="rx-frame-low"
|
||||
["tx-frames-low"]="tx-frame-low"
|
||||
["rx-frames-high"]="rx-frame-high"
|
||||
["tx-frames-high"]="tx-frame-high"
|
||||
["rx-usecs"]="rx-usecs"
|
||||
["rx-frames"]="rx-frames"
|
||||
["rx-usecs-irq"]="rx-usecs-irq"
|
||||
["rx-frames-irq"]="rx-frames-irq"
|
||||
["tx-usecs"]="tx-usecs"
|
||||
["tx-frames"]="tx-frames"
|
||||
["tx-usecs-irq"]="tx-usecs-irq"
|
||||
["tx-frames-irq"]="tx-frames-irq"
|
||||
["stats-block-usecs"]="stats-block-usecs"
|
||||
["pkt-rate-low"]="pkt-rate-low"
|
||||
["rx-usecs-low"]="rx-usecs-low"
|
||||
["tx-usecs-low"]="tx-usecs-low"
|
||||
["pkt-rate-high"]="pkt-rate-high"
|
||||
["rx-usecs-high"]="rx-usecs-high"
|
||||
["tx-usecs-high"]="tx-usecs-high"
|
||||
["sample-interval"]="sample-interval"
|
||||
)
|
||||
|
||||
declare -A CURRENT_SETTINGS=(
|
||||
["rx-frames-low"]=""
|
||||
["tx-frames-low"]=""
|
||||
["rx-frames-high"]=""
|
||||
["tx-frames-high"]=""
|
||||
["rx-usecs"]=""
|
||||
["rx-frames"]=""
|
||||
["rx-usecs-irq"]=""
|
||||
["rx-frames-irq"]=""
|
||||
["tx-usecs"]=""
|
||||
["tx-frames"]=""
|
||||
["tx-usecs-irq"]=""
|
||||
["tx-frames-irq"]=""
|
||||
["stats-block-usecs"]=""
|
||||
["pkt-rate-low"]=""
|
||||
["rx-usecs-low"]=""
|
||||
["tx-usecs-low"]=""
|
||||
["pkt-rate-high"]=""
|
||||
["rx-usecs-high"]=""
|
||||
["tx-usecs-high"]=""
|
||||
["sample-interval"]=""
|
||||
)
|
||||
|
||||
declare -A EXPECTED_SETTINGS=(
|
||||
["rx-frames-low"]=""
|
||||
["tx-frames-low"]=""
|
||||
["rx-frames-high"]=""
|
||||
["tx-frames-high"]=""
|
||||
["rx-usecs"]=""
|
||||
["rx-frames"]=""
|
||||
["rx-usecs-irq"]=""
|
||||
["rx-frames-irq"]=""
|
||||
["tx-usecs"]=""
|
||||
["tx-frames"]=""
|
||||
["tx-usecs-irq"]=""
|
||||
["tx-frames-irq"]=""
|
||||
["stats-block-usecs"]=""
|
||||
["pkt-rate-low"]=""
|
||||
["rx-usecs-low"]=""
|
||||
["tx-usecs-low"]=""
|
||||
["pkt-rate-high"]=""
|
||||
["rx-usecs-high"]=""
|
||||
["tx-usecs-high"]=""
|
||||
["sample-interval"]=""
|
||||
)
|
||||
|
||||
# populate the expected settings map
|
||||
for key in ${!SETTINGS_MAP[@]}; do
|
||||
EXPECTED_SETTINGS[$key]=$(get_value $key)
|
||||
done
|
||||
|
||||
# test
|
||||
for key in ${!SETTINGS_MAP[@]}; do
|
||||
value=$((RANDOM % $((2**32-1))))
|
||||
|
||||
ethtool -C $NSIM_NETDEV "$key" "$value"
|
||||
|
||||
EXPECTED_SETTINGS[$key]="$value"
|
||||
expected=${EXPECTED_SETTINGS[@]}
|
||||
current=$(update_current_settings)
|
||||
|
||||
check $? "$current" "$expected"
|
||||
set +x
|
||||
done
|
||||
|
||||
# bool settings which ethtool displays on the same line
|
||||
ethtool -C $NSIM_NETDEV adaptive-rx on
|
||||
s=$(ethtool -c $NSIM_NETDEV | grep -q "Adaptive RX: on TX: off")
|
||||
check $? "$s" ""
|
||||
|
||||
ethtool -C $NSIM_NETDEV adaptive-tx on
|
||||
s=$(ethtool -c $NSIM_NETDEV | grep -q "Adaptive RX: on TX: on")
|
||||
check $? "$s" ""
|
||||
|
||||
if [ $num_errors -eq 0 ]; then
|
||||
echo "PASSED all $((num_passes)) checks"
|
||||
exit 0
|
||||
else
|
||||
echo "FAILED $num_errors/$((num_errors+num_passes)) checks"
|
||||
exit 1
|
||||
fi
|
|
@ -0,0 +1,53 @@
|
|||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
NSIM_ID=$((RANDOM % 1024))
|
||||
NSIM_DEV_SYS=/sys/bus/netdevsim/devices/netdevsim$NSIM_ID
|
||||
NSIM_DEV_DFS=/sys/kernel/debug/netdevsim/netdevsim$NSIM_ID/ports/0
|
||||
NSIM_NETDEV=
|
||||
num_passes=0
|
||||
num_errors=0
|
||||
|
||||
function cleanup_nsim {
|
||||
if [ -e $NSIM_DEV_SYS ]; then
|
||||
echo $NSIM_ID > /sys/bus/netdevsim/del_device
|
||||
fi
|
||||
}
|
||||
|
||||
function cleanup {
|
||||
cleanup_nsim
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
function check {
|
||||
local code=$1
|
||||
local str=$2
|
||||
local exp_str=$3
|
||||
|
||||
if [ $code -ne 0 ]; then
|
||||
((num_errors++))
|
||||
return
|
||||
fi
|
||||
|
||||
if [ "$str" != "$exp_str" ]; then
|
||||
echo -e "Expected: '$exp_str', got '$str'"
|
||||
((num_errors++))
|
||||
return
|
||||
fi
|
||||
|
||||
((num_passes++))
|
||||
}
|
||||
|
||||
function make_netdev {
|
||||
# Make a netdevsim
|
||||
old_netdevs=$(ls /sys/class/net)
|
||||
|
||||
if ! $(lsmod | grep -q netdevsim); then
|
||||
modprobe netdevsim
|
||||
fi
|
||||
|
||||
echo $NSIM_ID > /sys/bus/netdevsim/new_device
|
||||
# get new device name
|
||||
ls /sys/bus/netdevsim/devices/netdevsim${NSIM_ID}/net/
|
||||
}
|
|
@ -1,60 +1,7 @@
|
|||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
NSIM_ID=$((RANDOM % 1024))
|
||||
NSIM_DEV_SYS=/sys/bus/netdevsim/devices/netdevsim$NSIM_ID
|
||||
NSIM_DEV_DFS=/sys/kernel/debug/netdevsim/netdevsim$NSIM_ID/ports/0
|
||||
NSIM_NETDEV=
|
||||
num_passes=0
|
||||
num_errors=0
|
||||
|
||||
function cleanup_nsim {
|
||||
if [ -e $NSIM_DEV_SYS ]; then
|
||||
echo $NSIM_ID > /sys/bus/netdevsim/del_device
|
||||
fi
|
||||
}
|
||||
|
||||
function cleanup {
|
||||
cleanup_nsim
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
function get_netdev_name {
|
||||
local -n old=$1
|
||||
|
||||
new=$(ls /sys/class/net)
|
||||
|
||||
for netdev in $new; do
|
||||
for check in $old; do
|
||||
[ $netdev == $check ] && break
|
||||
done
|
||||
|
||||
if [ $netdev != $check ]; then
|
||||
echo $netdev
|
||||
break
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
function check {
|
||||
local code=$1
|
||||
local str=$2
|
||||
local exp_str=$3
|
||||
|
||||
if [ $code -ne 0 ]; then
|
||||
((num_errors++))
|
||||
return
|
||||
fi
|
||||
|
||||
if [ "$str" != "$exp_str" ]; then
|
||||
echo -e "Expected: '$exp_str', got '$str'"
|
||||
((num_errors++))
|
||||
return
|
||||
fi
|
||||
|
||||
((num_passes++))
|
||||
}
|
||||
source ethtool-common.sh
|
||||
|
||||
# Bail if ethtool is too old
|
||||
if ! ethtool -h | grep include-stat 2>&1 >/dev/null; then
|
||||
|
@ -62,13 +9,7 @@ if ! ethtool -h | grep include-stat 2>&1 >/dev/null; then
|
|||
exit 4
|
||||
fi
|
||||
|
||||
# Make a netdevsim
|
||||
old_netdevs=$(ls /sys/class/net)
|
||||
|
||||
modprobe netdevsim
|
||||
echo $NSIM_ID > /sys/bus/netdevsim/new_device
|
||||
|
||||
NSIM_NETDEV=`get_netdev_name old_netdevs`
|
||||
NSIM_NETDEV=$(make_netdev)
|
||||
|
||||
set -o pipefail
|
||||
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
source ethtool-common.sh
|
||||
|
||||
function get_value {
|
||||
local query="${SETTINGS_MAP[$1]}"
|
||||
|
||||
echo $(ethtool -g $NSIM_NETDEV | \
|
||||
tail -n +$CURR_SETT_LINE | \
|
||||
awk -F':' -v pattern="$query:" '$0 ~ pattern {gsub(/[\t ]/, "", $2); print $2}')
|
||||
}
|
||||
|
||||
function update_current_settings {
|
||||
for key in ${!SETTINGS_MAP[@]}; do
|
||||
CURRENT_SETTINGS[$key]=$(get_value $key)
|
||||
done
|
||||
echo ${CURRENT_SETTINGS[@]}
|
||||
}
|
||||
|
||||
if ! ethtool -h | grep -q set-ring >/dev/null; then
|
||||
echo "SKIP: No --set-ring support in ethtool"
|
||||
exit 4
|
||||
fi
|
||||
|
||||
NSIM_NETDEV=$(make_netdev)
|
||||
|
||||
set -o pipefail
|
||||
|
||||
declare -A SETTINGS_MAP=(
|
||||
["rx"]="RX"
|
||||
["rx-mini"]="RX Mini"
|
||||
["rx-jumbo"]="RX Jumbo"
|
||||
["tx"]="TX"
|
||||
)
|
||||
|
||||
declare -A EXPECTED_SETTINGS=(
|
||||
["rx"]=""
|
||||
["rx-mini"]=""
|
||||
["rx-jumbo"]=""
|
||||
["tx"]=""
|
||||
)
|
||||
|
||||
declare -A CURRENT_SETTINGS=(
|
||||
["rx"]=""
|
||||
["rx-mini"]=""
|
||||
["rx-jumbo"]=""
|
||||
["tx"]=""
|
||||
)
|
||||
|
||||
MAX_VALUE=$((RANDOM % $((2**32-1))))
|
||||
RING_MAX_LIST=$(ls $NSIM_DEV_DFS/ethtool/ring/)
|
||||
|
||||
for ring_max_entry in $RING_MAX_LIST; do
|
||||
echo $MAX_VALUE > $NSIM_DEV_DFS/ethtool/ring/$ring_max_entry
|
||||
done
|
||||
|
||||
CURR_SETT_LINE=$(ethtool -g $NSIM_NETDEV | grep -i -m1 -n 'Current hardware settings' | cut -f1 -d:)
|
||||
|
||||
# populate the expected settings map
|
||||
for key in ${!SETTINGS_MAP[@]}; do
|
||||
EXPECTED_SETTINGS[$key]=$(get_value $key)
|
||||
done
|
||||
|
||||
# test
|
||||
for key in ${!SETTINGS_MAP[@]}; do
|
||||
value=$((RANDOM % $MAX_VALUE))
|
||||
|
||||
ethtool -G $NSIM_NETDEV "$key" "$value"
|
||||
|
||||
EXPECTED_SETTINGS[$key]="$value"
|
||||
expected=${EXPECTED_SETTINGS[@]}
|
||||
current=$(update_current_settings)
|
||||
|
||||
check $? "$current" "$expected"
|
||||
set +x
|
||||
done
|
||||
|
||||
if [ $num_errors -eq 0 ]; then
|
||||
echo "PASSED all $((num_passes)) checks"
|
||||
exit 0
|
||||
else
|
||||
echo "FAILED $num_errors/$((num_errors+num_passes)) checks"
|
||||
exit 1
|
||||
fi
|
Loading…
Reference in New Issue