131 lines
3.8 KiB
Python
Executable File
131 lines
3.8 KiB
Python
Executable File
#! /usr/bin/python3 -sP
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
|
|
import errno
|
|
import time
|
|
import os
|
|
from lib.py import ksft_run, ksft_exit, ksft_pr
|
|
from lib.py import KsftSkipEx, KsftFailEx
|
|
from lib.py import NetdevFamily, NlError
|
|
from lib.py import NetDrvEpEnv
|
|
from lib.py import cmd, tool, GenerateTraffic
|
|
|
|
|
|
def _write_fail_config(config):
|
|
for key, value in config.items():
|
|
with open("/sys/kernel/debug/fail_function/" + key, "w") as fp:
|
|
fp.write(str(value) + "\n")
|
|
|
|
|
|
def _enable_pp_allocation_fail():
|
|
if not os.path.exists("/sys/kernel/debug/fail_function"):
|
|
raise KsftSkipEx("Kernel built without function error injection (or DebugFS)")
|
|
|
|
if not os.path.exists("/sys/kernel/debug/fail_function/page_pool_alloc_pages"):
|
|
with open("/sys/kernel/debug/fail_function/inject", "w") as fp:
|
|
fp.write("page_pool_alloc_pages\n")
|
|
|
|
_write_fail_config({
|
|
"verbose": 0,
|
|
"interval": 511,
|
|
"probability": 100,
|
|
"times": -1,
|
|
})
|
|
|
|
|
|
def _disable_pp_allocation_fail():
|
|
if not os.path.exists("/sys/kernel/debug/fail_function"):
|
|
return
|
|
|
|
if os.path.exists("/sys/kernel/debug/fail_function/page_pool_alloc_pages"):
|
|
with open("/sys/kernel/debug/fail_function/inject", "w") as fp:
|
|
fp.write("\n")
|
|
|
|
_write_fail_config({
|
|
"probability": 0,
|
|
"times": 0,
|
|
})
|
|
|
|
|
|
def test_pp_alloc(cfg, netdevnl):
|
|
def get_stats():
|
|
return netdevnl.qstats_get({"ifindex": cfg.ifindex}, dump=True)[0]
|
|
|
|
def check_traffic_flowing():
|
|
stat1 = get_stats()
|
|
time.sleep(1)
|
|
stat2 = get_stats()
|
|
if stat2['rx-packets'] - stat1['rx-packets'] < 15000:
|
|
raise KsftFailEx("Traffic seems low:", stat2['rx-packets'] - stat1['rx-packets'])
|
|
|
|
|
|
try:
|
|
stats = get_stats()
|
|
except NlError as e:
|
|
if e.nl_msg.error == -errno.EOPNOTSUPP:
|
|
stats = {}
|
|
else:
|
|
raise
|
|
if 'rx-alloc-fail' not in stats:
|
|
raise KsftSkipEx("Driver does not report 'rx-alloc-fail' via qstats")
|
|
|
|
set_g = False
|
|
traffic = None
|
|
try:
|
|
traffic = GenerateTraffic(cfg)
|
|
|
|
check_traffic_flowing()
|
|
|
|
_enable_pp_allocation_fail()
|
|
|
|
s1 = get_stats()
|
|
time.sleep(3)
|
|
s2 = get_stats()
|
|
|
|
if s2['rx-alloc-fail'] - s1['rx-alloc-fail'] < 1:
|
|
raise KsftSkipEx("Allocation failures not increasing")
|
|
if s2['rx-alloc-fail'] - s1['rx-alloc-fail'] < 100:
|
|
raise KsftSkipEx("Allocation increasing too slowly", s2['rx-alloc-fail'] - s1['rx-alloc-fail'],
|
|
"packets:", s2['rx-packets'] - s1['rx-packets'])
|
|
|
|
# Basic failures are fine, try to wobble some settings to catch extra failures
|
|
check_traffic_flowing()
|
|
g = tool("ethtool", "-g " + cfg.ifname, json=True)[0]
|
|
if 'rx' in g and g["rx"] * 2 <= g["rx-max"]:
|
|
new_g = g['rx'] * 2
|
|
elif 'rx' in g:
|
|
new_g = g['rx'] // 2
|
|
else:
|
|
new_g = None
|
|
|
|
if new_g:
|
|
set_g = cmd(f"ethtool -G {cfg.ifname} rx {new_g}", fail=False).ret == 0
|
|
if set_g:
|
|
ksft_pr("ethtool -G change retval: success")
|
|
else:
|
|
ksft_pr("ethtool -G change retval: did not succeed", new_g)
|
|
else:
|
|
ksft_pr("ethtool -G change retval: did not try")
|
|
|
|
time.sleep(0.1)
|
|
check_traffic_flowing()
|
|
finally:
|
|
_disable_pp_allocation_fail()
|
|
if traffic:
|
|
traffic.stop()
|
|
time.sleep(0.1)
|
|
if set_g:
|
|
cmd(f"ethtool -G {cfg.ifname} rx {g['rx']}")
|
|
|
|
|
|
def main() -> None:
|
|
netdevnl = NetdevFamily()
|
|
with NetDrvEpEnv(__file__, nsim_test=False) as cfg:
|
|
|
|
ksft_run([test_pp_alloc], args=(cfg, netdevnl, ))
|
|
ksft_exit()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|