summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/bpf/bpftool/feature.c26
-rw-r--r--tools/bpf/bpftool/main.h3
-rw-r--r--tools/bpf/bpftool/map.c4
-rw-r--r--tools/lib/bpf/libbpf.h1
-rw-r--r--tools/lib/bpf/libbpf.map1
-rw-r--r--tools/lib/bpf/libbpf_probes.c84
6 files changed, 118 insertions, 1 deletions
diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c
index d6508dde4808..cc731475c74b 100644
--- a/tools/bpf/bpftool/feature.c
+++ b/tools/bpf/bpftool/feature.c
@@ -438,6 +438,26 @@ static void probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types)
438 print_bool_feature(feat_name, plain_desc, res); 438 print_bool_feature(feat_name, plain_desc, res);
439} 439}
440 440
441static void probe_map_type(enum bpf_map_type map_type)
442{
443 const char *plain_comment = "eBPF map_type ";
444 char feat_name[128], plain_desc[128];
445 size_t maxlen;
446 bool res;
447
448 res = bpf_probe_map_type(map_type, 0);
449
450 maxlen = sizeof(plain_desc) - strlen(plain_comment) - 1;
451 if (strlen(map_type_name[map_type]) > maxlen) {
452 p_info("map type name too long");
453 return;
454 }
455
456 sprintf(feat_name, "have_%s_map_type", map_type_name[map_type]);
457 sprintf(plain_desc, "%s%s", plain_comment, map_type_name[map_type]);
458 print_bool_feature(feat_name, plain_desc, res);
459}
460
441static int do_probe(int argc, char **argv) 461static int do_probe(int argc, char **argv)
442{ 462{
443 enum probe_component target = COMPONENT_UNSPEC; 463 enum probe_component target = COMPONENT_UNSPEC;
@@ -507,6 +527,12 @@ static int do_probe(int argc, char **argv)
507 for (i = BPF_PROG_TYPE_UNSPEC + 1; i < ARRAY_SIZE(prog_type_name); i++) 527 for (i = BPF_PROG_TYPE_UNSPEC + 1; i < ARRAY_SIZE(prog_type_name); i++)
508 probe_prog_type(i, supported_types); 528 probe_prog_type(i, supported_types);
509 529
530 print_end_then_start_section("map_types",
531 "Scanning eBPF map types...");
532
533 for (i = BPF_MAP_TYPE_UNSPEC + 1; i < map_type_name_size; i++)
534 probe_map_type(i);
535
510exit_close_json: 536exit_close_json:
511 if (json_output) { 537 if (json_output) {
512 /* End current "section" of probes */ 538 /* End current "section" of probes */
diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
index 5cfc6601de9b..d7dd84d3c660 100644
--- a/tools/bpf/bpftool/main.h
+++ b/tools/bpf/bpftool/main.h
@@ -75,6 +75,9 @@ static const char * const prog_type_name[] = {
75 [BPF_PROG_TYPE_FLOW_DISSECTOR] = "flow_dissector", 75 [BPF_PROG_TYPE_FLOW_DISSECTOR] = "flow_dissector",
76}; 76};
77 77
78extern const char * const map_type_name[];
79extern const size_t map_type_name_size;
80
78enum bpf_obj_type { 81enum bpf_obj_type {
79 BPF_OBJ_UNKNOWN, 82 BPF_OBJ_UNKNOWN,
80 BPF_OBJ_PROG, 83 BPF_OBJ_PROG,
diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c
index 850c99ac980f..f15c520195b7 100644
--- a/tools/bpf/bpftool/map.c
+++ b/tools/bpf/bpftool/map.c
@@ -21,7 +21,7 @@
21#include "json_writer.h" 21#include "json_writer.h"
22#include "main.h" 22#include "main.h"
23 23
24static const char * const map_type_name[] = { 24const char * const map_type_name[] = {
25 [BPF_MAP_TYPE_UNSPEC] = "unspec", 25 [BPF_MAP_TYPE_UNSPEC] = "unspec",
26 [BPF_MAP_TYPE_HASH] = "hash", 26 [BPF_MAP_TYPE_HASH] = "hash",
27 [BPF_MAP_TYPE_ARRAY] = "array", 27 [BPF_MAP_TYPE_ARRAY] = "array",
@@ -48,6 +48,8 @@ static const char * const map_type_name[] = {
48 [BPF_MAP_TYPE_STACK] = "stack", 48 [BPF_MAP_TYPE_STACK] = "stack",
49}; 49};
50 50
51const size_t map_type_name_size = ARRAY_SIZE(map_type_name);
52
51static bool map_is_per_cpu(__u32 type) 53static bool map_is_per_cpu(__u32 type)
52{ 54{
53 return type == BPF_MAP_TYPE_PERCPU_HASH || 55 return type == BPF_MAP_TYPE_PERCPU_HASH ||
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 8e63821109ab..72385f6f9415 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -365,6 +365,7 @@ bpf_prog_linfo__lfind(const struct bpf_prog_linfo *prog_linfo,
365 */ 365 */
366LIBBPF_API bool bpf_probe_prog_type(enum bpf_prog_type prog_type, 366LIBBPF_API bool bpf_probe_prog_type(enum bpf_prog_type prog_type,
367 __u32 ifindex); 367 __u32 ifindex);
368LIBBPF_API bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex);
368 369
369#ifdef __cplusplus 370#ifdef __cplusplus
370} /* extern "C" */ 371} /* extern "C" */
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index c7ec3ffa24e9..bb2dfc3b2d7b 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -127,5 +127,6 @@ LIBBPF_0.0.1 {
127 127
128LIBBPF_0.0.2 { 128LIBBPF_0.0.2 {
129 global: 129 global:
130 bpf_probe_map_type;
130 bpf_probe_prog_type; 131 bpf_probe_prog_type;
131} LIBBPF_0.0.1; 132} LIBBPF_0.0.1;
diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c
index 056c0c186f2a..f511bd317b87 100644
--- a/tools/lib/bpf/libbpf_probes.c
+++ b/tools/lib/bpf/libbpf_probes.c
@@ -93,3 +93,87 @@ bool bpf_probe_prog_type(enum bpf_prog_type prog_type, __u32 ifindex)
93 93
94 return errno != EINVAL && errno != EOPNOTSUPP; 94 return errno != EINVAL && errno != EOPNOTSUPP;
95} 95}
96
97bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex)
98{
99 int key_size, value_size, max_entries, map_flags;
100 struct bpf_create_map_attr attr = {};
101 int fd = -1, fd_inner;
102
103 key_size = sizeof(__u32);
104 value_size = sizeof(__u32);
105 max_entries = 1;
106 map_flags = 0;
107
108 switch (map_type) {
109 case BPF_MAP_TYPE_STACK_TRACE:
110 value_size = sizeof(__u64);
111 break;
112 case BPF_MAP_TYPE_LPM_TRIE:
113 key_size = sizeof(__u64);
114 value_size = sizeof(__u64);
115 map_flags = BPF_F_NO_PREALLOC;
116 break;
117 case BPF_MAP_TYPE_CGROUP_STORAGE:
118 case BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE:
119 key_size = sizeof(struct bpf_cgroup_storage_key);
120 value_size = sizeof(__u64);
121 max_entries = 0;
122 break;
123 case BPF_MAP_TYPE_QUEUE:
124 case BPF_MAP_TYPE_STACK:
125 key_size = 0;
126 break;
127 case BPF_MAP_TYPE_UNSPEC:
128 case BPF_MAP_TYPE_HASH:
129 case BPF_MAP_TYPE_ARRAY:
130 case BPF_MAP_TYPE_PROG_ARRAY:
131 case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
132 case BPF_MAP_TYPE_PERCPU_HASH:
133 case BPF_MAP_TYPE_PERCPU_ARRAY:
134 case BPF_MAP_TYPE_CGROUP_ARRAY:
135 case BPF_MAP_TYPE_LRU_HASH:
136 case BPF_MAP_TYPE_LRU_PERCPU_HASH:
137 case BPF_MAP_TYPE_ARRAY_OF_MAPS:
138 case BPF_MAP_TYPE_HASH_OF_MAPS:
139 case BPF_MAP_TYPE_DEVMAP:
140 case BPF_MAP_TYPE_SOCKMAP:
141 case BPF_MAP_TYPE_CPUMAP:
142 case BPF_MAP_TYPE_XSKMAP:
143 case BPF_MAP_TYPE_SOCKHASH:
144 case BPF_MAP_TYPE_REUSEPORT_SOCKARRAY:
145 default:
146 break;
147 }
148
149 if (map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
150 map_type == BPF_MAP_TYPE_HASH_OF_MAPS) {
151 /* TODO: probe for device, once libbpf has a function to create
152 * map-in-map for offload
153 */
154 if (ifindex)
155 return false;
156
157 fd_inner = bpf_create_map(BPF_MAP_TYPE_HASH,
158 sizeof(__u32), sizeof(__u32), 1, 0);
159 if (fd_inner < 0)
160 return false;
161 fd = bpf_create_map_in_map(map_type, NULL, sizeof(__u32),
162 fd_inner, 1, 0);
163 close(fd_inner);
164 } else {
165 /* Note: No other restriction on map type probes for offload */
166 attr.map_type = map_type;
167 attr.key_size = key_size;
168 attr.value_size = value_size;
169 attr.max_entries = max_entries;
170 attr.map_flags = map_flags;
171 attr.map_ifindex = ifindex;
172
173 fd = bpf_create_map_xattr(&attr);
174 }
175 if (fd >= 0)
176 close(fd);
177
178 return fd >= 0;
179}