/* Ensure map_info_alloc() has at least what the bpftool needs */
map_info_alloc_len = map_info_type->size; if (map_info_alloc_len < sizeof(struct bpf_map_info))
map_info_alloc_len = sizeof(struct bpf_map_info);
return map_info_type_id;
}
/* If the subcmd needs to print out the bpf_map_info, *itshouldalwayscallmap_info_alloctoallocate *abpf_map_infoobjectinsteadofallocatingit *onthestack. * *map_info_alloc()willtaketherunningkernel'sbtf *intoaccount.i.e.itwillconsiderthe *sizeof(structbpf_map_info)oftherunningkernel. * *Itwillenablethe"struct_ops"cmdtoprintthelatest *"structbpf_map_info". * *[Recallthat"struct_ops"requiresthekernel'sbtfto *beavailable]
*/ staticstruct bpf_map_info *map_info_alloc(__u32 *alloc_len)
{ struct bpf_map_info *info;
if (get_map_info_type_id() < 0) return NULL;
info = calloc(1, map_info_alloc_len); if (!info)
p_err("mem alloc failed"); else
*alloc_len = map_info_alloc_len;
return info;
}
/* It iterates all struct_ops maps of the system. *Itreturnsthefdin"*res_fd"andmap_infoin"*info". *Intheveryfirstiteration,info->idshouldbe0. *Anoptionalmap"*name"filtercanbespecified. *Thefiltercanbemademoreflexibleinthefuture. *e.g.filterbykernel-struct-ops-name,regex-name,glob-name,...etc. * *Returnvalue: *1:Astruct_opsmapfound.Itisreturnedin"*res_fd"and"*info". *Thecallercancontinuetocallget_nextinthefuture. *0:Nostruct_opsmapisreturned. *Allstruct_opsmaphasbeenfound. *-1:Errorandthecallershouldaborttheiteration.
*/ staticint get_next_struct_ops_map(constchar *name, int *res_fd, struct bpf_map_info *info, __u32 info_len)
{
__u32 id = info->id; int err, fd;
while (true) {
err = bpf_map_get_next_id(id, &id); if (err) { if (errno == ENOENT) return0;
p_err("can't get next map: %s", strerror(errno)); return -1;
}
fd = bpf_map_get_fd_by_id(id); if (fd < 0) { if (errno == ENOENT) continue;
p_err("can't get map by id (%u): %s",
id, strerror(errno)); return -1;
}
err = bpf_map_get_info_by_fd(fd, info, &info_len); if (err) {
p_err("can't get map info: %s", strerror(errno));
close(fd); return -1;
}
staticint cmd_retval(conststruct res *res, bool must_have_one_map)
{ if (res->nr_errs || (!res->nr_maps && must_have_one_map)) return -1;
return0;
}
/* "data" is the work_func private storage */ typedefint (*work_func)(int fd, conststruct bpf_map_info *info, void *data, struct json_writer *wtr);
/* Find all struct_ops map in the system. *Filteroutby"name"(ifspecified). *Thencall"func(fd,info,data,wtr)"oneachstruct_opsmapfound.
*/ staticstruct res do_search(constchar *name, work_func func, void *data, struct json_writer *wtr)
{ struct bpf_map_info *info; struct res res = {};
__u32 info_len; int fd, err;
info = map_info_alloc(&info_len); if (!info) {
res.nr_errs++; return res;
}
if (wtr)
jsonw_start_array(wtr); while ((err = get_next_struct_ops_map(name, &fd, info, info_len)) == 1) {
res.nr_maps++;
err = func(fd, info, data, wtr); if (err)
res.nr_errs++;
close(fd);
} if (wtr)
jsonw_end_array(wtr);
if (err)
res.nr_errs++;
if (!wtr && name && !res.nr_errs && !res.nr_maps) /* It is not printing empty []. *Thus,needstospecificallysaynothingfound *for"name"here.
*/
p_err("no struct_ops found for %s", name); elseif (!wtr && json_output && !res.nr_errs) /* The "func()" above is not writing any json (i.e. !wtr *testhere). * *However,"-j"isenabledandthereisnoerrshere, *socalljson_null()asthecurrentconventionof *othercmds.
*/
jsonw_null(json_wtr);
free(info); return res;
}
staticstruct res do_one_id(constchar *id_str, work_func func, void *data, struct json_writer *wtr)
{ struct bpf_map_info *info; struct res res = {}; unsignedlong id;
__u32 info_len; char *endptr; int fd;
id = strtoul(id_str, &endptr, 0); if (*endptr || !id || id > UINT32_MAX) {
p_err("invalid id %s", id_str);
res.nr_errs++; return res;
}
fd = bpf_map_get_fd_by_id(id); if (fd < 0) {
p_err("can't get map by id (%lu): %s", id, strerror(errno));
res.nr_errs++; return res;
}
info = map_info_alloc(&info_len); if (!info) {
res.nr_errs++; goto done;
}
if (bpf_map_get_info_by_fd(fd, info, &info_len)) {
p_err("can't get map info: %s", strerror(errno));
res.nr_errs++; goto done;
}
if (info->type != BPF_MAP_TYPE_STRUCT_OPS) {
p_err("%s id %u is not a struct_ops map", info->name, info->id);
res.nr_errs++; goto done;
}
res.nr_maps++;
if (wtr)
jsonw_start_array(wtr);
if (func(fd, info, data, wtr))
res.nr_errs++; elseif (!wtr && json_output) /* The "func()" above is not writing any json (i.e. !wtr *testhere). * *However,"-j"isenabledandthereisnoerrshere, *socalljson_null()asthecurrentconventionof *othercmds.
*/
jsonw_null(json_wtr);
if (wtr)
jsonw_end_array(wtr);
done:
free(info);
close(fd);
return res;
}
staticstruct res do_work_on_struct_ops(constchar *search_type, constchar *search_term,
work_func func, void *data, struct json_writer *wtr)
{ if (search_type) { if (is_prefix(search_type, "id")) return do_one_id(search_term, func, data, wtr); elseif (!is_prefix(search_type, "name"))
usage();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.