.. | .. |
---|
1 | 1 | #!/usr/bin/env python3 |
---|
2 | 2 | |
---|
3 | 3 | # Copyright (C) 2017 Netronome Systems, Inc. |
---|
| 4 | +# Copyright (c) 2019 Mellanox Technologies. All rights reserved |
---|
4 | 5 | # |
---|
5 | 6 | # This software is licensed under the GNU General License Version 2, |
---|
6 | 7 | # June 1991 as shown in the file COPYING in the top-level directory of this |
---|
.. | .. |
---|
15 | 16 | |
---|
16 | 17 | from datetime import datetime |
---|
17 | 18 | import argparse |
---|
| 19 | +import errno |
---|
18 | 20 | import json |
---|
19 | 21 | import os |
---|
20 | 22 | import pprint |
---|
21 | 23 | import random |
---|
| 24 | +import re |
---|
| 25 | +import stat |
---|
22 | 26 | import string |
---|
23 | 27 | import struct |
---|
24 | 28 | import subprocess |
---|
25 | 29 | import time |
---|
| 30 | +import traceback |
---|
26 | 31 | |
---|
27 | 32 | logfile = None |
---|
28 | 33 | log_level = 1 |
---|
.. | .. |
---|
78 | 83 | if not cond: |
---|
79 | 84 | return |
---|
80 | 85 | print("FAIL: " + msg) |
---|
81 | | - log("FAIL: " + msg, "", level=1) |
---|
| 86 | + tb = "".join(traceback.extract_stack().format()) |
---|
| 87 | + print(tb) |
---|
| 88 | + log("FAIL: " + msg, tb, level=1) |
---|
82 | 89 | os.sys.exit(1) |
---|
83 | 90 | |
---|
84 | 91 | def start_test(msg): |
---|
.. | .. |
---|
177 | 184 | def bpftool_map_list(expected=None, ns=""): |
---|
178 | 185 | _, maps = bpftool("map show", JSON=True, ns=ns, fail=True) |
---|
179 | 186 | # Remove the base maps |
---|
180 | | - for m in base_maps: |
---|
181 | | - if m in maps: |
---|
182 | | - maps.remove(m) |
---|
| 187 | + maps = [m for m in maps if m not in base_maps and m.get('name') not in base_map_names] |
---|
183 | 188 | if expected is not None: |
---|
184 | 189 | if len(maps) != expected: |
---|
185 | 190 | fail(True, "%d BPF maps loaded, expected %d" % |
---|
.. | .. |
---|
303 | 308 | |
---|
304 | 309 | _, out = cmd('ls ' + path) |
---|
305 | 310 | for f in out.split(): |
---|
| 311 | + if f == "ports": |
---|
| 312 | + continue |
---|
| 313 | + |
---|
306 | 314 | p = os.path.join(path, f) |
---|
| 315 | + if not os.stat(p).st_mode & stat.S_IRUSR: |
---|
| 316 | + continue |
---|
| 317 | + |
---|
307 | 318 | if os.path.isfile(p): |
---|
| 319 | + # We need to init trap_flow_action_cookie before read it |
---|
| 320 | + if f == "trap_flow_action_cookie": |
---|
| 321 | + cmd('echo deadbeef > %s/%s' % (path, f)) |
---|
308 | 322 | _, out = cmd('cat %s/%s' % (path, f)) |
---|
309 | 323 | dfs[f] = out.strip() |
---|
310 | 324 | elif os.path.isdir(p): |
---|
.. | .. |
---|
318 | 332 | |
---|
319 | 333 | return dfs |
---|
320 | 334 | |
---|
| 335 | +class NetdevSimDev: |
---|
| 336 | + """ |
---|
| 337 | + Class for netdevsim bus device and its attributes. |
---|
| 338 | + """ |
---|
| 339 | + @staticmethod |
---|
| 340 | + def ctrl_write(path, val): |
---|
| 341 | + fullpath = os.path.join("/sys/bus/netdevsim/", path) |
---|
| 342 | + try: |
---|
| 343 | + with open(fullpath, "w") as f: |
---|
| 344 | + f.write(val) |
---|
| 345 | + except OSError as e: |
---|
| 346 | + log("WRITE %s: %r" % (fullpath, val), -e.errno) |
---|
| 347 | + raise e |
---|
| 348 | + log("WRITE %s: %r" % (fullpath, val), 0) |
---|
| 349 | + |
---|
| 350 | + def __init__(self, port_count=1): |
---|
| 351 | + addr = 0 |
---|
| 352 | + while True: |
---|
| 353 | + try: |
---|
| 354 | + self.ctrl_write("new_device", "%u %u" % (addr, port_count)) |
---|
| 355 | + except OSError as e: |
---|
| 356 | + if e.errno == errno.ENOSPC: |
---|
| 357 | + addr += 1 |
---|
| 358 | + continue |
---|
| 359 | + raise e |
---|
| 360 | + break |
---|
| 361 | + self.addr = addr |
---|
| 362 | + |
---|
| 363 | + # As probe of netdevsim device might happen from a workqueue, |
---|
| 364 | + # so wait here until all netdevs appear. |
---|
| 365 | + self.wait_for_netdevs(port_count) |
---|
| 366 | + |
---|
| 367 | + ret, out = cmd("udevadm settle", fail=False) |
---|
| 368 | + if ret: |
---|
| 369 | + raise Exception("udevadm settle failed") |
---|
| 370 | + ifnames = self.get_ifnames() |
---|
| 371 | + |
---|
| 372 | + devs.append(self) |
---|
| 373 | + self.dfs_dir = "/sys/kernel/debug/netdevsim/netdevsim%u/" % addr |
---|
| 374 | + |
---|
| 375 | + self.nsims = [] |
---|
| 376 | + for port_index in range(port_count): |
---|
| 377 | + self.nsims.append(NetdevSim(self, port_index, ifnames[port_index])) |
---|
| 378 | + |
---|
| 379 | + def get_ifnames(self): |
---|
| 380 | + ifnames = [] |
---|
| 381 | + listdir = os.listdir("/sys/bus/netdevsim/devices/netdevsim%u/net/" % self.addr) |
---|
| 382 | + for ifname in listdir: |
---|
| 383 | + ifnames.append(ifname) |
---|
| 384 | + ifnames.sort() |
---|
| 385 | + return ifnames |
---|
| 386 | + |
---|
| 387 | + def wait_for_netdevs(self, port_count): |
---|
| 388 | + timeout = 5 |
---|
| 389 | + timeout_start = time.time() |
---|
| 390 | + |
---|
| 391 | + while True: |
---|
| 392 | + try: |
---|
| 393 | + ifnames = self.get_ifnames() |
---|
| 394 | + except FileNotFoundError as e: |
---|
| 395 | + ifnames = [] |
---|
| 396 | + if len(ifnames) == port_count: |
---|
| 397 | + break |
---|
| 398 | + if time.time() < timeout_start + timeout: |
---|
| 399 | + continue |
---|
| 400 | + raise Exception("netdevices did not appear within timeout") |
---|
| 401 | + |
---|
| 402 | + def dfs_num_bound_progs(self): |
---|
| 403 | + path = os.path.join(self.dfs_dir, "bpf_bound_progs") |
---|
| 404 | + _, progs = cmd('ls %s' % (path)) |
---|
| 405 | + return len(progs.split()) |
---|
| 406 | + |
---|
| 407 | + def dfs_get_bound_progs(self, expected): |
---|
| 408 | + progs = DebugfsDir(os.path.join(self.dfs_dir, "bpf_bound_progs")) |
---|
| 409 | + if expected is not None: |
---|
| 410 | + if len(progs) != expected: |
---|
| 411 | + fail(True, "%d BPF programs bound, expected %d" % |
---|
| 412 | + (len(progs), expected)) |
---|
| 413 | + return progs |
---|
| 414 | + |
---|
| 415 | + def remove(self): |
---|
| 416 | + self.ctrl_write("del_device", "%u" % (self.addr, )) |
---|
| 417 | + devs.remove(self) |
---|
| 418 | + |
---|
| 419 | + def remove_nsim(self, nsim): |
---|
| 420 | + self.nsims.remove(nsim) |
---|
| 421 | + self.ctrl_write("devices/netdevsim%u/del_port" % (self.addr, ), |
---|
| 422 | + "%u" % (nsim.port_index, )) |
---|
| 423 | + |
---|
321 | 424 | class NetdevSim: |
---|
322 | 425 | """ |
---|
323 | 426 | Class for netdevsim netdevice and its attributes. |
---|
324 | 427 | """ |
---|
325 | 428 | |
---|
326 | | - def __init__(self, link=None): |
---|
327 | | - self.link = link |
---|
| 429 | + def __init__(self, nsimdev, port_index, ifname): |
---|
| 430 | + # In case udev renamed the netdev to according to new schema, |
---|
| 431 | + # check if the name matches the port_index. |
---|
| 432 | + nsimnamere = re.compile("eni\d+np(\d+)") |
---|
| 433 | + match = nsimnamere.match(ifname) |
---|
| 434 | + if match and int(match.groups()[0]) != port_index + 1: |
---|
| 435 | + raise Exception("netdevice name mismatches the expected one") |
---|
328 | 436 | |
---|
329 | | - self.dev = self._netdevsim_create() |
---|
330 | | - devs.append(self) |
---|
331 | | - |
---|
| 437 | + self.nsimdev = nsimdev |
---|
| 438 | + self.port_index = port_index |
---|
332 | 439 | self.ns = "" |
---|
333 | | - |
---|
334 | | - self.dfs_dir = '/sys/kernel/debug/netdevsim/%s' % (self.dev['ifname']) |
---|
335 | | - self.sdev_dir = self.dfs_dir + '/sdev/' |
---|
| 440 | + self.dfs_dir = "%s/ports/%u/" % (nsimdev.dfs_dir, port_index) |
---|
336 | 441 | self.dfs_refresh() |
---|
| 442 | + _, [self.dev] = ip("link show dev %s" % ifname) |
---|
337 | 443 | |
---|
338 | 444 | def __getitem__(self, key): |
---|
339 | 445 | return self.dev[key] |
---|
340 | 446 | |
---|
341 | | - def _netdevsim_create(self): |
---|
342 | | - link = "" if self.link is None else "link " + self.link.dev['ifname'] |
---|
343 | | - _, old = ip("link show") |
---|
344 | | - ip("link add sim%d {link} type netdevsim".format(link=link)) |
---|
345 | | - _, new = ip("link show") |
---|
346 | | - |
---|
347 | | - for dev in new: |
---|
348 | | - f = filter(lambda x: x["ifname"] == dev["ifname"], old) |
---|
349 | | - if len(list(f)) == 0: |
---|
350 | | - return dev |
---|
351 | | - |
---|
352 | | - raise Exception("failed to create netdevsim device") |
---|
353 | | - |
---|
354 | 447 | def remove(self): |
---|
355 | | - devs.remove(self) |
---|
356 | | - ip("link del dev %s" % (self.dev["ifname"]), ns=self.ns) |
---|
| 448 | + self.nsimdev.remove_nsim(self) |
---|
357 | 449 | |
---|
358 | 450 | def dfs_refresh(self): |
---|
359 | 451 | self.dfs = DebugfsDir(self.dfs_dir) |
---|
.. | .. |
---|
364 | 456 | _, data = cmd('cat %s' % (path)) |
---|
365 | 457 | return data.strip() |
---|
366 | 458 | |
---|
367 | | - def dfs_num_bound_progs(self): |
---|
368 | | - path = os.path.join(self.sdev_dir, "bpf_bound_progs") |
---|
369 | | - _, progs = cmd('ls %s' % (path)) |
---|
370 | | - return len(progs.split()) |
---|
371 | | - |
---|
372 | | - def dfs_get_bound_progs(self, expected): |
---|
373 | | - progs = DebugfsDir(os.path.join(self.sdev_dir, "bpf_bound_progs")) |
---|
374 | | - if expected is not None: |
---|
375 | | - if len(progs) != expected: |
---|
376 | | - fail(True, "%d BPF programs bound, expected %d" % |
---|
377 | | - (len(progs), expected)) |
---|
378 | | - return progs |
---|
379 | | - |
---|
380 | 459 | def wait_for_flush(self, bound=0, total=0, n_retry=20): |
---|
381 | 460 | for i in range(n_retry): |
---|
382 | | - nbound = self.dfs_num_bound_progs() |
---|
| 461 | + nbound = self.nsimdev.dfs_num_bound_progs() |
---|
383 | 462 | nprogs = len(bpftool_prog_list()) |
---|
384 | 463 | if nbound == bound and nprogs == total: |
---|
385 | 464 | return |
---|
.. | .. |
---|
589 | 668 | return |
---|
590 | 669 | fail(True, "Missing or incorrect message from netdevsim in verifier log") |
---|
591 | 670 | |
---|
| 671 | +def check_multi_basic(two_xdps): |
---|
| 672 | + fail(two_xdps["mode"] != 4, "Bad mode reported with multiple programs") |
---|
| 673 | + fail("prog" in two_xdps, "Base program reported in multi program mode") |
---|
| 674 | + fail(len(two_xdps["attached"]) != 2, |
---|
| 675 | + "Wrong attached program count with two programs") |
---|
| 676 | + fail(two_xdps["attached"][0]["prog"]["id"] == |
---|
| 677 | + two_xdps["attached"][1]["prog"]["id"], |
---|
| 678 | + "Offloaded and other programs have the same id") |
---|
| 679 | + |
---|
592 | 680 | def test_spurios_extack(sim, obj, skip_hw, needle): |
---|
593 | 681 | res = sim.cls_bpf_add_filter(obj, prio=1, handle=1, skip_hw=skip_hw, |
---|
594 | 682 | include_stderr=True) |
---|
.. | .. |
---|
600 | 688 | include_stderr=True) |
---|
601 | 689 | check_no_extack(res, needle) |
---|
602 | 690 | |
---|
| 691 | +def test_multi_prog(simdev, sim, obj, modename, modeid): |
---|
| 692 | + start_test("Test multi-attachment XDP - %s + offload..." % |
---|
| 693 | + (modename or "default", )) |
---|
| 694 | + sim.set_xdp(obj, "offload") |
---|
| 695 | + xdp = sim.ip_link_show(xdp=True)["xdp"] |
---|
| 696 | + offloaded = sim.dfs_read("bpf_offloaded_id") |
---|
| 697 | + fail("prog" not in xdp, "Base program not reported in single program mode") |
---|
| 698 | + fail(len(xdp["attached"]) != 1, |
---|
| 699 | + "Wrong attached program count with one program") |
---|
| 700 | + |
---|
| 701 | + sim.set_xdp(obj, modename) |
---|
| 702 | + two_xdps = sim.ip_link_show(xdp=True)["xdp"] |
---|
| 703 | + |
---|
| 704 | + fail(xdp["attached"][0] not in two_xdps["attached"], |
---|
| 705 | + "Offload program not reported after other activated") |
---|
| 706 | + check_multi_basic(two_xdps) |
---|
| 707 | + |
---|
| 708 | + offloaded2 = sim.dfs_read("bpf_offloaded_id") |
---|
| 709 | + fail(offloaded != offloaded2, |
---|
| 710 | + "Offload ID changed after loading other program") |
---|
| 711 | + |
---|
| 712 | + start_test("Test multi-attachment XDP - replace...") |
---|
| 713 | + ret, _, err = sim.set_xdp(obj, "offload", fail=False, include_stderr=True) |
---|
| 714 | + fail(ret == 0, "Replaced one of programs without -force") |
---|
| 715 | + check_extack(err, "XDP program already attached.", args) |
---|
| 716 | + |
---|
| 717 | + start_test("Test multi-attachment XDP - remove without mode...") |
---|
| 718 | + ret, _, err = sim.unset_xdp("", force=True, |
---|
| 719 | + fail=False, include_stderr=True) |
---|
| 720 | + fail(ret == 0, "Removed program without a mode flag") |
---|
| 721 | + check_extack(err, "More than one program loaded, unset mode is ambiguous.", args) |
---|
| 722 | + |
---|
| 723 | + sim.unset_xdp("offload") |
---|
| 724 | + xdp = sim.ip_link_show(xdp=True)["xdp"] |
---|
| 725 | + offloaded = sim.dfs_read("bpf_offloaded_id") |
---|
| 726 | + |
---|
| 727 | + fail(xdp["mode"] != modeid, "Bad mode reported after multiple programs") |
---|
| 728 | + fail("prog" not in xdp, |
---|
| 729 | + "Base program not reported after multi program mode") |
---|
| 730 | + fail(xdp["attached"][0] not in two_xdps["attached"], |
---|
| 731 | + "Offload program not reported after other activated") |
---|
| 732 | + fail(len(xdp["attached"]) != 1, |
---|
| 733 | + "Wrong attached program count with remaining programs") |
---|
| 734 | + fail(offloaded != "0", "Offload ID reported with only other program left") |
---|
| 735 | + |
---|
| 736 | + start_test("Test multi-attachment XDP - reattach...") |
---|
| 737 | + sim.set_xdp(obj, "offload") |
---|
| 738 | + two_xdps = sim.ip_link_show(xdp=True)["xdp"] |
---|
| 739 | + |
---|
| 740 | + fail(xdp["attached"][0] not in two_xdps["attached"], |
---|
| 741 | + "Other program not reported after offload activated") |
---|
| 742 | + check_multi_basic(two_xdps) |
---|
| 743 | + |
---|
| 744 | + start_test("Test multi-attachment XDP - device remove...") |
---|
| 745 | + simdev.remove() |
---|
| 746 | + |
---|
| 747 | + simdev = NetdevSimDev() |
---|
| 748 | + sim, = simdev.nsims |
---|
| 749 | + sim.set_ethtool_tc_offloads(True) |
---|
| 750 | + return [simdev, sim] |
---|
603 | 751 | |
---|
604 | 752 | # Parse command line |
---|
605 | 753 | parser = argparse.ArgumentParser() |
---|
.. | .. |
---|
620 | 768 | skip(ret != 0, "bpftool not installed") |
---|
621 | 769 | base_progs = progs |
---|
622 | 770 | _, base_maps = bpftool("map") |
---|
| 771 | +base_map_names = [ |
---|
| 772 | + 'pid_iter.rodata' # created on each bpftool invocation |
---|
| 773 | +] |
---|
623 | 774 | |
---|
624 | 775 | # Check netdevsim |
---|
625 | 776 | ret, out = cmd("modprobe netdevsim", fail=False) |
---|
.. | .. |
---|
656 | 807 | bytecode = bpf_bytecode("1,6 0 0 4294967295,") |
---|
657 | 808 | |
---|
658 | 809 | start_test("Test destruction of generic XDP...") |
---|
659 | | - sim = NetdevSim() |
---|
| 810 | + simdev = NetdevSimDev() |
---|
| 811 | + sim, = simdev.nsims |
---|
660 | 812 | sim.set_xdp(obj, "generic") |
---|
661 | | - sim.remove() |
---|
| 813 | + simdev.remove() |
---|
662 | 814 | bpftool_prog_list_wait(expected=0) |
---|
663 | 815 | |
---|
664 | | - sim = NetdevSim() |
---|
| 816 | + simdev = NetdevSimDev() |
---|
| 817 | + sim, = simdev.nsims |
---|
665 | 818 | sim.tc_add_ingress() |
---|
666 | 819 | |
---|
667 | 820 | start_test("Test TC non-offloaded...") |
---|
.. | .. |
---|
671 | 824 | start_test("Test TC non-offloaded isn't getting bound...") |
---|
672 | 825 | ret, _ = sim.cls_bpf_add_filter(obj, fail=False) |
---|
673 | 826 | fail(ret != 0, "Software TC filter did not load") |
---|
674 | | - sim.dfs_get_bound_progs(expected=0) |
---|
| 827 | + simdev.dfs_get_bound_progs(expected=0) |
---|
675 | 828 | |
---|
676 | 829 | sim.tc_flush_filters() |
---|
677 | 830 | |
---|
.. | .. |
---|
688 | 841 | start_test("Test TC offload by default...") |
---|
689 | 842 | ret, _ = sim.cls_bpf_add_filter(obj, fail=False) |
---|
690 | 843 | fail(ret != 0, "Software TC filter did not load") |
---|
691 | | - sim.dfs_get_bound_progs(expected=0) |
---|
| 844 | + simdev.dfs_get_bound_progs(expected=0) |
---|
692 | 845 | ingress = sim.tc_show_ingress(expected=1) |
---|
693 | 846 | fltr = ingress[0] |
---|
694 | 847 | fail(not fltr["in_hw"], "Filter not offloaded by default") |
---|
.. | .. |
---|
698 | 851 | start_test("Test TC cBPF bytcode tries offload by default...") |
---|
699 | 852 | ret, _ = sim.cls_bpf_add_filter(bytecode, fail=False) |
---|
700 | 853 | fail(ret != 0, "Software TC filter did not load") |
---|
701 | | - sim.dfs_get_bound_progs(expected=0) |
---|
| 854 | + simdev.dfs_get_bound_progs(expected=0) |
---|
702 | 855 | ingress = sim.tc_show_ingress(expected=1) |
---|
703 | 856 | fltr = ingress[0] |
---|
704 | 857 | fail(not fltr["in_hw"], "Bytecode not offloaded by default") |
---|
.. | .. |
---|
759 | 912 | |
---|
760 | 913 | sim.tc_flush_filters() |
---|
761 | 914 | |
---|
| 915 | + start_test("Test TC offloads failure...") |
---|
| 916 | + sim.dfs["dev/bpf_bind_verifier_accept"] = 0 |
---|
| 917 | + ret, _, err = sim.cls_bpf_add_filter(obj, verbose=True, skip_sw=True, |
---|
| 918 | + fail=False, include_stderr=True) |
---|
| 919 | + fail(ret == 0, "TC filter did not reject with TC offloads enabled") |
---|
| 920 | + check_verifier_log(err, "[netdevsim] Hello from netdevsim!") |
---|
| 921 | + sim.dfs["dev/bpf_bind_verifier_accept"] = 1 |
---|
| 922 | + |
---|
762 | 923 | start_test("Test TC offloads work...") |
---|
763 | 924 | ret, _, err = sim.cls_bpf_add_filter(obj, verbose=True, skip_sw=True, |
---|
764 | 925 | fail=False, include_stderr=True) |
---|
765 | 926 | fail(ret != 0, "TC filter did not load with TC offloads enabled") |
---|
766 | | - check_verifier_log(err, "[netdevsim] Hello from netdevsim!") |
---|
767 | 927 | |
---|
768 | 928 | start_test("Test TC offload basics...") |
---|
769 | | - dfs = sim.dfs_get_bound_progs(expected=1) |
---|
| 929 | + dfs = simdev.dfs_get_bound_progs(expected=1) |
---|
770 | 930 | progs = bpftool_prog_list(expected=1) |
---|
771 | 931 | ingress = sim.tc_show_ingress(expected=1) |
---|
772 | 932 | |
---|
.. | .. |
---|
802 | 962 | |
---|
803 | 963 | start_test("Test destroying device gets rid of TC filters...") |
---|
804 | 964 | sim.cls_bpf_add_filter(obj, skip_sw=True) |
---|
805 | | - sim.remove() |
---|
| 965 | + simdev.remove() |
---|
806 | 966 | bpftool_prog_list_wait(expected=0) |
---|
807 | 967 | |
---|
808 | | - sim = NetdevSim() |
---|
| 968 | + simdev = NetdevSimDev() |
---|
| 969 | + sim, = simdev.nsims |
---|
809 | 970 | sim.set_ethtool_tc_offloads(True) |
---|
810 | 971 | |
---|
811 | 972 | start_test("Test destroying device gets rid of XDP...") |
---|
812 | 973 | sim.set_xdp(obj, "offload") |
---|
813 | | - sim.remove() |
---|
| 974 | + simdev.remove() |
---|
814 | 975 | bpftool_prog_list_wait(expected=0) |
---|
815 | 976 | |
---|
816 | | - sim = NetdevSim() |
---|
| 977 | + simdev = NetdevSimDev() |
---|
| 978 | + sim, = simdev.nsims |
---|
817 | 979 | sim.set_ethtool_tc_offloads(True) |
---|
818 | 980 | |
---|
819 | 981 | start_test("Test XDP prog reporting...") |
---|
.. | .. |
---|
843 | 1005 | ret, _, err = sim.set_xdp(obj, "generic", force=True, |
---|
844 | 1006 | fail=False, include_stderr=True) |
---|
845 | 1007 | fail(ret == 0, "Replaced XDP program with a program in different mode") |
---|
846 | | - fail(err.count("File exists") != 1, "Replaced driver XDP with generic") |
---|
847 | | - ret, _, err = sim.set_xdp(obj, "", force=True, |
---|
848 | | - fail=False, include_stderr=True) |
---|
849 | | - fail(ret == 0, "Replaced XDP program with a program in different mode") |
---|
850 | | - check_extack(err, "program loaded with different flags.", args) |
---|
851 | | - |
---|
852 | | - start_test("Test XDP prog remove with bad flags...") |
---|
853 | | - ret, _, err = sim.unset_xdp("", force=True, |
---|
854 | | - fail=False, include_stderr=True) |
---|
855 | | - fail(ret == 0, "Removed program with a bad mode") |
---|
856 | | - check_extack(err, "program loaded with different flags.", args) |
---|
| 1008 | + check_extack(err, |
---|
| 1009 | + "Native and generic XDP can't be active at the same time.", |
---|
| 1010 | + args) |
---|
857 | 1011 | |
---|
858 | 1012 | start_test("Test MTU restrictions...") |
---|
859 | 1013 | ret, _ = sim.set_mtu(9000, fail=False) |
---|
.. | .. |
---|
883 | 1037 | offload = bpf_pinned("/sys/fs/bpf/offload") |
---|
884 | 1038 | ret, _, err = sim.set_xdp(offload, "drv", fail=False, include_stderr=True) |
---|
885 | 1039 | fail(ret == 0, "attached offloaded XDP program to drv") |
---|
886 | | - check_extack(err, "using device-bound program without HW_MODE flag is not supported.", args) |
---|
| 1040 | + check_extack(err, "Using device-bound program without HW_MODE flag is not supported.", args) |
---|
887 | 1041 | rm("/sys/fs/bpf/offload") |
---|
| 1042 | + sim.wait_for_flush() |
---|
| 1043 | + |
---|
| 1044 | + start_test("Test XDP load failure...") |
---|
| 1045 | + sim.dfs["dev/bpf_bind_verifier_accept"] = 0 |
---|
| 1046 | + ret, _, err = bpftool_prog_load("sample_ret0.o", "/sys/fs/bpf/offload", |
---|
| 1047 | + dev=sim['ifname'], fail=False, include_stderr=True) |
---|
| 1048 | + fail(ret == 0, "verifier should fail on load") |
---|
| 1049 | + check_verifier_log(err, "[netdevsim] Hello from netdevsim!") |
---|
| 1050 | + sim.dfs["dev/bpf_bind_verifier_accept"] = 1 |
---|
888 | 1051 | sim.wait_for_flush() |
---|
889 | 1052 | |
---|
890 | 1053 | start_test("Test XDP offload...") |
---|
.. | .. |
---|
894 | 1057 | progs = bpftool_prog_list(expected=1) |
---|
895 | 1058 | prog = progs[0] |
---|
896 | 1059 | fail(link_xdp["id"] != prog["id"], "Loaded program has wrong ID") |
---|
897 | | - check_verifier_log(err, "[netdevsim] Hello from netdevsim!") |
---|
898 | 1060 | |
---|
899 | 1061 | start_test("Test XDP offload is device bound...") |
---|
900 | | - dfs = sim.dfs_get_bound_progs(expected=1) |
---|
| 1062 | + dfs = simdev.dfs_get_bound_progs(expected=1) |
---|
901 | 1063 | dprog = dfs[0] |
---|
902 | 1064 | |
---|
903 | 1065 | fail(prog["id"] != link_xdp["id"], "Program IDs don't match") |
---|
.. | .. |
---|
916 | 1078 | bpftool_prog_list_wait(expected=0) |
---|
917 | 1079 | |
---|
918 | 1080 | start_test("Test attempt to use a program for a wrong device...") |
---|
919 | | - sim2 = NetdevSim() |
---|
| 1081 | + simdev2 = NetdevSimDev() |
---|
| 1082 | + sim2, = simdev2.nsims |
---|
920 | 1083 | sim2.set_xdp(obj, "offload") |
---|
921 | 1084 | pin_file, pinned = pin_prog("/sys/fs/bpf/tmp") |
---|
922 | 1085 | |
---|
.. | .. |
---|
924 | 1087 | fail=False, include_stderr=True) |
---|
925 | 1088 | fail(ret == 0, "Pinned program loaded for a different device accepted") |
---|
926 | 1089 | check_extack_nsim(err, "program bound to different dev.", args) |
---|
927 | | - sim2.remove() |
---|
| 1090 | + simdev2.remove() |
---|
928 | 1091 | ret, _, err = sim.set_xdp(pinned, "offload", |
---|
929 | 1092 | fail=False, include_stderr=True) |
---|
930 | 1093 | fail(ret == 0, "Pinned program loaded for a removed device accepted") |
---|
.. | .. |
---|
932 | 1095 | rm(pin_file) |
---|
933 | 1096 | bpftool_prog_list_wait(expected=0) |
---|
934 | 1097 | |
---|
935 | | - start_test("Test multi-attachment XDP - attach...") |
---|
936 | | - sim.set_xdp(obj, "offload") |
---|
937 | | - xdp = sim.ip_link_show(xdp=True)["xdp"] |
---|
938 | | - offloaded = sim.dfs_read("bpf_offloaded_id") |
---|
939 | | - fail("prog" not in xdp, "Base program not reported in single program mode") |
---|
940 | | - fail(len(ipl["xdp"]["attached"]) != 1, |
---|
941 | | - "Wrong attached program count with one program") |
---|
942 | | - |
---|
943 | | - sim.set_xdp(obj, "") |
---|
944 | | - two_xdps = sim.ip_link_show(xdp=True)["xdp"] |
---|
945 | | - offloaded2 = sim.dfs_read("bpf_offloaded_id") |
---|
946 | | - |
---|
947 | | - fail(two_xdps["mode"] != 4, "Bad mode reported with multiple programs") |
---|
948 | | - fail("prog" in two_xdps, "Base program reported in multi program mode") |
---|
949 | | - fail(xdp["attached"][0] not in two_xdps["attached"], |
---|
950 | | - "Offload program not reported after driver activated") |
---|
951 | | - fail(len(two_xdps["attached"]) != 2, |
---|
952 | | - "Wrong attached program count with two programs") |
---|
953 | | - fail(two_xdps["attached"][0]["prog"]["id"] == |
---|
954 | | - two_xdps["attached"][1]["prog"]["id"], |
---|
955 | | - "offloaded and drv programs have the same id") |
---|
956 | | - fail(offloaded != offloaded2, |
---|
957 | | - "offload ID changed after loading driver program") |
---|
958 | | - |
---|
959 | | - start_test("Test multi-attachment XDP - replace...") |
---|
960 | | - ret, _, err = sim.set_xdp(obj, "offload", fail=False, include_stderr=True) |
---|
961 | | - fail(err.count("busy") != 1, "Replaced one of programs without -force") |
---|
962 | | - |
---|
963 | | - start_test("Test multi-attachment XDP - detach...") |
---|
964 | | - ret, _, err = sim.unset_xdp("drv", force=True, |
---|
965 | | - fail=False, include_stderr=True) |
---|
966 | | - fail(ret == 0, "Removed program with a bad mode") |
---|
967 | | - check_extack(err, "program loaded with different flags.", args) |
---|
968 | | - |
---|
969 | | - sim.unset_xdp("offload") |
---|
970 | | - xdp = sim.ip_link_show(xdp=True)["xdp"] |
---|
971 | | - offloaded = sim.dfs_read("bpf_offloaded_id") |
---|
972 | | - |
---|
973 | | - fail(xdp["mode"] != 1, "Bad mode reported after multiple programs") |
---|
974 | | - fail("prog" not in xdp, |
---|
975 | | - "Base program not reported after multi program mode") |
---|
976 | | - fail(xdp["attached"][0] not in two_xdps["attached"], |
---|
977 | | - "Offload program not reported after driver activated") |
---|
978 | | - fail(len(ipl["xdp"]["attached"]) != 1, |
---|
979 | | - "Wrong attached program count with remaining programs") |
---|
980 | | - fail(offloaded != "0", "offload ID reported with only driver program left") |
---|
981 | | - |
---|
982 | | - start_test("Test multi-attachment XDP - device remove...") |
---|
983 | | - sim.set_xdp(obj, "offload") |
---|
984 | | - sim.remove() |
---|
985 | | - |
---|
986 | | - sim = NetdevSim() |
---|
987 | | - sim.set_ethtool_tc_offloads(True) |
---|
| 1098 | + simdev, sim = test_multi_prog(simdev, sim, obj, "", 1) |
---|
| 1099 | + simdev, sim = test_multi_prog(simdev, sim, obj, "drv", 1) |
---|
| 1100 | + simdev, sim = test_multi_prog(simdev, sim, obj, "generic", 2) |
---|
988 | 1101 | |
---|
989 | 1102 | start_test("Test mixing of TC and XDP...") |
---|
990 | 1103 | sim.tc_add_ingress() |
---|
.. | .. |
---|
1031 | 1144 | |
---|
1032 | 1145 | start_test("Test if netdev removal waits for translation...") |
---|
1033 | 1146 | delay_msec = 500 |
---|
1034 | | - sim.dfs["bpf_bind_verifier_delay"] = delay_msec |
---|
| 1147 | + sim.dfs["dev/bpf_bind_verifier_delay"] = delay_msec |
---|
1035 | 1148 | start = time.time() |
---|
1036 | 1149 | cmd_line = "tc filter add dev %s ingress bpf %s da skip_sw" % \ |
---|
1037 | 1150 | (sim['ifname'], obj) |
---|
1038 | 1151 | tc_proc = cmd(cmd_line, background=True, fail=False) |
---|
1039 | 1152 | # Wait for the verifier to start |
---|
1040 | | - while sim.dfs_num_bound_progs() <= 2: |
---|
| 1153 | + while simdev.dfs_num_bound_progs() <= 2: |
---|
1041 | 1154 | pass |
---|
1042 | | - sim.remove() |
---|
| 1155 | + simdev.remove() |
---|
1043 | 1156 | end = time.time() |
---|
1044 | 1157 | ret, _ = cmd_result(tc_proc, fail=False) |
---|
1045 | 1158 | time_diff = end - start |
---|
.. | .. |
---|
1054 | 1167 | clean_up() |
---|
1055 | 1168 | bpftool_prog_list_wait(expected=0) |
---|
1056 | 1169 | |
---|
1057 | | - sim = NetdevSim() |
---|
| 1170 | + simdev = NetdevSimDev() |
---|
| 1171 | + sim, = simdev.nsims |
---|
1058 | 1172 | map_obj = bpf_obj("sample_map_ret0.o") |
---|
1059 | 1173 | start_test("Test loading program with maps...") |
---|
1060 | 1174 | sim.set_xdp(map_obj, "offload", JSON=False) # map fixup msg breaks JSON |
---|
.. | .. |
---|
1076 | 1190 | |
---|
1077 | 1191 | prog_file, _ = pin_prog("/sys/fs/bpf/tmp_prog") |
---|
1078 | 1192 | map_file, _ = pin_map("/sys/fs/bpf/tmp_map", idx=1, expected=2) |
---|
1079 | | - sim.remove() |
---|
| 1193 | + simdev.remove() |
---|
1080 | 1194 | |
---|
1081 | 1195 | start_test("Test bpftool bound info reporting (removed dev)...") |
---|
1082 | 1196 | check_dev_info_removed(prog_file=prog_file, map_file=map_file) |
---|
.. | .. |
---|
1085 | 1199 | clean_up() |
---|
1086 | 1200 | bpftool_prog_list_wait(expected=0) |
---|
1087 | 1201 | |
---|
1088 | | - sim = NetdevSim() |
---|
| 1202 | + simdev = NetdevSimDev() |
---|
| 1203 | + sim, = simdev.nsims |
---|
1089 | 1204 | |
---|
1090 | 1205 | start_test("Test map update (no flags)...") |
---|
1091 | 1206 | sim.set_xdp(map_obj, "offload", JSON=False) # map fixup msg breaks JSON |
---|
.. | .. |
---|
1166 | 1281 | start_test("Test map remove...") |
---|
1167 | 1282 | sim.unset_xdp("offload") |
---|
1168 | 1283 | bpftool_map_list_wait(expected=0) |
---|
1169 | | - sim.remove() |
---|
| 1284 | + simdev.remove() |
---|
1170 | 1285 | |
---|
1171 | | - sim = NetdevSim() |
---|
| 1286 | + simdev = NetdevSimDev() |
---|
| 1287 | + sim, = simdev.nsims |
---|
1172 | 1288 | sim.set_xdp(map_obj, "offload", JSON=False) # map fixup msg breaks JSON |
---|
1173 | | - sim.remove() |
---|
| 1289 | + simdev.remove() |
---|
1174 | 1290 | bpftool_map_list_wait(expected=0) |
---|
1175 | 1291 | |
---|
1176 | 1292 | start_test("Test map creation fail path...") |
---|
1177 | | - sim = NetdevSim() |
---|
| 1293 | + simdev = NetdevSimDev() |
---|
| 1294 | + sim, = simdev.nsims |
---|
1178 | 1295 | sim.dfs["bpf_map_accept"] = "N" |
---|
1179 | 1296 | ret, _ = sim.set_xdp(map_obj, "offload", JSON=False, fail=False) |
---|
1180 | 1297 | fail(ret == 0, |
---|
1181 | 1298 | "netdevsim didn't refuse to create a map with offload disabled") |
---|
1182 | 1299 | |
---|
1183 | | - sim.remove() |
---|
| 1300 | + simdev.remove() |
---|
1184 | 1301 | |
---|
1185 | 1302 | start_test("Test multi-dev ASIC program reuse...") |
---|
1186 | | - simA = NetdevSim() |
---|
1187 | | - simB1 = NetdevSim() |
---|
1188 | | - simB2 = NetdevSim(link=simB1) |
---|
1189 | | - simB3 = NetdevSim(link=simB1) |
---|
| 1303 | + simdevA = NetdevSimDev() |
---|
| 1304 | + simA, = simdevA.nsims |
---|
| 1305 | + simdevB = NetdevSimDev(3) |
---|
| 1306 | + simB1, simB2, simB3 = simdevB.nsims |
---|
1190 | 1307 | sims = (simA, simB1, simB2, simB3) |
---|
1191 | 1308 | simB = (simB1, simB2, simB3) |
---|
1192 | 1309 | |
---|
.. | .. |
---|
1198 | 1315 | progB = bpf_pinned("/sys/fs/bpf/nsimB") |
---|
1199 | 1316 | |
---|
1200 | 1317 | simA.set_xdp(progA, "offload", JSON=False) |
---|
1201 | | - for d in simB: |
---|
| 1318 | + for d in simdevB.nsims: |
---|
1202 | 1319 | d.set_xdp(progB, "offload", JSON=False) |
---|
1203 | 1320 | |
---|
1204 | 1321 | start_test("Test multi-dev ASIC cross-dev replace...") |
---|
1205 | 1322 | ret, _ = simA.set_xdp(progB, "offload", force=True, JSON=False, fail=False) |
---|
1206 | 1323 | fail(ret == 0, "cross-ASIC program allowed") |
---|
1207 | | - for d in simB: |
---|
| 1324 | + for d in simdevB.nsims: |
---|
1208 | 1325 | ret, _ = d.set_xdp(progA, "offload", force=True, JSON=False, fail=False) |
---|
1209 | 1326 | fail(ret == 0, "cross-ASIC program allowed") |
---|
1210 | 1327 | |
---|
.. | .. |
---|
1216 | 1333 | fail=False, include_stderr=True) |
---|
1217 | 1334 | fail(ret == 0, "cross-ASIC program allowed") |
---|
1218 | 1335 | check_extack_nsim(err, "program bound to different dev.", args) |
---|
1219 | | - for d in simB: |
---|
| 1336 | + for d in simdevB.nsims: |
---|
1220 | 1337 | ret, _, err = d.set_xdp(progA, "offload", force=True, JSON=False, |
---|
1221 | 1338 | fail=False, include_stderr=True) |
---|
1222 | 1339 | fail(ret == 0, "cross-ASIC program allowed") |
---|
.. | .. |
---|
1253 | 1370 | start_test("Test multi-dev ASIC cross-dev destruction...") |
---|
1254 | 1371 | bpftool_prog_list_wait(expected=2) |
---|
1255 | 1372 | |
---|
1256 | | - simA.remove() |
---|
| 1373 | + simdevA.remove() |
---|
1257 | 1374 | bpftool_prog_list_wait(expected=1) |
---|
1258 | 1375 | |
---|
1259 | 1376 | ifnameB = bpftool("prog show %s" % (progB))[1]["dev"]["ifname"] |
---|
1260 | | - fail(ifnameB != simB1['ifname'], "program not bound to originial device") |
---|
| 1377 | + fail(ifnameB != simB1['ifname'], "program not bound to original device") |
---|
1261 | 1378 | simB1.remove() |
---|
1262 | 1379 | bpftool_prog_list_wait(expected=1) |
---|
1263 | 1380 | |
---|
.. | .. |
---|
1271 | 1388 | fail(ifnameB != simB3['ifname'], "program not bound to remaining device") |
---|
1272 | 1389 | |
---|
1273 | 1390 | simB3.remove() |
---|
| 1391 | + simdevB.remove() |
---|
1274 | 1392 | bpftool_prog_list_wait(expected=0) |
---|
1275 | 1393 | |
---|
1276 | 1394 | start_test("Test multi-dev ASIC cross-dev destruction - orphaned...") |
---|