Message ID | 20230316023641.2092778-7-kuifeng@meta.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | BPF |
Headers | show |
Series | Transit between BPF TCP congestion controls. | expand |
On 3/15/23 7:36 PM, Kui-Feng Lee wrote: > 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 | 30 ++++++++++++++++++++++++++++++ > tools/lib/bpf/libbpf.h | 1 + > tools/lib/bpf/libbpf.map | 1 + > 3 files changed, 32 insertions(+) > > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c > index 6dbae7ffab48..63ec1f8fe8a0 100644 > --- a/tools/lib/bpf/libbpf.c > +++ b/tools/lib/bpf/libbpf.c > @@ -11659,6 +11659,36 @@ 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, fd; > + > + 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); > + if (err && err != -EBUSY) > + return err; > + > + fd = bpf_link_update(link->fd, map->fd, NULL); bpf_link_update() returns ok/error. Using "fd = ..." is confusing. Use "err = ..." instead and remove the need of "int fd;". > + if (fd < 0) > + return fd; > + > + 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..cc05be376257 100644 > --- a/tools/lib/bpf/libbpf.map > +++ b/tools/lib/bpf/libbpf.map > @@ -387,6 +387,7 @@ LIBBPF_1.2.0 { > global: > bpf_btf_get_info_by_fd; > bpf_link_get_info_by_fd; > + bpf_link__update_map; > bpf_map_get_info_by_fd; > bpf_prog_get_info_by_fd; > } LIBBPF_1.1.0;
On 3/17/23 12:42, Martin KaFai Lau wrote: > On 3/15/23 7:36 PM, Kui-Feng Lee wrote: >> 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 | 30 ++++++++++++++++++++++++++++++ >> tools/lib/bpf/libbpf.h | 1 + >> tools/lib/bpf/libbpf.map | 1 + >> 3 files changed, 32 insertions(+) >> >> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c >> index 6dbae7ffab48..63ec1f8fe8a0 100644 >> --- a/tools/lib/bpf/libbpf.c >> +++ b/tools/lib/bpf/libbpf.c >> @@ -11659,6 +11659,36 @@ 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, fd; >> + >> + 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); >> + if (err && err != -EBUSY) >> + return err; >> + >> + fd = bpf_link_update(link->fd, map->fd, NULL); > > bpf_link_update() returns ok/error. Using "fd = ..." is confusing. Use > "err = ..." instead and remove the need of "int fd;". got it. > >> + if (fd < 0) >> + return fd; >> + >> + 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..cc05be376257 100644 >> --- a/tools/lib/bpf/libbpf.map >> +++ b/tools/lib/bpf/libbpf.map >> @@ -387,6 +387,7 @@ LIBBPF_1.2.0 { >> global: >> bpf_btf_get_info_by_fd; >> bpf_link_get_info_by_fd; >> + bpf_link__update_map; >> bpf_map_get_info_by_fd; >> bpf_prog_get_info_by_fd; >> } LIBBPF_1.1.0; >
On Wed, Mar 15, 2023 at 7:37 PM Kui-Feng Lee <kuifeng@meta.com> wrote: > > 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 | 30 ++++++++++++++++++++++++++++++ > tools/lib/bpf/libbpf.h | 1 + > tools/lib/bpf/libbpf.map | 1 + > 3 files changed, 32 insertions(+) > > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c > index 6dbae7ffab48..63ec1f8fe8a0 100644 > --- a/tools/lib/bpf/libbpf.c > +++ b/tools/lib/bpf/libbpf.c > @@ -11659,6 +11659,36 @@ 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, fd; > + > + 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); > + if (err && err != -EBUSY) Why is it ok to ignore -EBUSY? Let's leave a comment as well, as this is not clear. > + return err; > + > + fd = bpf_link_update(link->fd, map->fd, NULL); > + if (fd < 0) > + return fd; > + > + 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..cc05be376257 100644 > --- a/tools/lib/bpf/libbpf.map > +++ b/tools/lib/bpf/libbpf.map > @@ -387,6 +387,7 @@ LIBBPF_1.2.0 { > global: > bpf_btf_get_info_by_fd; > bpf_link_get_info_by_fd; > + bpf_link__update_map; nit: this should go before bpf_link_get_info_by_fd ('_' orders before 'g') > bpf_map_get_info_by_fd; > bpf_prog_get_info_by_fd; > } LIBBPF_1.1.0; > -- > 2.34.1 >
On 3/17/23 15:33, Andrii Nakryiko wrote: > On Wed, Mar 15, 2023 at 7:37 PM Kui-Feng Lee <kuifeng@meta.com> wrote: >> >> 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 | 30 ++++++++++++++++++++++++++++++ >> tools/lib/bpf/libbpf.h | 1 + >> tools/lib/bpf/libbpf.map | 1 + >> 3 files changed, 32 insertions(+) >> >> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c >> index 6dbae7ffab48..63ec1f8fe8a0 100644 >> --- a/tools/lib/bpf/libbpf.c >> +++ b/tools/lib/bpf/libbpf.c >> @@ -11659,6 +11659,36 @@ 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, fd; >> + >> + 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); >> + if (err && err != -EBUSY) > > Why is it ok to ignore -EBUSY? Let's leave a comment as well, as this > is not clear. got it! > >> + return err; >> + >> + fd = bpf_link_update(link->fd, map->fd, NULL); >> + if (fd < 0) >> + return fd; >> + >> + 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..cc05be376257 100644 >> --- a/tools/lib/bpf/libbpf.map >> +++ b/tools/lib/bpf/libbpf.map >> @@ -387,6 +387,7 @@ LIBBPF_1.2.0 { >> global: >> bpf_btf_get_info_by_fd; >> bpf_link_get_info_by_fd; >> + bpf_link__update_map; > > nit: this should go before bpf_link_get_info_by_fd ('_' orders before 'g') ok! > >> bpf_map_get_info_by_fd; >> bpf_prog_get_info_by_fd; >> } LIBBPF_1.1.0; >> -- >> 2.34.1 >>
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 6dbae7ffab48..63ec1f8fe8a0 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -11659,6 +11659,36 @@ 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, fd; + + 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); + if (err && err != -EBUSY) + return err; + + fd = bpf_link_update(link->fd, map->fd, NULL); + if (fd < 0) + return fd; + + 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..cc05be376257 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map @@ -387,6 +387,7 @@ LIBBPF_1.2.0 { global: bpf_btf_get_info_by_fd; bpf_link_get_info_by_fd; + bpf_link__update_map; bpf_map_get_info_by_fd; bpf_prog_get_info_by_fd; } LIBBPF_1.1.0;
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 | 30 ++++++++++++++++++++++++++++++ tools/lib/bpf/libbpf.h | 1 + tools/lib/bpf/libbpf.map | 1 + 3 files changed, 32 insertions(+)