Skip to content

Commit e2b84c0

Browse files
committed
libbpf: Add link-based API for tcx
Implement tcx BPF link support for libbpf. The bpf_program__attach_fd_opts() API has been refactored slightly in order to pass bpf_link_create_opts pointer as input. A new bpf_program__attach_tcx_opts() has been added on top of this which allows for passing all relevant data via extensible struct bpf_tcx_opts. The program sections tcx/ingress and tcx/egress correspond to the hook locations for tc ingress and egress, respectively. For concrete usage examples, see the extensive selftests that have been developed as part of this series. Signed-off-by: Daniel Borkmann <[email protected]>
1 parent 8e34b69 commit e2b84c0

File tree

5 files changed

+77
-9
lines changed

5 files changed

+77
-9
lines changed

tools/lib/bpf/bpf.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,13 @@ int bpf_link_create(int prog_fd, int target_fd,
773773
if (!OPTS_ZEROED(opts, tracing))
774774
return libbpf_err(-EINVAL);
775775
break;
776+
case BPF_TCX_INGRESS:
777+
case BPF_TCX_EGRESS:
778+
attr.link_create.tcx.relative_fd = OPTS_GET(opts, tcx.relative_fd, 0);
779+
attr.link_create.tcx.expected_revision = OPTS_GET(opts, tcx.expected_revision, 0);
780+
if (!OPTS_ZEROED(opts, tcx))
781+
return libbpf_err(-EINVAL);
782+
break;
776783
default:
777784
if (!OPTS_ZEROED(opts, flags))
778785
return libbpf_err(-EINVAL);

tools/lib/bpf/bpf.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,11 @@ struct bpf_link_create_opts {
370370
struct {
371371
__u64 cookie;
372372
} tracing;
373+
struct {
374+
__u32 relative_fd;
375+
__u32 relative_id;
376+
__u64 expected_revision;
377+
} tcx;
373378
};
374379
size_t :0;
375380
};

tools/lib/bpf/libbpf.c

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ static const char * const link_type_name[] = {
133133
[BPF_LINK_TYPE_KPROBE_MULTI] = "kprobe_multi",
134134
[BPF_LINK_TYPE_STRUCT_OPS] = "struct_ops",
135135
[BPF_LINK_TYPE_NETFILTER] = "netfilter",
136+
[BPF_LINK_TYPE_TCX] = "tcx",
136137
};
137138

