19da271f8SJakub Kicinski#!/usr/bin/env python3 29da271f8SJakub Kicinski# SPDX-License-Identifier: GPL-2.0 39da271f8SJakub Kicinski 4*a48395f2SStanislav Fomichevimport errno 59da271f8SJakub Kicinskiimport time 69da271f8SJakub Kicinskiimport os 79da271f8SJakub Kicinskifrom lib.py import ksft_run, ksft_exit, ksft_pr 89da271f8SJakub Kicinskifrom lib.py import KsftSkipEx, KsftFailEx 99da271f8SJakub Kicinskifrom lib.py import NetdevFamily, NlError 109da271f8SJakub Kicinskifrom lib.py import NetDrvEpEnv 119da271f8SJakub Kicinskifrom lib.py import cmd, tool, GenerateTraffic 129da271f8SJakub Kicinski 139da271f8SJakub Kicinski 149da271f8SJakub Kicinskidef _write_fail_config(config): 159da271f8SJakub Kicinski for key, value in config.items(): 169da271f8SJakub Kicinski with open("/sys/kernel/debug/fail_function/" + key, "w") as fp: 179da271f8SJakub Kicinski fp.write(str(value) + "\n") 189da271f8SJakub Kicinski 199da271f8SJakub Kicinski 209da271f8SJakub Kicinskidef _enable_pp_allocation_fail(): 219da271f8SJakub Kicinski if not os.path.exists("/sys/kernel/debug/fail_function"): 229da271f8SJakub Kicinski raise KsftSkipEx("Kernel built without function error injection (or DebugFS)") 239da271f8SJakub Kicinski 249da271f8SJakub Kicinski if not os.path.exists("/sys/kernel/debug/fail_function/page_pool_alloc_pages"): 259da271f8SJakub Kicinski with open("/sys/kernel/debug/fail_function/inject", "w") as fp: 269da271f8SJakub Kicinski fp.write("page_pool_alloc_pages\n") 279da271f8SJakub Kicinski 289da271f8SJakub Kicinski _write_fail_config({ 299da271f8SJakub Kicinski "verbose": 0, 309da271f8SJakub Kicinski "interval": 511, 319da271f8SJakub Kicinski "probability": 100, 329da271f8SJakub Kicinski "times": -1, 339da271f8SJakub Kicinski }) 349da271f8SJakub Kicinski 359da271f8SJakub Kicinski 369da271f8SJakub Kicinskidef _disable_pp_allocation_fail(): 379da271f8SJakub Kicinski if not os.path.exists("/sys/kernel/debug/fail_function"): 389da271f8SJakub Kicinski return 399da271f8SJakub Kicinski 409da271f8SJakub Kicinski if os.path.exists("/sys/kernel/debug/fail_function/page_pool_alloc_pages"): 419da271f8SJakub Kicinski with open("/sys/kernel/debug/fail_function/inject", "w") as fp: 429da271f8SJakub Kicinski fp.write("\n") 439da271f8SJakub Kicinski 449da271f8SJakub Kicinski _write_fail_config({ 459da271f8SJakub Kicinski "probability": 0, 469da271f8SJakub Kicinski "times": 0, 479da271f8SJakub Kicinski }) 489da271f8SJakub Kicinski 499da271f8SJakub Kicinski 509da271f8SJakub Kicinskidef test_pp_alloc(cfg, netdevnl): 519da271f8SJakub Kicinski def get_stats(): 529da271f8SJakub Kicinski return netdevnl.qstats_get({"ifindex": cfg.ifindex}, dump=True)[0] 539da271f8SJakub Kicinski 549da271f8SJakub Kicinski def check_traffic_flowing(): 559da271f8SJakub Kicinski stat1 = get_stats() 569da271f8SJakub Kicinski time.sleep(1) 579da271f8SJakub Kicinski stat2 = get_stats() 589da271f8SJakub Kicinski if stat2['rx-packets'] - stat1['rx-packets'] < 15000: 599da271f8SJakub Kicinski raise KsftFailEx("Traffic seems low:", stat2['rx-packets'] - stat1['rx-packets']) 609da271f8SJakub Kicinski 619da271f8SJakub Kicinski 629da271f8SJakub Kicinski try: 639da271f8SJakub Kicinski stats = get_stats() 649da271f8SJakub Kicinski except NlError as e: 65*a48395f2SStanislav Fomichev if e.nl_msg.error == -errno.EOPNOTSUPP: 669da271f8SJakub Kicinski stats = {} 679da271f8SJakub Kicinski else: 689da271f8SJakub Kicinski raise 699da271f8SJakub Kicinski if 'rx-alloc-fail' not in stats: 709da271f8SJakub Kicinski raise KsftSkipEx("Driver does not report 'rx-alloc-fail' via qstats") 719da271f8SJakub Kicinski 729da271f8SJakub Kicinski set_g = False 739da271f8SJakub Kicinski traffic = None 749da271f8SJakub Kicinski try: 759da271f8SJakub Kicinski traffic = GenerateTraffic(cfg) 769da271f8SJakub Kicinski 779da271f8SJakub Kicinski check_traffic_flowing() 789da271f8SJakub Kicinski 799da271f8SJakub Kicinski _enable_pp_allocation_fail() 809da271f8SJakub Kicinski 819da271f8SJakub Kicinski s1 = get_stats() 829da271f8SJakub Kicinski time.sleep(3) 839da271f8SJakub Kicinski s2 = get_stats() 849da271f8SJakub Kicinski 859da271f8SJakub Kicinski if s2['rx-alloc-fail'] - s1['rx-alloc-fail'] < 1: 869da271f8SJakub Kicinski raise KsftSkipEx("Allocation failures not increasing") 879da271f8SJakub Kicinski if s2['rx-alloc-fail'] - s1['rx-alloc-fail'] < 100: 889da271f8SJakub Kicinski raise KsftSkipEx("Allocation increasing too slowly", s2['rx-alloc-fail'] - s1['rx-alloc-fail'], 899da271f8SJakub Kicinski "packets:", s2['rx-packets'] - s1['rx-packets']) 909da271f8SJakub Kicinski 919da271f8SJakub Kicinski # Basic failures are fine, try to wobble some settings to catch extra failures 929da271f8SJakub Kicinski check_traffic_flowing() 939da271f8SJakub Kicinski g = tool("ethtool", "-g " + cfg.ifname, json=True)[0] 949da271f8SJakub Kicinski if 'rx' in g and g["rx"] * 2 <= g["rx-max"]: 959da271f8SJakub Kicinski new_g = g['rx'] * 2 969da271f8SJakub Kicinski elif 'rx' in g: 979da271f8SJakub Kicinski new_g = g['rx'] // 2 989da271f8SJakub Kicinski else: 999da271f8SJakub Kicinski new_g = None 1009da271f8SJakub Kicinski 1019da271f8SJakub Kicinski if new_g: 1029da271f8SJakub Kicinski set_g = cmd(f"ethtool -G {cfg.ifname} rx {new_g}", fail=False).ret == 0 1039da271f8SJakub Kicinski if set_g: 1049da271f8SJakub Kicinski ksft_pr("ethtool -G change retval: success") 1059da271f8SJakub Kicinski else: 1069da271f8SJakub Kicinski ksft_pr("ethtool -G change retval: did not succeed", new_g) 1079da271f8SJakub Kicinski else: 1089da271f8SJakub Kicinski ksft_pr("ethtool -G change retval: did not try") 1099da271f8SJakub Kicinski 1109da271f8SJakub Kicinski time.sleep(0.1) 1119da271f8SJakub Kicinski check_traffic_flowing() 1129da271f8SJakub Kicinski finally: 1139da271f8SJakub Kicinski _disable_pp_allocation_fail() 1149da271f8SJakub Kicinski if traffic: 1159da271f8SJakub Kicinski traffic.stop() 1169da271f8SJakub Kicinski time.sleep(0.1) 1179da271f8SJakub Kicinski if set_g: 1189da271f8SJakub Kicinski cmd(f"ethtool -G {cfg.ifname} rx {g['rx']}") 1199da271f8SJakub Kicinski 1209da271f8SJakub Kicinski 1219da271f8SJakub Kicinskidef main() -> None: 1229da271f8SJakub Kicinski netdevnl = NetdevFamily() 1239da271f8SJakub Kicinski with NetDrvEpEnv(__file__, nsim_test=False) as cfg: 1249da271f8SJakub Kicinski 1259da271f8SJakub Kicinski ksft_run([test_pp_alloc], args=(cfg, netdevnl, )) 1269da271f8SJakub Kicinski ksft_exit() 1279da271f8SJakub Kicinski 1289da271f8SJakub Kicinski 1299da271f8SJakub Kicinskiif __name__ == "__main__": 1309da271f8SJakub Kicinski main() 131