3 # Copyright (C) 2017 Netronome Systems, Inc.
4 # Copyright (c) 2019 Mellanox Technologies. All rights reserved
6 # This software is licensed under the GNU General License Version 2,
7 # June 1991 as shown in the file COPYING in the top-level directory of this
10 # THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS"
11 # WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
12 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13 # FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
14 # OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
15 # THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
17 from datetime
import datetime
32 from lib
.py
import NetdevSim
, NetdevSimDev
38 bpf_test_dir
= os
.path
.dirname(os
.path
.realpath(__file__
))
39 pp
= pprint
.PrettyPrinter()
40 devs
= [] # devices we created for clean up
41 files
= [] # files to be removed
42 netns
= [] # net namespaces to be removed
44 def log_get_sec(level
=0):
45 return "*" * (log_level
+ level
)
47 def log_level_inc(add
=1):
51 def log_level_dec(sub
=1):
55 def log_level_set(level
):
59 def log(header
, data
, level
=None):
61 Output to an optional log.
68 if not isinstance(data
, str):
69 data
= pp
.pformat(data
)
72 logfile
.write("\n" + log_get_sec() + " ")
74 if len(header
) and len(data
.strip()):
82 log("SKIP: " + msg
, "", level
=1)
89 tb
= "".join(traceback
.extract_stack().format())
91 log("FAIL: " + msg
, tb
, level
=1)
99 def cmd(cmd
, shell
=True, include_stderr
=False, background
=False, fail
=True):
101 Run a command in subprocess and return tuple of (retval, stdout);
102 optionally return stderr as well as third value.
104 proc
= subprocess
.Popen(cmd
, shell
=shell
, stdout
=subprocess
.PIPE
,
105 stderr
=subprocess
.PIPE
)
107 msg
= "%s START: %s" % (log_get_sec(1),
108 datetime
.now().strftime("%H:%M:%S.%f"))
109 log("BKG " + proc
.args
, msg
)
112 return cmd_result(proc
, include_stderr
=include_stderr
, fail
=fail
)
114 def cmd_result(proc
, include_stderr
=False, fail
=False):
115 stdout
, stderr
= proc
.communicate()
116 stdout
= stdout
.decode("utf-8")
117 stderr
= stderr
.decode("utf-8")
121 stderr
= "\n" + stderr
122 if stderr
[-1] == "\n":
126 log("CMD " + proc
.args
,
127 "RETCODE: %d\n%s STDOUT:\n%s%s STDERR:%s\n%s END: %s" %
128 (proc
.returncode
, sec
, stdout
, sec
, stderr
,
129 sec
, datetime
.now().strftime("%H:%M:%S.%f")))
131 if proc
.returncode
!= 0 and fail
:
132 if len(stderr
) > 0 and stderr
[-1] == "\n":
134 raise Exception("Command failed: %s\n%s" % (proc
.args
, stderr
))
137 return proc
.returncode
, stdout
, stderr
139 return proc
.returncode
, stdout
142 cmd("rm -f %s" % (f
))
146 def tool(name
, args
, flags
, JSON
=True, ns
="", fail
=True, include_stderr
=False):
149 params
+= "%s " % (flags
["json"])
152 ns
= "ip netns exec %s " % (ns
)
157 ret
, stdout
, stderr
= cmd(ns
+ name
+ " " + params
+ args
,
158 fail
=fail
, include_stderr
=True)
160 ret
, stdout
= cmd(ns
+ name
+ " " + params
+ args
,
161 fail
=fail
, include_stderr
=False)
163 if JSON
and len(stdout
.strip()) != 0:
164 out
= json
.loads(stdout
)
169 return ret
, out
, stderr
173 def bpftool(args
, JSON
=True, ns
="", fail
=True, include_stderr
=False):
174 return tool("bpftool", args
, {"json":"-p"}, JSON
=JSON
, ns
=ns
,
175 fail
=fail
, include_stderr
=include_stderr
)
177 def bpftool_prog_list(expected
=None, ns
="", exclude_orphaned
=True):
178 _
, progs
= bpftool("prog show", JSON
=True, ns
=ns
, fail
=True)
179 # Remove the base progs
184 progs
= [ p
for p
in progs
if not p
['orphaned'] ]
185 if expected
is not None:
186 if len(progs
) != expected
:
187 fail(True, "%d BPF programs loaded, expected %d" %
188 (len(progs
), expected
))
191 def bpftool_map_list(expected
=None, ns
=""):
192 _
, maps
= bpftool("map show", JSON
=True, ns
=ns
, fail
=True)
193 # Remove the base maps
194 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
]
195 if expected
is not None:
196 if len(maps
) != expected
:
197 fail(True, "%d BPF maps loaded, expected %d" %
198 (len(maps
), expected
))
201 def bpftool_prog_list_wait(expected
=0, n_retry
=20):
202 for i
in range(n_retry
):
203 nprogs
= len(bpftool_prog_list())
204 if nprogs
== expected
:
207 raise Exception("Time out waiting for program counts to stabilize want %d, have %d" % (expected
, nprogs
))
209 def bpftool_map_list_wait(expected
=0, n_retry
=20, ns
=""):
210 for i
in range(n_retry
):
211 maps
= bpftool_map_list(ns
=ns
)
212 if len(maps
) == expected
:
215 raise Exception("Time out waiting for map counts to stabilize want %d, have %d" % (expected
, nmaps
))
217 def bpftool_prog_load(sample
, file_name
, maps
=[], prog_type
="xdp", dev
=None,
218 fail
=True, include_stderr
=False):
219 args
= "prog load %s %s" % (os
.path
.join(bpf_test_dir
, sample
), file_name
)
220 if prog_type
is not None:
221 args
+= " type " + prog_type
223 args
+= " dev " + dev
225 args
+= " map " + " map ".join(maps
)
227 res
= bpftool(args
, fail
=fail
, include_stderr
=include_stderr
)
229 files
.append(file_name
)
232 def ip(args
, force
=False, JSON
=True, ns
="", fail
=True, include_stderr
=False):
234 args
= "-force " + args
235 return tool("ip", args
, {"json":"-j"}, JSON
=JSON
, ns
=ns
,
236 fail
=fail
, include_stderr
=include_stderr
)
238 def tc(args
, JSON
=True, ns
="", fail
=True, include_stderr
=False):
239 return tool("tc", args
, {"json":"-p"}, JSON
=JSON
, ns
=ns
,
240 fail
=fail
, include_stderr
=include_stderr
)
242 def ethtool(dev
, opt
, args
, fail
=True):
243 return cmd("ethtool %s %s %s" % (opt
, dev
["ifname"], args
), fail
=fail
)
245 def bpf_obj(name
, sec
="xdp", path
=bpf_test_dir
,):
246 return "obj %s sec %s" % (os
.path
.join(path
, name
), sec
)
248 def bpf_pinned(name
):
249 return "pinned %s" % (name
)
251 def bpf_bytecode(bytecode
):
252 return "bytecode \"%s\"" % (bytecode
)
254 def mknetns(n_retry
=10):
255 for i
in range(n_retry
):
256 name
= ''.join([random
.choice(string
.ascii_letters
) for i
in range(8)])
257 ret
, _
= ip("netns add %s" % (name
), fail
=False)
263 def int2str(fmt
, val
):
265 for b
in struct
.pack(fmt
, val
):
267 return " ".join(map(lambda x
: str(x
), ret
))
272 inttab
.append(int(i
, 16))
273 ba
= bytearray(inttab
)
276 elif len(strtab
) == 8:
279 raise Exception("String array of len %d can't be unpacked to an int" %
281 return struct
.unpack(fmt
, ba
)[0]
285 Class for accessing DebugFS directories as a dictionary.
288 def __init__(self
, path
):
290 self
._dict
= self
._debugfs
_dir
_read
(path
)
293 return len(self
._dict
.keys())
295 def __getitem__(self
, key
):
297 key
= list(self
._dict
.keys())[key
]
298 return self
._dict
[key
]
300 def __setitem__(self
, key
, value
):
301 log("DebugFS set %s = %s" % (key
, value
), "")
304 cmd("echo '%s' > %s/%s" % (value
, self
.path
, key
))
307 _
, out
= cmd('cat %s/%s' % (self
.path
, key
))
308 self
._dict
[key
] = out
.strip()
310 def _debugfs_dir_read(self
, path
):
313 log("DebugFS state for %s" % (path
), "")
316 _
, out
= cmd('ls ' + path
)
317 for f
in out
.split():
321 p
= os
.path
.join(path
, f
)
322 if not os
.stat(p
).st_mode
& stat
.S_IRUSR
:
325 if os
.path
.isfile(p
):
326 # We need to init trap_flow_action_cookie before read it
327 if f
== "trap_flow_action_cookie":
328 cmd('echo deadbeef > %s/%s' % (path
, f
))
329 _
, out
= cmd('cat %s/%s' % (path
, f
))
331 elif os
.path
.isdir(p
):
332 dfs
[f
] = DebugfsDir(p
)
334 raise Exception("%s is neither file nor directory" % (p
))
337 log("DebugFS state", dfs
)
342 class BpfNetdevSimDev(NetdevSimDev
):
344 Class for netdevsim bus device and its attributes.
346 def __init__(self
, port_count
=1, ns
=None):
347 super().__init
__(port_count
, ns
=ns
)
350 def _make_port(self
, port_index
, ifname
):
351 return BpfNetdevSim(self
, port_index
, ifname
, self
.ns
)
353 def dfs_num_bound_progs(self
):
354 path
= os
.path
.join(self
.dfs_dir
, "bpf_bound_progs")
355 _
, progs
= cmd('ls %s' % (path
))
356 return len(progs
.split())
358 def dfs_get_bound_progs(self
, expected
):
359 progs
= DebugfsDir(os
.path
.join(self
.dfs_dir
, "bpf_bound_progs"))
360 if expected
is not None:
361 if len(progs
) != expected
:
362 fail(True, "%d BPF programs bound, expected %d" %
363 (len(progs
), expected
))
371 class BpfNetdevSim(NetdevSim
):
373 Class for netdevsim netdevice and its attributes.
376 def __init__(self
, nsimdev
, port_index
, ifname
, ns
=None):
377 super().__init
__(nsimdev
, port_index
, ifname
, ns
=ns
)
379 self
.dfs_dir
= "%s/ports/%u/" % (nsimdev
.dfs_dir
, port_index
)
382 def __getitem__(self
, key
):
386 self
.nsimdev
.remove_nsim(self
)
388 def dfs_refresh(self
):
389 self
.dfs
= DebugfsDir(self
.dfs_dir
)
392 def dfs_read(self
, f
):
393 path
= os
.path
.join(self
.dfs_dir
, f
)
394 _
, data
= cmd('cat %s' % (path
))
397 def wait_for_flush(self
, bound
=0, total
=0, n_retry
=20):
398 for i
in range(n_retry
):
399 nbound
= self
.nsimdev
.dfs_num_bound_progs()
400 nprogs
= len(bpftool_prog_list())
401 if nbound
== bound
and nprogs
== total
:
404 raise Exception("Time out waiting for program counts to stabilize want %d/%d, have %d bound, %d loaded" % (bound
, total
, nbound
, nprogs
))
406 def set_ns(self
, ns
):
407 name
= ns
if ns
else "1"
408 ip("link set dev %s netns %s" % (self
.dev
["ifname"], name
), ns
=self
.ns
)
411 def set_mtu(self
, mtu
, fail
=True):
412 return ip("link set dev %s mtu %d" % (self
.dev
["ifname"], mtu
),
415 def set_xdp(self
, bpf
, mode
, force
=False, JSON
=True, verbose
=False,
416 fail
=True, include_stderr
=False):
419 return ip("link set dev %s xdp%s %s" % (self
.dev
["ifname"], mode
, bpf
),
420 force
=force
, JSON
=JSON
,
421 fail
=fail
, include_stderr
=include_stderr
)
423 def unset_xdp(self
, mode
, force
=False, JSON
=True,
424 fail
=True, include_stderr
=False):
425 return ip("link set dev %s xdp%s off" % (self
.dev
["ifname"], mode
),
426 force
=force
, JSON
=JSON
,
427 fail
=fail
, include_stderr
=include_stderr
)
429 def ip_link_show(self
, xdp
):
430 _
, link
= ip("link show dev %s" % (self
['ifname']))
432 raise Exception("Multiple objects on ip link show")
435 fail(xdp
!= "xdp" in link
,
436 "XDP program not reporting in iplink (reported %s, expected %s)" %
437 ("xdp" in link
, xdp
))
440 def tc_add_ingress(self
):
441 tc("qdisc add dev %s ingress" % (self
['ifname']))
443 def tc_del_ingress(self
):
444 tc("qdisc del dev %s ingress" % (self
['ifname']))
446 def tc_flush_filters(self
, bound
=0, total
=0):
447 self
.tc_del_ingress()
448 self
.tc_add_ingress()
449 self
.wait_for_flush(bound
=bound
, total
=total
)
451 def tc_show_ingress(self
, expected
=None):
452 # No JSON support, oh well...
453 flags
= ["skip_sw", "skip_hw", "in_hw"]
454 named
= ["protocol", "pref", "chain", "handle", "id", "tag"]
456 args
= "-s filter show dev %s ingress" % (self
['ifname'])
457 _
, out
= tc(args
, JSON
=False)
460 lines
= out
.split('\n')
463 if "handle" not in words
:
467 fltr
[flag
] = flag
in words
470 idx
= words
.index(name
)
471 fltr
[name
] = words
[idx
+ 1]
476 if expected
is not None:
477 fail(len(filters
) != expected
,
478 "%d ingress filters loaded, expected %d" %
479 (len(filters
), expected
))
482 def cls_filter_op(self
, op
, qdisc
="ingress", prio
=None, handle
=None,
483 chain
=None, cls
="", params
="",
484 fail
=True, include_stderr
=False):
487 spec
+= " prio %d" % (prio
)
489 spec
+= " handle %s" % (handle
)
490 if chain
is not None:
491 spec
+= " chain %d" % (chain
)
493 return tc("filter {op} dev {dev} {qdisc} {spec} {cls} {params}"\
494 .format(op
=op
, dev
=self
['ifname'], qdisc
=qdisc
, spec
=spec
,
495 cls
=cls
, params
=params
),
496 fail
=fail
, include_stderr
=include_stderr
)
498 def cls_bpf_add_filter(self
, bpf
, op
="add", prio
=None, handle
=None,
499 chain
=None, da
=False, verbose
=False,
500 skip_sw
=False, skip_hw
=False,
501 fail
=True, include_stderr
=False):
514 return self
.cls_filter_op(op
=op
, prio
=prio
, handle
=handle
, cls
=cls
,
515 chain
=chain
, params
=params
,
516 fail
=fail
, include_stderr
=include_stderr
)
518 def set_ethtool_tc_offloads(self
, enable
, fail
=True):
519 args
= "hw-tc-offload %s" % ("on" if enable
else "off")
520 return ethtool(self
, "-K", args
, fail
=fail
)
522 ################################################################################
524 global files
, netns
, devs
529 cmd("rm -f %s" % (f
))
531 cmd("ip netns delete %s" % (ns
))
535 def pin_prog(file_name
, idx
=0):
536 progs
= bpftool_prog_list(expected
=(idx
+ 1))
538 bpftool("prog pin id %d %s" % (prog
["id"], file_name
))
539 files
.append(file_name
)
541 return file_name
, bpf_pinned(file_name
)
543 def pin_map(file_name
, idx
=0, expected
=1):
544 maps
= bpftool_map_list_wait(expected
=expected
)
546 bpftool("map pin id %d %s" % (m
["id"], file_name
))
547 files
.append(file_name
)
549 return file_name
, bpf_pinned(file_name
)
551 def check_dev_info_removed(prog_file
=None, map_file
=None):
552 bpftool_prog_list(expected
=0)
553 bpftool_prog_list(expected
=1, exclude_orphaned
=False)
554 ret
, err
= bpftool("prog show pin %s" % (prog_file
), fail
=False)
555 fail(ret
!= 0, "failed to show prog with removed device")
557 bpftool_map_list_wait(expected
=0)
558 ret
, err
= bpftool("map show pin %s" % (map_file
), fail
=False)
559 fail(ret
== 0, "Showing map with removed device did not fail")
560 fail(err
["error"].find("No such device") == -1,
561 "Showing map with removed device expected ENODEV, error is %s" %
564 def check_dev_info(other_ns
, ns
, prog_file
=None, map_file
=None, removed
=False):
565 progs
= bpftool_prog_list(expected
=1, ns
=ns
)
568 fail("dev" not in prog
.keys(), "Device parameters not reported")
570 fail("ifindex" not in dev
.keys(), "Device parameters not reported")
571 fail("ns_dev" not in dev
.keys(), "Device parameters not reported")
572 fail("ns_inode" not in dev
.keys(), "Device parameters not reported")
575 fail("ifname" not in dev
.keys(), "Ifname not reported")
576 fail(dev
["ifname"] != sim
["ifname"],
577 "Ifname incorrect %s vs %s" % (dev
["ifname"], sim
["ifname"]))
579 fail("ifname" in dev
.keys(), "Ifname is reported for other ns")
581 maps
= bpftool_map_list_wait(expected
=2, ns
=ns
)
583 fail("dev" not in m
.keys(), "Device parameters not reported")
584 fail(dev
!= m
["dev"], "Map's device different than program's")
586 def check_extack(output
, reference
, args
):
589 lines
= output
.split("\n")
590 comp
= len(lines
) >= 2 and lines
[1] == 'Error: ' + reference
591 fail(not comp
, "Missing or incorrect netlink extack message")
593 def check_extack_nsim(output
, reference
, args
):
594 check_extack(output
, "netdevsim: " + reference
, args
)
596 def check_no_extack(res
, needle
):
597 haystack
= (res
[1] + res
[2]).strip()
598 fail(haystack
.count(needle
) or haystack
.count("Warning:"),
599 "Unexpected command output, leaky extack? ('%s', '%s')" % (needle
, haystack
))
601 def check_verifier_log(output
, reference
):
602 lines
= output
.split("\n")
603 for l
in reversed(lines
):
606 fail(True, "Missing or incorrect message from netdevsim in verifier log")
608 def check_multi_basic(two_xdps
):
609 fail(two_xdps
["mode"] != 4, "Bad mode reported with multiple programs")
610 fail("prog" in two_xdps
, "Base program reported in multi program mode")
611 fail(len(two_xdps
["attached"]) != 2,
612 "Wrong attached program count with two programs")
613 fail(two_xdps
["attached"][0]["prog"]["id"] ==
614 two_xdps
["attached"][1]["prog"]["id"],
615 "Offloaded and other programs have the same id")
617 def test_spurios_extack(sim
, obj
, skip_hw
, needle
):
618 res
= sim
.cls_bpf_add_filter(obj
, prio
=1, handle
=1, skip_hw
=skip_hw
,
620 check_no_extack(res
, needle
)
621 res
= sim
.cls_bpf_add_filter(obj
, op
="replace", prio
=1, handle
=1,
622 skip_hw
=skip_hw
, include_stderr
=True)
623 check_no_extack(res
, needle
)
624 res
= sim
.cls_filter_op(op
="delete", prio
=1, handle
=1, cls
="bpf",
626 check_no_extack(res
, needle
)
628 def test_multi_prog(simdev
, sim
, obj
, modename
, modeid
):
629 start_test("Test multi-attachment XDP - %s + offload..." %
630 (modename
or "default", ))
631 sim
.set_xdp(obj
, "offload")
632 xdp
= sim
.ip_link_show(xdp
=True)["xdp"]
633 offloaded
= sim
.dfs_read("bpf_offloaded_id")
634 fail("prog" not in xdp
, "Base program not reported in single program mode")
635 fail(len(xdp
["attached"]) != 1,
636 "Wrong attached program count with one program")
638 sim
.set_xdp(obj
, modename
)
639 two_xdps
= sim
.ip_link_show(xdp
=True)["xdp"]
641 fail(xdp
["attached"][0] not in two_xdps
["attached"],
642 "Offload program not reported after other activated")
643 check_multi_basic(two_xdps
)
645 offloaded2
= sim
.dfs_read("bpf_offloaded_id")
646 fail(offloaded
!= offloaded2
,
647 "Offload ID changed after loading other program")
649 start_test("Test multi-attachment XDP - replace...")
650 ret
, _
, err
= sim
.set_xdp(obj
, "offload", fail
=False, include_stderr
=True)
651 fail(ret
== 0, "Replaced one of programs without -force")
652 check_extack(err
, "XDP program already attached.", args
)
654 start_test("Test multi-attachment XDP - remove without mode...")
655 ret
, _
, err
= sim
.unset_xdp("", force
=True,
656 fail
=False, include_stderr
=True)
657 fail(ret
== 0, "Removed program without a mode flag")
658 check_extack(err
, "More than one program loaded, unset mode is ambiguous.", args
)
660 sim
.unset_xdp("offload")
661 xdp
= sim
.ip_link_show(xdp
=True)["xdp"]
662 offloaded
= sim
.dfs_read("bpf_offloaded_id")
664 fail(xdp
["mode"] != modeid
, "Bad mode reported after multiple programs")
665 fail("prog" not in xdp
,
666 "Base program not reported after multi program mode")
667 fail(xdp
["attached"][0] not in two_xdps
["attached"],
668 "Offload program not reported after other activated")
669 fail(len(xdp
["attached"]) != 1,
670 "Wrong attached program count with remaining programs")
671 fail(offloaded
!= "0", "Offload ID reported with only other program left")
673 start_test("Test multi-attachment XDP - reattach...")
674 sim
.set_xdp(obj
, "offload")
675 two_xdps
= sim
.ip_link_show(xdp
=True)["xdp"]
677 fail(xdp
["attached"][0] not in two_xdps
["attached"],
678 "Other program not reported after offload activated")
679 check_multi_basic(two_xdps
)
681 start_test("Test multi-attachment XDP - device remove...")
684 simdev
= BpfNetdevSimDev()
686 sim
.set_ethtool_tc_offloads(True)
690 parser
= argparse
.ArgumentParser()
691 parser
.add_argument("--log", help="output verbose log to given file")
692 args
= parser
.parse_args()
694 logfile
= open(args
.log
, 'w+')
695 logfile
.write("# -*-Org-*-")
697 log("Prepare...", "", level
=1)
701 skip(os
.getuid() != 0, "test must be run as root")
704 ret
, progs
= bpftool("prog", fail
=False)
705 skip(ret
!= 0, "bpftool not installed")
707 _
, base_maps
= bpftool("map")
709 'pid_iter.rodata', # created on each bpftool invocation
710 'libbpf_det_bind', # created on each bpftool invocation
714 if not os
.path
.isdir("/sys/bus/netdevsim/"):
715 ret
, out
= cmd("modprobe netdevsim", fail
=False)
716 skip(ret
!= 0, "netdevsim module could not be loaded")
719 _
, out
= cmd("mount")
720 if out
.find("/sys/kernel/debug type debugfs") == -1:
721 cmd("mount -t debugfs none /sys/kernel/debug")
723 # Check samples are compiled
724 samples
= ["sample_ret0.bpf.o", "sample_map_ret0.bpf.o"]
726 ret
, out
= cmd("ls %s/%s" % (bpf_test_dir
, s
), fail
=False)
727 skip(ret
!= 0, "sample %s/%s not found, please compile it" %
730 # Check if iproute2 is built with libmnl (needed by extack support)
731 _
, _
, err
= cmd("tc qdisc delete dev lo handle 0",
732 fail
=False, include_stderr
=True)
733 if err
.find("Error: Failed to find qdisc with specified handle.") == -1:
734 print("Warning: no extack message in iproute2 output, libmnl missing?")
735 log("Warning: no extack message in iproute2 output, libmnl missing?", "")
738 # Check if net namespaces seem to work
740 skip(ns
is None, "Could not create a net namespace")
741 cmd("ip netns delete %s" % (ns
))
745 obj
= bpf_obj("sample_ret0.bpf.o")
746 bytecode
= bpf_bytecode("1,6 0 0 4294967295,")
748 start_test("Test destruction of generic XDP...")
749 simdev
= BpfNetdevSimDev()
751 sim
.set_xdp(obj
, "generic")
753 bpftool_prog_list_wait(expected
=0)
755 simdev
= BpfNetdevSimDev()
759 start_test("Test TC non-offloaded...")
760 ret
, _
= sim
.cls_bpf_add_filter(obj
, skip_hw
=True, fail
=False)
761 fail(ret
!= 0, "Software TC filter did not load")
763 start_test("Test TC non-offloaded isn't getting bound...")
764 ret
, _
= sim
.cls_bpf_add_filter(obj
, fail
=False)
765 fail(ret
!= 0, "Software TC filter did not load")
766 simdev
.dfs_get_bound_progs(expected
=0)
768 sim
.tc_flush_filters()
770 start_test("Test TC offloads are off by default...")
771 ret
, _
, err
= sim
.cls_bpf_add_filter(obj
, skip_sw
=True,
772 fail
=False, include_stderr
=True)
773 fail(ret
== 0, "TC filter loaded without enabling TC offloads")
774 check_extack(err
, "TC offload is disabled on net device.", args
)
777 sim
.set_ethtool_tc_offloads(True)
778 sim
.dfs
["bpf_tc_non_bound_accept"] = "Y"
780 start_test("Test TC offload by default...")
781 ret
, _
= sim
.cls_bpf_add_filter(obj
, fail
=False)
782 fail(ret
!= 0, "Software TC filter did not load")
783 simdev
.dfs_get_bound_progs(expected
=0)
784 ingress
= sim
.tc_show_ingress(expected
=1)
786 fail(not fltr
["in_hw"], "Filter not offloaded by default")
788 sim
.tc_flush_filters()
790 start_test("Test TC cBPF bytcode tries offload by default...")
791 ret
, _
= sim
.cls_bpf_add_filter(bytecode
, fail
=False)
792 fail(ret
!= 0, "Software TC filter did not load")
793 simdev
.dfs_get_bound_progs(expected
=0)
794 ingress
= sim
.tc_show_ingress(expected
=1)
796 fail(not fltr
["in_hw"], "Bytecode not offloaded by default")
798 sim
.tc_flush_filters()
799 sim
.dfs
["bpf_tc_non_bound_accept"] = "N"
801 start_test("Test TC cBPF unbound bytecode doesn't offload...")
802 ret
, _
, err
= sim
.cls_bpf_add_filter(bytecode
, skip_sw
=True,
803 fail
=False, include_stderr
=True)
804 fail(ret
== 0, "TC bytecode loaded for offload")
805 check_extack_nsim(err
, "netdevsim configured to reject unbound programs.",
809 start_test("Test non-0 chain offload...")
810 ret
, _
, err
= sim
.cls_bpf_add_filter(obj
, chain
=1, prio
=1, handle
=1,
812 fail
=False, include_stderr
=True)
813 fail(ret
== 0, "Offloaded a filter to chain other than 0")
814 check_extack(err
, "Driver supports only offload of chain 0.", args
)
815 sim
.tc_flush_filters()
817 start_test("Test TC replace...")
818 sim
.cls_bpf_add_filter(obj
, prio
=1, handle
=1)
819 sim
.cls_bpf_add_filter(obj
, op
="replace", prio
=1, handle
=1)
820 sim
.cls_filter_op(op
="delete", prio
=1, handle
=1, cls
="bpf")
822 sim
.cls_bpf_add_filter(obj
, prio
=1, handle
=1, skip_sw
=True)
823 sim
.cls_bpf_add_filter(obj
, op
="replace", prio
=1, handle
=1, skip_sw
=True)
824 sim
.cls_filter_op(op
="delete", prio
=1, handle
=1, cls
="bpf")
826 sim
.cls_bpf_add_filter(obj
, prio
=1, handle
=1, skip_hw
=True)
827 sim
.cls_bpf_add_filter(obj
, op
="replace", prio
=1, handle
=1, skip_hw
=True)
828 sim
.cls_filter_op(op
="delete", prio
=1, handle
=1, cls
="bpf")
830 start_test("Test TC replace bad flags...")
833 ret
, _
= sim
.cls_bpf_add_filter(obj
, op
="replace", prio
=1, handle
=1,
834 skip_sw
=(j
== 1), skip_hw
=(j
== 2),
836 fail(bool(ret
) != bool(j
),
837 "Software TC incorrect load in replace test, iteration %d" %
839 sim
.cls_filter_op(op
="delete", prio
=1, handle
=1, cls
="bpf")
841 start_test("Test spurious extack from the driver...")
842 test_spurios_extack(sim
, obj
, False, "netdevsim")
843 test_spurios_extack(sim
, obj
, True, "netdevsim")
845 sim
.set_ethtool_tc_offloads(False)
847 test_spurios_extack(sim
, obj
, False, "TC offload is disabled")
848 test_spurios_extack(sim
, obj
, True, "TC offload is disabled")
850 sim
.set_ethtool_tc_offloads(True)
852 sim
.tc_flush_filters()
854 start_test("Test TC offloads failure...")
855 sim
.dfs
["dev/bpf_bind_verifier_accept"] = 0
856 ret
, _
, err
= sim
.cls_bpf_add_filter(obj
, verbose
=True, skip_sw
=True,
857 fail
=False, include_stderr
=True)
858 fail(ret
== 0, "TC filter did not reject with TC offloads enabled")
859 check_verifier_log(err
, "[netdevsim] Hello from netdevsim!")
860 sim
.dfs
["dev/bpf_bind_verifier_accept"] = 1
862 start_test("Test TC offloads work...")
863 ret
, _
, err
= sim
.cls_bpf_add_filter(obj
, verbose
=True, skip_sw
=True,
864 fail
=False, include_stderr
=True)
865 fail(ret
!= 0, "TC filter did not load with TC offloads enabled")
867 start_test("Test TC offload basics...")
868 dfs
= simdev
.dfs_get_bound_progs(expected
=1)
869 progs
= bpftool_prog_list(expected
=1)
870 ingress
= sim
.tc_show_ingress(expected
=1)
875 fail(fltr
["skip_hw"], "TC does reports 'skip_hw' on offloaded filter")
876 fail(not fltr
["in_hw"], "TC does not report 'in_hw' for offloaded filter")
877 fail(not fltr
["skip_sw"], "TC does not report 'skip_sw' back")
879 start_test("Test TC offload is device-bound...")
880 fail(str(prog
["id"]) != fltr
["id"], "Program IDs don't match")
881 fail(prog
["tag"] != fltr
["tag"], "Program tags don't match")
882 fail(fltr
["id"] != dprog
["id"], "Program IDs don't match")
883 fail(dprog
["state"] != "xlated", "Offloaded program state not translated")
884 fail(dprog
["loaded"] != "Y", "Offloaded program is not loaded")
886 start_test("Test disabling TC offloads is rejected while filters installed...")
887 ret
, _
= sim
.set_ethtool_tc_offloads(False, fail
=False)
888 fail(ret
== 0, "Driver should refuse to disable TC offloads with filters installed...")
889 sim
.set_ethtool_tc_offloads(True)
891 start_test("Test qdisc removal frees things...")
892 sim
.tc_flush_filters()
893 sim
.tc_show_ingress(expected
=0)
895 start_test("Test disabling TC offloads is OK without filters...")
896 ret
, _
= sim
.set_ethtool_tc_offloads(False, fail
=False)
898 "Driver refused to disable TC offloads without filters installed...")
900 sim
.set_ethtool_tc_offloads(True)
902 start_test("Test destroying device gets rid of TC filters...")
903 sim
.cls_bpf_add_filter(obj
, skip_sw
=True)
905 bpftool_prog_list_wait(expected
=0)
907 simdev
= BpfNetdevSimDev()
909 sim
.set_ethtool_tc_offloads(True)
911 start_test("Test destroying device gets rid of XDP...")
912 sim
.set_xdp(obj
, "offload")
914 bpftool_prog_list_wait(expected
=0)
916 simdev
= BpfNetdevSimDev()
918 sim
.set_ethtool_tc_offloads(True)
920 start_test("Test XDP prog reporting...")
921 sim
.set_xdp(obj
, "drv")
922 ipl
= sim
.ip_link_show(xdp
=True)
923 progs
= bpftool_prog_list(expected
=1)
924 fail(ipl
["xdp"]["prog"]["id"] != progs
[0]["id"],
925 "Loaded program has wrong ID")
927 start_test("Test XDP prog replace without force...")
928 ret
, _
= sim
.set_xdp(obj
, "drv", fail
=False)
929 fail(ret
== 0, "Replaced XDP program without -force")
930 sim
.wait_for_flush(total
=1)
932 start_test("Test XDP prog replace with force...")
933 ret
, _
= sim
.set_xdp(obj
, "drv", force
=True, fail
=False)
934 fail(ret
!= 0, "Could not replace XDP program with -force")
935 bpftool_prog_list_wait(expected
=1)
936 ipl
= sim
.ip_link_show(xdp
=True)
937 progs
= bpftool_prog_list(expected
=1)
938 fail(ipl
["xdp"]["prog"]["id"] != progs
[0]["id"],
939 "Loaded program has wrong ID")
940 fail("dev" in progs
[0].keys(),
941 "Device parameters reported for non-offloaded program")
943 start_test("Test XDP prog replace with bad flags...")
944 ret
, _
, err
= sim
.set_xdp(obj
, "generic", force
=True,
945 fail
=False, include_stderr
=True)
946 fail(ret
== 0, "Replaced XDP program with a program in different mode")
948 "Native and generic XDP can't be active at the same time.",
951 start_test("Test MTU restrictions...")
952 ret
, _
= sim
.set_mtu(9000, fail
=False)
954 "Driver should refuse to increase MTU to 9000 with XDP loaded...")
956 bpftool_prog_list_wait(expected
=0)
958 ret
, _
, err
= sim
.set_xdp(obj
, "drv", fail
=False, include_stderr
=True)
959 fail(ret
== 0, "Driver should refuse to load program with MTU of 9000...")
960 check_extack_nsim(err
, "MTU too large w/ XDP enabled.", args
)
964 start_test("Test non-offload XDP attaching to HW...")
965 bpftool_prog_load("sample_ret0.bpf.o", "/sys/fs/bpf/nooffload")
966 nooffload
= bpf_pinned("/sys/fs/bpf/nooffload")
967 ret
, _
, err
= sim
.set_xdp(nooffload
, "offload",
968 fail
=False, include_stderr
=True)
969 fail(ret
== 0, "attached non-offloaded XDP program to HW")
970 check_extack_nsim(err
, "xdpoffload of non-bound program.", args
)
971 rm("/sys/fs/bpf/nooffload")
973 start_test("Test offload XDP attaching to drv...")
974 bpftool_prog_load("sample_ret0.bpf.o", "/sys/fs/bpf/offload",
976 offload
= bpf_pinned("/sys/fs/bpf/offload")
977 ret
, _
, err
= sim
.set_xdp(offload
, "drv", fail
=False, include_stderr
=True)
978 fail(ret
== 0, "attached offloaded XDP program to drv")
979 check_extack(err
, "Using offloaded program without HW_MODE flag is not supported.", args
)
980 rm("/sys/fs/bpf/offload")
983 start_test("Test XDP load failure...")
984 sim
.dfs
["dev/bpf_bind_verifier_accept"] = 0
985 ret
, _
, err
= bpftool_prog_load("sample_ret0.bpf.o", "/sys/fs/bpf/offload",
986 dev
=sim
['ifname'], fail
=False, include_stderr
=True)
987 fail(ret
== 0, "verifier should fail on load")
988 check_verifier_log(err
, "[netdevsim] Hello from netdevsim!")
989 sim
.dfs
["dev/bpf_bind_verifier_accept"] = 1
992 start_test("Test XDP offload...")
993 _
, _
, err
= sim
.set_xdp(obj
, "offload", verbose
=True, include_stderr
=True)
994 ipl
= sim
.ip_link_show(xdp
=True)
995 link_xdp
= ipl
["xdp"]["prog"]
996 progs
= bpftool_prog_list(expected
=1)
998 fail(link_xdp
["id"] != prog
["id"], "Loaded program has wrong ID")
1000 start_test("Test XDP offload is device bound...")
1001 dfs
= simdev
.dfs_get_bound_progs(expected
=1)
1004 fail(prog
["id"] != link_xdp
["id"], "Program IDs don't match")
1005 fail(prog
["tag"] != link_xdp
["tag"], "Program tags don't match")
1006 fail(str(link_xdp
["id"]) != dprog
["id"], "Program IDs don't match")
1007 fail(dprog
["state"] != "xlated", "Offloaded program state not translated")
1008 fail(dprog
["loaded"] != "Y", "Offloaded program is not loaded")
1010 start_test("Test removing XDP program many times...")
1011 sim
.unset_xdp("offload")
1012 sim
.unset_xdp("offload")
1013 sim
.unset_xdp("drv")
1014 sim
.unset_xdp("drv")
1017 bpftool_prog_list_wait(expected
=0)
1019 start_test("Test attempt to use a program for a wrong device...")
1020 simdev2
= BpfNetdevSimDev()
1021 sim2
, = simdev2
.nsims
1022 sim2
.set_xdp(obj
, "offload")
1023 pin_file
, pinned
= pin_prog("/sys/fs/bpf/tmp")
1025 ret
, _
, err
= sim
.set_xdp(pinned
, "offload",
1026 fail
=False, include_stderr
=True)
1027 fail(ret
== 0, "Pinned program loaded for a different device accepted")
1028 check_extack(err
, "Program bound to different device.", args
)
1030 ret
, _
, err
= sim
.set_xdp(pinned
, "offload",
1031 fail
=False, include_stderr
=True)
1032 fail(ret
== 0, "Pinned program loaded for a removed device accepted")
1033 check_extack(err
, "Program bound to different device.", args
)
1035 bpftool_prog_list_wait(expected
=0)
1037 simdev
, sim
= test_multi_prog(simdev
, sim
, obj
, "", 1)
1038 simdev
, sim
= test_multi_prog(simdev
, sim
, obj
, "drv", 1)
1039 simdev
, sim
= test_multi_prog(simdev
, sim
, obj
, "generic", 2)
1041 start_test("Test mixing of TC and XDP...")
1042 sim
.tc_add_ingress()
1043 sim
.set_xdp(obj
, "offload")
1044 ret
, _
, err
= sim
.cls_bpf_add_filter(obj
, skip_sw
=True,
1045 fail
=False, include_stderr
=True)
1046 fail(ret
== 0, "Loading TC when XDP active should fail")
1047 check_extack_nsim(err
, "driver and netdev offload states mismatch.", args
)
1048 sim
.unset_xdp("offload")
1049 sim
.wait_for_flush()
1051 sim
.cls_bpf_add_filter(obj
, skip_sw
=True)
1052 ret
, _
, err
= sim
.set_xdp(obj
, "offload", fail
=False, include_stderr
=True)
1053 fail(ret
== 0, "Loading XDP when TC active should fail")
1054 check_extack_nsim(err
, "TC program is already loaded.", args
)
1056 start_test("Test binding TC from pinned...")
1057 pin_file
, pinned
= pin_prog("/sys/fs/bpf/tmp")
1058 sim
.tc_flush_filters(bound
=1, total
=1)
1059 sim
.cls_bpf_add_filter(pinned
, da
=True, skip_sw
=True)
1060 sim
.tc_flush_filters(bound
=1, total
=1)
1062 start_test("Test binding XDP from pinned...")
1063 sim
.set_xdp(obj
, "offload")
1064 pin_file
, pinned
= pin_prog("/sys/fs/bpf/tmp2", idx
=1)
1066 sim
.set_xdp(pinned
, "offload", force
=True)
1067 sim
.unset_xdp("offload")
1068 sim
.set_xdp(pinned
, "offload", force
=True)
1069 sim
.unset_xdp("offload")
1071 start_test("Test offload of wrong type fails...")
1072 ret
, _
= sim
.cls_bpf_add_filter(pinned
, da
=True, skip_sw
=True, fail
=False)
1073 fail(ret
== 0, "Managed to attach XDP program to TC")
1075 start_test("Test asking for TC offload of two filters...")
1076 sim
.cls_bpf_add_filter(obj
, da
=True, skip_sw
=True)
1077 ret
, _
, err
= sim
.cls_bpf_add_filter(obj
, da
=True, skip_sw
=True,
1078 fail
=False, include_stderr
=True)
1079 fail(ret
== 0, "Managed to offload two TC filters at the same time")
1080 check_extack_nsim(err
, "driver and netdev offload states mismatch.", args
)
1082 sim
.tc_flush_filters(bound
=2, total
=2)
1084 start_test("Test if netdev removal waits for translation...")
1086 sim
.dfs
["dev/bpf_bind_verifier_delay"] = delay_msec
1088 cmd_line
= "tc filter add dev %s ingress bpf %s da skip_sw" % \
1089 (sim
['ifname'], obj
)
1090 tc_proc
= cmd(cmd_line
, background
=True, fail
=False)
1091 # Wait for the verifier to start
1092 while simdev
.dfs_num_bound_progs() <= 2:
1096 ret
, _
= cmd_result(tc_proc
, fail
=False)
1097 time_diff
= end
- start
1098 log("Time", "start:\t%s\nend:\t%s\ndiff:\t%s" % (start
, end
, time_diff
))
1100 fail(ret
== 0, "Managed to load TC filter on a unregistering device")
1101 delay_sec
= delay_msec
* 0.001
1102 fail(time_diff
< delay_sec
, "Removal process took %s, expected %s" %
1103 (time_diff
, delay_sec
))
1105 # Remove all pinned files and reinstantiate the netdev
1107 bpftool_prog_list_wait(expected
=0)
1109 simdev
= BpfNetdevSimDev()
1111 map_obj
= bpf_obj("sample_map_ret0.bpf.o")
1112 start_test("Test loading program with maps...")
1113 sim
.set_xdp(map_obj
, "offload", JSON
=False) # map fixup msg breaks JSON
1115 start_test("Test bpftool bound info reporting (own ns)...")
1116 check_dev_info(False, "")
1118 start_test("Test bpftool bound info reporting (other ns)...")
1121 check_dev_info(True, "")
1123 start_test("Test bpftool bound info reporting (remote ns)...")
1124 check_dev_info(False, ns
)
1126 start_test("Test bpftool bound info reporting (back to own ns)...")
1128 check_dev_info(False, "")
1130 prog_file
, _
= pin_prog("/sys/fs/bpf/tmp_prog")
1131 map_file
, _
= pin_map("/sys/fs/bpf/tmp_map", idx
=1, expected
=2)
1134 start_test("Test bpftool bound info reporting (removed dev)...")
1135 check_dev_info_removed(prog_file
=prog_file
, map_file
=map_file
)
1137 # Remove all pinned files and reinstantiate the netdev
1139 bpftool_prog_list_wait(expected
=0)
1141 simdev
= BpfNetdevSimDev()
1144 start_test("Test map update (no flags)...")
1145 sim
.set_xdp(map_obj
, "offload", JSON
=False) # map fixup msg breaks JSON
1146 maps
= bpftool_map_list_wait(expected
=2)
1147 array
= maps
[0] if maps
[0]["type"] == "array" else maps
[1]
1148 htab
= maps
[0] if maps
[0]["type"] == "hash" else maps
[1]
1151 bpftool("map update id %d key %s value %s" %
1152 (m
["id"], int2str("I", i
), int2str("Q", i
* 3)))
1155 ret
, _
= bpftool("map update id %d key %s value %s" %
1156 (m
["id"], int2str("I", 3), int2str("Q", 3 * 3)),
1158 fail(ret
== 0, "added too many entries")
1160 start_test("Test map update (exists)...")
1163 bpftool("map update id %d key %s value %s exist" %
1164 (m
["id"], int2str("I", i
), int2str("Q", i
* 3)))
1167 ret
, err
= bpftool("map update id %d key %s value %s exist" %
1168 (m
["id"], int2str("I", 3), int2str("Q", 3 * 3)),
1170 fail(ret
== 0, "updated non-existing key")
1171 fail(err
["error"].find("No such file or directory") == -1,
1172 "expected ENOENT, error is '%s'" % (err
["error"]))
1174 start_test("Test map update (noexist)...")
1177 ret
, err
= bpftool("map update id %d key %s value %s noexist" %
1178 (m
["id"], int2str("I", i
), int2str("Q", i
* 3)),
1180 fail(ret
== 0, "updated existing key")
1181 fail(err
["error"].find("File exists") == -1,
1182 "expected EEXIST, error is '%s'" % (err
["error"]))
1184 start_test("Test map dump...")
1186 _
, entries
= bpftool("map dump id %d" % (m
["id"]))
1188 key
= str2int(entries
[i
]["key"])
1189 fail(key
!= i
, "expected key %d, got %d" % (key
, i
))
1190 val
= str2int(entries
[i
]["value"])
1191 fail(val
!= i
* 3, "expected value %d, got %d" % (val
, i
* 3))
1193 start_test("Test map getnext...")
1195 _
, entry
= bpftool("map getnext id %d" % (m
["id"]))
1196 key
= str2int(entry
["next_key"])
1197 fail(key
!= 0, "next key %d, expected %d" % (key
, 0))
1198 _
, entry
= bpftool("map getnext id %d key %s" %
1199 (m
["id"], int2str("I", 0)))
1200 key
= str2int(entry
["next_key"])
1201 fail(key
!= 1, "next key %d, expected %d" % (key
, 1))
1202 ret
, err
= bpftool("map getnext id %d key %s" %
1203 (m
["id"], int2str("I", 1)), fail
=False)
1204 fail(ret
== 0, "got next key past the end of map")
1205 fail(err
["error"].find("No such file or directory") == -1,
1206 "expected ENOENT, error is '%s'" % (err
["error"]))
1208 start_test("Test map delete (htab)...")
1210 bpftool("map delete id %d key %s" % (htab
["id"], int2str("I", i
)))
1212 start_test("Test map delete (array)...")
1214 ret
, err
= bpftool("map delete id %d key %s" %
1215 (htab
["id"], int2str("I", i
)), fail
=False)
1216 fail(ret
== 0, "removed entry from an array")
1217 fail(err
["error"].find("No such file or directory") == -1,
1218 "expected ENOENT, error is '%s'" % (err
["error"]))
1220 start_test("Test map remove...")
1221 sim
.unset_xdp("offload")
1222 bpftool_map_list_wait(expected
=0)
1225 simdev
= BpfNetdevSimDev()
1227 sim
.set_xdp(map_obj
, "offload", JSON
=False) # map fixup msg breaks JSON
1229 bpftool_map_list_wait(expected
=0)
1231 start_test("Test map creation fail path...")
1232 simdev
= BpfNetdevSimDev()
1234 sim
.dfs
["bpf_map_accept"] = "N"
1235 ret
, _
= sim
.set_xdp(map_obj
, "offload", JSON
=False, fail
=False)
1237 "netdevsim didn't refuse to create a map with offload disabled")
1241 start_test("Test multi-dev ASIC program reuse...")
1242 simdevA
= BpfNetdevSimDev()
1243 simA
, = simdevA
.nsims
1244 simdevB
= BpfNetdevSimDev(3)
1245 simB1
, simB2
, simB3
= simdevB
.nsims
1246 sims
= (simA
, simB1
, simB2
, simB3
)
1247 simB
= (simB1
, simB2
, simB3
)
1249 bpftool_prog_load("sample_map_ret0.bpf.o", "/sys/fs/bpf/nsimA",
1251 progA
= bpf_pinned("/sys/fs/bpf/nsimA")
1252 bpftool_prog_load("sample_map_ret0.bpf.o", "/sys/fs/bpf/nsimB",
1253 dev
=simB1
['ifname'])
1254 progB
= bpf_pinned("/sys/fs/bpf/nsimB")
1256 simA
.set_xdp(progA
, "offload", JSON
=False)
1257 for d
in simdevB
.nsims
:
1258 d
.set_xdp(progB
, "offload", JSON
=False)
1260 start_test("Test multi-dev ASIC cross-dev replace...")
1261 ret
, _
= simA
.set_xdp(progB
, "offload", force
=True, JSON
=False, fail
=False)
1262 fail(ret
== 0, "cross-ASIC program allowed")
1263 for d
in simdevB
.nsims
:
1264 ret
, _
= d
.set_xdp(progA
, "offload", force
=True, JSON
=False, fail
=False)
1265 fail(ret
== 0, "cross-ASIC program allowed")
1267 start_test("Test multi-dev ASIC cross-dev install...")
1269 d
.unset_xdp("offload")
1271 ret
, _
, err
= simA
.set_xdp(progB
, "offload", force
=True, JSON
=False,
1272 fail
=False, include_stderr
=True)
1273 fail(ret
== 0, "cross-ASIC program allowed")
1274 check_extack(err
, "Program bound to different device.", args
)
1275 for d
in simdevB
.nsims
:
1276 ret
, _
, err
= d
.set_xdp(progA
, "offload", force
=True, JSON
=False,
1277 fail
=False, include_stderr
=True)
1278 fail(ret
== 0, "cross-ASIC program allowed")
1279 check_extack(err
, "Program bound to different device.", args
)
1281 start_test("Test multi-dev ASIC cross-dev map reuse...")
1283 mapA
= bpftool("prog show %s" % (progA
))[1]["map_ids"][0]
1284 mapB
= bpftool("prog show %s" % (progB
))[1]["map_ids"][0]
1286 ret
, _
= bpftool_prog_load("sample_map_ret0.bpf.o", "/sys/fs/bpf/nsimB_",
1287 dev
=simB3
['ifname'],
1288 maps
=["idx 0 id %d" % (mapB
)],
1290 fail(ret
!= 0, "couldn't reuse a map on the same ASIC")
1291 rm("/sys/fs/bpf/nsimB_")
1293 ret
, _
, err
= bpftool_prog_load("sample_map_ret0.bpf.o", "/sys/fs/bpf/nsimA_",
1295 maps
=["idx 0 id %d" % (mapB
)],
1296 fail
=False, include_stderr
=True)
1297 fail(ret
== 0, "could reuse a map on a different ASIC")
1298 fail(err
.count("offload device mismatch between prog and map") == 0,
1299 "error message missing for cross-ASIC map")
1301 ret
, _
, err
= bpftool_prog_load("sample_map_ret0.bpf.o", "/sys/fs/bpf/nsimB_",
1302 dev
=simB1
['ifname'],
1303 maps
=["idx 0 id %d" % (mapA
)],
1304 fail
=False, include_stderr
=True)
1305 fail(ret
== 0, "could reuse a map on a different ASIC")
1306 fail(err
.count("offload device mismatch between prog and map") == 0,
1307 "error message missing for cross-ASIC map")
1309 start_test("Test multi-dev ASIC cross-dev destruction...")
1310 bpftool_prog_list_wait(expected
=2)
1313 bpftool_prog_list_wait(expected
=1)
1315 ifnameB
= bpftool("prog show %s" % (progB
))[1]["dev"]["ifname"]
1316 fail(ifnameB
!= simB1
['ifname'], "program not bound to original device")
1318 bpftool_prog_list_wait(expected
=1)
1320 start_test("Test multi-dev ASIC cross-dev destruction - move...")
1321 ifnameB
= bpftool("prog show %s" % (progB
))[1]["dev"]["ifname"]
1322 fail(ifnameB
not in (simB2
['ifname'], simB3
['ifname']),
1323 "program not bound to remaining devices")
1326 ifnameB
= bpftool("prog show %s" % (progB
))[1]["dev"]["ifname"]
1327 fail(ifnameB
!= simB3
['ifname'], "program not bound to remaining device")
1331 bpftool_prog_list_wait(expected
=0)
1333 start_test("Test multi-dev ASIC cross-dev destruction - orphaned...")
1334 ret
, out
= bpftool("prog show %s" % (progB
), fail
=False)
1335 fail(ret
!= 0, "couldn't get information about orphaned program")
1337 print("%s: OK" % (os
.path
.basename(__file__
)))
1340 log("Clean up...", "", level
=1)