138139
static const char * const map_type_name[] = {
@@ -11685,11 +11686,10 @@ static int attach_lsm(const struct bpf_program *prog, long cookie, struct bpf_li
1168511686
}
1168611687

1168711688
static struct bpf_link *
11688-
bpf_program__attach_fd(const struct bpf_program *prog, int target_fd, int btf_id,
11689-
const char *target_name)
11689+
bpf_program_attach_fd_opts(const struct bpf_program *prog,
11690+
int target_fd, const char *target_name,
11691+
const struct bpf_link_create_opts *opts)
1169011692
{
11691-
DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts,
11692-
.target_btf_id = btf_id);
1169311693
enum bpf_attach_type attach_type;
1169411694
char errmsg[STRERR_BUFSIZE];
1169511695
struct bpf_link *link;
@@ -11707,7 +11707,7 @@ bpf_program__attach_fd(const struct bpf_program *prog, int target_fd, int btf_id
1170711707
link->detach = &bpf_link__detach_fd;
1170811708

1170911709
attach_type = bpf_program__expected_attach_type(prog);
11710-
link_fd = bpf_link_create(prog_fd, target_fd, attach_type, &opts);
11710+
link_fd = bpf_link_create(prog_fd, target_fd, attach_type, opts);
1171111711
if (link_fd < 0) {
1171211712
link_fd = -errno;
1171311713
free(link);
@@ -11723,19 +11723,54 @@ bpf_program__attach_fd(const struct bpf_program *prog, int target_fd, int btf_id
1172311723
struct bpf_link *
1172411724
bpf_program__attach_cgroup(const struct bpf_program *prog, int cgroup_fd)
1172511725
{
11726-
return bpf_program__attach_fd(prog, cgroup_fd, 0, "cgroup");
11726+
return bpf_program_attach_fd_opts(prog, cgroup_fd, "cgroup", NULL);
1172711727
}
1172811728

1172911729
struct bpf_link *
1173011730
bpf_program__attach_netns(const struct bpf_program *prog, int netns_fd)
1173111731
{
11732-
return bpf_program__attach_fd(prog, netns_fd, 0, "netns");
11732+
return bpf_program_attach_fd_opts(prog, netns_fd, "netns", NULL);
1173311733
}
1173411734

1173511735
struct bpf_link *bpf_program__attach_xdp(const struct bpf_program *prog, int ifindex)
1173611736
{
1173711737
/* target_fd/target_ifindex use the same field in LINK_CREATE */
11738-
return bpf_program__attach_fd(prog, ifindex, 0, "xdp");
11738+
return bpf_program_attach_fd_opts(prog, ifindex, "xdp", NULL);
11739+
}
11740+
11741+
struct bpf_link *
11742+
bpf_program__attach_tcx(const struct bpf_program *prog,
11743+
const struct bpf_tcx_opts *opts)
11744+
{
11745+
LIBBPF_OPTS(bpf_link_create_opts, link_create_opts);
11746+
__u32 relative_fd, relative_id;
11747+
int ifindex;
11748+
11749+
if (!OPTS_VALID(opts, bpf_tcx_opts))
11750+
return libbpf_err_ptr(-EINVAL);
11751+
11752+
ifindex = OPTS_GET(opts, ifindex, 0);
11753+
if (!ifindex) {
11754+
pr_warn("prog '%s': target netdevice ifindex cannot be zero\n",
11755+
prog->name);
11756+
return libbpf_err_ptr(-EINVAL);
11757+
}
11758+
11759+
relative_fd = OPTS_GET(opts, relative_fd, 0);
11760+
relative_id = OPTS_GET(opts, relative_id, 0);
11761+
if (relative_fd && relative_id) {
11762+
pr_warn("prog '%s': relative_fd and relative_id cannot be set at the same time\n",
11763+
prog->name);
11764+
return libbpf_err_ptr(-EINVAL);
11765+
}
11766+
11767+
link_create_opts.tcx.expected_revision = OPTS_GET(opts, expected_revision, 0);
11768+
link_create_opts.tcx.relative_fd = relative_fd;
11769+
link_create_opts.tcx.relative_id = relative_id;
11770+
link_create_opts.flags = OPTS_GET(opts, flags, 0);
11771+
11772+
/* target_fd/target_ifindex use the same field in LINK_CREATE */
11773+
return bpf_program_attach_fd_opts(prog, ifindex, "tc", &link_create_opts);
1173911774
}
1174011775

1174111776
struct bpf_link *bpf_program__attach_freplace(const struct bpf_program *prog,
@@ -11757,11 +11792,15 @@ struct bpf_link *bpf_program__attach_freplace(const struct bpf_program *prog,
1175711792
}
1175811793

1175911794
if (target_fd) {
11795+
LIBBPF_OPTS(bpf_link_create_opts, target_opts);
11796+
1176011797
btf_id = libbpf_find_prog_btf_id(attach_func_name, target_fd);
1176111798
if (btf_id < 0)
1176211799
return libbpf_err_ptr(btf_id);
11800+
target_opts.target_btf_id = btf_id;
1176311801

11764-
return bpf_program__attach_fd(prog, target_fd, btf_id, "freplace");
11802+
return bpf_program_attach_fd_opts(prog, target_fd, "freplace",
11803+
&target_opts);
1176511804
} else {
1176611805
/* no target, so use raw_tracepoint_open for compatibility
1176711806
* with old kernels

tools/lib/bpf/libbpf.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,22 @@ LIBBPF_API struct bpf_link *
718718
bpf_program__attach_freplace(const struct bpf_program *prog,
719719
int target_fd, const char *attach_func_name);
720720

721+
struct bpf_tcx_opts {
722+
/* size of this struct, for forward/backward compatibility */
723+
size_t sz;
724+
int ifindex;
725+
__u32 flags;
726+
__u32 relative_fd;
727+
__u32 relative_id;
728+
__u64 expected_revision;
729+
size_t :0;
730+
};
731+
#define bpf_tcx_opts__last_field expected_revision
732+
733+
LIBBPF_API struct bpf_link *
734+
bpf_program__attach_tcx(const struct bpf_program *prog,
735+
const struct bpf_tcx_opts *opts);
736+
721737
struct bpf_map;
722738

723739
LIBBPF_API struct bpf_link *bpf_map__attach_struct_ops(const struct bpf_map *map);

tools/lib/bpf/libbpf.map

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,4 +396,5 @@ LIBBPF_1.3.0 {
396396
global:
397397
bpf_obj_pin_opts;
398398
bpf_prog_detach_opts;
399+
bpf_program__attach_tcx;
399400
} LIBBPF_1.2.0;

0 commit comments

Comments
 (0)