Message ID | 20230320195644.1953096-7-kuifeng@meta.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | BPF |
Headers | show |
Series | Transit between BPF TCP congestion controls. | expand |
On 3/20/23 12:56 PM, Kui-Feng Lee wrote: > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c > index 56a60ab2ca8f..f84d68c049e3 100644 > --- a/tools/lib/bpf/libbpf.c > +++ b/tools/lib/bpf/libbpf.c > @@ -11639,6 +11639,11 @@ struct bpf_link *bpf_map__attach_struct_ops(const struct bpf_map *map) > > /* kern_vdata should be prepared during the loading phase. */ > err = bpf_map_update_elem(map->fd, &zero, map->st_ops->kern_vdata, 0); > + /* It can be EBUSY if the map has been used to create or > + * update a link before. We don't allow updating the value of > + * a struct_ops once it is set. That ensures that the value > + * never changed. So, it is safe to skip EBUSY. > + */ This belongs to the earlier patch (4?). > if (err && err != -EBUSY) { > free(link); > return libbpf_err_ptr(err);
On 3/21/23 14:04, Martin KaFai Lau wrote: > On 3/20/23 12:56 PM, Kui-Feng Lee wrote: >> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c >> index 56a60ab2ca8f..f84d68c049e3 100644 >> --- a/tools/lib/bpf/libbpf.c >> +++ b/tools/lib/bpf/libbpf.c >> @@ -11639,6 +11639,11 @@ struct bpf_link >> *bpf_map__attach_struct_ops(const struct bpf_map *map) >> /* kern_vdata should be prepared during the loading phase. */ >> err = bpf_map_update_elem(map->fd, &zero, >> map->st_ops->kern_vdata, 0); >> + /* It can be EBUSY if the map has been used to create or >> + * update a link before. We don't allow updating the value of >> + * a struct_ops once it is set. That ensures that the value >> + * never changed. So, it is safe to skip EBUSY. >> + */ > > This belongs to the earlier patch (4?). > Got it! >> if (err && err != -EBUSY) { >> free(link); >> return libbpf_err_ptr(err); >
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 56a60ab2ca8f..f84d68c049e3 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -11639,6 +11639,11 @@ struct bpf_link *bpf_map__attach_struct_ops(const struct bpf_map *map) /* kern_vdata should be prepared during the loading phase. */ err = bpf_map_update_elem(map->fd, &zero, map->st_ops->kern_vdata, 0); + /* It can be EBUSY if the map has been used to create or + * update a link before. We don't allow updating the value of + * a struct_ops once it is set. That ensures that the value + * never changed. So, it is safe to skip EBUSY. + */ if (err && err != -EBUSY) { free(link); return libbpf_err_ptr(err); @@ -11665,6 +11670,41 @@ struct bpf_link *bpf_map__attach_struct_ops(const struct bpf_map *map) return &link->link; } +/* + * Swap the back struct_ops of a link with a new struct_ops map. + */ +int bpf_link__update_map(struct bpf_link *link, const struct bpf_map *map) +{ + struct bpf_link_struct_ops *st_ops_link; + __u32 zero = 0; + int err; + + if (!bpf_map__is_struct_ops(map) || map->fd < 0) + return -EINVAL; + + st_ops_link = container_of(link, struct bpf_link_struct_ops, link); + /* Ensure the type of a link is correct */ + if (st_ops_link->map_fd < 0) + return -EINVAL; + + err = bpf_map_update_elem(map->fd, &zero, map->st_ops->kern_vdata, 0); + /* It can be EBUSY if the map has been used to create or + * update a link before. We don't allow updating the value of + * a struct_ops once it is set. That ensures that the value + * never changed. So, it is safe to skip EBUSY. + */ + if (err && err != -EBUSY) + return err; + + err = bpf_link_update(link->fd, map->fd, NULL); + if (err < 0) + return err; + + st_ops_link->map_fd = map->fd; + + return 0; +} + typedef enum bpf_perf_event_ret (*bpf_perf_event_print_t)(struct perf_event_header *hdr, void *private_data); diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index db4992a036f8..1615e55e2e79 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -719,6 +719,7 @@ bpf_program__attach_freplace(const struct bpf_program *prog, struct bpf_map; LIBBPF_API struct bpf_link *bpf_map__attach_struct_ops(const struct bpf_map *map); +LIBBPF_API int bpf_link__update_map(struct bpf_link *link, const struct bpf_map *map); struct bpf_iter_attach_opts { size_t sz; /* size of this struct for forward/backward compatibility */ diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map index 50dde1f6521e..a5aa3a383d69 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map @@ -386,6 +386,7 @@ LIBBPF_1.1.0 { LIBBPF_1.2.0 { global: bpf_btf_get_info_by_fd; + bpf_link__update_map; bpf_link_get_info_by_fd; bpf_map_get_info_by_fd; bpf_prog_get_info_by_fd;
Introduce bpf_link__update_map(), which allows to atomically update underlying struct_ops implementation for given struct_ops BPF link Signed-off-by: Kui-Feng Lee <kuifeng@meta.com> --- tools/lib/bpf/libbpf.c | 40 ++++++++++++++++++++++++++++++++++++++++ tools/lib/bpf/libbpf.h | 1 + tools/lib/bpf/libbpf.map | 1 + 3 files changed, 42 insertions(+)