Skip to content

Commit ad7cb9d

Browse files
borkmannKernel Patches Daemon
authored and
Kernel Patches Daemon
committed
libbpf: Add link-based API for tcx
Implement tcx BPF link support for libbpf. The bpf_program__attach_fd() API has been refactored slightly in order to pass bpf_link_create_opts pointer as input. A new bpf_program__attach_tcx() 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]> Acked-by: Andrii Nakryiko <[email protected]>
1 parent 33790dd commit ad7cb9d

File tree

5 files changed

+88
-11
lines changed

5 files changed

+88
-11
lines changed

tools/lib/bpf/bpf.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -719,9 +719,9 @@ int bpf_link_create(int prog_fd, int target_fd,
719719
const struct bpf_link_create_opts *opts)
720720
{
721721
const size_t attr_sz = offsetofend(union bpf_attr, link_create);
722-
__u32 target_btf_id, iter_info_len;
722+
__u32 target_btf_id, iter_info_len, relative_id;
723+
int fd, err, relative_fd;
723724
union bpf_attr attr;
724-
int fd, err;
725725

726726
if (!OPTS_VALID(opts, bpf_link_create_opts))
727727
return libbpf_err(-EINVAL);
@@ -783,6 +783,22 @@ int bpf_link_create(int prog_fd, int target_fd,
783783
if (!OPTS_ZEROED(opts, netfilter))
784784
return libbpf_err(-EINVAL);
785785
break;
786+
case BPF_TCX_INGRESS:
787+
case BPF_TCX_EGRESS:
788+
relative_fd = OPTS_GET(opts, tcx.relative_fd, 0);
789+
relative_id = OPTS_GET(opts, tcx.relative_id, 0);
790+
if (relative_fd && relative_id)
791+
return libbpf_err(-EINVAL);
792+
if (relative_id) {
793+
attr.link_create.tcx.relative_id = relative_id;
794+
attr.link_create.flags |= BPF_F_ID;
795+
} else {
796+
attr.link_create.tcx.relative_fd = relative_fd;
797+
}
798+
attr.link_create.tcx.expected_revision = OPTS_GET(opts, tcx.expected_revision, 0);
799+
if (!OPTS_ZEROED(opts, tcx))
800+
return libbpf_err(-EINVAL);
801+
break;
786802
default:
787803
if (!OPTS_ZEROED(opts, flags))
788804
return libbpf_err(-EINVAL);

tools/lib/bpf/bpf.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,11 @@ struct bpf_link_create_opts {
401401
__s32 priority;
402402
__u32 flags;
403403
} netfilter;
404+
struct {
405+
__u32 relative_fd;
406+
__u32 relative_id;
407+
__u64 expected_revision;
408+
} tcx;
404409
};
405410
size_t :0;
406411
};

tools/lib/bpf/libbpf.c

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

