diff options
author | David S. Miller <davem@davemloft.net> | 2018-01-23 20:24:32 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-01-23 20:25:28 -0500 |
commit | 43df215d99e6049d4680309c54232689e16ddd6b (patch) | |
tree | e7abd23f51bec81c3ae713c54009668fca214ea0 /tools | |
parent | 521504640f9ebec384a9c3ecd5e6de82fec6d928 (diff) | |
parent | 6d2d58f1b7ec379eb9467a5bc010ba49295d7714 (diff) |
Merge branch 'bpf-and-netdevsim-test-updates'
Jakub Kicinski says:
====================
bpf and netdevsim test updates
A number of test improvements (delayed by merges). Quentin provides
patches for checking printing to the verifier log from the drivers
and validating extack messages are propagated. There is also a test
for replacing TC filters to avoid adding back the bug Daniel recently
fixed in net and stable.
====================
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'tools')
-rwxr-xr-x | tools/testing/selftests/bpf/test_offload.py | 179 |
1 files changed, 149 insertions, 30 deletions
diff --git a/tools/testing/selftests/bpf/test_offload.py b/tools/testing/selftests/bpf/test_offload.py index 833b9c1ec450..ae3eea3ab820 100755 --- a/tools/testing/selftests/bpf/test_offload.py +++ b/tools/testing/selftests/bpf/test_offload.py | |||
@@ -26,6 +26,7 @@ import time | |||
26 | 26 | ||
27 | logfile = None | 27 | logfile = None |
28 | log_level = 1 | 28 | log_level = 1 |
29 | skip_extack = False | ||
29 | bpf_test_dir = os.path.dirname(os.path.realpath(__file__)) | 30 | bpf_test_dir = os.path.dirname(os.path.realpath(__file__)) |
30 | pp = pprint.PrettyPrinter() | 31 | pp = pprint.PrettyPrinter() |
31 | devs = [] # devices we created for clean up | 32 | devs = [] # devices we created for clean up |
@@ -132,7 +133,7 @@ def rm(f): | |||
132 | if f in files: | 133 | if f in files: |
133 | files.remove(f) | 134 | files.remove(f) |
134 | 135 | ||
135 | def tool(name, args, flags, JSON=True, ns="", fail=True): | 136 | def tool(name, args, flags, JSON=True, ns="", fail=True, include_stderr=False): |
136 | params = "" | 137 | params = "" |
137 | if JSON: | 138 | if JSON: |
138 | params += "%s " % (flags["json"]) | 139 | params += "%s " % (flags["json"]) |
@@ -140,9 +141,20 @@ def tool(name, args, flags, JSON=True, ns="", fail=True): | |||
140 | if ns != "": | 141 | if ns != "": |
141 | ns = "ip netns exec %s " % (ns) | 142 | ns = "ip netns exec %s " % (ns) |
142 | 143 | ||
143 | ret, out = cmd(ns + name + " " + params + args, fail=fail) | 144 | if include_stderr: |
144 | if JSON and len(out.strip()) != 0: | 145 | ret, stdout, stderr = cmd(ns + name + " " + params + args, |
145 | return ret, json.loads(out) | 146 | fail=fail, include_stderr=True) |
147 | else: | ||
148 | ret, stdout = cmd(ns + name + " " + params + args, | ||
149 | fail=fail, include_stderr=False) | ||
150 | |||
151 | if JSON and len(stdout.strip()) != 0: | ||
152 | out = json.loads(stdout) | ||
153 | else: | ||
154 | out = stdout | ||
155 | |||
156 | if include_stderr: | ||
157 | return ret, out, stderr | ||
146 | else: | 158 | else: |
147 | return ret, out | 159 | return ret, out |
148 | 160 | ||
@@ -181,13 +193,15 @@ def bpftool_map_list_wait(expected=0, n_retry=20): | |||
181 | time.sleep(0.05) | 193 | time.sleep(0.05) |
182 | raise Exception("Time out waiting for map counts to stabilize want %d, have %d" % (expected, nmaps)) | 194 | raise Exception("Time out waiting for map counts to stabilize want %d, have %d" % (expected, nmaps)) |
183 | 195 | ||
184 | def ip(args, force=False, JSON=True, ns="", fail=True): | 196 | def ip(args, force=False, JSON=True, ns="", fail=True, include_stderr=False): |
185 | if force: | 197 | if force: |
186 | args = "-force " + args | 198 | args = "-force " + args |
187 | return tool("ip", args, {"json":"-j"}, JSON=JSON, ns=ns, fail=fail) | 199 | return tool("ip", args, {"json":"-j"}, JSON=JSON, ns=ns, |
200 | fail=fail, include_stderr=include_stderr) | ||
188 | 201 | ||
189 | def tc(args, JSON=True, ns="", fail=True): | 202 | def tc(args, JSON=True, ns="", fail=True, include_stderr=False): |
190 | return tool("tc", args, {"json":"-p"}, JSON=JSON, ns=ns, fail=fail) | 203 | return tool("tc", args, {"json":"-p"}, JSON=JSON, ns=ns, |
204 | fail=fail, include_stderr=include_stderr) | ||
191 | 205 | ||
192 | def ethtool(dev, opt, args, fail=True): | 206 | def ethtool(dev, opt, args, fail=True): |
193 | return cmd("ethtool %s %s %s" % (opt, dev["ifname"], args), fail=fail) | 207 | return cmd("ethtool %s %s %s" % (opt, dev["ifname"], args), fail=fail) |
@@ -348,13 +362,19 @@ class NetdevSim: | |||
348 | return ip("link set dev %s mtu %d" % (self.dev["ifname"], mtu), | 362 | return ip("link set dev %s mtu %d" % (self.dev["ifname"], mtu), |
349 | fail=fail) | 363 | fail=fail) |
350 | 364 | ||
351 | def set_xdp(self, bpf, mode, force=False, JSON=True, fail=True): | 365 | def set_xdp(self, bpf, mode, force=False, JSON=True, verbose=False, |
366 | fail=True, include_stderr=False): | ||
367 | if verbose: | ||
368 | bpf += " verbose" | ||
352 | return ip("link set dev %s xdp%s %s" % (self.dev["ifname"], mode, bpf), | 369 | return ip("link set dev %s xdp%s %s" % (self.dev["ifname"], mode, bpf), |
353 | force=force, JSON=JSON, fail=fail) | 370 | force=force, JSON=JSON, |
371 | fail=fail, include_stderr=include_stderr) | ||
354 | 372 | ||
355 | def unset_xdp(self, mode, force=False, JSON=True, fail=True): | 373 | def unset_xdp(self, mode, force=False, JSON=True, |
374 | fail=True, include_stderr=False): | ||
356 | return ip("link set dev %s xdp%s off" % (self.dev["ifname"], mode), | 375 | return ip("link set dev %s xdp%s off" % (self.dev["ifname"], mode), |
357 | force=force, JSON=JSON, fail=fail) | 376 | force=force, JSON=JSON, |
377 | fail=fail, include_stderr=include_stderr) | ||
358 | 378 | ||
359 | def ip_link_show(self, xdp): | 379 | def ip_link_show(self, xdp): |
360 | _, link = ip("link show dev %s" % (self['ifname'])) | 380 | _, link = ip("link show dev %s" % (self['ifname'])) |
@@ -409,17 +429,39 @@ class NetdevSim: | |||
409 | (len(filters), expected)) | 429 | (len(filters), expected)) |
410 | return filters | 430 | return filters |
411 | 431 | ||
412 | def cls_bpf_add_filter(self, bpf, da=False, skip_sw=False, skip_hw=False, | 432 | def cls_filter_op(self, op, qdisc="ingress", prio=None, handle=None, |
413 | fail=True): | 433 | cls="", params="", |
434 | fail=True, include_stderr=False): | ||
435 | spec = "" | ||
436 | if prio is not None: | ||
437 | spec += " prio %d" % (prio) | ||
438 | if handle: | ||
439 | spec += " handle %s" % (handle) | ||
440 | |||
441 | return tc("filter {op} dev {dev} {qdisc} {spec} {cls} {params}"\ | ||
442 | .format(op=op, dev=self['ifname'], qdisc=qdisc, spec=spec, | ||
443 | cls=cls, params=params), | ||
444 | fail=fail, include_stderr=include_stderr) | ||
445 | |||
446 | def cls_bpf_add_filter(self, bpf, op="add", prio=None, handle=None, | ||
447 | da=False, verbose=False, | ||
448 | skip_sw=False, skip_hw=False, | ||
449 | fail=True, include_stderr=False): | ||
450 | cls = "bpf " + bpf | ||
451 | |||
414 | params = "" | 452 | params = "" |
415 | if da: | 453 | if da: |
416 | params += " da" | 454 | params += " da" |
455 | if verbose: | ||
456 | params += " verbose" | ||
417 | if skip_sw: | 457 | if skip_sw: |
418 | params += " skip_sw" | 458 | params += " skip_sw" |
419 | if skip_hw: | 459 | if skip_hw: |
420 | params += " skip_hw" | 460 | params += " skip_hw" |
421 | return tc("filter add dev %s ingress bpf %s %s" % | 461 | |
422 | (self['ifname'], bpf, params), fail=fail) | 462 | return self.cls_filter_op(op=op, prio=prio, handle=handle, cls=cls, |
463 | params=params, | ||
464 | fail=fail, include_stderr=include_stderr) | ||
423 | 465 | ||
424 | def set_ethtool_tc_offloads(self, enable, fail=True): | 466 | def set_ethtool_tc_offloads(self, enable, fail=True): |
425 | args = "hw-tc-offload %s" % ("on" if enable else "off") | 467 | args = "hw-tc-offload %s" % ("on" if enable else "off") |
@@ -491,6 +533,23 @@ def check_dev_info(other_ns, ns, prog_file=None, map_file=None, removed=False): | |||
491 | fail("dev" not in m.keys(), "Device parameters not reported") | 533 | fail("dev" not in m.keys(), "Device parameters not reported") |
492 | fail(dev != m["dev"], "Map's device different than program's") | 534 | fail(dev != m["dev"], "Map's device different than program's") |
493 | 535 | ||
536 | def check_extack(output, reference, args): | ||
537 | if skip_extack: | ||
538 | return | ||
539 | lines = output.split("\n") | ||
540 | comp = len(lines) >= 2 and lines[1] == reference | ||
541 | fail(not comp, "Missing or incorrect netlink extack message") | ||
542 | |||
543 | def check_extack_nsim(output, reference, args): | ||
544 | check_extack(output, "Error: netdevsim: " + reference, args) | ||
545 | |||
546 | def check_verifier_log(output, reference): | ||
547 | lines = output.split("\n") | ||
548 | for l in reversed(lines): | ||
549 | if l == reference: | ||
550 | return | ||
551 | fail(True, "Missing or incorrect message from netdevsim in verifier log") | ||
552 | |||
494 | # Parse command line | 553 | # Parse command line |
495 | parser = argparse.ArgumentParser() | 554 | parser = argparse.ArgumentParser() |
496 | parser.add_argument("--log", help="output verbose log to given file") | 555 | parser.add_argument("--log", help="output verbose log to given file") |
@@ -527,6 +586,14 @@ for s in samples: | |||
527 | skip(ret != 0, "sample %s/%s not found, please compile it" % | 586 | skip(ret != 0, "sample %s/%s not found, please compile it" % |
528 | (bpf_test_dir, s)) | 587 | (bpf_test_dir, s)) |
529 | 588 | ||
589 | # Check if iproute2 is built with libmnl (needed by extack support) | ||
590 | _, _, err = cmd("tc qdisc delete dev lo handle 0", | ||
591 | fail=False, include_stderr=True) | ||
592 | if err.find("Error: Failed to find qdisc with specified handle.") == -1: | ||
593 | print("Warning: no extack message in iproute2 output, libmnl missing?") | ||
594 | log("Warning: no extack message in iproute2 output, libmnl missing?", "") | ||
595 | skip_extack = True | ||
596 | |||
530 | # Check if net namespaces seem to work | 597 | # Check if net namespaces seem to work |
531 | ns = mknetns() | 598 | ns = mknetns() |
532 | skip(ns is None, "Could not create a net namespace") | 599 | skip(ns is None, "Could not create a net namespace") |
@@ -558,8 +625,10 @@ try: | |||
558 | sim.tc_flush_filters() | 625 | sim.tc_flush_filters() |
559 | 626 | ||
560 | start_test("Test TC offloads are off by default...") | 627 | start_test("Test TC offloads are off by default...") |
561 | ret, _ = sim.cls_bpf_add_filter(obj, skip_sw=True, fail=False) | 628 | ret, _, err = sim.cls_bpf_add_filter(obj, skip_sw=True, |
629 | fail=False, include_stderr=True) | ||
562 | fail(ret == 0, "TC filter loaded without enabling TC offloads") | 630 | fail(ret == 0, "TC filter loaded without enabling TC offloads") |
631 | check_extack(err, "Error: TC offload is disabled on net device.", args) | ||
563 | sim.wait_for_flush() | 632 | sim.wait_for_flush() |
564 | 633 | ||
565 | sim.set_ethtool_tc_offloads(True) | 634 | sim.set_ethtool_tc_offloads(True) |
@@ -587,13 +656,44 @@ try: | |||
587 | sim.dfs["bpf_tc_non_bound_accept"] = "N" | 656 | sim.dfs["bpf_tc_non_bound_accept"] = "N" |
588 | 657 | ||
589 | start_test("Test TC cBPF unbound bytecode doesn't offload...") | 658 | start_test("Test TC cBPF unbound bytecode doesn't offload...") |
590 | ret, _ = sim.cls_bpf_add_filter(bytecode, skip_sw=True, fail=False) | 659 | ret, _, err = sim.cls_bpf_add_filter(bytecode, skip_sw=True, |
660 | fail=False, include_stderr=True) | ||
591 | fail(ret == 0, "TC bytecode loaded for offload") | 661 | fail(ret == 0, "TC bytecode loaded for offload") |
662 | check_extack_nsim(err, "netdevsim configured to reject unbound programs.", | ||
663 | args) | ||
592 | sim.wait_for_flush() | 664 | sim.wait_for_flush() |
593 | 665 | ||
666 | start_test("Test TC replace...") | ||
667 | sim.cls_bpf_add_filter(obj, prio=1, handle=1) | ||
668 | sim.cls_bpf_add_filter(obj, op="replace", prio=1, handle=1) | ||
669 | sim.cls_filter_op(op="delete", prio=1, handle=1, cls="bpf") | ||
670 | |||
671 | sim.cls_bpf_add_filter(obj, prio=1, handle=1, skip_sw=True) | ||
672 | sim.cls_bpf_add_filter(obj, op="replace", prio=1, handle=1, skip_sw=True) | ||
673 | sim.cls_filter_op(op="delete", prio=1, handle=1, cls="bpf") | ||
674 | |||
675 | sim.cls_bpf_add_filter(obj, prio=1, handle=1, skip_hw=True) | ||
676 | sim.cls_bpf_add_filter(obj, op="replace", prio=1, handle=1, skip_hw=True) | ||
677 | sim.cls_filter_op(op="delete", prio=1, handle=1, cls="bpf") | ||
678 | |||
679 | start_test("Test TC replace bad flags...") | ||
680 | for i in range(3): | ||
681 | for j in range(3): | ||
682 | ret, _ = sim.cls_bpf_add_filter(obj, op="replace", prio=1, handle=1, | ||
683 | skip_sw=(j == 1), skip_hw=(j == 2), | ||
684 | fail=False) | ||
685 | fail(bool(ret) != bool(j), | ||
686 | "Software TC incorrect load in replace test, iteration %d" % | ||
687 | (j)) | ||
688 | sim.cls_filter_op(op="delete", prio=1, handle=1, cls="bpf") | ||
689 | |||
690 | sim.tc_flush_filters() | ||
691 | |||
594 | start_test("Test TC offloads work...") | 692 | start_test("Test TC offloads work...") |
595 | ret, _ = sim.cls_bpf_add_filter(obj, skip_sw=True, fail=False) | 693 | ret, _, err = sim.cls_bpf_add_filter(obj, verbose=True, skip_sw=True, |
694 | fail=False, include_stderr=True) | ||
596 | fail(ret != 0, "TC filter did not load with TC offloads enabled") | 695 | fail(ret != 0, "TC filter did not load with TC offloads enabled") |
696 | check_verifier_log(err, "[netdevsim] Hello from netdevsim!") | ||
597 | 697 | ||
598 | start_test("Test TC offload basics...") | 698 | start_test("Test TC offload basics...") |
599 | dfs = sim.dfs_get_bound_progs(expected=1) | 699 | dfs = sim.dfs_get_bound_progs(expected=1) |
@@ -669,16 +769,24 @@ try: | |||
669 | "Device parameters reported for non-offloaded program") | 769 | "Device parameters reported for non-offloaded program") |
670 | 770 | ||
671 | start_test("Test XDP prog replace with bad flags...") | 771 | start_test("Test XDP prog replace with bad flags...") |
672 | ret, _ = sim.set_xdp(obj, "offload", force=True, fail=False) | 772 | ret, _, err = sim.set_xdp(obj, "offload", force=True, |
773 | fail=False, include_stderr=True) | ||
673 | fail(ret == 0, "Replaced XDP program with a program in different mode") | 774 | fail(ret == 0, "Replaced XDP program with a program in different mode") |
674 | ret, _ = sim.set_xdp(obj, "", force=True, fail=False) | 775 | check_extack_nsim(err, "program loaded with different flags.", args) |
776 | ret, _, err = sim.set_xdp(obj, "", force=True, | ||
777 | fail=False, include_stderr=True) | ||
675 | fail(ret == 0, "Replaced XDP program with a program in different mode") | 778 | fail(ret == 0, "Replaced XDP program with a program in different mode") |
779 | check_extack_nsim(err, "program loaded with different flags.", args) | ||
676 | 780 | ||
677 | start_test("Test XDP prog remove with bad flags...") | 781 | start_test("Test XDP prog remove with bad flags...") |
678 | ret, _ = sim.unset_xdp("offload", force=True, fail=False) | 782 | ret, _, err = sim.unset_xdp("offload", force=True, |
783 | fail=False, include_stderr=True) | ||
679 | fail(ret == 0, "Removed program with a bad mode mode") | 784 | fail(ret == 0, "Removed program with a bad mode mode") |
680 | ret, _ = sim.unset_xdp("", force=True, fail=False) | 785 | check_extack_nsim(err, "program loaded with different flags.", args) |
786 | ret, _, err = sim.unset_xdp("", force=True, | ||
787 | fail=False, include_stderr=True) | ||
681 | fail(ret == 0, "Removed program with a bad mode mode") | 788 | fail(ret == 0, "Removed program with a bad mode mode") |
789 | check_extack_nsim(err, "program loaded with different flags.", args) | ||
682 | 790 | ||
683 | start_test("Test MTU restrictions...") | 791 | start_test("Test MTU restrictions...") |
684 | ret, _ = sim.set_mtu(9000, fail=False) | 792 | ret, _ = sim.set_mtu(9000, fail=False) |
@@ -687,18 +795,20 @@ try: | |||
687 | sim.unset_xdp("drv") | 795 | sim.unset_xdp("drv") |
688 | bpftool_prog_list_wait(expected=0) | 796 | bpftool_prog_list_wait(expected=0) |
689 | sim.set_mtu(9000) | 797 | sim.set_mtu(9000) |
690 | ret, _ = sim.set_xdp(obj, "drv", fail=False) | 798 | ret, _, err = sim.set_xdp(obj, "drv", fail=False, include_stderr=True) |
691 | fail(ret == 0, "Driver should refuse to load program with MTU of 9000...") | 799 | fail(ret == 0, "Driver should refuse to load program with MTU of 9000...") |
800 | check_extack_nsim(err, "MTU too large w/ XDP enabled.", args) | ||
692 | sim.set_mtu(1500) | 801 | sim.set_mtu(1500) |
693 | 802 | ||
694 | sim.wait_for_flush() | 803 | sim.wait_for_flush() |
695 | start_test("Test XDP offload...") | 804 | start_test("Test XDP offload...") |
696 | sim.set_xdp(obj, "offload") | 805 | _, _, err = sim.set_xdp(obj, "offload", verbose=True, include_stderr=True) |
697 | ipl = sim.ip_link_show(xdp=True) | 806 | ipl = sim.ip_link_show(xdp=True) |
698 | link_xdp = ipl["xdp"]["prog"] | 807 | link_xdp = ipl["xdp"]["prog"] |
699 | progs = bpftool_prog_list(expected=1) | 808 | progs = bpftool_prog_list(expected=1) |
700 | prog = progs[0] | 809 | prog = progs[0] |
701 | fail(link_xdp["id"] != prog["id"], "Loaded program has wrong ID") | 810 | fail(link_xdp["id"] != prog["id"], "Loaded program has wrong ID") |
811 | check_verifier_log(err, "[netdevsim] Hello from netdevsim!") | ||
702 | 812 | ||
703 | start_test("Test XDP offload is device bound...") | 813 | start_test("Test XDP offload is device bound...") |
704 | dfs = sim.dfs_get_bound_progs(expected=1) | 814 | dfs = sim.dfs_get_bound_progs(expected=1) |
@@ -724,25 +834,32 @@ try: | |||
724 | sim2.set_xdp(obj, "offload") | 834 | sim2.set_xdp(obj, "offload") |
725 | pin_file, pinned = pin_prog("/sys/fs/bpf/tmp") | 835 | pin_file, pinned = pin_prog("/sys/fs/bpf/tmp") |
726 | 836 | ||
727 | ret, _ = sim.set_xdp(pinned, "offload", fail=False) | 837 | ret, _, err = sim.set_xdp(pinned, "offload", |
838 | fail=False, include_stderr=True) | ||
728 | fail(ret == 0, "Pinned program loaded for a different device accepted") | 839 | fail(ret == 0, "Pinned program loaded for a different device accepted") |
840 | check_extack_nsim(err, "program bound to different dev.", args) | ||
729 | sim2.remove() | 841 | sim2.remove() |
730 | ret, _ = sim.set_xdp(pinned, "offload", fail=False) | 842 | ret, _, err = sim.set_xdp(pinned, "offload", |
843 | fail=False, include_stderr=True) | ||
731 | fail(ret == 0, "Pinned program loaded for a removed device accepted") | 844 | fail(ret == 0, "Pinned program loaded for a removed device accepted") |
845 | check_extack_nsim(err, "xdpoffload of non-bound program.", args) | ||
732 | rm(pin_file) | 846 | rm(pin_file) |
733 | bpftool_prog_list_wait(expected=0) | 847 | bpftool_prog_list_wait(expected=0) |
734 | 848 | ||
735 | start_test("Test mixing of TC and XDP...") | 849 | start_test("Test mixing of TC and XDP...") |
736 | sim.tc_add_ingress() | 850 | sim.tc_add_ingress() |
737 | sim.set_xdp(obj, "offload") | 851 | sim.set_xdp(obj, "offload") |
738 | ret, _ = sim.cls_bpf_add_filter(obj, skip_sw=True, fail=False) | 852 | ret, _, err = sim.cls_bpf_add_filter(obj, skip_sw=True, |
853 | fail=False, include_stderr=True) | ||
739 | fail(ret == 0, "Loading TC when XDP active should fail") | 854 | fail(ret == 0, "Loading TC when XDP active should fail") |
855 | check_extack_nsim(err, "driver and netdev offload states mismatch.", args) | ||
740 | sim.unset_xdp("offload") | 856 | sim.unset_xdp("offload") |
741 | sim.wait_for_flush() | 857 | sim.wait_for_flush() |
742 | 858 | ||
743 | sim.cls_bpf_add_filter(obj, skip_sw=True) | 859 | sim.cls_bpf_add_filter(obj, skip_sw=True) |
744 | ret, _ = sim.set_xdp(obj, "offload", fail=False) | 860 | ret, _, err = sim.set_xdp(obj, "offload", fail=False, include_stderr=True) |
745 | fail(ret == 0, "Loading XDP when TC active should fail") | 861 | fail(ret == 0, "Loading XDP when TC active should fail") |
862 | check_extack_nsim(err, "TC program is already loaded.", args) | ||
746 | 863 | ||
747 | start_test("Test binding TC from pinned...") | 864 | start_test("Test binding TC from pinned...") |
748 | pin_file, pinned = pin_prog("/sys/fs/bpf/tmp") | 865 | pin_file, pinned = pin_prog("/sys/fs/bpf/tmp") |
@@ -765,8 +882,10 @@ try: | |||
765 | 882 | ||
766 | start_test("Test asking for TC offload of two filters...") | 883 | start_test("Test asking for TC offload of two filters...") |
767 | sim.cls_bpf_add_filter(obj, da=True, skip_sw=True) | 884 | sim.cls_bpf_add_filter(obj, da=True, skip_sw=True) |
768 | ret, _ = sim.cls_bpf_add_filter(obj, da=True, skip_sw=True, fail=False) | 885 | ret, _, err = sim.cls_bpf_add_filter(obj, da=True, skip_sw=True, |
886 | fail=False, include_stderr=True) | ||
769 | fail(ret == 0, "Managed to offload two TC filters at the same time") | 887 | fail(ret == 0, "Managed to offload two TC filters at the same time") |
888 | check_extack_nsim(err, "driver and netdev offload states mismatch.", args) | ||
770 | 889 | ||
771 | sim.tc_flush_filters(bound=2, total=2) | 890 | sim.tc_flush_filters(bound=2, total=2) |
772 | 891 | ||