18c2ecf20Sopenharmony_ci#!/usr/bin/env python3 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci# Copyright (C) 2017 Netronome Systems, Inc. 48c2ecf20Sopenharmony_ci# Copyright (c) 2019 Mellanox Technologies. All rights reserved 58c2ecf20Sopenharmony_ci# 68c2ecf20Sopenharmony_ci# This software is licensed under the GNU General License Version 2, 78c2ecf20Sopenharmony_ci# June 1991 as shown in the file COPYING in the top-level directory of this 88c2ecf20Sopenharmony_ci# source tree. 98c2ecf20Sopenharmony_ci# 108c2ecf20Sopenharmony_ci# THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" 118c2ecf20Sopenharmony_ci# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, 128c2ecf20Sopenharmony_ci# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 138c2ecf20Sopenharmony_ci# FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE 148c2ecf20Sopenharmony_ci# OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME 158c2ecf20Sopenharmony_ci# THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cifrom datetime import datetime 188c2ecf20Sopenharmony_ciimport argparse 198c2ecf20Sopenharmony_ciimport errno 208c2ecf20Sopenharmony_ciimport json 218c2ecf20Sopenharmony_ciimport os 228c2ecf20Sopenharmony_ciimport pprint 238c2ecf20Sopenharmony_ciimport random 248c2ecf20Sopenharmony_ciimport re 258c2ecf20Sopenharmony_ciimport stat 268c2ecf20Sopenharmony_ciimport string 278c2ecf20Sopenharmony_ciimport struct 288c2ecf20Sopenharmony_ciimport subprocess 298c2ecf20Sopenharmony_ciimport time 308c2ecf20Sopenharmony_ciimport traceback 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cilogfile = None 338c2ecf20Sopenharmony_cilog_level = 1 348c2ecf20Sopenharmony_ciskip_extack = False 358c2ecf20Sopenharmony_cibpf_test_dir = os.path.dirname(os.path.realpath(__file__)) 368c2ecf20Sopenharmony_cipp = pprint.PrettyPrinter() 378c2ecf20Sopenharmony_cidevs = [] # devices we created for clean up 388c2ecf20Sopenharmony_cifiles = [] # files to be removed 398c2ecf20Sopenharmony_cinetns = [] # net namespaces to be removed 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cidef log_get_sec(level=0): 428c2ecf20Sopenharmony_ci return "*" * (log_level + level) 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cidef log_level_inc(add=1): 458c2ecf20Sopenharmony_ci global log_level 468c2ecf20Sopenharmony_ci log_level += add 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cidef log_level_dec(sub=1): 498c2ecf20Sopenharmony_ci global log_level 508c2ecf20Sopenharmony_ci log_level -= sub 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cidef log_level_set(level): 538c2ecf20Sopenharmony_ci global log_level 548c2ecf20Sopenharmony_ci log_level = level 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cidef log(header, data, level=None): 578c2ecf20Sopenharmony_ci """ 588c2ecf20Sopenharmony_ci Output to an optional log. 598c2ecf20Sopenharmony_ci """ 608c2ecf20Sopenharmony_ci if logfile is None: 618c2ecf20Sopenharmony_ci return 628c2ecf20Sopenharmony_ci if level is not None: 638c2ecf20Sopenharmony_ci log_level_set(level) 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci if not isinstance(data, str): 668c2ecf20Sopenharmony_ci data = pp.pformat(data) 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci if len(header): 698c2ecf20Sopenharmony_ci logfile.write("\n" + log_get_sec() + " ") 708c2ecf20Sopenharmony_ci logfile.write(header) 718c2ecf20Sopenharmony_ci if len(header) and len(data.strip()): 728c2ecf20Sopenharmony_ci logfile.write("\n") 738c2ecf20Sopenharmony_ci logfile.write(data) 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cidef skip(cond, msg): 768c2ecf20Sopenharmony_ci if not cond: 778c2ecf20Sopenharmony_ci return 788c2ecf20Sopenharmony_ci print("SKIP: " + msg) 798c2ecf20Sopenharmony_ci log("SKIP: " + msg, "", level=1) 808c2ecf20Sopenharmony_ci os.sys.exit(0) 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cidef fail(cond, msg): 838c2ecf20Sopenharmony_ci if not cond: 848c2ecf20Sopenharmony_ci return 858c2ecf20Sopenharmony_ci print("FAIL: " + msg) 868c2ecf20Sopenharmony_ci tb = "".join(traceback.extract_stack().format()) 878c2ecf20Sopenharmony_ci print(tb) 888c2ecf20Sopenharmony_ci log("FAIL: " + msg, tb, level=1) 898c2ecf20Sopenharmony_ci os.sys.exit(1) 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cidef start_test(msg): 928c2ecf20Sopenharmony_ci log(msg, "", level=1) 938c2ecf20Sopenharmony_ci log_level_inc() 948c2ecf20Sopenharmony_ci print(msg) 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cidef cmd(cmd, shell=True, include_stderr=False, background=False, fail=True): 978c2ecf20Sopenharmony_ci """ 988c2ecf20Sopenharmony_ci Run a command in subprocess and return tuple of (retval, stdout); 998c2ecf20Sopenharmony_ci optionally return stderr as well as third value. 1008c2ecf20Sopenharmony_ci """ 1018c2ecf20Sopenharmony_ci proc = subprocess.Popen(cmd, shell=shell, stdout=subprocess.PIPE, 1028c2ecf20Sopenharmony_ci stderr=subprocess.PIPE) 1038c2ecf20Sopenharmony_ci if background: 1048c2ecf20Sopenharmony_ci msg = "%s START: %s" % (log_get_sec(1), 1058c2ecf20Sopenharmony_ci datetime.now().strftime("%H:%M:%S.%f")) 1068c2ecf20Sopenharmony_ci log("BKG " + proc.args, msg) 1078c2ecf20Sopenharmony_ci return proc 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci return cmd_result(proc, include_stderr=include_stderr, fail=fail) 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_cidef cmd_result(proc, include_stderr=False, fail=False): 1128c2ecf20Sopenharmony_ci stdout, stderr = proc.communicate() 1138c2ecf20Sopenharmony_ci stdout = stdout.decode("utf-8") 1148c2ecf20Sopenharmony_ci stderr = stderr.decode("utf-8") 1158c2ecf20Sopenharmony_ci proc.stdout.close() 1168c2ecf20Sopenharmony_ci proc.stderr.close() 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci stderr = "\n" + stderr 1198c2ecf20Sopenharmony_ci if stderr[-1] == "\n": 1208c2ecf20Sopenharmony_ci stderr = stderr[:-1] 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci sec = log_get_sec(1) 1238c2ecf20Sopenharmony_ci log("CMD " + proc.args, 1248c2ecf20Sopenharmony_ci "RETCODE: %d\n%s STDOUT:\n%s%s STDERR:%s\n%s END: %s" % 1258c2ecf20Sopenharmony_ci (proc.returncode, sec, stdout, sec, stderr, 1268c2ecf20Sopenharmony_ci sec, datetime.now().strftime("%H:%M:%S.%f"))) 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci if proc.returncode != 0 and fail: 1298c2ecf20Sopenharmony_ci if len(stderr) > 0 and stderr[-1] == "\n": 1308c2ecf20Sopenharmony_ci stderr = stderr[:-1] 1318c2ecf20Sopenharmony_ci raise Exception("Command failed: %s\n%s" % (proc.args, stderr)) 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci if include_stderr: 1348c2ecf20Sopenharmony_ci return proc.returncode, stdout, stderr 1358c2ecf20Sopenharmony_ci else: 1368c2ecf20Sopenharmony_ci return proc.returncode, stdout 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cidef rm(f): 1398c2ecf20Sopenharmony_ci cmd("rm -f %s" % (f)) 1408c2ecf20Sopenharmony_ci if f in files: 1418c2ecf20Sopenharmony_ci files.remove(f) 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cidef tool(name, args, flags, JSON=True, ns="", fail=True, include_stderr=False): 1448c2ecf20Sopenharmony_ci params = "" 1458c2ecf20Sopenharmony_ci if JSON: 1468c2ecf20Sopenharmony_ci params += "%s " % (flags["json"]) 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci if ns != "": 1498c2ecf20Sopenharmony_ci ns = "ip netns exec %s " % (ns) 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci if include_stderr: 1528c2ecf20Sopenharmony_ci ret, stdout, stderr = cmd(ns + name + " " + params + args, 1538c2ecf20Sopenharmony_ci fail=fail, include_stderr=True) 1548c2ecf20Sopenharmony_ci else: 1558c2ecf20Sopenharmony_ci ret, stdout = cmd(ns + name + " " + params + args, 1568c2ecf20Sopenharmony_ci fail=fail, include_stderr=False) 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci if JSON and len(stdout.strip()) != 0: 1598c2ecf20Sopenharmony_ci out = json.loads(stdout) 1608c2ecf20Sopenharmony_ci else: 1618c2ecf20Sopenharmony_ci out = stdout 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci if include_stderr: 1648c2ecf20Sopenharmony_ci return ret, out, stderr 1658c2ecf20Sopenharmony_ci else: 1668c2ecf20Sopenharmony_ci return ret, out 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cidef bpftool(args, JSON=True, ns="", fail=True, include_stderr=False): 1698c2ecf20Sopenharmony_ci return tool("bpftool", args, {"json":"-p"}, JSON=JSON, ns=ns, 1708c2ecf20Sopenharmony_ci fail=fail, include_stderr=include_stderr) 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_cidef bpftool_prog_list(expected=None, ns=""): 1738c2ecf20Sopenharmony_ci _, progs = bpftool("prog show", JSON=True, ns=ns, fail=True) 1748c2ecf20Sopenharmony_ci # Remove the base progs 1758c2ecf20Sopenharmony_ci for p in base_progs: 1768c2ecf20Sopenharmony_ci if p in progs: 1778c2ecf20Sopenharmony_ci progs.remove(p) 1788c2ecf20Sopenharmony_ci if expected is not None: 1798c2ecf20Sopenharmony_ci if len(progs) != expected: 1808c2ecf20Sopenharmony_ci fail(True, "%d BPF programs loaded, expected %d" % 1818c2ecf20Sopenharmony_ci (len(progs), expected)) 1828c2ecf20Sopenharmony_ci return progs 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_cidef bpftool_map_list(expected=None, ns=""): 1858c2ecf20Sopenharmony_ci _, maps = bpftool("map show", JSON=True, ns=ns, fail=True) 1868c2ecf20Sopenharmony_ci # Remove the base maps 1878c2ecf20Sopenharmony_ci maps = [m for m in maps if m not in base_maps and m.get('name') not in base_map_names] 1888c2ecf20Sopenharmony_ci if expected is not None: 1898c2ecf20Sopenharmony_ci if len(maps) != expected: 1908c2ecf20Sopenharmony_ci fail(True, "%d BPF maps loaded, expected %d" % 1918c2ecf20Sopenharmony_ci (len(maps), expected)) 1928c2ecf20Sopenharmony_ci return maps 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_cidef bpftool_prog_list_wait(expected=0, n_retry=20): 1958c2ecf20Sopenharmony_ci for i in range(n_retry): 1968c2ecf20Sopenharmony_ci nprogs = len(bpftool_prog_list()) 1978c2ecf20Sopenharmony_ci if nprogs == expected: 1988c2ecf20Sopenharmony_ci return 1998c2ecf20Sopenharmony_ci time.sleep(0.05) 2008c2ecf20Sopenharmony_ci raise Exception("Time out waiting for program counts to stabilize want %d, have %d" % (expected, nprogs)) 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cidef bpftool_map_list_wait(expected=0, n_retry=20): 2038c2ecf20Sopenharmony_ci for i in range(n_retry): 2048c2ecf20Sopenharmony_ci nmaps = len(bpftool_map_list()) 2058c2ecf20Sopenharmony_ci if nmaps == expected: 2068c2ecf20Sopenharmony_ci return 2078c2ecf20Sopenharmony_ci time.sleep(0.05) 2088c2ecf20Sopenharmony_ci raise Exception("Time out waiting for map counts to stabilize want %d, have %d" % (expected, nmaps)) 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_cidef bpftool_prog_load(sample, file_name, maps=[], prog_type="xdp", dev=None, 2118c2ecf20Sopenharmony_ci fail=True, include_stderr=False): 2128c2ecf20Sopenharmony_ci args = "prog load %s %s" % (os.path.join(bpf_test_dir, sample), file_name) 2138c2ecf20Sopenharmony_ci if prog_type is not None: 2148c2ecf20Sopenharmony_ci args += " type " + prog_type 2158c2ecf20Sopenharmony_ci if dev is not None: 2168c2ecf20Sopenharmony_ci args += " dev " + dev 2178c2ecf20Sopenharmony_ci if len(maps): 2188c2ecf20Sopenharmony_ci args += " map " + " map ".join(maps) 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci res = bpftool(args, fail=fail, include_stderr=include_stderr) 2218c2ecf20Sopenharmony_ci if res[0] == 0: 2228c2ecf20Sopenharmony_ci files.append(file_name) 2238c2ecf20Sopenharmony_ci return res 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cidef ip(args, force=False, JSON=True, ns="", fail=True, include_stderr=False): 2268c2ecf20Sopenharmony_ci if force: 2278c2ecf20Sopenharmony_ci args = "-force " + args 2288c2ecf20Sopenharmony_ci return tool("ip", args, {"json":"-j"}, JSON=JSON, ns=ns, 2298c2ecf20Sopenharmony_ci fail=fail, include_stderr=include_stderr) 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_cidef tc(args, JSON=True, ns="", fail=True, include_stderr=False): 2328c2ecf20Sopenharmony_ci return tool("tc", args, {"json":"-p"}, JSON=JSON, ns=ns, 2338c2ecf20Sopenharmony_ci fail=fail, include_stderr=include_stderr) 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_cidef ethtool(dev, opt, args, fail=True): 2368c2ecf20Sopenharmony_ci return cmd("ethtool %s %s %s" % (opt, dev["ifname"], args), fail=fail) 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cidef bpf_obj(name, sec=".text", path=bpf_test_dir,): 2398c2ecf20Sopenharmony_ci return "obj %s sec %s" % (os.path.join(path, name), sec) 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cidef bpf_pinned(name): 2428c2ecf20Sopenharmony_ci return "pinned %s" % (name) 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_cidef bpf_bytecode(bytecode): 2458c2ecf20Sopenharmony_ci return "bytecode \"%s\"" % (bytecode) 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_cidef mknetns(n_retry=10): 2488c2ecf20Sopenharmony_ci for i in range(n_retry): 2498c2ecf20Sopenharmony_ci name = ''.join([random.choice(string.ascii_letters) for i in range(8)]) 2508c2ecf20Sopenharmony_ci ret, _ = ip("netns add %s" % (name), fail=False) 2518c2ecf20Sopenharmony_ci if ret == 0: 2528c2ecf20Sopenharmony_ci netns.append(name) 2538c2ecf20Sopenharmony_ci return name 2548c2ecf20Sopenharmony_ci return None 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_cidef int2str(fmt, val): 2578c2ecf20Sopenharmony_ci ret = [] 2588c2ecf20Sopenharmony_ci for b in struct.pack(fmt, val): 2598c2ecf20Sopenharmony_ci ret.append(int(b)) 2608c2ecf20Sopenharmony_ci return " ".join(map(lambda x: str(x), ret)) 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_cidef str2int(strtab): 2638c2ecf20Sopenharmony_ci inttab = [] 2648c2ecf20Sopenharmony_ci for i in strtab: 2658c2ecf20Sopenharmony_ci inttab.append(int(i, 16)) 2668c2ecf20Sopenharmony_ci ba = bytearray(inttab) 2678c2ecf20Sopenharmony_ci if len(strtab) == 4: 2688c2ecf20Sopenharmony_ci fmt = "I" 2698c2ecf20Sopenharmony_ci elif len(strtab) == 8: 2708c2ecf20Sopenharmony_ci fmt = "Q" 2718c2ecf20Sopenharmony_ci else: 2728c2ecf20Sopenharmony_ci raise Exception("String array of len %d can't be unpacked to an int" % 2738c2ecf20Sopenharmony_ci (len(strtab))) 2748c2ecf20Sopenharmony_ci return struct.unpack(fmt, ba)[0] 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ciclass DebugfsDir: 2778c2ecf20Sopenharmony_ci """ 2788c2ecf20Sopenharmony_ci Class for accessing DebugFS directories as a dictionary. 2798c2ecf20Sopenharmony_ci """ 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci def __init__(self, path): 2828c2ecf20Sopenharmony_ci self.path = path 2838c2ecf20Sopenharmony_ci self._dict = self._debugfs_dir_read(path) 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci def __len__(self): 2868c2ecf20Sopenharmony_ci return len(self._dict.keys()) 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci def __getitem__(self, key): 2898c2ecf20Sopenharmony_ci if type(key) is int: 2908c2ecf20Sopenharmony_ci key = list(self._dict.keys())[key] 2918c2ecf20Sopenharmony_ci return self._dict[key] 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci def __setitem__(self, key, value): 2948c2ecf20Sopenharmony_ci log("DebugFS set %s = %s" % (key, value), "") 2958c2ecf20Sopenharmony_ci log_level_inc() 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci cmd("echo '%s' > %s/%s" % (value, self.path, key)) 2988c2ecf20Sopenharmony_ci log_level_dec() 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci _, out = cmd('cat %s/%s' % (self.path, key)) 3018c2ecf20Sopenharmony_ci self._dict[key] = out.strip() 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci def _debugfs_dir_read(self, path): 3048c2ecf20Sopenharmony_ci dfs = {} 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci log("DebugFS state for %s" % (path), "") 3078c2ecf20Sopenharmony_ci log_level_inc(add=2) 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci _, out = cmd('ls ' + path) 3108c2ecf20Sopenharmony_ci for f in out.split(): 3118c2ecf20Sopenharmony_ci if f == "ports": 3128c2ecf20Sopenharmony_ci continue 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci p = os.path.join(path, f) 3158c2ecf20Sopenharmony_ci if not os.stat(p).st_mode & stat.S_IRUSR: 3168c2ecf20Sopenharmony_ci continue 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci if os.path.isfile(p): 3198c2ecf20Sopenharmony_ci # We need to init trap_flow_action_cookie before read it 3208c2ecf20Sopenharmony_ci if f == "trap_flow_action_cookie": 3218c2ecf20Sopenharmony_ci cmd('echo deadbeef > %s/%s' % (path, f)) 3228c2ecf20Sopenharmony_ci _, out = cmd('cat %s/%s' % (path, f)) 3238c2ecf20Sopenharmony_ci dfs[f] = out.strip() 3248c2ecf20Sopenharmony_ci elif os.path.isdir(p): 3258c2ecf20Sopenharmony_ci dfs[f] = DebugfsDir(p) 3268c2ecf20Sopenharmony_ci else: 3278c2ecf20Sopenharmony_ci raise Exception("%s is neither file nor directory" % (p)) 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci log_level_dec() 3308c2ecf20Sopenharmony_ci log("DebugFS state", dfs) 3318c2ecf20Sopenharmony_ci log_level_dec() 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci return dfs 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ciclass NetdevSimDev: 3368c2ecf20Sopenharmony_ci """ 3378c2ecf20Sopenharmony_ci Class for netdevsim bus device and its attributes. 3388c2ecf20Sopenharmony_ci """ 3398c2ecf20Sopenharmony_ci @staticmethod 3408c2ecf20Sopenharmony_ci def ctrl_write(path, val): 3418c2ecf20Sopenharmony_ci fullpath = os.path.join("/sys/bus/netdevsim/", path) 3428c2ecf20Sopenharmony_ci try: 3438c2ecf20Sopenharmony_ci with open(fullpath, "w") as f: 3448c2ecf20Sopenharmony_ci f.write(val) 3458c2ecf20Sopenharmony_ci except OSError as e: 3468c2ecf20Sopenharmony_ci log("WRITE %s: %r" % (fullpath, val), -e.errno) 3478c2ecf20Sopenharmony_ci raise e 3488c2ecf20Sopenharmony_ci log("WRITE %s: %r" % (fullpath, val), 0) 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci def __init__(self, port_count=1): 3518c2ecf20Sopenharmony_ci addr = 0 3528c2ecf20Sopenharmony_ci while True: 3538c2ecf20Sopenharmony_ci try: 3548c2ecf20Sopenharmony_ci self.ctrl_write("new_device", "%u %u" % (addr, port_count)) 3558c2ecf20Sopenharmony_ci except OSError as e: 3568c2ecf20Sopenharmony_ci if e.errno == errno.ENOSPC: 3578c2ecf20Sopenharmony_ci addr += 1 3588c2ecf20Sopenharmony_ci continue 3598c2ecf20Sopenharmony_ci raise e 3608c2ecf20Sopenharmony_ci break 3618c2ecf20Sopenharmony_ci self.addr = addr 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci # As probe of netdevsim device might happen from a workqueue, 3648c2ecf20Sopenharmony_ci # so wait here until all netdevs appear. 3658c2ecf20Sopenharmony_ci self.wait_for_netdevs(port_count) 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci ret, out = cmd("udevadm settle", fail=False) 3688c2ecf20Sopenharmony_ci if ret: 3698c2ecf20Sopenharmony_ci raise Exception("udevadm settle failed") 3708c2ecf20Sopenharmony_ci ifnames = self.get_ifnames() 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci devs.append(self) 3738c2ecf20Sopenharmony_ci self.dfs_dir = "/sys/kernel/debug/netdevsim/netdevsim%u/" % addr 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci self.nsims = [] 3768c2ecf20Sopenharmony_ci for port_index in range(port_count): 3778c2ecf20Sopenharmony_ci self.nsims.append(NetdevSim(self, port_index, ifnames[port_index])) 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci def get_ifnames(self): 3808c2ecf20Sopenharmony_ci ifnames = [] 3818c2ecf20Sopenharmony_ci listdir = os.listdir("/sys/bus/netdevsim/devices/netdevsim%u/net/" % self.addr) 3828c2ecf20Sopenharmony_ci for ifname in listdir: 3838c2ecf20Sopenharmony_ci ifnames.append(ifname) 3848c2ecf20Sopenharmony_ci ifnames.sort() 3858c2ecf20Sopenharmony_ci return ifnames 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci def wait_for_netdevs(self, port_count): 3888c2ecf20Sopenharmony_ci timeout = 5 3898c2ecf20Sopenharmony_ci timeout_start = time.time() 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci while True: 3928c2ecf20Sopenharmony_ci try: 3938c2ecf20Sopenharmony_ci ifnames = self.get_ifnames() 3948c2ecf20Sopenharmony_ci except FileNotFoundError as e: 3958c2ecf20Sopenharmony_ci ifnames = [] 3968c2ecf20Sopenharmony_ci if len(ifnames) == port_count: 3978c2ecf20Sopenharmony_ci break 3988c2ecf20Sopenharmony_ci if time.time() < timeout_start + timeout: 3998c2ecf20Sopenharmony_ci continue 4008c2ecf20Sopenharmony_ci raise Exception("netdevices did not appear within timeout") 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci def dfs_num_bound_progs(self): 4038c2ecf20Sopenharmony_ci path = os.path.join(self.dfs_dir, "bpf_bound_progs") 4048c2ecf20Sopenharmony_ci _, progs = cmd('ls %s' % (path)) 4058c2ecf20Sopenharmony_ci return len(progs.split()) 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci def dfs_get_bound_progs(self, expected): 4088c2ecf20Sopenharmony_ci progs = DebugfsDir(os.path.join(self.dfs_dir, "bpf_bound_progs")) 4098c2ecf20Sopenharmony_ci if expected is not None: 4108c2ecf20Sopenharmony_ci if len(progs) != expected: 4118c2ecf20Sopenharmony_ci fail(True, "%d BPF programs bound, expected %d" % 4128c2ecf20Sopenharmony_ci (len(progs), expected)) 4138c2ecf20Sopenharmony_ci return progs 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci def remove(self): 4168c2ecf20Sopenharmony_ci self.ctrl_write("del_device", "%u" % (self.addr, )) 4178c2ecf20Sopenharmony_ci devs.remove(self) 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci def remove_nsim(self, nsim): 4208c2ecf20Sopenharmony_ci self.nsims.remove(nsim) 4218c2ecf20Sopenharmony_ci self.ctrl_write("devices/netdevsim%u/del_port" % (self.addr, ), 4228c2ecf20Sopenharmony_ci "%u" % (nsim.port_index, )) 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ciclass NetdevSim: 4258c2ecf20Sopenharmony_ci """ 4268c2ecf20Sopenharmony_ci Class for netdevsim netdevice and its attributes. 4278c2ecf20Sopenharmony_ci """ 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci def __init__(self, nsimdev, port_index, ifname): 4308c2ecf20Sopenharmony_ci # In case udev renamed the netdev to according to new schema, 4318c2ecf20Sopenharmony_ci # check if the name matches the port_index. 4328c2ecf20Sopenharmony_ci nsimnamere = re.compile("eni\d+np(\d+)") 4338c2ecf20Sopenharmony_ci match = nsimnamere.match(ifname) 4348c2ecf20Sopenharmony_ci if match and int(match.groups()[0]) != port_index + 1: 4358c2ecf20Sopenharmony_ci raise Exception("netdevice name mismatches the expected one") 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci self.nsimdev = nsimdev 4388c2ecf20Sopenharmony_ci self.port_index = port_index 4398c2ecf20Sopenharmony_ci self.ns = "" 4408c2ecf20Sopenharmony_ci self.dfs_dir = "%s/ports/%u/" % (nsimdev.dfs_dir, port_index) 4418c2ecf20Sopenharmony_ci self.dfs_refresh() 4428c2ecf20Sopenharmony_ci _, [self.dev] = ip("link show dev %s" % ifname) 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci def __getitem__(self, key): 4458c2ecf20Sopenharmony_ci return self.dev[key] 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci def remove(self): 4488c2ecf20Sopenharmony_ci self.nsimdev.remove_nsim(self) 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci def dfs_refresh(self): 4518c2ecf20Sopenharmony_ci self.dfs = DebugfsDir(self.dfs_dir) 4528c2ecf20Sopenharmony_ci return self.dfs 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci def dfs_read(self, f): 4558c2ecf20Sopenharmony_ci path = os.path.join(self.dfs_dir, f) 4568c2ecf20Sopenharmony_ci _, data = cmd('cat %s' % (path)) 4578c2ecf20Sopenharmony_ci return data.strip() 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci def wait_for_flush(self, bound=0, total=0, n_retry=20): 4608c2ecf20Sopenharmony_ci for i in range(n_retry): 4618c2ecf20Sopenharmony_ci nbound = self.nsimdev.dfs_num_bound_progs() 4628c2ecf20Sopenharmony_ci nprogs = len(bpftool_prog_list()) 4638c2ecf20Sopenharmony_ci if nbound == bound and nprogs == total: 4648c2ecf20Sopenharmony_ci return 4658c2ecf20Sopenharmony_ci time.sleep(0.05) 4668c2ecf20Sopenharmony_ci raise Exception("Time out waiting for program counts to stabilize want %d/%d, have %d bound, %d loaded" % (bound, total, nbound, nprogs)) 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci def set_ns(self, ns): 4698c2ecf20Sopenharmony_ci name = "1" if ns == "" else ns 4708c2ecf20Sopenharmony_ci ip("link set dev %s netns %s" % (self.dev["ifname"], name), ns=self.ns) 4718c2ecf20Sopenharmony_ci self.ns = ns 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci def set_mtu(self, mtu, fail=True): 4748c2ecf20Sopenharmony_ci return ip("link set dev %s mtu %d" % (self.dev["ifname"], mtu), 4758c2ecf20Sopenharmony_ci fail=fail) 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci def set_xdp(self, bpf, mode, force=False, JSON=True, verbose=False, 4788c2ecf20Sopenharmony_ci fail=True, include_stderr=False): 4798c2ecf20Sopenharmony_ci if verbose: 4808c2ecf20Sopenharmony_ci bpf += " verbose" 4818c2ecf20Sopenharmony_ci return ip("link set dev %s xdp%s %s" % (self.dev["ifname"], mode, bpf), 4828c2ecf20Sopenharmony_ci force=force, JSON=JSON, 4838c2ecf20Sopenharmony_ci fail=fail, include_stderr=include_stderr) 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci def unset_xdp(self, mode, force=False, JSON=True, 4868c2ecf20Sopenharmony_ci fail=True, include_stderr=False): 4878c2ecf20Sopenharmony_ci return ip("link set dev %s xdp%s off" % (self.dev["ifname"], mode), 4888c2ecf20Sopenharmony_ci force=force, JSON=JSON, 4898c2ecf20Sopenharmony_ci fail=fail, include_stderr=include_stderr) 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci def ip_link_show(self, xdp): 4928c2ecf20Sopenharmony_ci _, link = ip("link show dev %s" % (self['ifname'])) 4938c2ecf20Sopenharmony_ci if len(link) > 1: 4948c2ecf20Sopenharmony_ci raise Exception("Multiple objects on ip link show") 4958c2ecf20Sopenharmony_ci if len(link) < 1: 4968c2ecf20Sopenharmony_ci return {} 4978c2ecf20Sopenharmony_ci fail(xdp != "xdp" in link, 4988c2ecf20Sopenharmony_ci "XDP program not reporting in iplink (reported %s, expected %s)" % 4998c2ecf20Sopenharmony_ci ("xdp" in link, xdp)) 5008c2ecf20Sopenharmony_ci return link[0] 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci def tc_add_ingress(self): 5038c2ecf20Sopenharmony_ci tc("qdisc add dev %s ingress" % (self['ifname'])) 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci def tc_del_ingress(self): 5068c2ecf20Sopenharmony_ci tc("qdisc del dev %s ingress" % (self['ifname'])) 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci def tc_flush_filters(self, bound=0, total=0): 5098c2ecf20Sopenharmony_ci self.tc_del_ingress() 5108c2ecf20Sopenharmony_ci self.tc_add_ingress() 5118c2ecf20Sopenharmony_ci self.wait_for_flush(bound=bound, total=total) 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci def tc_show_ingress(self, expected=None): 5148c2ecf20Sopenharmony_ci # No JSON support, oh well... 5158c2ecf20Sopenharmony_ci flags = ["skip_sw", "skip_hw", "in_hw"] 5168c2ecf20Sopenharmony_ci named = ["protocol", "pref", "chain", "handle", "id", "tag"] 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci args = "-s filter show dev %s ingress" % (self['ifname']) 5198c2ecf20Sopenharmony_ci _, out = tc(args, JSON=False) 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci filters = [] 5228c2ecf20Sopenharmony_ci lines = out.split('\n') 5238c2ecf20Sopenharmony_ci for line in lines: 5248c2ecf20Sopenharmony_ci words = line.split() 5258c2ecf20Sopenharmony_ci if "handle" not in words: 5268c2ecf20Sopenharmony_ci continue 5278c2ecf20Sopenharmony_ci fltr = {} 5288c2ecf20Sopenharmony_ci for flag in flags: 5298c2ecf20Sopenharmony_ci fltr[flag] = flag in words 5308c2ecf20Sopenharmony_ci for name in named: 5318c2ecf20Sopenharmony_ci try: 5328c2ecf20Sopenharmony_ci idx = words.index(name) 5338c2ecf20Sopenharmony_ci fltr[name] = words[idx + 1] 5348c2ecf20Sopenharmony_ci except ValueError: 5358c2ecf20Sopenharmony_ci pass 5368c2ecf20Sopenharmony_ci filters.append(fltr) 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci if expected is not None: 5398c2ecf20Sopenharmony_ci fail(len(filters) != expected, 5408c2ecf20Sopenharmony_ci "%d ingress filters loaded, expected %d" % 5418c2ecf20Sopenharmony_ci (len(filters), expected)) 5428c2ecf20Sopenharmony_ci return filters 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci def cls_filter_op(self, op, qdisc="ingress", prio=None, handle=None, 5458c2ecf20Sopenharmony_ci chain=None, cls="", params="", 5468c2ecf20Sopenharmony_ci fail=True, include_stderr=False): 5478c2ecf20Sopenharmony_ci spec = "" 5488c2ecf20Sopenharmony_ci if prio is not None: 5498c2ecf20Sopenharmony_ci spec += " prio %d" % (prio) 5508c2ecf20Sopenharmony_ci if handle: 5518c2ecf20Sopenharmony_ci spec += " handle %s" % (handle) 5528c2ecf20Sopenharmony_ci if chain is not None: 5538c2ecf20Sopenharmony_ci spec += " chain %d" % (chain) 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci return tc("filter {op} dev {dev} {qdisc} {spec} {cls} {params}"\ 5568c2ecf20Sopenharmony_ci .format(op=op, dev=self['ifname'], qdisc=qdisc, spec=spec, 5578c2ecf20Sopenharmony_ci cls=cls, params=params), 5588c2ecf20Sopenharmony_ci fail=fail, include_stderr=include_stderr) 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci def cls_bpf_add_filter(self, bpf, op="add", prio=None, handle=None, 5618c2ecf20Sopenharmony_ci chain=None, da=False, verbose=False, 5628c2ecf20Sopenharmony_ci skip_sw=False, skip_hw=False, 5638c2ecf20Sopenharmony_ci fail=True, include_stderr=False): 5648c2ecf20Sopenharmony_ci cls = "bpf " + bpf 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci params = "" 5678c2ecf20Sopenharmony_ci if da: 5688c2ecf20Sopenharmony_ci params += " da" 5698c2ecf20Sopenharmony_ci if verbose: 5708c2ecf20Sopenharmony_ci params += " verbose" 5718c2ecf20Sopenharmony_ci if skip_sw: 5728c2ecf20Sopenharmony_ci params += " skip_sw" 5738c2ecf20Sopenharmony_ci if skip_hw: 5748c2ecf20Sopenharmony_ci params += " skip_hw" 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci return self.cls_filter_op(op=op, prio=prio, handle=handle, cls=cls, 5778c2ecf20Sopenharmony_ci chain=chain, params=params, 5788c2ecf20Sopenharmony_ci fail=fail, include_stderr=include_stderr) 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci def set_ethtool_tc_offloads(self, enable, fail=True): 5818c2ecf20Sopenharmony_ci args = "hw-tc-offload %s" % ("on" if enable else "off") 5828c2ecf20Sopenharmony_ci return ethtool(self, "-K", args, fail=fail) 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci################################################################################ 5858c2ecf20Sopenharmony_cidef clean_up(): 5868c2ecf20Sopenharmony_ci global files, netns, devs 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci for dev in devs: 5898c2ecf20Sopenharmony_ci dev.remove() 5908c2ecf20Sopenharmony_ci for f in files: 5918c2ecf20Sopenharmony_ci cmd("rm -f %s" % (f)) 5928c2ecf20Sopenharmony_ci for ns in netns: 5938c2ecf20Sopenharmony_ci cmd("ip netns delete %s" % (ns)) 5948c2ecf20Sopenharmony_ci files = [] 5958c2ecf20Sopenharmony_ci netns = [] 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_cidef pin_prog(file_name, idx=0): 5988c2ecf20Sopenharmony_ci progs = bpftool_prog_list(expected=(idx + 1)) 5998c2ecf20Sopenharmony_ci prog = progs[idx] 6008c2ecf20Sopenharmony_ci bpftool("prog pin id %d %s" % (prog["id"], file_name)) 6018c2ecf20Sopenharmony_ci files.append(file_name) 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci return file_name, bpf_pinned(file_name) 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_cidef pin_map(file_name, idx=0, expected=1): 6068c2ecf20Sopenharmony_ci maps = bpftool_map_list(expected=expected) 6078c2ecf20Sopenharmony_ci m = maps[idx] 6088c2ecf20Sopenharmony_ci bpftool("map pin id %d %s" % (m["id"], file_name)) 6098c2ecf20Sopenharmony_ci files.append(file_name) 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci return file_name, bpf_pinned(file_name) 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_cidef check_dev_info_removed(prog_file=None, map_file=None): 6148c2ecf20Sopenharmony_ci bpftool_prog_list(expected=0) 6158c2ecf20Sopenharmony_ci ret, err = bpftool("prog show pin %s" % (prog_file), fail=False) 6168c2ecf20Sopenharmony_ci fail(ret == 0, "Showing prog with removed device did not fail") 6178c2ecf20Sopenharmony_ci fail(err["error"].find("No such device") == -1, 6188c2ecf20Sopenharmony_ci "Showing prog with removed device expected ENODEV, error is %s" % 6198c2ecf20Sopenharmony_ci (err["error"])) 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci bpftool_map_list(expected=0) 6228c2ecf20Sopenharmony_ci ret, err = bpftool("map show pin %s" % (map_file), fail=False) 6238c2ecf20Sopenharmony_ci fail(ret == 0, "Showing map with removed device did not fail") 6248c2ecf20Sopenharmony_ci fail(err["error"].find("No such device") == -1, 6258c2ecf20Sopenharmony_ci "Showing map with removed device expected ENODEV, error is %s" % 6268c2ecf20Sopenharmony_ci (err["error"])) 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_cidef check_dev_info(other_ns, ns, prog_file=None, map_file=None, removed=False): 6298c2ecf20Sopenharmony_ci progs = bpftool_prog_list(expected=1, ns=ns) 6308c2ecf20Sopenharmony_ci prog = progs[0] 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci fail("dev" not in prog.keys(), "Device parameters not reported") 6338c2ecf20Sopenharmony_ci dev = prog["dev"] 6348c2ecf20Sopenharmony_ci fail("ifindex" not in dev.keys(), "Device parameters not reported") 6358c2ecf20Sopenharmony_ci fail("ns_dev" not in dev.keys(), "Device parameters not reported") 6368c2ecf20Sopenharmony_ci fail("ns_inode" not in dev.keys(), "Device parameters not reported") 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci if not other_ns: 6398c2ecf20Sopenharmony_ci fail("ifname" not in dev.keys(), "Ifname not reported") 6408c2ecf20Sopenharmony_ci fail(dev["ifname"] != sim["ifname"], 6418c2ecf20Sopenharmony_ci "Ifname incorrect %s vs %s" % (dev["ifname"], sim["ifname"])) 6428c2ecf20Sopenharmony_ci else: 6438c2ecf20Sopenharmony_ci fail("ifname" in dev.keys(), "Ifname is reported for other ns") 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci maps = bpftool_map_list(expected=2, ns=ns) 6468c2ecf20Sopenharmony_ci for m in maps: 6478c2ecf20Sopenharmony_ci fail("dev" not in m.keys(), "Device parameters not reported") 6488c2ecf20Sopenharmony_ci fail(dev != m["dev"], "Map's device different than program's") 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_cidef check_extack(output, reference, args): 6518c2ecf20Sopenharmony_ci if skip_extack: 6528c2ecf20Sopenharmony_ci return 6538c2ecf20Sopenharmony_ci lines = output.split("\n") 6548c2ecf20Sopenharmony_ci comp = len(lines) >= 2 and lines[1] == 'Error: ' + reference 6558c2ecf20Sopenharmony_ci fail(not comp, "Missing or incorrect netlink extack message") 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_cidef check_extack_nsim(output, reference, args): 6588c2ecf20Sopenharmony_ci check_extack(output, "netdevsim: " + reference, args) 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_cidef check_no_extack(res, needle): 6618c2ecf20Sopenharmony_ci fail((res[1] + res[2]).count(needle) or (res[1] + res[2]).count("Warning:"), 6628c2ecf20Sopenharmony_ci "Found '%s' in command output, leaky extack?" % (needle)) 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_cidef check_verifier_log(output, reference): 6658c2ecf20Sopenharmony_ci lines = output.split("\n") 6668c2ecf20Sopenharmony_ci for l in reversed(lines): 6678c2ecf20Sopenharmony_ci if l == reference: 6688c2ecf20Sopenharmony_ci return 6698c2ecf20Sopenharmony_ci fail(True, "Missing or incorrect message from netdevsim in verifier log") 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_cidef check_multi_basic(two_xdps): 6728c2ecf20Sopenharmony_ci fail(two_xdps["mode"] != 4, "Bad mode reported with multiple programs") 6738c2ecf20Sopenharmony_ci fail("prog" in two_xdps, "Base program reported in multi program mode") 6748c2ecf20Sopenharmony_ci fail(len(two_xdps["attached"]) != 2, 6758c2ecf20Sopenharmony_ci "Wrong attached program count with two programs") 6768c2ecf20Sopenharmony_ci fail(two_xdps["attached"][0]["prog"]["id"] == 6778c2ecf20Sopenharmony_ci two_xdps["attached"][1]["prog"]["id"], 6788c2ecf20Sopenharmony_ci "Offloaded and other programs have the same id") 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_cidef test_spurios_extack(sim, obj, skip_hw, needle): 6818c2ecf20Sopenharmony_ci res = sim.cls_bpf_add_filter(obj, prio=1, handle=1, skip_hw=skip_hw, 6828c2ecf20Sopenharmony_ci include_stderr=True) 6838c2ecf20Sopenharmony_ci check_no_extack(res, needle) 6848c2ecf20Sopenharmony_ci res = sim.cls_bpf_add_filter(obj, op="replace", prio=1, handle=1, 6858c2ecf20Sopenharmony_ci skip_hw=skip_hw, include_stderr=True) 6868c2ecf20Sopenharmony_ci check_no_extack(res, needle) 6878c2ecf20Sopenharmony_ci res = sim.cls_filter_op(op="delete", prio=1, handle=1, cls="bpf", 6888c2ecf20Sopenharmony_ci include_stderr=True) 6898c2ecf20Sopenharmony_ci check_no_extack(res, needle) 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_cidef test_multi_prog(simdev, sim, obj, modename, modeid): 6928c2ecf20Sopenharmony_ci start_test("Test multi-attachment XDP - %s + offload..." % 6938c2ecf20Sopenharmony_ci (modename or "default", )) 6948c2ecf20Sopenharmony_ci sim.set_xdp(obj, "offload") 6958c2ecf20Sopenharmony_ci xdp = sim.ip_link_show(xdp=True)["xdp"] 6968c2ecf20Sopenharmony_ci offloaded = sim.dfs_read("bpf_offloaded_id") 6978c2ecf20Sopenharmony_ci fail("prog" not in xdp, "Base program not reported in single program mode") 6988c2ecf20Sopenharmony_ci fail(len(xdp["attached"]) != 1, 6998c2ecf20Sopenharmony_ci "Wrong attached program count with one program") 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci sim.set_xdp(obj, modename) 7028c2ecf20Sopenharmony_ci two_xdps = sim.ip_link_show(xdp=True)["xdp"] 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci fail(xdp["attached"][0] not in two_xdps["attached"], 7058c2ecf20Sopenharmony_ci "Offload program not reported after other activated") 7068c2ecf20Sopenharmony_ci check_multi_basic(two_xdps) 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci offloaded2 = sim.dfs_read("bpf_offloaded_id") 7098c2ecf20Sopenharmony_ci fail(offloaded != offloaded2, 7108c2ecf20Sopenharmony_ci "Offload ID changed after loading other program") 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci start_test("Test multi-attachment XDP - replace...") 7138c2ecf20Sopenharmony_ci ret, _, err = sim.set_xdp(obj, "offload", fail=False, include_stderr=True) 7148c2ecf20Sopenharmony_ci fail(ret == 0, "Replaced one of programs without -force") 7158c2ecf20Sopenharmony_ci check_extack(err, "XDP program already attached.", args) 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci start_test("Test multi-attachment XDP - remove without mode...") 7188c2ecf20Sopenharmony_ci ret, _, err = sim.unset_xdp("", force=True, 7198c2ecf20Sopenharmony_ci fail=False, include_stderr=True) 7208c2ecf20Sopenharmony_ci fail(ret == 0, "Removed program without a mode flag") 7218c2ecf20Sopenharmony_ci check_extack(err, "More than one program loaded, unset mode is ambiguous.", args) 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci sim.unset_xdp("offload") 7248c2ecf20Sopenharmony_ci xdp = sim.ip_link_show(xdp=True)["xdp"] 7258c2ecf20Sopenharmony_ci offloaded = sim.dfs_read("bpf_offloaded_id") 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci fail(xdp["mode"] != modeid, "Bad mode reported after multiple programs") 7288c2ecf20Sopenharmony_ci fail("prog" not in xdp, 7298c2ecf20Sopenharmony_ci "Base program not reported after multi program mode") 7308c2ecf20Sopenharmony_ci fail(xdp["attached"][0] not in two_xdps["attached"], 7318c2ecf20Sopenharmony_ci "Offload program not reported after other activated") 7328c2ecf20Sopenharmony_ci fail(len(xdp["attached"]) != 1, 7338c2ecf20Sopenharmony_ci "Wrong attached program count with remaining programs") 7348c2ecf20Sopenharmony_ci fail(offloaded != "0", "Offload ID reported with only other program left") 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci start_test("Test multi-attachment XDP - reattach...") 7378c2ecf20Sopenharmony_ci sim.set_xdp(obj, "offload") 7388c2ecf20Sopenharmony_ci two_xdps = sim.ip_link_show(xdp=True)["xdp"] 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci fail(xdp["attached"][0] not in two_xdps["attached"], 7418c2ecf20Sopenharmony_ci "Other program not reported after offload activated") 7428c2ecf20Sopenharmony_ci check_multi_basic(two_xdps) 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci start_test("Test multi-attachment XDP - device remove...") 7458c2ecf20Sopenharmony_ci simdev.remove() 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci simdev = NetdevSimDev() 7488c2ecf20Sopenharmony_ci sim, = simdev.nsims 7498c2ecf20Sopenharmony_ci sim.set_ethtool_tc_offloads(True) 7508c2ecf20Sopenharmony_ci return [simdev, sim] 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci# Parse command line 7538c2ecf20Sopenharmony_ciparser = argparse.ArgumentParser() 7548c2ecf20Sopenharmony_ciparser.add_argument("--log", help="output verbose log to given file") 7558c2ecf20Sopenharmony_ciargs = parser.parse_args() 7568c2ecf20Sopenharmony_ciif args.log: 7578c2ecf20Sopenharmony_ci logfile = open(args.log, 'w+') 7588c2ecf20Sopenharmony_ci logfile.write("# -*-Org-*-") 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_cilog("Prepare...", "", level=1) 7618c2ecf20Sopenharmony_cilog_level_inc() 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci# Check permissions 7648c2ecf20Sopenharmony_ciskip(os.getuid() != 0, "test must be run as root") 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci# Check tools 7678c2ecf20Sopenharmony_ciret, progs = bpftool("prog", fail=False) 7688c2ecf20Sopenharmony_ciskip(ret != 0, "bpftool not installed") 7698c2ecf20Sopenharmony_cibase_progs = progs 7708c2ecf20Sopenharmony_ci_, base_maps = bpftool("map") 7718c2ecf20Sopenharmony_cibase_map_names = [ 7728c2ecf20Sopenharmony_ci 'pid_iter.rodata' # created on each bpftool invocation 7738c2ecf20Sopenharmony_ci] 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci# Check netdevsim 7768c2ecf20Sopenharmony_ciret, out = cmd("modprobe netdevsim", fail=False) 7778c2ecf20Sopenharmony_ciskip(ret != 0, "netdevsim module could not be loaded") 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci# Check debugfs 7808c2ecf20Sopenharmony_ci_, out = cmd("mount") 7818c2ecf20Sopenharmony_ciif out.find("/sys/kernel/debug type debugfs") == -1: 7828c2ecf20Sopenharmony_ci cmd("mount -t debugfs none /sys/kernel/debug") 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci# Check samples are compiled 7858c2ecf20Sopenharmony_cisamples = ["sample_ret0.o", "sample_map_ret0.o"] 7868c2ecf20Sopenharmony_cifor s in samples: 7878c2ecf20Sopenharmony_ci ret, out = cmd("ls %s/%s" % (bpf_test_dir, s), fail=False) 7888c2ecf20Sopenharmony_ci skip(ret != 0, "sample %s/%s not found, please compile it" % 7898c2ecf20Sopenharmony_ci (bpf_test_dir, s)) 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci# Check if iproute2 is built with libmnl (needed by extack support) 7928c2ecf20Sopenharmony_ci_, _, err = cmd("tc qdisc delete dev lo handle 0", 7938c2ecf20Sopenharmony_ci fail=False, include_stderr=True) 7948c2ecf20Sopenharmony_ciif err.find("Error: Failed to find qdisc with specified handle.") == -1: 7958c2ecf20Sopenharmony_ci print("Warning: no extack message in iproute2 output, libmnl missing?") 7968c2ecf20Sopenharmony_ci log("Warning: no extack message in iproute2 output, libmnl missing?", "") 7978c2ecf20Sopenharmony_ci skip_extack = True 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci# Check if net namespaces seem to work 8008c2ecf20Sopenharmony_cins = mknetns() 8018c2ecf20Sopenharmony_ciskip(ns is None, "Could not create a net namespace") 8028c2ecf20Sopenharmony_cicmd("ip netns delete %s" % (ns)) 8038c2ecf20Sopenharmony_cinetns = [] 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_citry: 8068c2ecf20Sopenharmony_ci obj = bpf_obj("sample_ret0.o") 8078c2ecf20Sopenharmony_ci bytecode = bpf_bytecode("1,6 0 0 4294967295,") 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci start_test("Test destruction of generic XDP...") 8108c2ecf20Sopenharmony_ci simdev = NetdevSimDev() 8118c2ecf20Sopenharmony_ci sim, = simdev.nsims 8128c2ecf20Sopenharmony_ci sim.set_xdp(obj, "generic") 8138c2ecf20Sopenharmony_ci simdev.remove() 8148c2ecf20Sopenharmony_ci bpftool_prog_list_wait(expected=0) 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci simdev = NetdevSimDev() 8178c2ecf20Sopenharmony_ci sim, = simdev.nsims 8188c2ecf20Sopenharmony_ci sim.tc_add_ingress() 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci start_test("Test TC non-offloaded...") 8218c2ecf20Sopenharmony_ci ret, _ = sim.cls_bpf_add_filter(obj, skip_hw=True, fail=False) 8228c2ecf20Sopenharmony_ci fail(ret != 0, "Software TC filter did not load") 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci start_test("Test TC non-offloaded isn't getting bound...") 8258c2ecf20Sopenharmony_ci ret, _ = sim.cls_bpf_add_filter(obj, fail=False) 8268c2ecf20Sopenharmony_ci fail(ret != 0, "Software TC filter did not load") 8278c2ecf20Sopenharmony_ci simdev.dfs_get_bound_progs(expected=0) 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci sim.tc_flush_filters() 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci start_test("Test TC offloads are off by default...") 8328c2ecf20Sopenharmony_ci ret, _, err = sim.cls_bpf_add_filter(obj, skip_sw=True, 8338c2ecf20Sopenharmony_ci fail=False, include_stderr=True) 8348c2ecf20Sopenharmony_ci fail(ret == 0, "TC filter loaded without enabling TC offloads") 8358c2ecf20Sopenharmony_ci check_extack(err, "TC offload is disabled on net device.", args) 8368c2ecf20Sopenharmony_ci sim.wait_for_flush() 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci sim.set_ethtool_tc_offloads(True) 8398c2ecf20Sopenharmony_ci sim.dfs["bpf_tc_non_bound_accept"] = "Y" 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci start_test("Test TC offload by default...") 8428c2ecf20Sopenharmony_ci ret, _ = sim.cls_bpf_add_filter(obj, fail=False) 8438c2ecf20Sopenharmony_ci fail(ret != 0, "Software TC filter did not load") 8448c2ecf20Sopenharmony_ci simdev.dfs_get_bound_progs(expected=0) 8458c2ecf20Sopenharmony_ci ingress = sim.tc_show_ingress(expected=1) 8468c2ecf20Sopenharmony_ci fltr = ingress[0] 8478c2ecf20Sopenharmony_ci fail(not fltr["in_hw"], "Filter not offloaded by default") 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci sim.tc_flush_filters() 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci start_test("Test TC cBPF bytcode tries offload by default...") 8528c2ecf20Sopenharmony_ci ret, _ = sim.cls_bpf_add_filter(bytecode, fail=False) 8538c2ecf20Sopenharmony_ci fail(ret != 0, "Software TC filter did not load") 8548c2ecf20Sopenharmony_ci simdev.dfs_get_bound_progs(expected=0) 8558c2ecf20Sopenharmony_ci ingress = sim.tc_show_ingress(expected=1) 8568c2ecf20Sopenharmony_ci fltr = ingress[0] 8578c2ecf20Sopenharmony_ci fail(not fltr["in_hw"], "Bytecode not offloaded by default") 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci sim.tc_flush_filters() 8608c2ecf20Sopenharmony_ci sim.dfs["bpf_tc_non_bound_accept"] = "N" 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci start_test("Test TC cBPF unbound bytecode doesn't offload...") 8638c2ecf20Sopenharmony_ci ret, _, err = sim.cls_bpf_add_filter(bytecode, skip_sw=True, 8648c2ecf20Sopenharmony_ci fail=False, include_stderr=True) 8658c2ecf20Sopenharmony_ci fail(ret == 0, "TC bytecode loaded for offload") 8668c2ecf20Sopenharmony_ci check_extack_nsim(err, "netdevsim configured to reject unbound programs.", 8678c2ecf20Sopenharmony_ci args) 8688c2ecf20Sopenharmony_ci sim.wait_for_flush() 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci start_test("Test non-0 chain offload...") 8718c2ecf20Sopenharmony_ci ret, _, err = sim.cls_bpf_add_filter(obj, chain=1, prio=1, handle=1, 8728c2ecf20Sopenharmony_ci skip_sw=True, 8738c2ecf20Sopenharmony_ci fail=False, include_stderr=True) 8748c2ecf20Sopenharmony_ci fail(ret == 0, "Offloaded a filter to chain other than 0") 8758c2ecf20Sopenharmony_ci check_extack(err, "Driver supports only offload of chain 0.", args) 8768c2ecf20Sopenharmony_ci sim.tc_flush_filters() 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci start_test("Test TC replace...") 8798c2ecf20Sopenharmony_ci sim.cls_bpf_add_filter(obj, prio=1, handle=1) 8808c2ecf20Sopenharmony_ci sim.cls_bpf_add_filter(obj, op="replace", prio=1, handle=1) 8818c2ecf20Sopenharmony_ci sim.cls_filter_op(op="delete", prio=1, handle=1, cls="bpf") 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci sim.cls_bpf_add_filter(obj, prio=1, handle=1, skip_sw=True) 8848c2ecf20Sopenharmony_ci sim.cls_bpf_add_filter(obj, op="replace", prio=1, handle=1, skip_sw=True) 8858c2ecf20Sopenharmony_ci sim.cls_filter_op(op="delete", prio=1, handle=1, cls="bpf") 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci sim.cls_bpf_add_filter(obj, prio=1, handle=1, skip_hw=True) 8888c2ecf20Sopenharmony_ci sim.cls_bpf_add_filter(obj, op="replace", prio=1, handle=1, skip_hw=True) 8898c2ecf20Sopenharmony_ci sim.cls_filter_op(op="delete", prio=1, handle=1, cls="bpf") 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci start_test("Test TC replace bad flags...") 8928c2ecf20Sopenharmony_ci for i in range(3): 8938c2ecf20Sopenharmony_ci for j in range(3): 8948c2ecf20Sopenharmony_ci ret, _ = sim.cls_bpf_add_filter(obj, op="replace", prio=1, handle=1, 8958c2ecf20Sopenharmony_ci skip_sw=(j == 1), skip_hw=(j == 2), 8968c2ecf20Sopenharmony_ci fail=False) 8978c2ecf20Sopenharmony_ci fail(bool(ret) != bool(j), 8988c2ecf20Sopenharmony_ci "Software TC incorrect load in replace test, iteration %d" % 8998c2ecf20Sopenharmony_ci (j)) 9008c2ecf20Sopenharmony_ci sim.cls_filter_op(op="delete", prio=1, handle=1, cls="bpf") 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_ci start_test("Test spurious extack from the driver...") 9038c2ecf20Sopenharmony_ci test_spurios_extack(sim, obj, False, "netdevsim") 9048c2ecf20Sopenharmony_ci test_spurios_extack(sim, obj, True, "netdevsim") 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci sim.set_ethtool_tc_offloads(False) 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci test_spurios_extack(sim, obj, False, "TC offload is disabled") 9098c2ecf20Sopenharmony_ci test_spurios_extack(sim, obj, True, "TC offload is disabled") 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci sim.set_ethtool_tc_offloads(True) 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci sim.tc_flush_filters() 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci start_test("Test TC offloads failure...") 9168c2ecf20Sopenharmony_ci sim.dfs["dev/bpf_bind_verifier_accept"] = 0 9178c2ecf20Sopenharmony_ci ret, _, err = sim.cls_bpf_add_filter(obj, verbose=True, skip_sw=True, 9188c2ecf20Sopenharmony_ci fail=False, include_stderr=True) 9198c2ecf20Sopenharmony_ci fail(ret == 0, "TC filter did not reject with TC offloads enabled") 9208c2ecf20Sopenharmony_ci check_verifier_log(err, "[netdevsim] Hello from netdevsim!") 9218c2ecf20Sopenharmony_ci sim.dfs["dev/bpf_bind_verifier_accept"] = 1 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci start_test("Test TC offloads work...") 9248c2ecf20Sopenharmony_ci ret, _, err = sim.cls_bpf_add_filter(obj, verbose=True, skip_sw=True, 9258c2ecf20Sopenharmony_ci fail=False, include_stderr=True) 9268c2ecf20Sopenharmony_ci fail(ret != 0, "TC filter did not load with TC offloads enabled") 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci start_test("Test TC offload basics...") 9298c2ecf20Sopenharmony_ci dfs = simdev.dfs_get_bound_progs(expected=1) 9308c2ecf20Sopenharmony_ci progs = bpftool_prog_list(expected=1) 9318c2ecf20Sopenharmony_ci ingress = sim.tc_show_ingress(expected=1) 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci dprog = dfs[0] 9348c2ecf20Sopenharmony_ci prog = progs[0] 9358c2ecf20Sopenharmony_ci fltr = ingress[0] 9368c2ecf20Sopenharmony_ci fail(fltr["skip_hw"], "TC does reports 'skip_hw' on offloaded filter") 9378c2ecf20Sopenharmony_ci fail(not fltr["in_hw"], "TC does not report 'in_hw' for offloaded filter") 9388c2ecf20Sopenharmony_ci fail(not fltr["skip_sw"], "TC does not report 'skip_sw' back") 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_ci start_test("Test TC offload is device-bound...") 9418c2ecf20Sopenharmony_ci fail(str(prog["id"]) != fltr["id"], "Program IDs don't match") 9428c2ecf20Sopenharmony_ci fail(prog["tag"] != fltr["tag"], "Program tags don't match") 9438c2ecf20Sopenharmony_ci fail(fltr["id"] != dprog["id"], "Program IDs don't match") 9448c2ecf20Sopenharmony_ci fail(dprog["state"] != "xlated", "Offloaded program state not translated") 9458c2ecf20Sopenharmony_ci fail(dprog["loaded"] != "Y", "Offloaded program is not loaded") 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci start_test("Test disabling TC offloads is rejected while filters installed...") 9488c2ecf20Sopenharmony_ci ret, _ = sim.set_ethtool_tc_offloads(False, fail=False) 9498c2ecf20Sopenharmony_ci fail(ret == 0, "Driver should refuse to disable TC offloads with filters installed...") 9508c2ecf20Sopenharmony_ci sim.set_ethtool_tc_offloads(True) 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci start_test("Test qdisc removal frees things...") 9538c2ecf20Sopenharmony_ci sim.tc_flush_filters() 9548c2ecf20Sopenharmony_ci sim.tc_show_ingress(expected=0) 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci start_test("Test disabling TC offloads is OK without filters...") 9578c2ecf20Sopenharmony_ci ret, _ = sim.set_ethtool_tc_offloads(False, fail=False) 9588c2ecf20Sopenharmony_ci fail(ret != 0, 9598c2ecf20Sopenharmony_ci "Driver refused to disable TC offloads without filters installed...") 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci sim.set_ethtool_tc_offloads(True) 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci start_test("Test destroying device gets rid of TC filters...") 9648c2ecf20Sopenharmony_ci sim.cls_bpf_add_filter(obj, skip_sw=True) 9658c2ecf20Sopenharmony_ci simdev.remove() 9668c2ecf20Sopenharmony_ci bpftool_prog_list_wait(expected=0) 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci simdev = NetdevSimDev() 9698c2ecf20Sopenharmony_ci sim, = simdev.nsims 9708c2ecf20Sopenharmony_ci sim.set_ethtool_tc_offloads(True) 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci start_test("Test destroying device gets rid of XDP...") 9738c2ecf20Sopenharmony_ci sim.set_xdp(obj, "offload") 9748c2ecf20Sopenharmony_ci simdev.remove() 9758c2ecf20Sopenharmony_ci bpftool_prog_list_wait(expected=0) 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci simdev = NetdevSimDev() 9788c2ecf20Sopenharmony_ci sim, = simdev.nsims 9798c2ecf20Sopenharmony_ci sim.set_ethtool_tc_offloads(True) 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci start_test("Test XDP prog reporting...") 9828c2ecf20Sopenharmony_ci sim.set_xdp(obj, "drv") 9838c2ecf20Sopenharmony_ci ipl = sim.ip_link_show(xdp=True) 9848c2ecf20Sopenharmony_ci progs = bpftool_prog_list(expected=1) 9858c2ecf20Sopenharmony_ci fail(ipl["xdp"]["prog"]["id"] != progs[0]["id"], 9868c2ecf20Sopenharmony_ci "Loaded program has wrong ID") 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci start_test("Test XDP prog replace without force...") 9898c2ecf20Sopenharmony_ci ret, _ = sim.set_xdp(obj, "drv", fail=False) 9908c2ecf20Sopenharmony_ci fail(ret == 0, "Replaced XDP program without -force") 9918c2ecf20Sopenharmony_ci sim.wait_for_flush(total=1) 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci start_test("Test XDP prog replace with force...") 9948c2ecf20Sopenharmony_ci ret, _ = sim.set_xdp(obj, "drv", force=True, fail=False) 9958c2ecf20Sopenharmony_ci fail(ret != 0, "Could not replace XDP program with -force") 9968c2ecf20Sopenharmony_ci bpftool_prog_list_wait(expected=1) 9978c2ecf20Sopenharmony_ci ipl = sim.ip_link_show(xdp=True) 9988c2ecf20Sopenharmony_ci progs = bpftool_prog_list(expected=1) 9998c2ecf20Sopenharmony_ci fail(ipl["xdp"]["prog"]["id"] != progs[0]["id"], 10008c2ecf20Sopenharmony_ci "Loaded program has wrong ID") 10018c2ecf20Sopenharmony_ci fail("dev" in progs[0].keys(), 10028c2ecf20Sopenharmony_ci "Device parameters reported for non-offloaded program") 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci start_test("Test XDP prog replace with bad flags...") 10058c2ecf20Sopenharmony_ci ret, _, err = sim.set_xdp(obj, "generic", force=True, 10068c2ecf20Sopenharmony_ci fail=False, include_stderr=True) 10078c2ecf20Sopenharmony_ci fail(ret == 0, "Replaced XDP program with a program in different mode") 10088c2ecf20Sopenharmony_ci check_extack(err, 10098c2ecf20Sopenharmony_ci "Native and generic XDP can't be active at the same time.", 10108c2ecf20Sopenharmony_ci args) 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci start_test("Test MTU restrictions...") 10138c2ecf20Sopenharmony_ci ret, _ = sim.set_mtu(9000, fail=False) 10148c2ecf20Sopenharmony_ci fail(ret == 0, 10158c2ecf20Sopenharmony_ci "Driver should refuse to increase MTU to 9000 with XDP loaded...") 10168c2ecf20Sopenharmony_ci sim.unset_xdp("drv") 10178c2ecf20Sopenharmony_ci bpftool_prog_list_wait(expected=0) 10188c2ecf20Sopenharmony_ci sim.set_mtu(9000) 10198c2ecf20Sopenharmony_ci ret, _, err = sim.set_xdp(obj, "drv", fail=False, include_stderr=True) 10208c2ecf20Sopenharmony_ci fail(ret == 0, "Driver should refuse to load program with MTU of 9000...") 10218c2ecf20Sopenharmony_ci check_extack_nsim(err, "MTU too large w/ XDP enabled.", args) 10228c2ecf20Sopenharmony_ci sim.set_mtu(1500) 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci sim.wait_for_flush() 10258c2ecf20Sopenharmony_ci start_test("Test non-offload XDP attaching to HW...") 10268c2ecf20Sopenharmony_ci bpftool_prog_load("sample_ret0.o", "/sys/fs/bpf/nooffload") 10278c2ecf20Sopenharmony_ci nooffload = bpf_pinned("/sys/fs/bpf/nooffload") 10288c2ecf20Sopenharmony_ci ret, _, err = sim.set_xdp(nooffload, "offload", 10298c2ecf20Sopenharmony_ci fail=False, include_stderr=True) 10308c2ecf20Sopenharmony_ci fail(ret == 0, "attached non-offloaded XDP program to HW") 10318c2ecf20Sopenharmony_ci check_extack_nsim(err, "xdpoffload of non-bound program.", args) 10328c2ecf20Sopenharmony_ci rm("/sys/fs/bpf/nooffload") 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci start_test("Test offload XDP attaching to drv...") 10358c2ecf20Sopenharmony_ci bpftool_prog_load("sample_ret0.o", "/sys/fs/bpf/offload", 10368c2ecf20Sopenharmony_ci dev=sim['ifname']) 10378c2ecf20Sopenharmony_ci offload = bpf_pinned("/sys/fs/bpf/offload") 10388c2ecf20Sopenharmony_ci ret, _, err = sim.set_xdp(offload, "drv", fail=False, include_stderr=True) 10398c2ecf20Sopenharmony_ci fail(ret == 0, "attached offloaded XDP program to drv") 10408c2ecf20Sopenharmony_ci check_extack(err, "Using device-bound program without HW_MODE flag is not supported.", args) 10418c2ecf20Sopenharmony_ci rm("/sys/fs/bpf/offload") 10428c2ecf20Sopenharmony_ci sim.wait_for_flush() 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci start_test("Test XDP load failure...") 10458c2ecf20Sopenharmony_ci sim.dfs["dev/bpf_bind_verifier_accept"] = 0 10468c2ecf20Sopenharmony_ci ret, _, err = bpftool_prog_load("sample_ret0.o", "/sys/fs/bpf/offload", 10478c2ecf20Sopenharmony_ci dev=sim['ifname'], fail=False, include_stderr=True) 10488c2ecf20Sopenharmony_ci fail(ret == 0, "verifier should fail on load") 10498c2ecf20Sopenharmony_ci check_verifier_log(err, "[netdevsim] Hello from netdevsim!") 10508c2ecf20Sopenharmony_ci sim.dfs["dev/bpf_bind_verifier_accept"] = 1 10518c2ecf20Sopenharmony_ci sim.wait_for_flush() 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci start_test("Test XDP offload...") 10548c2ecf20Sopenharmony_ci _, _, err = sim.set_xdp(obj, "offload", verbose=True, include_stderr=True) 10558c2ecf20Sopenharmony_ci ipl = sim.ip_link_show(xdp=True) 10568c2ecf20Sopenharmony_ci link_xdp = ipl["xdp"]["prog"] 10578c2ecf20Sopenharmony_ci progs = bpftool_prog_list(expected=1) 10588c2ecf20Sopenharmony_ci prog = progs[0] 10598c2ecf20Sopenharmony_ci fail(link_xdp["id"] != prog["id"], "Loaded program has wrong ID") 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci start_test("Test XDP offload is device bound...") 10628c2ecf20Sopenharmony_ci dfs = simdev.dfs_get_bound_progs(expected=1) 10638c2ecf20Sopenharmony_ci dprog = dfs[0] 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci fail(prog["id"] != link_xdp["id"], "Program IDs don't match") 10668c2ecf20Sopenharmony_ci fail(prog["tag"] != link_xdp["tag"], "Program tags don't match") 10678c2ecf20Sopenharmony_ci fail(str(link_xdp["id"]) != dprog["id"], "Program IDs don't match") 10688c2ecf20Sopenharmony_ci fail(dprog["state"] != "xlated", "Offloaded program state not translated") 10698c2ecf20Sopenharmony_ci fail(dprog["loaded"] != "Y", "Offloaded program is not loaded") 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci start_test("Test removing XDP program many times...") 10728c2ecf20Sopenharmony_ci sim.unset_xdp("offload") 10738c2ecf20Sopenharmony_ci sim.unset_xdp("offload") 10748c2ecf20Sopenharmony_ci sim.unset_xdp("drv") 10758c2ecf20Sopenharmony_ci sim.unset_xdp("drv") 10768c2ecf20Sopenharmony_ci sim.unset_xdp("") 10778c2ecf20Sopenharmony_ci sim.unset_xdp("") 10788c2ecf20Sopenharmony_ci bpftool_prog_list_wait(expected=0) 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci start_test("Test attempt to use a program for a wrong device...") 10818c2ecf20Sopenharmony_ci simdev2 = NetdevSimDev() 10828c2ecf20Sopenharmony_ci sim2, = simdev2.nsims 10838c2ecf20Sopenharmony_ci sim2.set_xdp(obj, "offload") 10848c2ecf20Sopenharmony_ci pin_file, pinned = pin_prog("/sys/fs/bpf/tmp") 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_ci ret, _, err = sim.set_xdp(pinned, "offload", 10878c2ecf20Sopenharmony_ci fail=False, include_stderr=True) 10888c2ecf20Sopenharmony_ci fail(ret == 0, "Pinned program loaded for a different device accepted") 10898c2ecf20Sopenharmony_ci check_extack_nsim(err, "program bound to different dev.", args) 10908c2ecf20Sopenharmony_ci simdev2.remove() 10918c2ecf20Sopenharmony_ci ret, _, err = sim.set_xdp(pinned, "offload", 10928c2ecf20Sopenharmony_ci fail=False, include_stderr=True) 10938c2ecf20Sopenharmony_ci fail(ret == 0, "Pinned program loaded for a removed device accepted") 10948c2ecf20Sopenharmony_ci check_extack_nsim(err, "xdpoffload of non-bound program.", args) 10958c2ecf20Sopenharmony_ci rm(pin_file) 10968c2ecf20Sopenharmony_ci bpftool_prog_list_wait(expected=0) 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci simdev, sim = test_multi_prog(simdev, sim, obj, "", 1) 10998c2ecf20Sopenharmony_ci simdev, sim = test_multi_prog(simdev, sim, obj, "drv", 1) 11008c2ecf20Sopenharmony_ci simdev, sim = test_multi_prog(simdev, sim, obj, "generic", 2) 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_ci start_test("Test mixing of TC and XDP...") 11038c2ecf20Sopenharmony_ci sim.tc_add_ingress() 11048c2ecf20Sopenharmony_ci sim.set_xdp(obj, "offload") 11058c2ecf20Sopenharmony_ci ret, _, err = sim.cls_bpf_add_filter(obj, skip_sw=True, 11068c2ecf20Sopenharmony_ci fail=False, include_stderr=True) 11078c2ecf20Sopenharmony_ci fail(ret == 0, "Loading TC when XDP active should fail") 11088c2ecf20Sopenharmony_ci check_extack_nsim(err, "driver and netdev offload states mismatch.", args) 11098c2ecf20Sopenharmony_ci sim.unset_xdp("offload") 11108c2ecf20Sopenharmony_ci sim.wait_for_flush() 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci sim.cls_bpf_add_filter(obj, skip_sw=True) 11138c2ecf20Sopenharmony_ci ret, _, err = sim.set_xdp(obj, "offload", fail=False, include_stderr=True) 11148c2ecf20Sopenharmony_ci fail(ret == 0, "Loading XDP when TC active should fail") 11158c2ecf20Sopenharmony_ci check_extack_nsim(err, "TC program is already loaded.", args) 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci start_test("Test binding TC from pinned...") 11188c2ecf20Sopenharmony_ci pin_file, pinned = pin_prog("/sys/fs/bpf/tmp") 11198c2ecf20Sopenharmony_ci sim.tc_flush_filters(bound=1, total=1) 11208c2ecf20Sopenharmony_ci sim.cls_bpf_add_filter(pinned, da=True, skip_sw=True) 11218c2ecf20Sopenharmony_ci sim.tc_flush_filters(bound=1, total=1) 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci start_test("Test binding XDP from pinned...") 11248c2ecf20Sopenharmony_ci sim.set_xdp(obj, "offload") 11258c2ecf20Sopenharmony_ci pin_file, pinned = pin_prog("/sys/fs/bpf/tmp2", idx=1) 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci sim.set_xdp(pinned, "offload", force=True) 11288c2ecf20Sopenharmony_ci sim.unset_xdp("offload") 11298c2ecf20Sopenharmony_ci sim.set_xdp(pinned, "offload", force=True) 11308c2ecf20Sopenharmony_ci sim.unset_xdp("offload") 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci start_test("Test offload of wrong type fails...") 11338c2ecf20Sopenharmony_ci ret, _ = sim.cls_bpf_add_filter(pinned, da=True, skip_sw=True, fail=False) 11348c2ecf20Sopenharmony_ci fail(ret == 0, "Managed to attach XDP program to TC") 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci start_test("Test asking for TC offload of two filters...") 11378c2ecf20Sopenharmony_ci sim.cls_bpf_add_filter(obj, da=True, skip_sw=True) 11388c2ecf20Sopenharmony_ci ret, _, err = sim.cls_bpf_add_filter(obj, da=True, skip_sw=True, 11398c2ecf20Sopenharmony_ci fail=False, include_stderr=True) 11408c2ecf20Sopenharmony_ci fail(ret == 0, "Managed to offload two TC filters at the same time") 11418c2ecf20Sopenharmony_ci check_extack_nsim(err, "driver and netdev offload states mismatch.", args) 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci sim.tc_flush_filters(bound=2, total=2) 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci start_test("Test if netdev removal waits for translation...") 11468c2ecf20Sopenharmony_ci delay_msec = 500 11478c2ecf20Sopenharmony_ci sim.dfs["dev/bpf_bind_verifier_delay"] = delay_msec 11488c2ecf20Sopenharmony_ci start = time.time() 11498c2ecf20Sopenharmony_ci cmd_line = "tc filter add dev %s ingress bpf %s da skip_sw" % \ 11508c2ecf20Sopenharmony_ci (sim['ifname'], obj) 11518c2ecf20Sopenharmony_ci tc_proc = cmd(cmd_line, background=True, fail=False) 11528c2ecf20Sopenharmony_ci # Wait for the verifier to start 11538c2ecf20Sopenharmony_ci while simdev.dfs_num_bound_progs() <= 2: 11548c2ecf20Sopenharmony_ci pass 11558c2ecf20Sopenharmony_ci simdev.remove() 11568c2ecf20Sopenharmony_ci end = time.time() 11578c2ecf20Sopenharmony_ci ret, _ = cmd_result(tc_proc, fail=False) 11588c2ecf20Sopenharmony_ci time_diff = end - start 11598c2ecf20Sopenharmony_ci log("Time", "start:\t%s\nend:\t%s\ndiff:\t%s" % (start, end, time_diff)) 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci fail(ret == 0, "Managed to load TC filter on a unregistering device") 11628c2ecf20Sopenharmony_ci delay_sec = delay_msec * 0.001 11638c2ecf20Sopenharmony_ci fail(time_diff < delay_sec, "Removal process took %s, expected %s" % 11648c2ecf20Sopenharmony_ci (time_diff, delay_sec)) 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci # Remove all pinned files and reinstantiate the netdev 11678c2ecf20Sopenharmony_ci clean_up() 11688c2ecf20Sopenharmony_ci bpftool_prog_list_wait(expected=0) 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_ci simdev = NetdevSimDev() 11718c2ecf20Sopenharmony_ci sim, = simdev.nsims 11728c2ecf20Sopenharmony_ci map_obj = bpf_obj("sample_map_ret0.o") 11738c2ecf20Sopenharmony_ci start_test("Test loading program with maps...") 11748c2ecf20Sopenharmony_ci sim.set_xdp(map_obj, "offload", JSON=False) # map fixup msg breaks JSON 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci start_test("Test bpftool bound info reporting (own ns)...") 11778c2ecf20Sopenharmony_ci check_dev_info(False, "") 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci start_test("Test bpftool bound info reporting (other ns)...") 11808c2ecf20Sopenharmony_ci ns = mknetns() 11818c2ecf20Sopenharmony_ci sim.set_ns(ns) 11828c2ecf20Sopenharmony_ci check_dev_info(True, "") 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci start_test("Test bpftool bound info reporting (remote ns)...") 11858c2ecf20Sopenharmony_ci check_dev_info(False, ns) 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci start_test("Test bpftool bound info reporting (back to own ns)...") 11888c2ecf20Sopenharmony_ci sim.set_ns("") 11898c2ecf20Sopenharmony_ci check_dev_info(False, "") 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_ci prog_file, _ = pin_prog("/sys/fs/bpf/tmp_prog") 11928c2ecf20Sopenharmony_ci map_file, _ = pin_map("/sys/fs/bpf/tmp_map", idx=1, expected=2) 11938c2ecf20Sopenharmony_ci simdev.remove() 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci start_test("Test bpftool bound info reporting (removed dev)...") 11968c2ecf20Sopenharmony_ci check_dev_info_removed(prog_file=prog_file, map_file=map_file) 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_ci # Remove all pinned files and reinstantiate the netdev 11998c2ecf20Sopenharmony_ci clean_up() 12008c2ecf20Sopenharmony_ci bpftool_prog_list_wait(expected=0) 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci simdev = NetdevSimDev() 12038c2ecf20Sopenharmony_ci sim, = simdev.nsims 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci start_test("Test map update (no flags)...") 12068c2ecf20Sopenharmony_ci sim.set_xdp(map_obj, "offload", JSON=False) # map fixup msg breaks JSON 12078c2ecf20Sopenharmony_ci maps = bpftool_map_list(expected=2) 12088c2ecf20Sopenharmony_ci array = maps[0] if maps[0]["type"] == "array" else maps[1] 12098c2ecf20Sopenharmony_ci htab = maps[0] if maps[0]["type"] == "hash" else maps[1] 12108c2ecf20Sopenharmony_ci for m in maps: 12118c2ecf20Sopenharmony_ci for i in range(2): 12128c2ecf20Sopenharmony_ci bpftool("map update id %d key %s value %s" % 12138c2ecf20Sopenharmony_ci (m["id"], int2str("I", i), int2str("Q", i * 3))) 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_ci for m in maps: 12168c2ecf20Sopenharmony_ci ret, _ = bpftool("map update id %d key %s value %s" % 12178c2ecf20Sopenharmony_ci (m["id"], int2str("I", 3), int2str("Q", 3 * 3)), 12188c2ecf20Sopenharmony_ci fail=False) 12198c2ecf20Sopenharmony_ci fail(ret == 0, "added too many entries") 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_ci start_test("Test map update (exists)...") 12228c2ecf20Sopenharmony_ci for m in maps: 12238c2ecf20Sopenharmony_ci for i in range(2): 12248c2ecf20Sopenharmony_ci bpftool("map update id %d key %s value %s exist" % 12258c2ecf20Sopenharmony_ci (m["id"], int2str("I", i), int2str("Q", i * 3))) 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci for m in maps: 12288c2ecf20Sopenharmony_ci ret, err = bpftool("map update id %d key %s value %s exist" % 12298c2ecf20Sopenharmony_ci (m["id"], int2str("I", 3), int2str("Q", 3 * 3)), 12308c2ecf20Sopenharmony_ci fail=False) 12318c2ecf20Sopenharmony_ci fail(ret == 0, "updated non-existing key") 12328c2ecf20Sopenharmony_ci fail(err["error"].find("No such file or directory") == -1, 12338c2ecf20Sopenharmony_ci "expected ENOENT, error is '%s'" % (err["error"])) 12348c2ecf20Sopenharmony_ci 12358c2ecf20Sopenharmony_ci start_test("Test map update (noexist)...") 12368c2ecf20Sopenharmony_ci for m in maps: 12378c2ecf20Sopenharmony_ci for i in range(2): 12388c2ecf20Sopenharmony_ci ret, err = bpftool("map update id %d key %s value %s noexist" % 12398c2ecf20Sopenharmony_ci (m["id"], int2str("I", i), int2str("Q", i * 3)), 12408c2ecf20Sopenharmony_ci fail=False) 12418c2ecf20Sopenharmony_ci fail(ret == 0, "updated existing key") 12428c2ecf20Sopenharmony_ci fail(err["error"].find("File exists") == -1, 12438c2ecf20Sopenharmony_ci "expected EEXIST, error is '%s'" % (err["error"])) 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci start_test("Test map dump...") 12468c2ecf20Sopenharmony_ci for m in maps: 12478c2ecf20Sopenharmony_ci _, entries = bpftool("map dump id %d" % (m["id"])) 12488c2ecf20Sopenharmony_ci for i in range(2): 12498c2ecf20Sopenharmony_ci key = str2int(entries[i]["key"]) 12508c2ecf20Sopenharmony_ci fail(key != i, "expected key %d, got %d" % (key, i)) 12518c2ecf20Sopenharmony_ci val = str2int(entries[i]["value"]) 12528c2ecf20Sopenharmony_ci fail(val != i * 3, "expected value %d, got %d" % (val, i * 3)) 12538c2ecf20Sopenharmony_ci 12548c2ecf20Sopenharmony_ci start_test("Test map getnext...") 12558c2ecf20Sopenharmony_ci for m in maps: 12568c2ecf20Sopenharmony_ci _, entry = bpftool("map getnext id %d" % (m["id"])) 12578c2ecf20Sopenharmony_ci key = str2int(entry["next_key"]) 12588c2ecf20Sopenharmony_ci fail(key != 0, "next key %d, expected %d" % (key, 0)) 12598c2ecf20Sopenharmony_ci _, entry = bpftool("map getnext id %d key %s" % 12608c2ecf20Sopenharmony_ci (m["id"], int2str("I", 0))) 12618c2ecf20Sopenharmony_ci key = str2int(entry["next_key"]) 12628c2ecf20Sopenharmony_ci fail(key != 1, "next key %d, expected %d" % (key, 1)) 12638c2ecf20Sopenharmony_ci ret, err = bpftool("map getnext id %d key %s" % 12648c2ecf20Sopenharmony_ci (m["id"], int2str("I", 1)), fail=False) 12658c2ecf20Sopenharmony_ci fail(ret == 0, "got next key past the end of map") 12668c2ecf20Sopenharmony_ci fail(err["error"].find("No such file or directory") == -1, 12678c2ecf20Sopenharmony_ci "expected ENOENT, error is '%s'" % (err["error"])) 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci start_test("Test map delete (htab)...") 12708c2ecf20Sopenharmony_ci for i in range(2): 12718c2ecf20Sopenharmony_ci bpftool("map delete id %d key %s" % (htab["id"], int2str("I", i))) 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci start_test("Test map delete (array)...") 12748c2ecf20Sopenharmony_ci for i in range(2): 12758c2ecf20Sopenharmony_ci ret, err = bpftool("map delete id %d key %s" % 12768c2ecf20Sopenharmony_ci (htab["id"], int2str("I", i)), fail=False) 12778c2ecf20Sopenharmony_ci fail(ret == 0, "removed entry from an array") 12788c2ecf20Sopenharmony_ci fail(err["error"].find("No such file or directory") == -1, 12798c2ecf20Sopenharmony_ci "expected ENOENT, error is '%s'" % (err["error"])) 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci start_test("Test map remove...") 12828c2ecf20Sopenharmony_ci sim.unset_xdp("offload") 12838c2ecf20Sopenharmony_ci bpftool_map_list_wait(expected=0) 12848c2ecf20Sopenharmony_ci simdev.remove() 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_ci simdev = NetdevSimDev() 12878c2ecf20Sopenharmony_ci sim, = simdev.nsims 12888c2ecf20Sopenharmony_ci sim.set_xdp(map_obj, "offload", JSON=False) # map fixup msg breaks JSON 12898c2ecf20Sopenharmony_ci simdev.remove() 12908c2ecf20Sopenharmony_ci bpftool_map_list_wait(expected=0) 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci start_test("Test map creation fail path...") 12938c2ecf20Sopenharmony_ci simdev = NetdevSimDev() 12948c2ecf20Sopenharmony_ci sim, = simdev.nsims 12958c2ecf20Sopenharmony_ci sim.dfs["bpf_map_accept"] = "N" 12968c2ecf20Sopenharmony_ci ret, _ = sim.set_xdp(map_obj, "offload", JSON=False, fail=False) 12978c2ecf20Sopenharmony_ci fail(ret == 0, 12988c2ecf20Sopenharmony_ci "netdevsim didn't refuse to create a map with offload disabled") 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci simdev.remove() 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci start_test("Test multi-dev ASIC program reuse...") 13038c2ecf20Sopenharmony_ci simdevA = NetdevSimDev() 13048c2ecf20Sopenharmony_ci simA, = simdevA.nsims 13058c2ecf20Sopenharmony_ci simdevB = NetdevSimDev(3) 13068c2ecf20Sopenharmony_ci simB1, simB2, simB3 = simdevB.nsims 13078c2ecf20Sopenharmony_ci sims = (simA, simB1, simB2, simB3) 13088c2ecf20Sopenharmony_ci simB = (simB1, simB2, simB3) 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci bpftool_prog_load("sample_map_ret0.o", "/sys/fs/bpf/nsimA", 13118c2ecf20Sopenharmony_ci dev=simA['ifname']) 13128c2ecf20Sopenharmony_ci progA = bpf_pinned("/sys/fs/bpf/nsimA") 13138c2ecf20Sopenharmony_ci bpftool_prog_load("sample_map_ret0.o", "/sys/fs/bpf/nsimB", 13148c2ecf20Sopenharmony_ci dev=simB1['ifname']) 13158c2ecf20Sopenharmony_ci progB = bpf_pinned("/sys/fs/bpf/nsimB") 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci simA.set_xdp(progA, "offload", JSON=False) 13188c2ecf20Sopenharmony_ci for d in simdevB.nsims: 13198c2ecf20Sopenharmony_ci d.set_xdp(progB, "offload", JSON=False) 13208c2ecf20Sopenharmony_ci 13218c2ecf20Sopenharmony_ci start_test("Test multi-dev ASIC cross-dev replace...") 13228c2ecf20Sopenharmony_ci ret, _ = simA.set_xdp(progB, "offload", force=True, JSON=False, fail=False) 13238c2ecf20Sopenharmony_ci fail(ret == 0, "cross-ASIC program allowed") 13248c2ecf20Sopenharmony_ci for d in simdevB.nsims: 13258c2ecf20Sopenharmony_ci ret, _ = d.set_xdp(progA, "offload", force=True, JSON=False, fail=False) 13268c2ecf20Sopenharmony_ci fail(ret == 0, "cross-ASIC program allowed") 13278c2ecf20Sopenharmony_ci 13288c2ecf20Sopenharmony_ci start_test("Test multi-dev ASIC cross-dev install...") 13298c2ecf20Sopenharmony_ci for d in sims: 13308c2ecf20Sopenharmony_ci d.unset_xdp("offload") 13318c2ecf20Sopenharmony_ci 13328c2ecf20Sopenharmony_ci ret, _, err = simA.set_xdp(progB, "offload", force=True, JSON=False, 13338c2ecf20Sopenharmony_ci fail=False, include_stderr=True) 13348c2ecf20Sopenharmony_ci fail(ret == 0, "cross-ASIC program allowed") 13358c2ecf20Sopenharmony_ci check_extack_nsim(err, "program bound to different dev.", args) 13368c2ecf20Sopenharmony_ci for d in simdevB.nsims: 13378c2ecf20Sopenharmony_ci ret, _, err = d.set_xdp(progA, "offload", force=True, JSON=False, 13388c2ecf20Sopenharmony_ci fail=False, include_stderr=True) 13398c2ecf20Sopenharmony_ci fail(ret == 0, "cross-ASIC program allowed") 13408c2ecf20Sopenharmony_ci check_extack_nsim(err, "program bound to different dev.", args) 13418c2ecf20Sopenharmony_ci 13428c2ecf20Sopenharmony_ci start_test("Test multi-dev ASIC cross-dev map reuse...") 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_ci mapA = bpftool("prog show %s" % (progA))[1]["map_ids"][0] 13458c2ecf20Sopenharmony_ci mapB = bpftool("prog show %s" % (progB))[1]["map_ids"][0] 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci ret, _ = bpftool_prog_load("sample_map_ret0.o", "/sys/fs/bpf/nsimB_", 13488c2ecf20Sopenharmony_ci dev=simB3['ifname'], 13498c2ecf20Sopenharmony_ci maps=["idx 0 id %d" % (mapB)], 13508c2ecf20Sopenharmony_ci fail=False) 13518c2ecf20Sopenharmony_ci fail(ret != 0, "couldn't reuse a map on the same ASIC") 13528c2ecf20Sopenharmony_ci rm("/sys/fs/bpf/nsimB_") 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci ret, _, err = bpftool_prog_load("sample_map_ret0.o", "/sys/fs/bpf/nsimA_", 13558c2ecf20Sopenharmony_ci dev=simA['ifname'], 13568c2ecf20Sopenharmony_ci maps=["idx 0 id %d" % (mapB)], 13578c2ecf20Sopenharmony_ci fail=False, include_stderr=True) 13588c2ecf20Sopenharmony_ci fail(ret == 0, "could reuse a map on a different ASIC") 13598c2ecf20Sopenharmony_ci fail(err.count("offload device mismatch between prog and map") == 0, 13608c2ecf20Sopenharmony_ci "error message missing for cross-ASIC map") 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci ret, _, err = bpftool_prog_load("sample_map_ret0.o", "/sys/fs/bpf/nsimB_", 13638c2ecf20Sopenharmony_ci dev=simB1['ifname'], 13648c2ecf20Sopenharmony_ci maps=["idx 0 id %d" % (mapA)], 13658c2ecf20Sopenharmony_ci fail=False, include_stderr=True) 13668c2ecf20Sopenharmony_ci fail(ret == 0, "could reuse a map on a different ASIC") 13678c2ecf20Sopenharmony_ci fail(err.count("offload device mismatch between prog and map") == 0, 13688c2ecf20Sopenharmony_ci "error message missing for cross-ASIC map") 13698c2ecf20Sopenharmony_ci 13708c2ecf20Sopenharmony_ci start_test("Test multi-dev ASIC cross-dev destruction...") 13718c2ecf20Sopenharmony_ci bpftool_prog_list_wait(expected=2) 13728c2ecf20Sopenharmony_ci 13738c2ecf20Sopenharmony_ci simdevA.remove() 13748c2ecf20Sopenharmony_ci bpftool_prog_list_wait(expected=1) 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ci ifnameB = bpftool("prog show %s" % (progB))[1]["dev"]["ifname"] 13778c2ecf20Sopenharmony_ci fail(ifnameB != simB1['ifname'], "program not bound to original device") 13788c2ecf20Sopenharmony_ci simB1.remove() 13798c2ecf20Sopenharmony_ci bpftool_prog_list_wait(expected=1) 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_ci start_test("Test multi-dev ASIC cross-dev destruction - move...") 13828c2ecf20Sopenharmony_ci ifnameB = bpftool("prog show %s" % (progB))[1]["dev"]["ifname"] 13838c2ecf20Sopenharmony_ci fail(ifnameB not in (simB2['ifname'], simB3['ifname']), 13848c2ecf20Sopenharmony_ci "program not bound to remaining devices") 13858c2ecf20Sopenharmony_ci 13868c2ecf20Sopenharmony_ci simB2.remove() 13878c2ecf20Sopenharmony_ci ifnameB = bpftool("prog show %s" % (progB))[1]["dev"]["ifname"] 13888c2ecf20Sopenharmony_ci fail(ifnameB != simB3['ifname'], "program not bound to remaining device") 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_ci simB3.remove() 13918c2ecf20Sopenharmony_ci simdevB.remove() 13928c2ecf20Sopenharmony_ci bpftool_prog_list_wait(expected=0) 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_ci start_test("Test multi-dev ASIC cross-dev destruction - orphaned...") 13958c2ecf20Sopenharmony_ci ret, out = bpftool("prog show %s" % (progB), fail=False) 13968c2ecf20Sopenharmony_ci fail(ret == 0, "got information about orphaned program") 13978c2ecf20Sopenharmony_ci fail("error" not in out, "no error reported for get info on orphaned") 13988c2ecf20Sopenharmony_ci fail(out["error"] != "can't get prog info: No such device", 13998c2ecf20Sopenharmony_ci "wrong error for get info on orphaned") 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ci print("%s: OK" % (os.path.basename(__file__))) 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_cifinally: 14048c2ecf20Sopenharmony_ci log("Clean up...", "", level=1) 14058c2ecf20Sopenharmony_ci log_level_inc() 14068c2ecf20Sopenharmony_ci clean_up() 1407