162306a36Sopenharmony_ci#!/usr/bin/env python3 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci# Copyright (C) 2017 Netronome Systems, Inc. 462306a36Sopenharmony_ci# Copyright (c) 2019 Mellanox Technologies. All rights reserved 562306a36Sopenharmony_ci# 662306a36Sopenharmony_ci# This software is licensed under the GNU General License Version 2, 762306a36Sopenharmony_ci# June 1991 as shown in the file COPYING in the top-level directory of this 862306a36Sopenharmony_ci# source tree. 962306a36Sopenharmony_ci# 1062306a36Sopenharmony_ci# THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" 1162306a36Sopenharmony_ci# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, 1262306a36Sopenharmony_ci# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 1362306a36Sopenharmony_ci# FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE 1462306a36Sopenharmony_ci# OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME 1562306a36Sopenharmony_ci# THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cifrom datetime import datetime 1862306a36Sopenharmony_ciimport argparse 1962306a36Sopenharmony_ciimport errno 2062306a36Sopenharmony_ciimport json 2162306a36Sopenharmony_ciimport os 2262306a36Sopenharmony_ciimport pprint 2362306a36Sopenharmony_ciimport random 2462306a36Sopenharmony_ciimport re 2562306a36Sopenharmony_ciimport stat 2662306a36Sopenharmony_ciimport string 2762306a36Sopenharmony_ciimport struct 2862306a36Sopenharmony_ciimport subprocess 2962306a36Sopenharmony_ciimport time 3062306a36Sopenharmony_ciimport traceback 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cilogfile = None 3362306a36Sopenharmony_cilog_level = 1 3462306a36Sopenharmony_ciskip_extack = False 3562306a36Sopenharmony_cibpf_test_dir = os.path.dirname(os.path.realpath(__file__)) 3662306a36Sopenharmony_cipp = pprint.PrettyPrinter() 3762306a36Sopenharmony_cidevs = [] # devices we created for clean up 3862306a36Sopenharmony_cifiles = [] # files to be removed 3962306a36Sopenharmony_cinetns = [] # net namespaces to be removed 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cidef log_get_sec(level=0): 4262306a36Sopenharmony_ci return "*" * (log_level + level) 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cidef log_level_inc(add=1): 4562306a36Sopenharmony_ci global log_level 4662306a36Sopenharmony_ci log_level += add 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cidef log_level_dec(sub=1): 4962306a36Sopenharmony_ci global log_level 5062306a36Sopenharmony_ci log_level -= sub 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cidef log_level_set(level): 5362306a36Sopenharmony_ci global log_level 5462306a36Sopenharmony_ci log_level = level 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cidef log(header, data, level=None): 5762306a36Sopenharmony_ci """ 5862306a36Sopenharmony_ci Output to an optional log. 5962306a36Sopenharmony_ci """ 6062306a36Sopenharmony_ci if logfile is None: 6162306a36Sopenharmony_ci return 6262306a36Sopenharmony_ci if level is not None: 6362306a36Sopenharmony_ci log_level_set(level) 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci if not isinstance(data, str): 6662306a36Sopenharmony_ci data = pp.pformat(data) 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci if len(header): 6962306a36Sopenharmony_ci logfile.write("\n" + log_get_sec() + " ") 7062306a36Sopenharmony_ci logfile.write(header) 7162306a36Sopenharmony_ci if len(header) and len(data.strip()): 7262306a36Sopenharmony_ci logfile.write("\n") 7362306a36Sopenharmony_ci logfile.write(data) 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cidef skip(cond, msg): 7662306a36Sopenharmony_ci if not cond: 7762306a36Sopenharmony_ci return 7862306a36Sopenharmony_ci print("SKIP: " + msg) 7962306a36Sopenharmony_ci log("SKIP: " + msg, "", level=1) 8062306a36Sopenharmony_ci os.sys.exit(0) 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cidef fail(cond, msg): 8362306a36Sopenharmony_ci if not cond: 8462306a36Sopenharmony_ci return 8562306a36Sopenharmony_ci print("FAIL: " + msg) 8662306a36Sopenharmony_ci tb = "".join(traceback.extract_stack().format()) 8762306a36Sopenharmony_ci print(tb) 8862306a36Sopenharmony_ci log("FAIL: " + msg, tb, level=1) 8962306a36Sopenharmony_ci os.sys.exit(1) 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cidef start_test(msg): 9262306a36Sopenharmony_ci log(msg, "", level=1) 9362306a36Sopenharmony_ci log_level_inc() 9462306a36Sopenharmony_ci print(msg) 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_cidef cmd(cmd, shell=True, include_stderr=False, background=False, fail=True): 9762306a36Sopenharmony_ci """ 9862306a36Sopenharmony_ci Run a command in subprocess and return tuple of (retval, stdout); 9962306a36Sopenharmony_ci optionally return stderr as well as third value. 10062306a36Sopenharmony_ci """ 10162306a36Sopenharmony_ci proc = subprocess.Popen(cmd, shell=shell, stdout=subprocess.PIPE, 10262306a36Sopenharmony_ci stderr=subprocess.PIPE) 10362306a36Sopenharmony_ci if background: 10462306a36Sopenharmony_ci msg = "%s START: %s" % (log_get_sec(1), 10562306a36Sopenharmony_ci datetime.now().strftime("%H:%M:%S.%f")) 10662306a36Sopenharmony_ci log("BKG " + proc.args, msg) 10762306a36Sopenharmony_ci return proc 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci return cmd_result(proc, include_stderr=include_stderr, fail=fail) 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cidef cmd_result(proc, include_stderr=False, fail=False): 11262306a36Sopenharmony_ci stdout, stderr = proc.communicate() 11362306a36Sopenharmony_ci stdout = stdout.decode("utf-8") 11462306a36Sopenharmony_ci stderr = stderr.decode("utf-8") 11562306a36Sopenharmony_ci proc.stdout.close() 11662306a36Sopenharmony_ci proc.stderr.close() 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci stderr = "\n" + stderr 11962306a36Sopenharmony_ci if stderr[-1] == "\n": 12062306a36Sopenharmony_ci stderr = stderr[:-1] 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci sec = log_get_sec(1) 12362306a36Sopenharmony_ci log("CMD " + proc.args, 12462306a36Sopenharmony_ci "RETCODE: %d\n%s STDOUT:\n%s%s STDERR:%s\n%s END: %s" % 12562306a36Sopenharmony_ci (proc.returncode, sec, stdout, sec, stderr, 12662306a36Sopenharmony_ci sec, datetime.now().strftime("%H:%M:%S.%f"))) 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci if proc.returncode != 0 and fail: 12962306a36Sopenharmony_ci if len(stderr) > 0 and stderr[-1] == "\n": 13062306a36Sopenharmony_ci stderr = stderr[:-1] 13162306a36Sopenharmony_ci raise Exception("Command failed: %s\n%s" % (proc.args, stderr)) 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci if include_stderr: 13462306a36Sopenharmony_ci return proc.returncode, stdout, stderr 13562306a36Sopenharmony_ci else: 13662306a36Sopenharmony_ci return proc.returncode, stdout 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_cidef rm(f): 13962306a36Sopenharmony_ci cmd("rm -f %s" % (f)) 14062306a36Sopenharmony_ci if f in files: 14162306a36Sopenharmony_ci files.remove(f) 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cidef tool(name, args, flags, JSON=True, ns="", fail=True, include_stderr=False): 14462306a36Sopenharmony_ci params = "" 14562306a36Sopenharmony_ci if JSON: 14662306a36Sopenharmony_ci params += "%s " % (flags["json"]) 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci if ns != "": 14962306a36Sopenharmony_ci ns = "ip netns exec %s " % (ns) 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci if include_stderr: 15262306a36Sopenharmony_ci ret, stdout, stderr = cmd(ns + name + " " + params + args, 15362306a36Sopenharmony_ci fail=fail, include_stderr=True) 15462306a36Sopenharmony_ci else: 15562306a36Sopenharmony_ci ret, stdout = cmd(ns + name + " " + params + args, 15662306a36Sopenharmony_ci fail=fail, include_stderr=False) 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci if JSON and len(stdout.strip()) != 0: 15962306a36Sopenharmony_ci out = json.loads(stdout) 16062306a36Sopenharmony_ci else: 16162306a36Sopenharmony_ci out = stdout 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci if include_stderr: 16462306a36Sopenharmony_ci return ret, out, stderr 16562306a36Sopenharmony_ci else: 16662306a36Sopenharmony_ci return ret, out 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cidef bpftool(args, JSON=True, ns="", fail=True, include_stderr=False): 16962306a36Sopenharmony_ci return tool("bpftool", args, {"json":"-p"}, JSON=JSON, ns=ns, 17062306a36Sopenharmony_ci fail=fail, include_stderr=include_stderr) 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cidef bpftool_prog_list(expected=None, ns=""): 17362306a36Sopenharmony_ci _, progs = bpftool("prog show", JSON=True, ns=ns, fail=True) 17462306a36Sopenharmony_ci # Remove the base progs 17562306a36Sopenharmony_ci for p in base_progs: 17662306a36Sopenharmony_ci if p in progs: 17762306a36Sopenharmony_ci progs.remove(p) 17862306a36Sopenharmony_ci if expected is not None: 17962306a36Sopenharmony_ci if len(progs) != expected: 18062306a36Sopenharmony_ci fail(True, "%d BPF programs loaded, expected %d" % 18162306a36Sopenharmony_ci (len(progs), expected)) 18262306a36Sopenharmony_ci return progs 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cidef bpftool_map_list(expected=None, ns=""): 18562306a36Sopenharmony_ci _, maps = bpftool("map show", JSON=True, ns=ns, fail=True) 18662306a36Sopenharmony_ci # Remove the base maps 18762306a36Sopenharmony_ci maps = [m for m in maps if m not in base_maps and m.get('name') and m.get('name') not in base_map_names] 18862306a36Sopenharmony_ci if expected is not None: 18962306a36Sopenharmony_ci if len(maps) != expected: 19062306a36Sopenharmony_ci fail(True, "%d BPF maps loaded, expected %d" % 19162306a36Sopenharmony_ci (len(maps), expected)) 19262306a36Sopenharmony_ci return maps 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_cidef bpftool_prog_list_wait(expected=0, n_retry=20): 19562306a36Sopenharmony_ci for i in range(n_retry): 19662306a36Sopenharmony_ci nprogs = len(bpftool_prog_list()) 19762306a36Sopenharmony_ci if nprogs == expected: 19862306a36Sopenharmony_ci return 19962306a36Sopenharmony_ci time.sleep(0.05) 20062306a36Sopenharmony_ci raise Exception("Time out waiting for program counts to stabilize want %d, have %d" % (expected, nprogs)) 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_cidef bpftool_map_list_wait(expected=0, n_retry=20): 20362306a36Sopenharmony_ci for i in range(n_retry): 20462306a36Sopenharmony_ci nmaps = len(bpftool_map_list()) 20562306a36Sopenharmony_ci if nmaps == expected: 20662306a36Sopenharmony_ci return 20762306a36Sopenharmony_ci time.sleep(0.05) 20862306a36Sopenharmony_ci raise Exception("Time out waiting for map counts to stabilize want %d, have %d" % (expected, nmaps)) 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_cidef bpftool_prog_load(sample, file_name, maps=[], prog_type="xdp", dev=None, 21162306a36Sopenharmony_ci fail=True, include_stderr=False): 21262306a36Sopenharmony_ci args = "prog load %s %s" % (os.path.join(bpf_test_dir, sample), file_name) 21362306a36Sopenharmony_ci if prog_type is not None: 21462306a36Sopenharmony_ci args += " type " + prog_type 21562306a36Sopenharmony_ci if dev is not None: 21662306a36Sopenharmony_ci args += " dev " + dev 21762306a36Sopenharmony_ci if len(maps): 21862306a36Sopenharmony_ci args += " map " + " map ".join(maps) 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci res = bpftool(args, fail=fail, include_stderr=include_stderr) 22162306a36Sopenharmony_ci if res[0] == 0: 22262306a36Sopenharmony_ci files.append(file_name) 22362306a36Sopenharmony_ci return res 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cidef ip(args, force=False, JSON=True, ns="", fail=True, include_stderr=False): 22662306a36Sopenharmony_ci if force: 22762306a36Sopenharmony_ci args = "-force " + args 22862306a36Sopenharmony_ci return tool("ip", args, {"json":"-j"}, JSON=JSON, ns=ns, 22962306a36Sopenharmony_ci fail=fail, include_stderr=include_stderr) 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cidef tc(args, JSON=True, ns="", fail=True, include_stderr=False): 23262306a36Sopenharmony_ci return tool("tc", args, {"json":"-p"}, JSON=JSON, ns=ns, 23362306a36Sopenharmony_ci fail=fail, include_stderr=include_stderr) 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_cidef ethtool(dev, opt, args, fail=True): 23662306a36Sopenharmony_ci return cmd("ethtool %s %s %s" % (opt, dev["ifname"], args), fail=fail) 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cidef bpf_obj(name, sec=".text", path=bpf_test_dir,): 23962306a36Sopenharmony_ci return "obj %s sec %s" % (os.path.join(path, name), sec) 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cidef bpf_pinned(name): 24262306a36Sopenharmony_ci return "pinned %s" % (name) 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cidef bpf_bytecode(bytecode): 24562306a36Sopenharmony_ci return "bytecode \"%s\"" % (bytecode) 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cidef mknetns(n_retry=10): 24862306a36Sopenharmony_ci for i in range(n_retry): 24962306a36Sopenharmony_ci name = ''.join([random.choice(string.ascii_letters) for i in range(8)]) 25062306a36Sopenharmony_ci ret, _ = ip("netns add %s" % (name), fail=False) 25162306a36Sopenharmony_ci if ret == 0: 25262306a36Sopenharmony_ci netns.append(name) 25362306a36Sopenharmony_ci return name 25462306a36Sopenharmony_ci return None 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cidef int2str(fmt, val): 25762306a36Sopenharmony_ci ret = [] 25862306a36Sopenharmony_ci for b in struct.pack(fmt, val): 25962306a36Sopenharmony_ci ret.append(int(b)) 26062306a36Sopenharmony_ci return " ".join(map(lambda x: str(x), ret)) 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_cidef str2int(strtab): 26362306a36Sopenharmony_ci inttab = [] 26462306a36Sopenharmony_ci for i in strtab: 26562306a36Sopenharmony_ci inttab.append(int(i, 16)) 26662306a36Sopenharmony_ci ba = bytearray(inttab) 26762306a36Sopenharmony_ci if len(strtab) == 4: 26862306a36Sopenharmony_ci fmt = "I" 26962306a36Sopenharmony_ci elif len(strtab) == 8: 27062306a36Sopenharmony_ci fmt = "Q" 27162306a36Sopenharmony_ci else: 27262306a36Sopenharmony_ci raise Exception("String array of len %d can't be unpacked to an int" % 27362306a36Sopenharmony_ci (len(strtab))) 27462306a36Sopenharmony_ci return struct.unpack(fmt, ba)[0] 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ciclass DebugfsDir: 27762306a36Sopenharmony_ci """ 27862306a36Sopenharmony_ci Class for accessing DebugFS directories as a dictionary. 27962306a36Sopenharmony_ci """ 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci def __init__(self, path): 28262306a36Sopenharmony_ci self.path = path 28362306a36Sopenharmony_ci self._dict = self._debugfs_dir_read(path) 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci def __len__(self): 28662306a36Sopenharmony_ci return len(self._dict.keys()) 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci def __getitem__(self, key): 28962306a36Sopenharmony_ci if type(key) is int: 29062306a36Sopenharmony_ci key = list(self._dict.keys())[key] 29162306a36Sopenharmony_ci return self._dict[key] 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci def __setitem__(self, key, value): 29462306a36Sopenharmony_ci log("DebugFS set %s = %s" % (key, value), "") 29562306a36Sopenharmony_ci log_level_inc() 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci cmd("echo '%s' > %s/%s" % (value, self.path, key)) 29862306a36Sopenharmony_ci log_level_dec() 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci _, out = cmd('cat %s/%s' % (self.path, key)) 30162306a36Sopenharmony_ci self._dict[key] = out.strip() 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci def _debugfs_dir_read(self, path): 30462306a36Sopenharmony_ci dfs = {} 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci log("DebugFS state for %s" % (path), "") 30762306a36Sopenharmony_ci log_level_inc(add=2) 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci _, out = cmd('ls ' + path) 31062306a36Sopenharmony_ci for f in out.split(): 31162306a36Sopenharmony_ci if f == "ports": 31262306a36Sopenharmony_ci continue 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci p = os.path.join(path, f) 31562306a36Sopenharmony_ci if not os.stat(p).st_mode & stat.S_IRUSR: 31662306a36Sopenharmony_ci continue 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci if os.path.isfile(p): 31962306a36Sopenharmony_ci # We need to init trap_flow_action_cookie before read it 32062306a36Sopenharmony_ci if f == "trap_flow_action_cookie": 32162306a36Sopenharmony_ci cmd('echo deadbeef > %s/%s' % (path, f)) 32262306a36Sopenharmony_ci _, out = cmd('cat %s/%s' % (path, f)) 32362306a36Sopenharmony_ci dfs[f] = out.strip() 32462306a36Sopenharmony_ci elif os.path.isdir(p): 32562306a36Sopenharmony_ci dfs[f] = DebugfsDir(p) 32662306a36Sopenharmony_ci else: 32762306a36Sopenharmony_ci raise Exception("%s is neither file nor directory" % (p)) 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci log_level_dec() 33062306a36Sopenharmony_ci log("DebugFS state", dfs) 33162306a36Sopenharmony_ci log_level_dec() 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci return dfs 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ciclass NetdevSimDev: 33662306a36Sopenharmony_ci """ 33762306a36Sopenharmony_ci Class for netdevsim bus device and its attributes. 33862306a36Sopenharmony_ci """ 33962306a36Sopenharmony_ci @staticmethod 34062306a36Sopenharmony_ci def ctrl_write(path, val): 34162306a36Sopenharmony_ci fullpath = os.path.join("/sys/bus/netdevsim/", path) 34262306a36Sopenharmony_ci try: 34362306a36Sopenharmony_ci with open(fullpath, "w") as f: 34462306a36Sopenharmony_ci f.write(val) 34562306a36Sopenharmony_ci except OSError as e: 34662306a36Sopenharmony_ci log("WRITE %s: %r" % (fullpath, val), -e.errno) 34762306a36Sopenharmony_ci raise e 34862306a36Sopenharmony_ci log("WRITE %s: %r" % (fullpath, val), 0) 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci def __init__(self, port_count=1): 35162306a36Sopenharmony_ci addr = 0 35262306a36Sopenharmony_ci while True: 35362306a36Sopenharmony_ci try: 35462306a36Sopenharmony_ci self.ctrl_write("new_device", "%u %u" % (addr, port_count)) 35562306a36Sopenharmony_ci except OSError as e: 35662306a36Sopenharmony_ci if e.errno == errno.ENOSPC: 35762306a36Sopenharmony_ci addr += 1 35862306a36Sopenharmony_ci continue 35962306a36Sopenharmony_ci raise e 36062306a36Sopenharmony_ci break 36162306a36Sopenharmony_ci self.addr = addr 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci # As probe of netdevsim device might happen from a workqueue, 36462306a36Sopenharmony_ci # so wait here until all netdevs appear. 36562306a36Sopenharmony_ci self.wait_for_netdevs(port_count) 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci ret, out = cmd("udevadm settle", fail=False) 36862306a36Sopenharmony_ci if ret: 36962306a36Sopenharmony_ci raise Exception("udevadm settle failed") 37062306a36Sopenharmony_ci ifnames = self.get_ifnames() 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci devs.append(self) 37362306a36Sopenharmony_ci self.dfs_dir = "/sys/kernel/debug/netdevsim/netdevsim%u/" % addr 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci self.nsims = [] 37662306a36Sopenharmony_ci for port_index in range(port_count): 37762306a36Sopenharmony_ci self.nsims.append(NetdevSim(self, port_index, ifnames[port_index])) 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci def get_ifnames(self): 38062306a36Sopenharmony_ci ifnames = [] 38162306a36Sopenharmony_ci listdir = os.listdir("/sys/bus/netdevsim/devices/netdevsim%u/net/" % self.addr) 38262306a36Sopenharmony_ci for ifname in listdir: 38362306a36Sopenharmony_ci ifnames.append(ifname) 38462306a36Sopenharmony_ci ifnames.sort() 38562306a36Sopenharmony_ci return ifnames 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci def wait_for_netdevs(self, port_count): 38862306a36Sopenharmony_ci timeout = 5 38962306a36Sopenharmony_ci timeout_start = time.time() 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci while True: 39262306a36Sopenharmony_ci try: 39362306a36Sopenharmony_ci ifnames = self.get_ifnames() 39462306a36Sopenharmony_ci except FileNotFoundError as e: 39562306a36Sopenharmony_ci ifnames = [] 39662306a36Sopenharmony_ci if len(ifnames) == port_count: 39762306a36Sopenharmony_ci break 39862306a36Sopenharmony_ci if time.time() < timeout_start + timeout: 39962306a36Sopenharmony_ci continue 40062306a36Sopenharmony_ci raise Exception("netdevices did not appear within timeout") 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci def dfs_num_bound_progs(self): 40362306a36Sopenharmony_ci path = os.path.join(self.dfs_dir, "bpf_bound_progs") 40462306a36Sopenharmony_ci _, progs = cmd('ls %s' % (path)) 40562306a36Sopenharmony_ci return len(progs.split()) 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci def dfs_get_bound_progs(self, expected): 40862306a36Sopenharmony_ci progs = DebugfsDir(os.path.join(self.dfs_dir, "bpf_bound_progs")) 40962306a36Sopenharmony_ci if expected is not None: 41062306a36Sopenharmony_ci if len(progs) != expected: 41162306a36Sopenharmony_ci fail(True, "%d BPF programs bound, expected %d" % 41262306a36Sopenharmony_ci (len(progs), expected)) 41362306a36Sopenharmony_ci return progs 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci def remove(self): 41662306a36Sopenharmony_ci self.ctrl_write("del_device", "%u" % (self.addr, )) 41762306a36Sopenharmony_ci devs.remove(self) 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci def remove_nsim(self, nsim): 42062306a36Sopenharmony_ci self.nsims.remove(nsim) 42162306a36Sopenharmony_ci self.ctrl_write("devices/netdevsim%u/del_port" % (self.addr, ), 42262306a36Sopenharmony_ci "%u" % (nsim.port_index, )) 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ciclass NetdevSim: 42562306a36Sopenharmony_ci """ 42662306a36Sopenharmony_ci Class for netdevsim netdevice and its attributes. 42762306a36Sopenharmony_ci """ 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci def __init__(self, nsimdev, port_index, ifname): 43062306a36Sopenharmony_ci # In case udev renamed the netdev to according to new schema, 43162306a36Sopenharmony_ci # check if the name matches the port_index. 43262306a36Sopenharmony_ci nsimnamere = re.compile("eni\d+np(\d+)") 43362306a36Sopenharmony_ci match = nsimnamere.match(ifname) 43462306a36Sopenharmony_ci if match and int(match.groups()[0]) != port_index + 1: 43562306a36Sopenharmony_ci raise Exception("netdevice name mismatches the expected one") 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci self.nsimdev = nsimdev 43862306a36Sopenharmony_ci self.port_index = port_index 43962306a36Sopenharmony_ci self.ns = "" 44062306a36Sopenharmony_ci self.dfs_dir = "%s/ports/%u/" % (nsimdev.dfs_dir, port_index) 44162306a36Sopenharmony_ci self.dfs_refresh() 44262306a36Sopenharmony_ci _, [self.dev] = ip("link show dev %s" % ifname) 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci def __getitem__(self, key): 44562306a36Sopenharmony_ci return self.dev[key] 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci def remove(self): 44862306a36Sopenharmony_ci self.nsimdev.remove_nsim(self) 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci def dfs_refresh(self): 45162306a36Sopenharmony_ci self.dfs = DebugfsDir(self.dfs_dir) 45262306a36Sopenharmony_ci return self.dfs 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci def dfs_read(self, f): 45562306a36Sopenharmony_ci path = os.path.join(self.dfs_dir, f) 45662306a36Sopenharmony_ci _, data = cmd('cat %s' % (path)) 45762306a36Sopenharmony_ci return data.strip() 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci def wait_for_flush(self, bound=0, total=0, n_retry=20): 46062306a36Sopenharmony_ci for i in range(n_retry): 46162306a36Sopenharmony_ci nbound = self.nsimdev.dfs_num_bound_progs() 46262306a36Sopenharmony_ci nprogs = len(bpftool_prog_list()) 46362306a36Sopenharmony_ci if nbound == bound and nprogs == total: 46462306a36Sopenharmony_ci return 46562306a36Sopenharmony_ci time.sleep(0.05) 46662306a36Sopenharmony_ci raise Exception("Time out waiting for program counts to stabilize want %d/%d, have %d bound, %d loaded" % (bound, total, nbound, nprogs)) 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci def set_ns(self, ns): 46962306a36Sopenharmony_ci name = "1" if ns == "" else ns 47062306a36Sopenharmony_ci ip("link set dev %s netns %s" % (self.dev["ifname"], name), ns=self.ns) 47162306a36Sopenharmony_ci self.ns = ns 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci def set_mtu(self, mtu, fail=True): 47462306a36Sopenharmony_ci return ip("link set dev %s mtu %d" % (self.dev["ifname"], mtu), 47562306a36Sopenharmony_ci fail=fail) 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci def set_xdp(self, bpf, mode, force=False, JSON=True, verbose=False, 47862306a36Sopenharmony_ci fail=True, include_stderr=False): 47962306a36Sopenharmony_ci if verbose: 48062306a36Sopenharmony_ci bpf += " verbose" 48162306a36Sopenharmony_ci return ip("link set dev %s xdp%s %s" % (self.dev["ifname"], mode, bpf), 48262306a36Sopenharmony_ci force=force, JSON=JSON, 48362306a36Sopenharmony_ci fail=fail, include_stderr=include_stderr) 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci def unset_xdp(self, mode, force=False, JSON=True, 48662306a36Sopenharmony_ci fail=True, include_stderr=False): 48762306a36Sopenharmony_ci return ip("link set dev %s xdp%s off" % (self.dev["ifname"], mode), 48862306a36Sopenharmony_ci force=force, JSON=JSON, 48962306a36Sopenharmony_ci fail=fail, include_stderr=include_stderr) 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci def ip_link_show(self, xdp): 49262306a36Sopenharmony_ci _, link = ip("link show dev %s" % (self['ifname'])) 49362306a36Sopenharmony_ci if len(link) > 1: 49462306a36Sopenharmony_ci raise Exception("Multiple objects on ip link show") 49562306a36Sopenharmony_ci if len(link) < 1: 49662306a36Sopenharmony_ci return {} 49762306a36Sopenharmony_ci fail(xdp != "xdp" in link, 49862306a36Sopenharmony_ci "XDP program not reporting in iplink (reported %s, expected %s)" % 49962306a36Sopenharmony_ci ("xdp" in link, xdp)) 50062306a36Sopenharmony_ci return link[0] 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci def tc_add_ingress(self): 50362306a36Sopenharmony_ci tc("qdisc add dev %s ingress" % (self['ifname'])) 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci def tc_del_ingress(self): 50662306a36Sopenharmony_ci tc("qdisc del dev %s ingress" % (self['ifname'])) 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci def tc_flush_filters(self, bound=0, total=0): 50962306a36Sopenharmony_ci self.tc_del_ingress() 51062306a36Sopenharmony_ci self.tc_add_ingress() 51162306a36Sopenharmony_ci self.wait_for_flush(bound=bound, total=total) 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci def tc_show_ingress(self, expected=None): 51462306a36Sopenharmony_ci # No JSON support, oh well... 51562306a36Sopenharmony_ci flags = ["skip_sw", "skip_hw", "in_hw"] 51662306a36Sopenharmony_ci named = ["protocol", "pref", "chain", "handle", "id", "tag"] 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci args = "-s filter show dev %s ingress" % (self['ifname']) 51962306a36Sopenharmony_ci _, out = tc(args, JSON=False) 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci filters = [] 52262306a36Sopenharmony_ci lines = out.split('\n') 52362306a36Sopenharmony_ci for line in lines: 52462306a36Sopenharmony_ci words = line.split() 52562306a36Sopenharmony_ci if "handle" not in words: 52662306a36Sopenharmony_ci continue 52762306a36Sopenharmony_ci fltr = {} 52862306a36Sopenharmony_ci for flag in flags: 52962306a36Sopenharmony_ci fltr[flag] = flag in words 53062306a36Sopenharmony_ci for name in named: 53162306a36Sopenharmony_ci try: 53262306a36Sopenharmony_ci idx = words.index(name) 53362306a36Sopenharmony_ci fltr[name] = words[idx + 1] 53462306a36Sopenharmony_ci except ValueError: 53562306a36Sopenharmony_ci pass 53662306a36Sopenharmony_ci filters.append(fltr) 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci if expected is not None: 53962306a36Sopenharmony_ci fail(len(filters) != expected, 54062306a36Sopenharmony_ci "%d ingress filters loaded, expected %d" % 54162306a36Sopenharmony_ci (len(filters), expected)) 54262306a36Sopenharmony_ci return filters 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci def cls_filter_op(self, op, qdisc="ingress", prio=None, handle=None, 54562306a36Sopenharmony_ci chain=None, cls="", params="", 54662306a36Sopenharmony_ci fail=True, include_stderr=False): 54762306a36Sopenharmony_ci spec = "" 54862306a36Sopenharmony_ci if prio is not None: 54962306a36Sopenharmony_ci spec += " prio %d" % (prio) 55062306a36Sopenharmony_ci if handle: 55162306a36Sopenharmony_ci spec += " handle %s" % (handle) 55262306a36Sopenharmony_ci if chain is not None: 55362306a36Sopenharmony_ci spec += " chain %d" % (chain) 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci return tc("filter {op} dev {dev} {qdisc} {spec} {cls} {params}"\ 55662306a36Sopenharmony_ci .format(op=op, dev=self['ifname'], qdisc=qdisc, spec=spec, 55762306a36Sopenharmony_ci cls=cls, params=params), 55862306a36Sopenharmony_ci fail=fail, include_stderr=include_stderr) 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci def cls_bpf_add_filter(self, bpf, op="add", prio=None, handle=None, 56162306a36Sopenharmony_ci chain=None, da=False, verbose=False, 56262306a36Sopenharmony_ci skip_sw=False, skip_hw=False, 56362306a36Sopenharmony_ci fail=True, include_stderr=False): 56462306a36Sopenharmony_ci cls = "bpf " + bpf 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci params = "" 56762306a36Sopenharmony_ci if da: 56862306a36Sopenharmony_ci params += " da" 56962306a36Sopenharmony_ci if verbose: 57062306a36Sopenharmony_ci params += " verbose" 57162306a36Sopenharmony_ci if skip_sw: 57262306a36Sopenharmony_ci params += " skip_sw" 57362306a36Sopenharmony_ci if skip_hw: 57462306a36Sopenharmony_ci params += " skip_hw" 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci return self.cls_filter_op(op=op, prio=prio, handle=handle, cls=cls, 57762306a36Sopenharmony_ci chain=chain, params=params, 57862306a36Sopenharmony_ci fail=fail, include_stderr=include_stderr) 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci def set_ethtool_tc_offloads(self, enable, fail=True): 58162306a36Sopenharmony_ci args = "hw-tc-offload %s" % ("on" if enable else "off") 58262306a36Sopenharmony_ci return ethtool(self, "-K", args, fail=fail) 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci################################################################################ 58562306a36Sopenharmony_cidef clean_up(): 58662306a36Sopenharmony_ci global files, netns, devs 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci for dev in devs: 58962306a36Sopenharmony_ci dev.remove() 59062306a36Sopenharmony_ci for f in files: 59162306a36Sopenharmony_ci cmd("rm -f %s" % (f)) 59262306a36Sopenharmony_ci for ns in netns: 59362306a36Sopenharmony_ci cmd("ip netns delete %s" % (ns)) 59462306a36Sopenharmony_ci files = [] 59562306a36Sopenharmony_ci netns = [] 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_cidef pin_prog(file_name, idx=0): 59862306a36Sopenharmony_ci progs = bpftool_prog_list(expected=(idx + 1)) 59962306a36Sopenharmony_ci prog = progs[idx] 60062306a36Sopenharmony_ci bpftool("prog pin id %d %s" % (prog["id"], file_name)) 60162306a36Sopenharmony_ci files.append(file_name) 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci return file_name, bpf_pinned(file_name) 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_cidef pin_map(file_name, idx=0, expected=1): 60662306a36Sopenharmony_ci maps = bpftool_map_list(expected=expected) 60762306a36Sopenharmony_ci m = maps[idx] 60862306a36Sopenharmony_ci bpftool("map pin id %d %s" % (m["id"], file_name)) 60962306a36Sopenharmony_ci files.append(file_name) 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci return file_name, bpf_pinned(file_name) 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_cidef check_dev_info_removed(prog_file=None, map_file=None): 61462306a36Sopenharmony_ci bpftool_prog_list(expected=0) 61562306a36Sopenharmony_ci ret, err = bpftool("prog show pin %s" % (prog_file), fail=False) 61662306a36Sopenharmony_ci fail(ret == 0, "Showing prog with removed device did not fail") 61762306a36Sopenharmony_ci fail(err["error"].find("No such device") == -1, 61862306a36Sopenharmony_ci "Showing prog with removed device expected ENODEV, error is %s" % 61962306a36Sopenharmony_ci (err["error"])) 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci bpftool_map_list(expected=0) 62262306a36Sopenharmony_ci ret, err = bpftool("map show pin %s" % (map_file), fail=False) 62362306a36Sopenharmony_ci fail(ret == 0, "Showing map with removed device did not fail") 62462306a36Sopenharmony_ci fail(err["error"].find("No such device") == -1, 62562306a36Sopenharmony_ci "Showing map with removed device expected ENODEV, error is %s" % 62662306a36Sopenharmony_ci (err["error"])) 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_cidef check_dev_info(other_ns, ns, prog_file=None, map_file=None, removed=False): 62962306a36Sopenharmony_ci progs = bpftool_prog_list(expected=1, ns=ns) 63062306a36Sopenharmony_ci prog = progs[0] 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci fail("dev" not in prog.keys(), "Device parameters not reported") 63362306a36Sopenharmony_ci dev = prog["dev"] 63462306a36Sopenharmony_ci fail("ifindex" not in dev.keys(), "Device parameters not reported") 63562306a36Sopenharmony_ci fail("ns_dev" not in dev.keys(), "Device parameters not reported") 63662306a36Sopenharmony_ci fail("ns_inode" not in dev.keys(), "Device parameters not reported") 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci if not other_ns: 63962306a36Sopenharmony_ci fail("ifname" not in dev.keys(), "Ifname not reported") 64062306a36Sopenharmony_ci fail(dev["ifname"] != sim["ifname"], 64162306a36Sopenharmony_ci "Ifname incorrect %s vs %s" % (dev["ifname"], sim["ifname"])) 64262306a36Sopenharmony_ci else: 64362306a36Sopenharmony_ci fail("ifname" in dev.keys(), "Ifname is reported for other ns") 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci maps = bpftool_map_list(expected=2, ns=ns) 64662306a36Sopenharmony_ci for m in maps: 64762306a36Sopenharmony_ci fail("dev" not in m.keys(), "Device parameters not reported") 64862306a36Sopenharmony_ci fail(dev != m["dev"], "Map's device different than program's") 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_cidef check_extack(output, reference, args): 65162306a36Sopenharmony_ci if skip_extack: 65262306a36Sopenharmony_ci return 65362306a36Sopenharmony_ci lines = output.split("\n") 65462306a36Sopenharmony_ci comp = len(lines) >= 2 and lines[1] == 'Error: ' + reference 65562306a36Sopenharmony_ci fail(not comp, "Missing or incorrect netlink extack message") 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_cidef check_extack_nsim(output, reference, args): 65862306a36Sopenharmony_ci check_extack(output, "netdevsim: " + reference, args) 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_cidef check_no_extack(res, needle): 66162306a36Sopenharmony_ci fail((res[1] + res[2]).count(needle) or (res[1] + res[2]).count("Warning:"), 66262306a36Sopenharmony_ci "Found '%s' in command output, leaky extack?" % (needle)) 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_cidef check_verifier_log(output, reference): 66562306a36Sopenharmony_ci lines = output.split("\n") 66662306a36Sopenharmony_ci for l in reversed(lines): 66762306a36Sopenharmony_ci if l == reference: 66862306a36Sopenharmony_ci return 66962306a36Sopenharmony_ci fail(True, "Missing or incorrect message from netdevsim in verifier log") 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_cidef check_multi_basic(two_xdps): 67262306a36Sopenharmony_ci fail(two_xdps["mode"] != 4, "Bad mode reported with multiple programs") 67362306a36Sopenharmony_ci fail("prog" in two_xdps, "Base program reported in multi program mode") 67462306a36Sopenharmony_ci fail(len(two_xdps["attached"]) != 2, 67562306a36Sopenharmony_ci "Wrong attached program count with two programs") 67662306a36Sopenharmony_ci fail(two_xdps["attached"][0]["prog"]["id"] == 67762306a36Sopenharmony_ci two_xdps["attached"][1]["prog"]["id"], 67862306a36Sopenharmony_ci "Offloaded and other programs have the same id") 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_cidef test_spurios_extack(sim, obj, skip_hw, needle): 68162306a36Sopenharmony_ci res = sim.cls_bpf_add_filter(obj, prio=1, handle=1, skip_hw=skip_hw, 68262306a36Sopenharmony_ci include_stderr=True) 68362306a36Sopenharmony_ci check_no_extack(res, needle) 68462306a36Sopenharmony_ci res = sim.cls_bpf_add_filter(obj, op="replace", prio=1, handle=1, 68562306a36Sopenharmony_ci skip_hw=skip_hw, include_stderr=True) 68662306a36Sopenharmony_ci check_no_extack(res, needle) 68762306a36Sopenharmony_ci res = sim.cls_filter_op(op="delete", prio=1, handle=1, cls="bpf", 68862306a36Sopenharmony_ci include_stderr=True) 68962306a36Sopenharmony_ci check_no_extack(res, needle) 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_cidef test_multi_prog(simdev, sim, obj, modename, modeid): 69262306a36Sopenharmony_ci start_test("Test multi-attachment XDP - %s + offload..." % 69362306a36Sopenharmony_ci (modename or "default", )) 69462306a36Sopenharmony_ci sim.set_xdp(obj, "offload") 69562306a36Sopenharmony_ci xdp = sim.ip_link_show(xdp=True)["xdp"] 69662306a36Sopenharmony_ci offloaded = sim.dfs_read("bpf_offloaded_id") 69762306a36Sopenharmony_ci fail("prog" not in xdp, "Base program not reported in single program mode") 69862306a36Sopenharmony_ci fail(len(xdp["attached"]) != 1, 69962306a36Sopenharmony_ci "Wrong attached program count with one program") 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci sim.set_xdp(obj, modename) 70262306a36Sopenharmony_ci two_xdps = sim.ip_link_show(xdp=True)["xdp"] 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci fail(xdp["attached"][0] not in two_xdps["attached"], 70562306a36Sopenharmony_ci "Offload program not reported after other activated") 70662306a36Sopenharmony_ci check_multi_basic(two_xdps) 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci offloaded2 = sim.dfs_read("bpf_offloaded_id") 70962306a36Sopenharmony_ci fail(offloaded != offloaded2, 71062306a36Sopenharmony_ci "Offload ID changed after loading other program") 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci start_test("Test multi-attachment XDP - replace...") 71362306a36Sopenharmony_ci ret, _, err = sim.set_xdp(obj, "offload", fail=False, include_stderr=True) 71462306a36Sopenharmony_ci fail(ret == 0, "Replaced one of programs without -force") 71562306a36Sopenharmony_ci check_extack(err, "XDP program already attached.", args) 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci start_test("Test multi-attachment XDP - remove without mode...") 71862306a36Sopenharmony_ci ret, _, err = sim.unset_xdp("", force=True, 71962306a36Sopenharmony_ci fail=False, include_stderr=True) 72062306a36Sopenharmony_ci fail(ret == 0, "Removed program without a mode flag") 72162306a36Sopenharmony_ci check_extack(err, "More than one program loaded, unset mode is ambiguous.", args) 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci sim.unset_xdp("offload") 72462306a36Sopenharmony_ci xdp = sim.ip_link_show(xdp=True)["xdp"] 72562306a36Sopenharmony_ci offloaded = sim.dfs_read("bpf_offloaded_id") 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci fail(xdp["mode"] != modeid, "Bad mode reported after multiple programs") 72862306a36Sopenharmony_ci fail("prog" not in xdp, 72962306a36Sopenharmony_ci "Base program not reported after multi program mode") 73062306a36Sopenharmony_ci fail(xdp["attached"][0] not in two_xdps["attached"], 73162306a36Sopenharmony_ci "Offload program not reported after other activated") 73262306a36Sopenharmony_ci fail(len(xdp["attached"]) != 1, 73362306a36Sopenharmony_ci "Wrong attached program count with remaining programs") 73462306a36Sopenharmony_ci fail(offloaded != "0", "Offload ID reported with only other program left") 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci start_test("Test multi-attachment XDP - reattach...") 73762306a36Sopenharmony_ci sim.set_xdp(obj, "offload") 73862306a36Sopenharmony_ci two_xdps = sim.ip_link_show(xdp=True)["xdp"] 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci fail(xdp["attached"][0] not in two_xdps["attached"], 74162306a36Sopenharmony_ci "Other program not reported after offload activated") 74262306a36Sopenharmony_ci check_multi_basic(two_xdps) 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci start_test("Test multi-attachment XDP - device remove...") 74562306a36Sopenharmony_ci simdev.remove() 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci simdev = NetdevSimDev() 74862306a36Sopenharmony_ci sim, = simdev.nsims 74962306a36Sopenharmony_ci sim.set_ethtool_tc_offloads(True) 75062306a36Sopenharmony_ci return [simdev, sim] 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci# Parse command line 75362306a36Sopenharmony_ciparser = argparse.ArgumentParser() 75462306a36Sopenharmony_ciparser.add_argument("--log", help="output verbose log to given file") 75562306a36Sopenharmony_ciargs = parser.parse_args() 75662306a36Sopenharmony_ciif args.log: 75762306a36Sopenharmony_ci logfile = open(args.log, 'w+') 75862306a36Sopenharmony_ci logfile.write("# -*-Org-*-") 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_cilog("Prepare...", "", level=1) 76162306a36Sopenharmony_cilog_level_inc() 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci# Check permissions 76462306a36Sopenharmony_ciskip(os.getuid() != 0, "test must be run as root") 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci# Check tools 76762306a36Sopenharmony_ciret, progs = bpftool("prog", fail=False) 76862306a36Sopenharmony_ciskip(ret != 0, "bpftool not installed") 76962306a36Sopenharmony_cibase_progs = progs 77062306a36Sopenharmony_ci_, base_maps = bpftool("map") 77162306a36Sopenharmony_cibase_map_names = [ 77262306a36Sopenharmony_ci 'pid_iter.rodata', # created on each bpftool invocation 77362306a36Sopenharmony_ci 'libbpf_det_bind', # created on each bpftool invocation 77462306a36Sopenharmony_ci] 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci# Check netdevsim 77762306a36Sopenharmony_ciif not os.path.isdir("/sys/bus/netdevsim/"): 77862306a36Sopenharmony_ci ret, out = cmd("modprobe netdevsim", fail=False) 77962306a36Sopenharmony_ci skip(ret != 0, "netdevsim module could not be loaded") 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci# Check debugfs 78262306a36Sopenharmony_ci_, out = cmd("mount") 78362306a36Sopenharmony_ciif out.find("/sys/kernel/debug type debugfs") == -1: 78462306a36Sopenharmony_ci cmd("mount -t debugfs none /sys/kernel/debug") 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci# Check samples are compiled 78762306a36Sopenharmony_cisamples = ["sample_ret0.bpf.o", "sample_map_ret0.bpf.o"] 78862306a36Sopenharmony_cifor s in samples: 78962306a36Sopenharmony_ci ret, out = cmd("ls %s/%s" % (bpf_test_dir, s), fail=False) 79062306a36Sopenharmony_ci skip(ret != 0, "sample %s/%s not found, please compile it" % 79162306a36Sopenharmony_ci (bpf_test_dir, s)) 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci# Check if iproute2 is built with libmnl (needed by extack support) 79462306a36Sopenharmony_ci_, _, err = cmd("tc qdisc delete dev lo handle 0", 79562306a36Sopenharmony_ci fail=False, include_stderr=True) 79662306a36Sopenharmony_ciif err.find("Error: Failed to find qdisc with specified handle.") == -1: 79762306a36Sopenharmony_ci print("Warning: no extack message in iproute2 output, libmnl missing?") 79862306a36Sopenharmony_ci log("Warning: no extack message in iproute2 output, libmnl missing?", "") 79962306a36Sopenharmony_ci skip_extack = True 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci# Check if net namespaces seem to work 80262306a36Sopenharmony_cins = mknetns() 80362306a36Sopenharmony_ciskip(ns is None, "Could not create a net namespace") 80462306a36Sopenharmony_cicmd("ip netns delete %s" % (ns)) 80562306a36Sopenharmony_cinetns = [] 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_citry: 80862306a36Sopenharmony_ci obj = bpf_obj("sample_ret0.bpf.o") 80962306a36Sopenharmony_ci bytecode = bpf_bytecode("1,6 0 0 4294967295,") 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci start_test("Test destruction of generic XDP...") 81262306a36Sopenharmony_ci simdev = NetdevSimDev() 81362306a36Sopenharmony_ci sim, = simdev.nsims 81462306a36Sopenharmony_ci sim.set_xdp(obj, "generic") 81562306a36Sopenharmony_ci simdev.remove() 81662306a36Sopenharmony_ci bpftool_prog_list_wait(expected=0) 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci simdev = NetdevSimDev() 81962306a36Sopenharmony_ci sim, = simdev.nsims 82062306a36Sopenharmony_ci sim.tc_add_ingress() 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci start_test("Test TC non-offloaded...") 82362306a36Sopenharmony_ci ret, _ = sim.cls_bpf_add_filter(obj, skip_hw=True, fail=False) 82462306a36Sopenharmony_ci fail(ret != 0, "Software TC filter did not load") 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci start_test("Test TC non-offloaded isn't getting bound...") 82762306a36Sopenharmony_ci ret, _ = sim.cls_bpf_add_filter(obj, fail=False) 82862306a36Sopenharmony_ci fail(ret != 0, "Software TC filter did not load") 82962306a36Sopenharmony_ci simdev.dfs_get_bound_progs(expected=0) 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci sim.tc_flush_filters() 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci start_test("Test TC offloads are off by default...") 83462306a36Sopenharmony_ci ret, _, err = sim.cls_bpf_add_filter(obj, skip_sw=True, 83562306a36Sopenharmony_ci fail=False, include_stderr=True) 83662306a36Sopenharmony_ci fail(ret == 0, "TC filter loaded without enabling TC offloads") 83762306a36Sopenharmony_ci check_extack(err, "TC offload is disabled on net device.", args) 83862306a36Sopenharmony_ci sim.wait_for_flush() 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci sim.set_ethtool_tc_offloads(True) 84162306a36Sopenharmony_ci sim.dfs["bpf_tc_non_bound_accept"] = "Y" 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ci start_test("Test TC offload by default...") 84462306a36Sopenharmony_ci ret, _ = sim.cls_bpf_add_filter(obj, fail=False) 84562306a36Sopenharmony_ci fail(ret != 0, "Software TC filter did not load") 84662306a36Sopenharmony_ci simdev.dfs_get_bound_progs(expected=0) 84762306a36Sopenharmony_ci ingress = sim.tc_show_ingress(expected=1) 84862306a36Sopenharmony_ci fltr = ingress[0] 84962306a36Sopenharmony_ci fail(not fltr["in_hw"], "Filter not offloaded by default") 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci sim.tc_flush_filters() 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci start_test("Test TC cBPF bytcode tries offload by default...") 85462306a36Sopenharmony_ci ret, _ = sim.cls_bpf_add_filter(bytecode, fail=False) 85562306a36Sopenharmony_ci fail(ret != 0, "Software TC filter did not load") 85662306a36Sopenharmony_ci simdev.dfs_get_bound_progs(expected=0) 85762306a36Sopenharmony_ci ingress = sim.tc_show_ingress(expected=1) 85862306a36Sopenharmony_ci fltr = ingress[0] 85962306a36Sopenharmony_ci fail(not fltr["in_hw"], "Bytecode not offloaded by default") 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci sim.tc_flush_filters() 86262306a36Sopenharmony_ci sim.dfs["bpf_tc_non_bound_accept"] = "N" 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci start_test("Test TC cBPF unbound bytecode doesn't offload...") 86562306a36Sopenharmony_ci ret, _, err = sim.cls_bpf_add_filter(bytecode, skip_sw=True, 86662306a36Sopenharmony_ci fail=False, include_stderr=True) 86762306a36Sopenharmony_ci fail(ret == 0, "TC bytecode loaded for offload") 86862306a36Sopenharmony_ci check_extack_nsim(err, "netdevsim configured to reject unbound programs.", 86962306a36Sopenharmony_ci args) 87062306a36Sopenharmony_ci sim.wait_for_flush() 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci start_test("Test non-0 chain offload...") 87362306a36Sopenharmony_ci ret, _, err = sim.cls_bpf_add_filter(obj, chain=1, prio=1, handle=1, 87462306a36Sopenharmony_ci skip_sw=True, 87562306a36Sopenharmony_ci fail=False, include_stderr=True) 87662306a36Sopenharmony_ci fail(ret == 0, "Offloaded a filter to chain other than 0") 87762306a36Sopenharmony_ci check_extack(err, "Driver supports only offload of chain 0.", args) 87862306a36Sopenharmony_ci sim.tc_flush_filters() 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci start_test("Test TC replace...") 88162306a36Sopenharmony_ci sim.cls_bpf_add_filter(obj, prio=1, handle=1) 88262306a36Sopenharmony_ci sim.cls_bpf_add_filter(obj, op="replace", prio=1, handle=1) 88362306a36Sopenharmony_ci sim.cls_filter_op(op="delete", prio=1, handle=1, cls="bpf") 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci sim.cls_bpf_add_filter(obj, prio=1, handle=1, skip_sw=True) 88662306a36Sopenharmony_ci sim.cls_bpf_add_filter(obj, op="replace", prio=1, handle=1, skip_sw=True) 88762306a36Sopenharmony_ci sim.cls_filter_op(op="delete", prio=1, handle=1, cls="bpf") 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ci sim.cls_bpf_add_filter(obj, prio=1, handle=1, skip_hw=True) 89062306a36Sopenharmony_ci sim.cls_bpf_add_filter(obj, op="replace", prio=1, handle=1, skip_hw=True) 89162306a36Sopenharmony_ci sim.cls_filter_op(op="delete", prio=1, handle=1, cls="bpf") 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci start_test("Test TC replace bad flags...") 89462306a36Sopenharmony_ci for i in range(3): 89562306a36Sopenharmony_ci for j in range(3): 89662306a36Sopenharmony_ci ret, _ = sim.cls_bpf_add_filter(obj, op="replace", prio=1, handle=1, 89762306a36Sopenharmony_ci skip_sw=(j == 1), skip_hw=(j == 2), 89862306a36Sopenharmony_ci fail=False) 89962306a36Sopenharmony_ci fail(bool(ret) != bool(j), 90062306a36Sopenharmony_ci "Software TC incorrect load in replace test, iteration %d" % 90162306a36Sopenharmony_ci (j)) 90262306a36Sopenharmony_ci sim.cls_filter_op(op="delete", prio=1, handle=1, cls="bpf") 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci start_test("Test spurious extack from the driver...") 90562306a36Sopenharmony_ci test_spurios_extack(sim, obj, False, "netdevsim") 90662306a36Sopenharmony_ci test_spurios_extack(sim, obj, True, "netdevsim") 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci sim.set_ethtool_tc_offloads(False) 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci test_spurios_extack(sim, obj, False, "TC offload is disabled") 91162306a36Sopenharmony_ci test_spurios_extack(sim, obj, True, "TC offload is disabled") 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci sim.set_ethtool_tc_offloads(True) 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci sim.tc_flush_filters() 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci start_test("Test TC offloads failure...") 91862306a36Sopenharmony_ci sim.dfs["dev/bpf_bind_verifier_accept"] = 0 91962306a36Sopenharmony_ci ret, _, err = sim.cls_bpf_add_filter(obj, verbose=True, skip_sw=True, 92062306a36Sopenharmony_ci fail=False, include_stderr=True) 92162306a36Sopenharmony_ci fail(ret == 0, "TC filter did not reject with TC offloads enabled") 92262306a36Sopenharmony_ci check_verifier_log(err, "[netdevsim] Hello from netdevsim!") 92362306a36Sopenharmony_ci sim.dfs["dev/bpf_bind_verifier_accept"] = 1 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci start_test("Test TC offloads work...") 92662306a36Sopenharmony_ci ret, _, err = sim.cls_bpf_add_filter(obj, verbose=True, skip_sw=True, 92762306a36Sopenharmony_ci fail=False, include_stderr=True) 92862306a36Sopenharmony_ci fail(ret != 0, "TC filter did not load with TC offloads enabled") 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci start_test("Test TC offload basics...") 93162306a36Sopenharmony_ci dfs = simdev.dfs_get_bound_progs(expected=1) 93262306a36Sopenharmony_ci progs = bpftool_prog_list(expected=1) 93362306a36Sopenharmony_ci ingress = sim.tc_show_ingress(expected=1) 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci dprog = dfs[0] 93662306a36Sopenharmony_ci prog = progs[0] 93762306a36Sopenharmony_ci fltr = ingress[0] 93862306a36Sopenharmony_ci fail(fltr["skip_hw"], "TC does reports 'skip_hw' on offloaded filter") 93962306a36Sopenharmony_ci fail(not fltr["in_hw"], "TC does not report 'in_hw' for offloaded filter") 94062306a36Sopenharmony_ci fail(not fltr["skip_sw"], "TC does not report 'skip_sw' back") 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci start_test("Test TC offload is device-bound...") 94362306a36Sopenharmony_ci fail(str(prog["id"]) != fltr["id"], "Program IDs don't match") 94462306a36Sopenharmony_ci fail(prog["tag"] != fltr["tag"], "Program tags don't match") 94562306a36Sopenharmony_ci fail(fltr["id"] != dprog["id"], "Program IDs don't match") 94662306a36Sopenharmony_ci fail(dprog["state"] != "xlated", "Offloaded program state not translated") 94762306a36Sopenharmony_ci fail(dprog["loaded"] != "Y", "Offloaded program is not loaded") 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci start_test("Test disabling TC offloads is rejected while filters installed...") 95062306a36Sopenharmony_ci ret, _ = sim.set_ethtool_tc_offloads(False, fail=False) 95162306a36Sopenharmony_ci fail(ret == 0, "Driver should refuse to disable TC offloads with filters installed...") 95262306a36Sopenharmony_ci sim.set_ethtool_tc_offloads(True) 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ci start_test("Test qdisc removal frees things...") 95562306a36Sopenharmony_ci sim.tc_flush_filters() 95662306a36Sopenharmony_ci sim.tc_show_ingress(expected=0) 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci start_test("Test disabling TC offloads is OK without filters...") 95962306a36Sopenharmony_ci ret, _ = sim.set_ethtool_tc_offloads(False, fail=False) 96062306a36Sopenharmony_ci fail(ret != 0, 96162306a36Sopenharmony_ci "Driver refused to disable TC offloads without filters installed...") 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci sim.set_ethtool_tc_offloads(True) 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci start_test("Test destroying device gets rid of TC filters...") 96662306a36Sopenharmony_ci sim.cls_bpf_add_filter(obj, skip_sw=True) 96762306a36Sopenharmony_ci simdev.remove() 96862306a36Sopenharmony_ci bpftool_prog_list_wait(expected=0) 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci simdev = NetdevSimDev() 97162306a36Sopenharmony_ci sim, = simdev.nsims 97262306a36Sopenharmony_ci sim.set_ethtool_tc_offloads(True) 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci start_test("Test destroying device gets rid of XDP...") 97562306a36Sopenharmony_ci sim.set_xdp(obj, "offload") 97662306a36Sopenharmony_ci simdev.remove() 97762306a36Sopenharmony_ci bpftool_prog_list_wait(expected=0) 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci simdev = NetdevSimDev() 98062306a36Sopenharmony_ci sim, = simdev.nsims 98162306a36Sopenharmony_ci sim.set_ethtool_tc_offloads(True) 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci start_test("Test XDP prog reporting...") 98462306a36Sopenharmony_ci sim.set_xdp(obj, "drv") 98562306a36Sopenharmony_ci ipl = sim.ip_link_show(xdp=True) 98662306a36Sopenharmony_ci progs = bpftool_prog_list(expected=1) 98762306a36Sopenharmony_ci fail(ipl["xdp"]["prog"]["id"] != progs[0]["id"], 98862306a36Sopenharmony_ci "Loaded program has wrong ID") 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci start_test("Test XDP prog replace without force...") 99162306a36Sopenharmony_ci ret, _ = sim.set_xdp(obj, "drv", fail=False) 99262306a36Sopenharmony_ci fail(ret == 0, "Replaced XDP program without -force") 99362306a36Sopenharmony_ci sim.wait_for_flush(total=1) 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci start_test("Test XDP prog replace with force...") 99662306a36Sopenharmony_ci ret, _ = sim.set_xdp(obj, "drv", force=True, fail=False) 99762306a36Sopenharmony_ci fail(ret != 0, "Could not replace XDP program with -force") 99862306a36Sopenharmony_ci bpftool_prog_list_wait(expected=1) 99962306a36Sopenharmony_ci ipl = sim.ip_link_show(xdp=True) 100062306a36Sopenharmony_ci progs = bpftool_prog_list(expected=1) 100162306a36Sopenharmony_ci fail(ipl["xdp"]["prog"]["id"] != progs[0]["id"], 100262306a36Sopenharmony_ci "Loaded program has wrong ID") 100362306a36Sopenharmony_ci fail("dev" in progs[0].keys(), 100462306a36Sopenharmony_ci "Device parameters reported for non-offloaded program") 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_ci start_test("Test XDP prog replace with bad flags...") 100762306a36Sopenharmony_ci ret, _, err = sim.set_xdp(obj, "generic", force=True, 100862306a36Sopenharmony_ci fail=False, include_stderr=True) 100962306a36Sopenharmony_ci fail(ret == 0, "Replaced XDP program with a program in different mode") 101062306a36Sopenharmony_ci check_extack(err, 101162306a36Sopenharmony_ci "Native and generic XDP can't be active at the same time.", 101262306a36Sopenharmony_ci args) 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci start_test("Test MTU restrictions...") 101562306a36Sopenharmony_ci ret, _ = sim.set_mtu(9000, fail=False) 101662306a36Sopenharmony_ci fail(ret == 0, 101762306a36Sopenharmony_ci "Driver should refuse to increase MTU to 9000 with XDP loaded...") 101862306a36Sopenharmony_ci sim.unset_xdp("drv") 101962306a36Sopenharmony_ci bpftool_prog_list_wait(expected=0) 102062306a36Sopenharmony_ci sim.set_mtu(9000) 102162306a36Sopenharmony_ci ret, _, err = sim.set_xdp(obj, "drv", fail=False, include_stderr=True) 102262306a36Sopenharmony_ci fail(ret == 0, "Driver should refuse to load program with MTU of 9000...") 102362306a36Sopenharmony_ci check_extack_nsim(err, "MTU too large w/ XDP enabled.", args) 102462306a36Sopenharmony_ci sim.set_mtu(1500) 102562306a36Sopenharmony_ci 102662306a36Sopenharmony_ci sim.wait_for_flush() 102762306a36Sopenharmony_ci start_test("Test non-offload XDP attaching to HW...") 102862306a36Sopenharmony_ci bpftool_prog_load("sample_ret0.bpf.o", "/sys/fs/bpf/nooffload") 102962306a36Sopenharmony_ci nooffload = bpf_pinned("/sys/fs/bpf/nooffload") 103062306a36Sopenharmony_ci ret, _, err = sim.set_xdp(nooffload, "offload", 103162306a36Sopenharmony_ci fail=False, include_stderr=True) 103262306a36Sopenharmony_ci fail(ret == 0, "attached non-offloaded XDP program to HW") 103362306a36Sopenharmony_ci check_extack_nsim(err, "xdpoffload of non-bound program.", args) 103462306a36Sopenharmony_ci rm("/sys/fs/bpf/nooffload") 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci start_test("Test offload XDP attaching to drv...") 103762306a36Sopenharmony_ci bpftool_prog_load("sample_ret0.bpf.o", "/sys/fs/bpf/offload", 103862306a36Sopenharmony_ci dev=sim['ifname']) 103962306a36Sopenharmony_ci offload = bpf_pinned("/sys/fs/bpf/offload") 104062306a36Sopenharmony_ci ret, _, err = sim.set_xdp(offload, "drv", fail=False, include_stderr=True) 104162306a36Sopenharmony_ci fail(ret == 0, "attached offloaded XDP program to drv") 104262306a36Sopenharmony_ci check_extack(err, "Using offloaded program without HW_MODE flag is not supported.", args) 104362306a36Sopenharmony_ci rm("/sys/fs/bpf/offload") 104462306a36Sopenharmony_ci sim.wait_for_flush() 104562306a36Sopenharmony_ci 104662306a36Sopenharmony_ci start_test("Test XDP load failure...") 104762306a36Sopenharmony_ci sim.dfs["dev/bpf_bind_verifier_accept"] = 0 104862306a36Sopenharmony_ci ret, _, err = bpftool_prog_load("sample_ret0.bpf.o", "/sys/fs/bpf/offload", 104962306a36Sopenharmony_ci dev=sim['ifname'], fail=False, include_stderr=True) 105062306a36Sopenharmony_ci fail(ret == 0, "verifier should fail on load") 105162306a36Sopenharmony_ci check_verifier_log(err, "[netdevsim] Hello from netdevsim!") 105262306a36Sopenharmony_ci sim.dfs["dev/bpf_bind_verifier_accept"] = 1 105362306a36Sopenharmony_ci sim.wait_for_flush() 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_ci start_test("Test XDP offload...") 105662306a36Sopenharmony_ci _, _, err = sim.set_xdp(obj, "offload", verbose=True, include_stderr=True) 105762306a36Sopenharmony_ci ipl = sim.ip_link_show(xdp=True) 105862306a36Sopenharmony_ci link_xdp = ipl["xdp"]["prog"] 105962306a36Sopenharmony_ci progs = bpftool_prog_list(expected=1) 106062306a36Sopenharmony_ci prog = progs[0] 106162306a36Sopenharmony_ci fail(link_xdp["id"] != prog["id"], "Loaded program has wrong ID") 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci start_test("Test XDP offload is device bound...") 106462306a36Sopenharmony_ci dfs = simdev.dfs_get_bound_progs(expected=1) 106562306a36Sopenharmony_ci dprog = dfs[0] 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci fail(prog["id"] != link_xdp["id"], "Program IDs don't match") 106862306a36Sopenharmony_ci fail(prog["tag"] != link_xdp["tag"], "Program tags don't match") 106962306a36Sopenharmony_ci fail(str(link_xdp["id"]) != dprog["id"], "Program IDs don't match") 107062306a36Sopenharmony_ci fail(dprog["state"] != "xlated", "Offloaded program state not translated") 107162306a36Sopenharmony_ci fail(dprog["loaded"] != "Y", "Offloaded program is not loaded") 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci start_test("Test removing XDP program many times...") 107462306a36Sopenharmony_ci sim.unset_xdp("offload") 107562306a36Sopenharmony_ci sim.unset_xdp("offload") 107662306a36Sopenharmony_ci sim.unset_xdp("drv") 107762306a36Sopenharmony_ci sim.unset_xdp("drv") 107862306a36Sopenharmony_ci sim.unset_xdp("") 107962306a36Sopenharmony_ci sim.unset_xdp("") 108062306a36Sopenharmony_ci bpftool_prog_list_wait(expected=0) 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci start_test("Test attempt to use a program for a wrong device...") 108362306a36Sopenharmony_ci simdev2 = NetdevSimDev() 108462306a36Sopenharmony_ci sim2, = simdev2.nsims 108562306a36Sopenharmony_ci sim2.set_xdp(obj, "offload") 108662306a36Sopenharmony_ci pin_file, pinned = pin_prog("/sys/fs/bpf/tmp") 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci ret, _, err = sim.set_xdp(pinned, "offload", 108962306a36Sopenharmony_ci fail=False, include_stderr=True) 109062306a36Sopenharmony_ci fail(ret == 0, "Pinned program loaded for a different device accepted") 109162306a36Sopenharmony_ci check_extack(err, "Program bound to different device.", args) 109262306a36Sopenharmony_ci simdev2.remove() 109362306a36Sopenharmony_ci ret, _, err = sim.set_xdp(pinned, "offload", 109462306a36Sopenharmony_ci fail=False, include_stderr=True) 109562306a36Sopenharmony_ci fail(ret == 0, "Pinned program loaded for a removed device accepted") 109662306a36Sopenharmony_ci check_extack(err, "Program bound to different device.", args) 109762306a36Sopenharmony_ci rm(pin_file) 109862306a36Sopenharmony_ci bpftool_prog_list_wait(expected=0) 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci simdev, sim = test_multi_prog(simdev, sim, obj, "", 1) 110162306a36Sopenharmony_ci simdev, sim = test_multi_prog(simdev, sim, obj, "drv", 1) 110262306a36Sopenharmony_ci simdev, sim = test_multi_prog(simdev, sim, obj, "generic", 2) 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci start_test("Test mixing of TC and XDP...") 110562306a36Sopenharmony_ci sim.tc_add_ingress() 110662306a36Sopenharmony_ci sim.set_xdp(obj, "offload") 110762306a36Sopenharmony_ci ret, _, err = sim.cls_bpf_add_filter(obj, skip_sw=True, 110862306a36Sopenharmony_ci fail=False, include_stderr=True) 110962306a36Sopenharmony_ci fail(ret == 0, "Loading TC when XDP active should fail") 111062306a36Sopenharmony_ci check_extack_nsim(err, "driver and netdev offload states mismatch.", args) 111162306a36Sopenharmony_ci sim.unset_xdp("offload") 111262306a36Sopenharmony_ci sim.wait_for_flush() 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_ci sim.cls_bpf_add_filter(obj, skip_sw=True) 111562306a36Sopenharmony_ci ret, _, err = sim.set_xdp(obj, "offload", fail=False, include_stderr=True) 111662306a36Sopenharmony_ci fail(ret == 0, "Loading XDP when TC active should fail") 111762306a36Sopenharmony_ci check_extack_nsim(err, "TC program is already loaded.", args) 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci start_test("Test binding TC from pinned...") 112062306a36Sopenharmony_ci pin_file, pinned = pin_prog("/sys/fs/bpf/tmp") 112162306a36Sopenharmony_ci sim.tc_flush_filters(bound=1, total=1) 112262306a36Sopenharmony_ci sim.cls_bpf_add_filter(pinned, da=True, skip_sw=True) 112362306a36Sopenharmony_ci sim.tc_flush_filters(bound=1, total=1) 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci start_test("Test binding XDP from pinned...") 112662306a36Sopenharmony_ci sim.set_xdp(obj, "offload") 112762306a36Sopenharmony_ci pin_file, pinned = pin_prog("/sys/fs/bpf/tmp2", idx=1) 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci sim.set_xdp(pinned, "offload", force=True) 113062306a36Sopenharmony_ci sim.unset_xdp("offload") 113162306a36Sopenharmony_ci sim.set_xdp(pinned, "offload", force=True) 113262306a36Sopenharmony_ci sim.unset_xdp("offload") 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci start_test("Test offload of wrong type fails...") 113562306a36Sopenharmony_ci ret, _ = sim.cls_bpf_add_filter(pinned, da=True, skip_sw=True, fail=False) 113662306a36Sopenharmony_ci fail(ret == 0, "Managed to attach XDP program to TC") 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci start_test("Test asking for TC offload of two filters...") 113962306a36Sopenharmony_ci sim.cls_bpf_add_filter(obj, da=True, skip_sw=True) 114062306a36Sopenharmony_ci ret, _, err = sim.cls_bpf_add_filter(obj, da=True, skip_sw=True, 114162306a36Sopenharmony_ci fail=False, include_stderr=True) 114262306a36Sopenharmony_ci fail(ret == 0, "Managed to offload two TC filters at the same time") 114362306a36Sopenharmony_ci check_extack_nsim(err, "driver and netdev offload states mismatch.", args) 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci sim.tc_flush_filters(bound=2, total=2) 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci start_test("Test if netdev removal waits for translation...") 114862306a36Sopenharmony_ci delay_msec = 500 114962306a36Sopenharmony_ci sim.dfs["dev/bpf_bind_verifier_delay"] = delay_msec 115062306a36Sopenharmony_ci start = time.time() 115162306a36Sopenharmony_ci cmd_line = "tc filter add dev %s ingress bpf %s da skip_sw" % \ 115262306a36Sopenharmony_ci (sim['ifname'], obj) 115362306a36Sopenharmony_ci tc_proc = cmd(cmd_line, background=True, fail=False) 115462306a36Sopenharmony_ci # Wait for the verifier to start 115562306a36Sopenharmony_ci while simdev.dfs_num_bound_progs() <= 2: 115662306a36Sopenharmony_ci pass 115762306a36Sopenharmony_ci simdev.remove() 115862306a36Sopenharmony_ci end = time.time() 115962306a36Sopenharmony_ci ret, _ = cmd_result(tc_proc, fail=False) 116062306a36Sopenharmony_ci time_diff = end - start 116162306a36Sopenharmony_ci log("Time", "start:\t%s\nend:\t%s\ndiff:\t%s" % (start, end, time_diff)) 116262306a36Sopenharmony_ci 116362306a36Sopenharmony_ci fail(ret == 0, "Managed to load TC filter on a unregistering device") 116462306a36Sopenharmony_ci delay_sec = delay_msec * 0.001 116562306a36Sopenharmony_ci fail(time_diff < delay_sec, "Removal process took %s, expected %s" % 116662306a36Sopenharmony_ci (time_diff, delay_sec)) 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci # Remove all pinned files and reinstantiate the netdev 116962306a36Sopenharmony_ci clean_up() 117062306a36Sopenharmony_ci bpftool_prog_list_wait(expected=0) 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci simdev = NetdevSimDev() 117362306a36Sopenharmony_ci sim, = simdev.nsims 117462306a36Sopenharmony_ci map_obj = bpf_obj("sample_map_ret0.bpf.o") 117562306a36Sopenharmony_ci start_test("Test loading program with maps...") 117662306a36Sopenharmony_ci sim.set_xdp(map_obj, "offload", JSON=False) # map fixup msg breaks JSON 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_ci start_test("Test bpftool bound info reporting (own ns)...") 117962306a36Sopenharmony_ci check_dev_info(False, "") 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_ci start_test("Test bpftool bound info reporting (other ns)...") 118262306a36Sopenharmony_ci ns = mknetns() 118362306a36Sopenharmony_ci sim.set_ns(ns) 118462306a36Sopenharmony_ci check_dev_info(True, "") 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci start_test("Test bpftool bound info reporting (remote ns)...") 118762306a36Sopenharmony_ci check_dev_info(False, ns) 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_ci start_test("Test bpftool bound info reporting (back to own ns)...") 119062306a36Sopenharmony_ci sim.set_ns("") 119162306a36Sopenharmony_ci check_dev_info(False, "") 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_ci prog_file, _ = pin_prog("/sys/fs/bpf/tmp_prog") 119462306a36Sopenharmony_ci map_file, _ = pin_map("/sys/fs/bpf/tmp_map", idx=1, expected=2) 119562306a36Sopenharmony_ci simdev.remove() 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci start_test("Test bpftool bound info reporting (removed dev)...") 119862306a36Sopenharmony_ci check_dev_info_removed(prog_file=prog_file, map_file=map_file) 119962306a36Sopenharmony_ci 120062306a36Sopenharmony_ci # Remove all pinned files and reinstantiate the netdev 120162306a36Sopenharmony_ci clean_up() 120262306a36Sopenharmony_ci bpftool_prog_list_wait(expected=0) 120362306a36Sopenharmony_ci 120462306a36Sopenharmony_ci simdev = NetdevSimDev() 120562306a36Sopenharmony_ci sim, = simdev.nsims 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci start_test("Test map update (no flags)...") 120862306a36Sopenharmony_ci sim.set_xdp(map_obj, "offload", JSON=False) # map fixup msg breaks JSON 120962306a36Sopenharmony_ci maps = bpftool_map_list(expected=2) 121062306a36Sopenharmony_ci array = maps[0] if maps[0]["type"] == "array" else maps[1] 121162306a36Sopenharmony_ci htab = maps[0] if maps[0]["type"] == "hash" else maps[1] 121262306a36Sopenharmony_ci for m in maps: 121362306a36Sopenharmony_ci for i in range(2): 121462306a36Sopenharmony_ci bpftool("map update id %d key %s value %s" % 121562306a36Sopenharmony_ci (m["id"], int2str("I", i), int2str("Q", i * 3))) 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_ci for m in maps: 121862306a36Sopenharmony_ci ret, _ = bpftool("map update id %d key %s value %s" % 121962306a36Sopenharmony_ci (m["id"], int2str("I", 3), int2str("Q", 3 * 3)), 122062306a36Sopenharmony_ci fail=False) 122162306a36Sopenharmony_ci fail(ret == 0, "added too many entries") 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_ci start_test("Test map update (exists)...") 122462306a36Sopenharmony_ci for m in maps: 122562306a36Sopenharmony_ci for i in range(2): 122662306a36Sopenharmony_ci bpftool("map update id %d key %s value %s exist" % 122762306a36Sopenharmony_ci (m["id"], int2str("I", i), int2str("Q", i * 3))) 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci for m in maps: 123062306a36Sopenharmony_ci ret, err = bpftool("map update id %d key %s value %s exist" % 123162306a36Sopenharmony_ci (m["id"], int2str("I", 3), int2str("Q", 3 * 3)), 123262306a36Sopenharmony_ci fail=False) 123362306a36Sopenharmony_ci fail(ret == 0, "updated non-existing key") 123462306a36Sopenharmony_ci fail(err["error"].find("No such file or directory") == -1, 123562306a36Sopenharmony_ci "expected ENOENT, error is '%s'" % (err["error"])) 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_ci start_test("Test map update (noexist)...") 123862306a36Sopenharmony_ci for m in maps: 123962306a36Sopenharmony_ci for i in range(2): 124062306a36Sopenharmony_ci ret, err = bpftool("map update id %d key %s value %s noexist" % 124162306a36Sopenharmony_ci (m["id"], int2str("I", i), int2str("Q", i * 3)), 124262306a36Sopenharmony_ci fail=False) 124362306a36Sopenharmony_ci fail(ret == 0, "updated existing key") 124462306a36Sopenharmony_ci fail(err["error"].find("File exists") == -1, 124562306a36Sopenharmony_ci "expected EEXIST, error is '%s'" % (err["error"])) 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci start_test("Test map dump...") 124862306a36Sopenharmony_ci for m in maps: 124962306a36Sopenharmony_ci _, entries = bpftool("map dump id %d" % (m["id"])) 125062306a36Sopenharmony_ci for i in range(2): 125162306a36Sopenharmony_ci key = str2int(entries[i]["key"]) 125262306a36Sopenharmony_ci fail(key != i, "expected key %d, got %d" % (key, i)) 125362306a36Sopenharmony_ci val = str2int(entries[i]["value"]) 125462306a36Sopenharmony_ci fail(val != i * 3, "expected value %d, got %d" % (val, i * 3)) 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci start_test("Test map getnext...") 125762306a36Sopenharmony_ci for m in maps: 125862306a36Sopenharmony_ci _, entry = bpftool("map getnext id %d" % (m["id"])) 125962306a36Sopenharmony_ci key = str2int(entry["next_key"]) 126062306a36Sopenharmony_ci fail(key != 0, "next key %d, expected %d" % (key, 0)) 126162306a36Sopenharmony_ci _, entry = bpftool("map getnext id %d key %s" % 126262306a36Sopenharmony_ci (m["id"], int2str("I", 0))) 126362306a36Sopenharmony_ci key = str2int(entry["next_key"]) 126462306a36Sopenharmony_ci fail(key != 1, "next key %d, expected %d" % (key, 1)) 126562306a36Sopenharmony_ci ret, err = bpftool("map getnext id %d key %s" % 126662306a36Sopenharmony_ci (m["id"], int2str("I", 1)), fail=False) 126762306a36Sopenharmony_ci fail(ret == 0, "got next key past the end of map") 126862306a36Sopenharmony_ci fail(err["error"].find("No such file or directory") == -1, 126962306a36Sopenharmony_ci "expected ENOENT, error is '%s'" % (err["error"])) 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci start_test("Test map delete (htab)...") 127262306a36Sopenharmony_ci for i in range(2): 127362306a36Sopenharmony_ci bpftool("map delete id %d key %s" % (htab["id"], int2str("I", i))) 127462306a36Sopenharmony_ci 127562306a36Sopenharmony_ci start_test("Test map delete (array)...") 127662306a36Sopenharmony_ci for i in range(2): 127762306a36Sopenharmony_ci ret, err = bpftool("map delete id %d key %s" % 127862306a36Sopenharmony_ci (htab["id"], int2str("I", i)), fail=False) 127962306a36Sopenharmony_ci fail(ret == 0, "removed entry from an array") 128062306a36Sopenharmony_ci fail(err["error"].find("No such file or directory") == -1, 128162306a36Sopenharmony_ci "expected ENOENT, error is '%s'" % (err["error"])) 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci start_test("Test map remove...") 128462306a36Sopenharmony_ci sim.unset_xdp("offload") 128562306a36Sopenharmony_ci bpftool_map_list_wait(expected=0) 128662306a36Sopenharmony_ci simdev.remove() 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ci simdev = NetdevSimDev() 128962306a36Sopenharmony_ci sim, = simdev.nsims 129062306a36Sopenharmony_ci sim.set_xdp(map_obj, "offload", JSON=False) # map fixup msg breaks JSON 129162306a36Sopenharmony_ci simdev.remove() 129262306a36Sopenharmony_ci bpftool_map_list_wait(expected=0) 129362306a36Sopenharmony_ci 129462306a36Sopenharmony_ci start_test("Test map creation fail path...") 129562306a36Sopenharmony_ci simdev = NetdevSimDev() 129662306a36Sopenharmony_ci sim, = simdev.nsims 129762306a36Sopenharmony_ci sim.dfs["bpf_map_accept"] = "N" 129862306a36Sopenharmony_ci ret, _ = sim.set_xdp(map_obj, "offload", JSON=False, fail=False) 129962306a36Sopenharmony_ci fail(ret == 0, 130062306a36Sopenharmony_ci "netdevsim didn't refuse to create a map with offload disabled") 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_ci simdev.remove() 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_ci start_test("Test multi-dev ASIC program reuse...") 130562306a36Sopenharmony_ci simdevA = NetdevSimDev() 130662306a36Sopenharmony_ci simA, = simdevA.nsims 130762306a36Sopenharmony_ci simdevB = NetdevSimDev(3) 130862306a36Sopenharmony_ci simB1, simB2, simB3 = simdevB.nsims 130962306a36Sopenharmony_ci sims = (simA, simB1, simB2, simB3) 131062306a36Sopenharmony_ci simB = (simB1, simB2, simB3) 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci bpftool_prog_load("sample_map_ret0.bpf.o", "/sys/fs/bpf/nsimA", 131362306a36Sopenharmony_ci dev=simA['ifname']) 131462306a36Sopenharmony_ci progA = bpf_pinned("/sys/fs/bpf/nsimA") 131562306a36Sopenharmony_ci bpftool_prog_load("sample_map_ret0.bpf.o", "/sys/fs/bpf/nsimB", 131662306a36Sopenharmony_ci dev=simB1['ifname']) 131762306a36Sopenharmony_ci progB = bpf_pinned("/sys/fs/bpf/nsimB") 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci simA.set_xdp(progA, "offload", JSON=False) 132062306a36Sopenharmony_ci for d in simdevB.nsims: 132162306a36Sopenharmony_ci d.set_xdp(progB, "offload", JSON=False) 132262306a36Sopenharmony_ci 132362306a36Sopenharmony_ci start_test("Test multi-dev ASIC cross-dev replace...") 132462306a36Sopenharmony_ci ret, _ = simA.set_xdp(progB, "offload", force=True, JSON=False, fail=False) 132562306a36Sopenharmony_ci fail(ret == 0, "cross-ASIC program allowed") 132662306a36Sopenharmony_ci for d in simdevB.nsims: 132762306a36Sopenharmony_ci ret, _ = d.set_xdp(progA, "offload", force=True, JSON=False, fail=False) 132862306a36Sopenharmony_ci fail(ret == 0, "cross-ASIC program allowed") 132962306a36Sopenharmony_ci 133062306a36Sopenharmony_ci start_test("Test multi-dev ASIC cross-dev install...") 133162306a36Sopenharmony_ci for d in sims: 133262306a36Sopenharmony_ci d.unset_xdp("offload") 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_ci ret, _, err = simA.set_xdp(progB, "offload", force=True, JSON=False, 133562306a36Sopenharmony_ci fail=False, include_stderr=True) 133662306a36Sopenharmony_ci fail(ret == 0, "cross-ASIC program allowed") 133762306a36Sopenharmony_ci check_extack(err, "Program bound to different device.", args) 133862306a36Sopenharmony_ci for d in simdevB.nsims: 133962306a36Sopenharmony_ci ret, _, err = d.set_xdp(progA, "offload", force=True, JSON=False, 134062306a36Sopenharmony_ci fail=False, include_stderr=True) 134162306a36Sopenharmony_ci fail(ret == 0, "cross-ASIC program allowed") 134262306a36Sopenharmony_ci check_extack(err, "Program bound to different device.", args) 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci start_test("Test multi-dev ASIC cross-dev map reuse...") 134562306a36Sopenharmony_ci 134662306a36Sopenharmony_ci mapA = bpftool("prog show %s" % (progA))[1]["map_ids"][0] 134762306a36Sopenharmony_ci mapB = bpftool("prog show %s" % (progB))[1]["map_ids"][0] 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_ci ret, _ = bpftool_prog_load("sample_map_ret0.bpf.o", "/sys/fs/bpf/nsimB_", 135062306a36Sopenharmony_ci dev=simB3['ifname'], 135162306a36Sopenharmony_ci maps=["idx 0 id %d" % (mapB)], 135262306a36Sopenharmony_ci fail=False) 135362306a36Sopenharmony_ci fail(ret != 0, "couldn't reuse a map on the same ASIC") 135462306a36Sopenharmony_ci rm("/sys/fs/bpf/nsimB_") 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_ci ret, _, err = bpftool_prog_load("sample_map_ret0.bpf.o", "/sys/fs/bpf/nsimA_", 135762306a36Sopenharmony_ci dev=simA['ifname'], 135862306a36Sopenharmony_ci maps=["idx 0 id %d" % (mapB)], 135962306a36Sopenharmony_ci fail=False, include_stderr=True) 136062306a36Sopenharmony_ci fail(ret == 0, "could reuse a map on a different ASIC") 136162306a36Sopenharmony_ci fail(err.count("offload device mismatch between prog and map") == 0, 136262306a36Sopenharmony_ci "error message missing for cross-ASIC map") 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_ci ret, _, err = bpftool_prog_load("sample_map_ret0.bpf.o", "/sys/fs/bpf/nsimB_", 136562306a36Sopenharmony_ci dev=simB1['ifname'], 136662306a36Sopenharmony_ci maps=["idx 0 id %d" % (mapA)], 136762306a36Sopenharmony_ci fail=False, include_stderr=True) 136862306a36Sopenharmony_ci fail(ret == 0, "could reuse a map on a different ASIC") 136962306a36Sopenharmony_ci fail(err.count("offload device mismatch between prog and map") == 0, 137062306a36Sopenharmony_ci "error message missing for cross-ASIC map") 137162306a36Sopenharmony_ci 137262306a36Sopenharmony_ci start_test("Test multi-dev ASIC cross-dev destruction...") 137362306a36Sopenharmony_ci bpftool_prog_list_wait(expected=2) 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_ci simdevA.remove() 137662306a36Sopenharmony_ci bpftool_prog_list_wait(expected=1) 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_ci ifnameB = bpftool("prog show %s" % (progB))[1]["dev"]["ifname"] 137962306a36Sopenharmony_ci fail(ifnameB != simB1['ifname'], "program not bound to original device") 138062306a36Sopenharmony_ci simB1.remove() 138162306a36Sopenharmony_ci bpftool_prog_list_wait(expected=1) 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_ci start_test("Test multi-dev ASIC cross-dev destruction - move...") 138462306a36Sopenharmony_ci ifnameB = bpftool("prog show %s" % (progB))[1]["dev"]["ifname"] 138562306a36Sopenharmony_ci fail(ifnameB not in (simB2['ifname'], simB3['ifname']), 138662306a36Sopenharmony_ci "program not bound to remaining devices") 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ci simB2.remove() 138962306a36Sopenharmony_ci ifnameB = bpftool("prog show %s" % (progB))[1]["dev"]["ifname"] 139062306a36Sopenharmony_ci fail(ifnameB != simB3['ifname'], "program not bound to remaining device") 139162306a36Sopenharmony_ci 139262306a36Sopenharmony_ci simB3.remove() 139362306a36Sopenharmony_ci simdevB.remove() 139462306a36Sopenharmony_ci bpftool_prog_list_wait(expected=0) 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_ci start_test("Test multi-dev ASIC cross-dev destruction - orphaned...") 139762306a36Sopenharmony_ci ret, out = bpftool("prog show %s" % (progB), fail=False) 139862306a36Sopenharmony_ci fail(ret == 0, "got information about orphaned program") 139962306a36Sopenharmony_ci fail("error" not in out, "no error reported for get info on orphaned") 140062306a36Sopenharmony_ci fail(out["error"] != "can't get prog info: No such device", 140162306a36Sopenharmony_ci "wrong error for get info on orphaned") 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci print("%s: OK" % (os.path.basename(__file__))) 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_cifinally: 140662306a36Sopenharmony_ci log("Clean up...", "", level=1) 140762306a36Sopenharmony_ci log_level_inc() 140862306a36Sopenharmony_ci clean_up() 1409