139140
static const char * const map_type_name[] = {
@@ -11854,11 +11855,10 @@ static int attach_lsm(const struct bpf_program *prog, long cookie, struct bpf_li
1185411855
}
1185511856

1185611857
static struct bpf_link *
11857-
bpf_program__attach_fd(const struct bpf_program *prog, int target_fd, int btf_id,
11858-
const char *target_name)
11858+
bpf_program_attach_fd(const struct bpf_program *prog,
11859+
int target_fd, const char *target_name,
11860+
const struct bpf_link_create_opts *opts)
1185911861
{
11860-
DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts,
11861-
.target_btf_id = btf_id);
1186211862
enum bpf_attach_type attach_type;
1186311863
char errmsg[STRERR_BUFSIZE];
1186411864
struct bpf_link *link;
@@ -11876,7 +11876,7 @@ bpf_program__attach_fd(const struct bpf_program *prog, int target_fd, int btf_id
1187611876
link->detach = &bpf_link__detach_fd;
1187711877

1187811878
attach_type = bpf_program__expected_attach_type(prog);
11879-
link_fd = bpf_link_create(prog_fd, target_fd, attach_type, &opts);
11879+
link_fd = bpf_link_create(prog_fd, target_fd, attach_type, opts);
1188011880
if (link_fd < 0) {
1188111881
link_fd = -errno;
1188211882
free(link);
@@ -11892,19 +11892,54 @@ bpf_program__attach_fd(const struct bpf_program *prog, int target_fd, int btf_id
1189211892
struct bpf_link *
1189311893
bpf_program__attach_cgroup(const struct bpf_program *prog, int cgroup_fd)
1189411894
{
11895-
return bpf_program__attach_fd(prog, cgroup_fd, 0, "cgroup");
11895+
return bpf_program_attach_fd(prog, cgroup_fd, "cgroup", NULL);
1189611896
}
1189711897

1189811898
struct bpf_link *
1189911899
bpf_program__attach_netns(const struct bpf_program *prog, int netns_fd)
1190011900
{
11901-
return bpf_program__attach_fd(prog, netns_fd, 0, "netns");
11901+
return bpf_program_attach_fd(prog, netns_fd, "netns", NULL);
1190211902
}
1190311903

1190411904
struct bpf_link *bpf_program__attach_xdp(const struct bpf_program *prog, int ifindex)
1190511905
{
1190611906
/* target_fd/target_ifindex use the same field in LINK_CREATE */
11907-
return bpf_program__attach_fd(prog, ifindex, 0, "xdp");
11907+
return bpf_program_attach_fd(prog, ifindex, "xdp", NULL);
11908+
}
11909+
11910+
struct bpf_link *
11911+
bpf_program__attach_tcx(const struct bpf_program *prog, int ifindex,
11912+
const struct bpf_tcx_opts *opts)
11913+
{
11914+
LIBBPF_OPTS(bpf_link_create_opts, link_create_opts);
11915+
__u32 relative_id;
11916+
int relative_fd;
11917+
11918+
if (!OPTS_VALID(opts, bpf_tcx_opts))
11919+
return libbpf_err_ptr(-EINVAL);
11920+
11921+
relative_id = OPTS_GET(opts, relative_id, 0);
11922+
relative_fd = OPTS_GET(opts, relative_fd, 0);
11923+
11924+
/* validate we don't have unexpected combinations of non-zero fields */
11925+
if (!ifindex) {
11926+
pr_warn("prog '%s': target netdevice ifindex cannot be zero\n",
11927+
prog->name);
11928+
return libbpf_err_ptr(-EINVAL);
11929+
}
11930+
if (relative_fd && relative_id) {
11931+
pr_warn("prog '%s': relative_fd and relative_id cannot be set at the same time\n",
11932+
prog->name);
11933+
return libbpf_err_ptr(-EINVAL);
11934+
}
11935+
11936+
link_create_opts.tcx.expected_revision = OPTS_GET(opts, expected_revision, 0);
11937+
link_create_opts.tcx.relative_fd = relative_fd;
11938+
link_create_opts.tcx.relative_id = relative_id;
11939+
link_create_opts.flags = OPTS_GET(opts, flags, 0);
11940+
11941+
/* target_fd/target_ifindex use the same field in LINK_CREATE */
11942+
return bpf_program_attach_fd(prog, ifindex, "tcx", &link_create_opts);
1190811943
}
1190911944

1191011945
struct bpf_link *bpf_program__attach_freplace(const struct bpf_program *prog,
@@ -11926,11 +11961,16 @@ struct bpf_link *bpf_program__attach_freplace(const struct bpf_program *prog,
1192611961
}
1192711962

1192811963
if (target_fd) {
11964+
LIBBPF_OPTS(bpf_link_create_opts, target_opts);
11965+
1192911966
btf_id = libbpf_find_prog_btf_id(attach_func_name, target_fd);
1193011967
if (btf_id < 0)
1193111968
return libbpf_err_ptr(btf_id);
1193211969

11933-
return bpf_program__attach_fd(prog, target_fd, btf_id, "freplace");
11970+
target_opts.target_btf_id = btf_id;
11971+
11972+
return bpf_program_attach_fd(prog, target_fd, "freplace",
11973+
&target_opts);
1193411974
} else {
1193511975
/* no target, so use raw_tracepoint_open for compatibility
1193611976
* with old kernels

tools/lib/bpf/libbpf.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,21 @@ LIBBPF_API struct bpf_link *
733733
bpf_program__attach_netfilter(const struct bpf_program *prog,
734734
const struct bpf_netfilter_opts *opts);
735735

736+
struct bpf_tcx_opts {
737+
/* size of this struct, for forward/backward compatibility */
738+
size_t sz;
739+
__u32 flags;
740+
__u32 relative_fd;
741+
__u32 relative_id;
742+
__u64 expected_revision;
743+
size_t :0;
744+
};
745+
#define bpf_tcx_opts__last_field expected_revision
746+
747+
LIBBPF_API struct bpf_link *
748+
bpf_program__attach_tcx(const struct bpf_program *prog, int ifindex,
749+
const struct bpf_tcx_opts *opts);
750+
736751
struct bpf_map;
737752

738753
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
@@ -397,4 +397,5 @@ LIBBPF_1.3.0 {
397397
bpf_obj_pin_opts;
398398
bpf_prog_detach_opts;
399399
bpf_program__attach_netfilter;
400+
bpf_program__attach_tcx;
400401
} LIBBPF_1.2.0;

0 commit comments

Comments
 (0)