1 # SPDX-License-Identifier: GPL-2.0
2 # Copyright (c) 2020 SUSE LLC.
13 # Add the source tree of bpftool and /usr/local/sbin to PATH
14 cur_dir = os.path.dirname(os.path.realpath(__file__))
15 bpftool_dir = os.path.abspath(os.path.join(cur_dir, "..", "..", "..", "..",
16 "tools", "bpf", "bpftool"))
17 os.environ["PATH"] = bpftool_dir + ":/usr/local/sbin:" + os.environ["PATH"]
20 class IfaceNotFoundError(Exception):
24 class UnprivilegedUserError(Exception):
28 def _bpftool(args, json=True):
34 return subprocess.check_output(_args)
38 return _bpftool(args, json=False).decode("utf-8")
41 def bpftool_json(args):
43 return json.loads(res)
46 def get_default_iface():
47 for iface in socket.if_nameindex():
50 raise IfaceNotFoundError("Could not find any network interface to probe")
55 def wrapper(*args, **kwargs):
56 iface = get_default_iface()
57 return f(*args, iface, **kwargs)
61 class TestBpftool(unittest.TestCase):
65 raise UnprivilegedUserError(
66 "This test suite needs root privileges")
69 def test_feature_dev_json(self, iface):
70 unexpected_helpers = [
71 "bpf_probe_write_user",
82 res = bpftool_json(["feature", "probe", "dev", iface])
83 # Check if the result has all expected keys.
84 self.assertCountEqual(res.keys(), expected_keys)
85 # Check if unexpected helpers are not included in helpers probes
87 for helpers in res["helpers"].values():
88 for unexpected_helper in unexpected_helpers:
89 self.assertNotIn(unexpected_helper, helpers)
91 def test_feature_kernel(self):
93 bpftool_json(["feature", "probe", "kernel"]),
94 bpftool_json(["feature", "probe"]),
95 bpftool_json(["feature"]),
97 unexpected_helpers = [
98 "bpf_probe_write_user",
110 for tc in test_cases:
111 # Check if the result has all expected keys.
112 self.assertCountEqual(tc.keys(), expected_keys)
113 # Check if unexpected helpers are not included in helpers probes
115 for helpers in tc["helpers"].values():
116 for unexpected_helper in unexpected_helpers:
117 self.assertNotIn(unexpected_helper, helpers)
119 def test_feature_kernel_full(self):
121 bpftool_json(["feature", "probe", "kernel", "full"]),
122 bpftool_json(["feature", "probe", "full"]),
125 "bpf_probe_write_user",
129 for tc in test_cases:
130 # Check if expected helpers are included at least once in any
131 # helpers list for any program type. Unfortunately we cannot assume
132 # that they will be included in all program types or a specific
133 # subset of programs. It depends on the kernel version and
135 found_helpers = False
137 for helpers in tc["helpers"].values():
138 if all(expected_helper in helpers
139 for expected_helper in expected_helpers):
143 self.assertTrue(found_helpers)
145 def test_feature_kernel_full_vs_not_full(self):
146 full_res = bpftool_json(["feature", "probe", "full"])
147 not_full_res = bpftool_json(["feature", "probe"])
151 for helpers in full_res["helpers"].values():
152 for helper in helpers:
155 for helpers in not_full_res["helpers"].values():
156 for helper in helpers:
157 not_full_set.add(helper)
159 self.assertCountEqual(full_set - not_full_set,
160 {"bpf_probe_write_user", "bpf_trace_printk"})
161 self.assertCountEqual(not_full_set - full_set, set())
163 def test_feature_macros(self):
164 expected_patterns = [
165 r"/\*\*\* System call availability \*\*\*/",
166 r"#define HAVE_BPF_SYSCALL",
167 r"/\*\*\* eBPF program types \*\*\*/",
168 r"#define HAVE.*PROG_TYPE",
169 r"/\*\*\* eBPF map types \*\*\*/",
170 r"#define HAVE.*MAP_TYPE",
171 r"/\*\*\* eBPF helper functions \*\*\*/",
172 r"#define HAVE.*HELPER",
173 r"/\*\*\* eBPF misc features \*\*\*/",
176 res = bpftool(["feature", "probe", "macros"])
177 for pattern in expected_patterns:
178 self.assertRegex(res, pattern)