logfile = None
log_level = 1
+skip_extack = False
bpf_test_dir = os.path.dirname(os.path.realpath(__file__))
pp = pprint.PrettyPrinter()
devs = [] # devices we created for clean up
if f in files:
files.remove(f)
-def tool(name, args, flags, JSON=True, ns="", fail=True):
+def tool(name, args, flags, JSON=True, ns="", fail=True, include_stderr=False):
params = ""
if JSON:
params += "%s " % (flags["json"])
if ns != "":
ns = "ip netns exec %s " % (ns)
- ret, out = cmd(ns + name + " " + params + args, fail=fail)
- if JSON and len(out.strip()) != 0:
- return ret, json.loads(out)
+ if include_stderr:
+ ret, stdout, stderr = cmd(ns + name + " " + params + args,
+ fail=fail, include_stderr=True)
+ else:
+ ret, stdout = cmd(ns + name + " " + params + args,
+ fail=fail, include_stderr=False)
+
+ if JSON and len(stdout.strip()) != 0:
+ out = json.loads(stdout)
+ else:
+ out = stdout
+
+ if include_stderr:
+ return ret, out, stderr
else:
return ret, out
time.sleep(0.05)
raise Exception("Time out waiting for map counts to stabilize want %d, have %d" % (expected, nmaps))
-def ip(args, force=False, JSON=True, ns="", fail=True):
+def ip(args, force=False, JSON=True, ns="", fail=True, include_stderr=False):
if force:
args = "-force " + args
- return tool("ip", args, {"json":"-j"}, JSON=JSON, ns=ns, fail=fail)
+ return tool("ip", args, {"json":"-j"}, JSON=JSON, ns=ns,
+ fail=fail, include_stderr=include_stderr)
-def tc(args, JSON=True, ns="", fail=True):
- return tool("tc", args, {"json":"-p"}, JSON=JSON, ns=ns, fail=fail)
+def tc(args, JSON=True, ns="", fail=True, include_stderr=False):
+ return tool("tc", args, {"json":"-p"}, JSON=JSON, ns=ns,
+ fail=fail, include_stderr=include_stderr)
def ethtool(dev, opt, args, fail=True):
return cmd("ethtool %s %s %s" % (opt, dev["ifname"], args), fail=fail)
return ip("link set dev %s mtu %d" % (self.dev["ifname"], mtu),
fail=fail)
- def set_xdp(self, bpf, mode, force=False, JSON=True, fail=True):
+ def set_xdp(self, bpf, mode, force=False, JSON=True,
+ fail=True, include_stderr=False):
return ip("link set dev %s xdp%s %s" % (self.dev["ifname"], mode, bpf),
- force=force, JSON=JSON, fail=fail)
+ force=force, JSON=JSON,
+ fail=fail, include_stderr=include_stderr)
- def unset_xdp(self, mode, force=False, JSON=True, fail=True):
+ def unset_xdp(self, mode, force=False, JSON=True,
+ fail=True, include_stderr=False):
return ip("link set dev %s xdp%s off" % (self.dev["ifname"], mode),
- force=force, JSON=JSON, fail=fail)
+ force=force, JSON=JSON,
+ fail=fail, include_stderr=include_stderr)
def ip_link_show(self, xdp):
_, link = ip("link show dev %s" % (self['ifname']))
return filters
def cls_bpf_add_filter(self, bpf, da=False, skip_sw=False, skip_hw=False,
- fail=True):
+ fail=True, include_stderr=False):
params = ""
if da:
params += " da"
if skip_hw:
params += " skip_hw"
return tc("filter add dev %s ingress bpf %s %s" %
- (self['ifname'], bpf, params), fail=fail)
+ (self['ifname'], bpf, params),
+ fail=fail, include_stderr=include_stderr)
def set_ethtool_tc_offloads(self, enable, fail=True):
args = "hw-tc-offload %s" % ("on" if enable else "off")
fail("dev" not in m.keys(), "Device parameters not reported")
fail(dev != m["dev"], "Map's device different than program's")
+def check_extack(output, reference, args):
+ if skip_extack:
+ return
+ lines = output.split("\n")
+ comp = len(lines) >= 2 and lines[1] == reference
+ fail(not comp, "Missing or incorrect netlink extack message")
+
+def check_extack_nsim(output, reference, args):
+ check_extack(output, "Error: netdevsim: " + reference, args)
+
# Parse command line
parser = argparse.ArgumentParser()
parser.add_argument("--log", help="output verbose log to given file")
skip(ret != 0, "sample %s/%s not found, please compile it" %
(bpf_test_dir, s))
+# Check if iproute2 is built with libmnl (needed by extack support)
+_, _, err = cmd("tc qdisc delete dev lo handle 0",
+ fail=False, include_stderr=True)
+if err.find("Error: Failed to find qdisc with specified handle.") == -1:
+ print("Warning: no extack message in iproute2 output, libmnl missing?")
+ log("Warning: no extack message in iproute2 output, libmnl missing?", "")
+ skip_extack = True
+
# Check if net namespaces seem to work
ns = mknetns()
skip(ns is None, "Could not create a net namespace")
sim.tc_flush_filters()
start_test("Test TC offloads are off by default...")
- ret, _ = sim.cls_bpf_add_filter(obj, skip_sw=True, fail=False)
+ ret, _, err = sim.cls_bpf_add_filter(obj, skip_sw=True,
+ fail=False, include_stderr=True)
fail(ret == 0, "TC filter loaded without enabling TC offloads")
+ check_extack(err, "Error: TC offload is disabled on net device.", args)
sim.wait_for_flush()
sim.set_ethtool_tc_offloads(True)
sim.dfs["bpf_tc_non_bound_accept"] = "N"
start_test("Test TC cBPF unbound bytecode doesn't offload...")
- ret, _ = sim.cls_bpf_add_filter(bytecode, skip_sw=True, fail=False)
+ ret, _, err = sim.cls_bpf_add_filter(bytecode, skip_sw=True,
+ fail=False, include_stderr=True)
fail(ret == 0, "TC bytecode loaded for offload")
+ check_extack_nsim(err, "netdevsim configured to reject unbound programs.",
+ args)
sim.wait_for_flush()
start_test("Test TC offloads work...")
"Device parameters reported for non-offloaded program")
start_test("Test XDP prog replace with bad flags...")
- ret, _ = sim.set_xdp(obj, "offload", force=True, fail=False)
+ ret, _, err = sim.set_xdp(obj, "offload", force=True,
+ fail=False, include_stderr=True)
fail(ret == 0, "Replaced XDP program with a program in different mode")
- ret, _ = sim.set_xdp(obj, "", force=True, fail=False)
+ check_extack_nsim(err, "program loaded with different flags.", args)
+ ret, _, err = sim.set_xdp(obj, "", force=True,
+ fail=False, include_stderr=True)
fail(ret == 0, "Replaced XDP program with a program in different mode")
+ check_extack_nsim(err, "program loaded with different flags.", args)
start_test("Test XDP prog remove with bad flags...")
- ret, _ = sim.unset_xdp("offload", force=True, fail=False)
+ ret, _, err = sim.unset_xdp("offload", force=True,
+ fail=False, include_stderr=True)
fail(ret == 0, "Removed program with a bad mode mode")
- ret, _ = sim.unset_xdp("", force=True, fail=False)
+ check_extack_nsim(err, "program loaded with different flags.", args)
+ ret, _, err = sim.unset_xdp("", force=True,
+ fail=False, include_stderr=True)
fail(ret == 0, "Removed program with a bad mode mode")
+ check_extack_nsim(err, "program loaded with different flags.", args)
start_test("Test MTU restrictions...")
ret, _ = sim.set_mtu(9000, fail=False)
sim.unset_xdp("drv")
bpftool_prog_list_wait(expected=0)
sim.set_mtu(9000)
- ret, _ = sim.set_xdp(obj, "drv", fail=False)
+ ret, _, err = sim.set_xdp(obj, "drv", fail=False, include_stderr=True)
fail(ret == 0, "Driver should refuse to load program with MTU of 9000...")
+ check_extack_nsim(err, "MTU too large w/ XDP enabled.", args)
sim.set_mtu(1500)
sim.wait_for_flush()
sim2.set_xdp(obj, "offload")
pin_file, pinned = pin_prog("/sys/fs/bpf/tmp")
- ret, _ = sim.set_xdp(pinned, "offload", fail=False)
+ ret, _, err = sim.set_xdp(pinned, "offload",
+ fail=False, include_stderr=True)
fail(ret == 0, "Pinned program loaded for a different device accepted")
+ check_extack_nsim(err, "program bound to different dev.", args)
sim2.remove()
- ret, _ = sim.set_xdp(pinned, "offload", fail=False)
+ ret, _, err = sim.set_xdp(pinned, "offload",
+ fail=False, include_stderr=True)
fail(ret == 0, "Pinned program loaded for a removed device accepted")
+ check_extack_nsim(err, "xdpoffload of non-bound program.", args)
rm(pin_file)
bpftool_prog_list_wait(expected=0)
start_test("Test mixing of TC and XDP...")
sim.tc_add_ingress()
sim.set_xdp(obj, "offload")
- ret, _ = sim.cls_bpf_add_filter(obj, skip_sw=True, fail=False)
+ ret, _, err = sim.cls_bpf_add_filter(obj, skip_sw=True,
+ fail=False, include_stderr=True)
fail(ret == 0, "Loading TC when XDP active should fail")
+ check_extack_nsim(err, "driver and netdev offload states mismatch.", args)
sim.unset_xdp("offload")
sim.wait_for_flush()
sim.cls_bpf_add_filter(obj, skip_sw=True)
- ret, _ = sim.set_xdp(obj, "offload", fail=False)
+ ret, _, err = sim.set_xdp(obj, "offload", fail=False, include_stderr=True)
fail(ret == 0, "Loading XDP when TC active should fail")
+ check_extack_nsim(err, "TC program is already loaded.", args)
start_test("Test binding TC from pinned...")
pin_file, pinned = pin_prog("/sys/fs/bpf/tmp")
start_test("Test asking for TC offload of two filters...")
sim.cls_bpf_add_filter(obj, da=True, skip_sw=True)
- ret, _ = sim.cls_bpf_add_filter(obj, da=True, skip_sw=True, fail=False)
+ ret, _, err = sim.cls_bpf_add_filter(obj, da=True, skip_sw=True,
+ fail=False, include_stderr=True)
fail(ret == 0, "Managed to offload two TC filters at the same time")
+ check_extack_nsim(err, "driver and netdev offload states mismatch.", args)
sim.tc_flush_filters(bound=2, total=2)