Skip to content

Commit 0232b78

Browse files
ThinkerYzu1Alexei Starovoitov
authored andcommitted
bpftool: Register struct_ops with a link.
You can include an optional path after specifying the object name for the 'struct_ops register' subcommand. Since the commit 226bc6a ("Merge branch 'Transit between BPF TCP congestion controls.'") has been accepted, it is now possible to create a link for a struct_ops. This can be done by defining a struct_ops in SEC(".struct_ops.link") to make libbpf returns a real link. If we don't pin the links before leaving bpftool, they will disappear. To instruct bpftool to pin the links in a directory with the names of the maps, we need to provide the path of that directory. Signed-off-by: Kui-Feng Lee <[email protected]> Reviewed-by: Quentin Monnet <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 833d67e commit 0232b78

File tree

4 files changed

+75
-25
lines changed

4 files changed

+75
-25
lines changed

tools/bpf/bpftool/common.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,3 +1091,17 @@ const char *bpf_attach_type_input_str(enum bpf_attach_type t)
10911091
default: return libbpf_bpf_attach_type_str(t);
10921092
}
10931093
}
1094+
1095+
int pathname_concat(char *buf, int buf_sz, const char *path,
1096+
const char *name)
1097+
{
1098+
int len;
1099+
1100+
len = snprintf(buf, buf_sz, "%s/%s", path, name);
1101+
if (len < 0)
1102+
return -EINVAL;
1103+
if (len >= buf_sz)
1104+
return -ENAMETOOLONG;
1105+
1106+
return 0;
1107+
}

tools/bpf/bpftool/main.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,4 +264,7 @@ static inline bool hashmap__empty(struct hashmap *map)
264264
return map ? hashmap__size(map) == 0 : true;
265265
}
266266

267+
int pathname_concat(char *buf, int buf_sz, const char *path,
268+
const char *name);
269+
267270
#endif

tools/bpf/bpftool/prog.c

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1476,19 +1476,6 @@ auto_attach_program(struct bpf_program *prog, const char *path)
14761476
return err;
14771477
}
14781478

1479-
static int pathname_concat(char *buf, size_t buf_sz, const char *path, const char *name)
1480-
{
1481-
int len;
1482-
1483-
len = snprintf(buf, buf_sz, "%s/%s", path, name);
1484-
if (len < 0)
1485-
return -EINVAL;
1486-
if ((size_t)len >= buf_sz)
1487-
return -ENAMETOOLONG;
1488-
1489-
return 0;
1490-
}
1491-
14921479
static int
14931480
auto_attach_programs(struct bpf_object *obj, const char *path)
14941481
{

tools/bpf/bpftool/struct_ops.c

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -475,21 +475,44 @@ static int do_unregister(int argc, char **argv)
475475
return cmd_retval(&res, true);
476476
}
477477

478+
static int pin_link(struct bpf_link *link, const char *pindir,
479+
const char *name)
480+
{
481+
char pinfile[PATH_MAX];
482+
int err;
483+
484+
err = pathname_concat(pinfile, sizeof(pinfile), pindir, name);
485+
if (err)
486+
return -1;
487+
488+
return bpf_link__pin(link, pinfile);
489+
}
490+
478491
static int do_register(int argc, char **argv)
479492
{
480493
LIBBPF_OPTS(bpf_object_open_opts, open_opts);
494+
__u32 link_info_len = sizeof(struct bpf_link_info);
495+
struct bpf_link_info link_info = {};
481496
struct bpf_map_info info = {};
482497
__u32 info_len = sizeof(info);
483498
int nr_errs = 0, nr_maps = 0;
499+
const char *linkdir = NULL;
484500
struct bpf_object *obj;
485501
struct bpf_link *link;
486502
struct bpf_map *map;
487503
const char *file;
488504

489-
if (argc != 1)
505+
if (argc != 1 && argc != 2)
490506
usage();
491507

492508
file = GET_ARG();
509+
if (argc == 1)
510+
linkdir = GET_ARG();
511+
512+
if (linkdir && mount_bpffs_for_pin(linkdir)) {
513+
p_err("can't mount bpffs for pinning");
514+
return -1;
515+
}
493516

494517
if (verifier_logs)
495518
/* log_level1 + log_level2 + stats, but not stable UAPI */
@@ -519,21 +542,44 @@ static int do_register(int argc, char **argv)
519542
}
520543
nr_maps++;
521544

522-
bpf_link__disconnect(link);
523-
bpf_link__destroy(link);
524-
525-
if (!bpf_map_get_info_by_fd(bpf_map__fd(map), &info,
526-
&info_len))
527-
p_info("Registered %s %s id %u",
528-
get_kern_struct_ops_name(&info),
529-
bpf_map__name(map),
530-
info.id);
531-
else
545+
if (bpf_map_get_info_by_fd(bpf_map__fd(map), &info,
546+
&info_len)) {
532547
/* Not p_err. The struct_ops was attached
533548
* successfully.
534549
*/
535550
p_info("Registered %s but can't find id: %s",
536551
bpf_map__name(map), strerror(errno));
552+
goto clean_link;
553+
}
554+
if (!(bpf_map__map_flags(map) & BPF_F_LINK)) {
555+
p_info("Registered %s %s id %u",
556+
get_kern_struct_ops_name(&info),
557+
info.name,
558+
info.id);
559+
goto clean_link;
560+
}
561+
if (bpf_link_get_info_by_fd(bpf_link__fd(link),
562+
&link_info,
563+
&link_info_len)) {
564+
p_err("Registered %s but can't find link id: %s",
565+
bpf_map__name(map), strerror(errno));
566+
nr_errs++;
567+
goto clean_link;
568+
}
569+
if (linkdir && pin_link(link, linkdir, info.name)) {
570+
p_err("can't pin link %u for %s: %s",
571+
link_info.id, info.name,
572+
strerror(errno));
573+
nr_errs++;
574+
goto clean_link;
575+
}
576+
p_info("Registered %s %s map id %u link id %u",
577+
get_kern_struct_ops_name(&info),
578+
info.name, info.id, link_info.id);
579+
580+
clean_link:
581+
bpf_link__disconnect(link);
582+
bpf_link__destroy(link);
537583
}
538584

539585
bpf_object__close(obj);
@@ -562,7 +608,7 @@ static int do_help(int argc, char **argv)
562608
fprintf(stderr,
563609
"Usage: %1$s %2$s { show | list } [STRUCT_OPS_MAP]\n"
564610
" %1$s %2$s dump [STRUCT_OPS_MAP]\n"
565-
" %1$s %2$s register OBJ\n"
611+
" %1$s %2$s register OBJ [LINK_DIR]\n"
566612
" %1$s %2$s unregister STRUCT_OPS_MAP\n"
567613
" %1$s %2$s help\n"
568614
"\n"

0 commit comments

Comments
 (0)