diff options
-rw-r--r-- | tools/bpf/bpftool/feature.c | 26 | ||||
-rw-r--r-- | tools/bpf/bpftool/main.h | 3 | ||||
-rw-r--r-- | tools/bpf/bpftool/map.c | 4 | ||||
-rw-r--r-- | tools/lib/bpf/libbpf.h | 1 | ||||
-rw-r--r-- | tools/lib/bpf/libbpf.map | 1 | ||||
-rw-r--r-- | tools/lib/bpf/libbpf_probes.c | 84 |
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 | ||
441 | static 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 | |||
441 | static int do_probe(int argc, char **argv) | 461 | static 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 | |||
510 | exit_close_json: | 536 | exit_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 | ||
78 | extern const char * const map_type_name[]; | ||
79 | extern const size_t map_type_name_size; | ||
80 | |||
78 | enum bpf_obj_type { | 81 | enum 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 | ||
24 | static const char * const map_type_name[] = { | 24 | const 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 | ||
51 | const size_t map_type_name_size = ARRAY_SIZE(map_type_name); | ||
52 | |||
51 | static bool map_is_per_cpu(__u32 type) | 53 | static 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 | */ |
366 | LIBBPF_API bool bpf_probe_prog_type(enum bpf_prog_type prog_type, | 366 | LIBBPF_API bool bpf_probe_prog_type(enum bpf_prog_type prog_type, |
367 | __u32 ifindex); | 367 | __u32 ifindex); |
368 | LIBBPF_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 | ||
128 | LIBBPF_0.0.2 { | 128 | LIBBPF_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 | |||
97 | bool 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 | } | ||