public inbox for bpf@vger.kernel.org
 help / color / mirror / Atom feed
From: Kui-Feng Lee <sinquersw@gmail.com>
To: Andrii Nakryiko <andrii.nakryiko@gmail.com>,
	Kui-Feng Lee <kuifeng@meta.com>
Cc: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev,
	song@kernel.org, kernel-team@meta.com, andrii@kernel.org,
	sdf@google.com
Subject: Re: [PATCH bpf-next v4 8/9] libbpf: Use .struct_ops.link section to indicate a struct_ops with a link.
Date: Tue, 7 Mar 2023 20:23:05 -0800	[thread overview]
Message-ID: <7425b219-4b47-c3f1-844d-61e27d03af03@gmail.com> (raw)
In-Reply-To: <CAEf4BzaopfY5azUh4yi=Bx3h7x9W9r=XCA1OeVrTFSK_X3s7UQ@mail.gmail.com>



On 3/7/23 17:07, Andrii Nakryiko wrote:
> On Tue, Mar 7, 2023 at 3:33 PM Kui-Feng Lee <kuifeng@meta.com> wrote:
>>
>> Flags a struct_ops is to back a bpf_link by putting it to the
>> ".struct_ops.link" section.  Once it is flagged, the created
>> struct_ops can be used to create a bpf_link or update a bpf_link that
>> has been backed by another struct_ops.
>>
>> Signed-off-by: Kui-Feng Lee <kuifeng@meta.com>
>> ---
>>   tools/lib/bpf/libbpf.c | 64 +++++++++++++++++++++++++++++++++---------
>>   1 file changed, 50 insertions(+), 14 deletions(-)
>>
>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
>> index 247de39d136f..d66acd2fdbaa 100644
>> --- a/tools/lib/bpf/libbpf.c
>> +++ b/tools/lib/bpf/libbpf.c
>> @@ -467,6 +467,7 @@ struct bpf_struct_ops {
>>   #define KCONFIG_SEC ".kconfig"
>>   #define KSYMS_SEC ".ksyms"
>>   #define STRUCT_OPS_SEC ".struct_ops"
>> +#define STRUCT_OPS_LINK_SEC ".struct_ops.link"
>>
>>   enum libbpf_map_type {
>>          LIBBPF_MAP_UNSPEC,
>> @@ -596,6 +597,7 @@ struct elf_state {
>>          Elf64_Ehdr *ehdr;
>>          Elf_Data *symbols;
>>          Elf_Data *st_ops_data;
>> +       Elf_Data *st_ops_link_data;
>>          size_t shstrndx; /* section index for section name strings */
>>          size_t strtabidx;
>>          struct elf_sec_desc *secs;
>> @@ -605,6 +607,7 @@ struct elf_state {
>>          int text_shndx;
>>          int symbols_shndx;
>>          int st_ops_shndx;
>> +       int st_ops_link_shndx;
>>   };
>>
>>   struct usdt_manager;
>> @@ -1119,7 +1122,7 @@ static int bpf_object__init_kern_struct_ops_maps(struct bpf_object *obj)
>>          return 0;
>>   }
>>
>> -static int bpf_object__init_struct_ops_maps(struct bpf_object *obj)
>> +static int bpf_object__init_struct_ops_maps_link(struct bpf_object *obj, bool link)
> 
> let's shorten it and not use double underscores, as this is not a
> public bpf_object API, just "init_struct_ops_maps" probably is fine
> 
>>   {
>>          const struct btf_type *type, *datasec;
>>          const struct btf_var_secinfo *vsi;
>> @@ -1127,18 +1130,33 @@ static int bpf_object__init_struct_ops_maps(struct bpf_object *obj)
>>          const char *tname, *var_name;
>>          __s32 type_id, datasec_id;
>>          const struct btf *btf;
>> +       const char *sec_name;
>>          struct bpf_map *map;
>> -       __u32 i;
>> +       __u32 i, map_flags;
>> +       Elf_Data *data;
>> +       int shndx;
>>
>> -       if (obj->efile.st_ops_shndx == -1)
>> +       if (link) {
>> +               sec_name = STRUCT_OPS_LINK_SEC;
>> +               shndx = obj->efile.st_ops_link_shndx;
>> +               data = obj->efile.st_ops_link_data;
>> +               map_flags = BPF_F_LINK;
>> +       } else {
>> +               sec_name = STRUCT_OPS_SEC;
>> +               shndx = obj->efile.st_ops_shndx;
>> +               data = obj->efile.st_ops_data;
>> +               map_flags = 0;
>> +       }
> 
> let's pass these as function arguments instead
> 
>> +
>> +       if (shndx == -1)
>>                  return 0;
>>
>>          btf = obj->btf;
>> -       datasec_id = btf__find_by_name_kind(btf, STRUCT_OPS_SEC,
>> +       datasec_id = btf__find_by_name_kind(btf, sec_name,
>>                                              BTF_KIND_DATASEC);
>>          if (datasec_id < 0) {
>>                  pr_warn("struct_ops init: DATASEC %s not found\n",
>> -                       STRUCT_OPS_SEC);
>> +                       sec_name);
>>                  return -EINVAL;
>>          }
>>
>> @@ -1151,7 +1169,7 @@ static int bpf_object__init_struct_ops_maps(struct bpf_object *obj)
>>                  type_id = btf__resolve_type(obj->btf, vsi->type);
>>                  if (type_id < 0) {
>>                          pr_warn("struct_ops init: Cannot resolve var type_id %u in DATASEC %s\n",
>> -                               vsi->type, STRUCT_OPS_SEC);
>> +                               vsi->type, sec_name);
>>                          return -EINVAL;
>>                  }
>>
>> @@ -1170,7 +1188,7 @@ static int bpf_object__init_struct_ops_maps(struct bpf_object *obj)
>>                  if (IS_ERR(map))
>>                          return PTR_ERR(map);
>>
>> -               map->sec_idx = obj->efile.st_ops_shndx;
>> +               map->sec_idx = shndx;
>>                  map->sec_offset = vsi->offset;
>>                  map->name = strdup(var_name);
>>                  if (!map->name)
>> @@ -1180,6 +1198,7 @@ static int bpf_object__init_struct_ops_maps(struct bpf_object *obj)
>>                  map->def.key_size = sizeof(int);
>>                  map->def.value_size = type->size;
>>                  map->def.max_entries = 1;
>> +               map->def.map_flags = map_flags;
>>
>>                  map->st_ops = calloc(1, sizeof(*map->st_ops));
>>                  if (!map->st_ops)
>> @@ -1192,14 +1211,14 @@ static int bpf_object__init_struct_ops_maps(struct bpf_object *obj)
>>                  if (!st_ops->data || !st_ops->progs || !st_ops->kern_func_off)
>>                          return -ENOMEM;
>>
>> -               if (vsi->offset + type->size > obj->efile.st_ops_data->d_size) {
>> +               if (vsi->offset + type->size > data->d_size) {
>>                          pr_warn("struct_ops init: var %s is beyond the end of DATASEC %s\n",
>> -                               var_name, STRUCT_OPS_SEC);
>> +                               var_name, sec_name);
>>                          return -EINVAL;
>>                  }
>>
>>                  memcpy(st_ops->data,
>> -                      obj->efile.st_ops_data->d_buf + vsi->offset,
>> +                      data->d_buf + vsi->offset,
>>                         type->size);
>>                  st_ops->tname = tname;
>>                  st_ops->type = type;
>> @@ -1212,6 +1231,15 @@ static int bpf_object__init_struct_ops_maps(struct bpf_object *obj)
>>          return 0;
>>   }
>>
>> +static int bpf_object__init_struct_ops_maps(struct bpf_object *obj)
> 
> let's name this bpf_object_init_struct_ops, no double underscores
> 
>> +{
>> +       int err;
>> +
>> +       err = bpf_object__init_struct_ops_maps_link(obj, false);
>> +       err = err ?: bpf_object__init_struct_ops_maps_link(obj, true);
>> +       return err;
>> +}
>> +
>>   static struct bpf_object *bpf_object__new(const char *path,
>>                                            const void *obj_buf,
>>                                            size_t obj_buf_sz,
>> @@ -1248,6 +1276,7 @@ static struct bpf_object *bpf_object__new(const char *path,
>>          obj->efile.obj_buf_sz = obj_buf_sz;
>>          obj->efile.btf_maps_shndx = -1;
>>          obj->efile.st_ops_shndx = -1;
>> +       obj->efile.st_ops_link_shndx = -1;
>>          obj->kconfig_map_idx = -1;
>>
>>          obj->kern_version = get_kernel_version();
>> @@ -1265,6 +1294,7 @@ static void bpf_object__elf_finish(struct bpf_object *obj)
>>          obj->efile.elf = NULL;
>>          obj->efile.symbols = NULL;
>>          obj->efile.st_ops_data = NULL;
>> +       obj->efile.st_ops_link_data = NULL;
>>
>>          zfree(&obj->efile.secs);
>>          obj->efile.sec_cnt = 0;
>> @@ -2753,12 +2783,13 @@ static bool libbpf_needs_btf(const struct bpf_object *obj)
>>   {
>>          return obj->efile.btf_maps_shndx >= 0 ||
>>                 obj->efile.st_ops_shndx >= 0 ||
>> +              obj->efile.st_ops_link_shndx >= 0 ||
>>                 obj->nr_extern > 0;
>>   }
>>
>>   static bool kernel_needs_btf(const struct bpf_object *obj)
>>   {
>> -       return obj->efile.st_ops_shndx >= 0;
>> +       return obj->efile.st_ops_shndx >= 0 || obj->efile.st_ops_link_shndx >= 0;
>>   }
>>
>>   static int bpf_object__init_btf(struct bpf_object *obj,
>> @@ -3451,6 +3482,9 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
>>                          } else if (strcmp(name, STRUCT_OPS_SEC) == 0) {
>>                                  obj->efile.st_ops_data = data;
>>                                  obj->efile.st_ops_shndx = idx;
>> +                       } else if (strcmp(name, STRUCT_OPS_LINK_SEC) == 0) {
>> +                               obj->efile.st_ops_link_data = data;
>> +                               obj->efile.st_ops_link_shndx = idx;
>>                          } else {
>>                                  pr_info("elf: skipping unrecognized data section(%d) %s\n",
>>                                          idx, name);
>> @@ -3465,6 +3499,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
>>                          /* Only do relo for section with exec instructions */
>>                          if (!section_have_execinstr(obj, targ_sec_idx) &&
>>                              strcmp(name, ".rel" STRUCT_OPS_SEC) &&
>> +                           strcmp(name, ".rel" STRUCT_OPS_LINK_SEC) &&
>>                              strcmp(name, ".rel" MAPS_ELF_SEC)) {
>>                                  pr_info("elf: skipping relo section(%d) %s for section(%d) %s\n",
>>                                          idx, name, targ_sec_idx,
>> @@ -6611,7 +6646,7 @@ static int bpf_object__collect_relos(struct bpf_object *obj)
>>                          return -LIBBPF_ERRNO__INTERNAL;
>>                  }
>>
>> -               if (idx == obj->efile.st_ops_shndx)
>> +               if (idx == obj->efile.st_ops_shndx || idx == obj->efile.st_ops_link_shndx)
>>                          err = bpf_object__collect_st_ops_relos(obj, shdr, data);
> 
> this function calls find_struct_ops_map_by_offset() which assumes we
> only have one struct_ops section. This won't work now, please double
> check all this, there should be no assumption about specific section
> index

Yes, I will check the section index of maps.

> 
>>                  else if (idx == obj->efile.btf_maps_shndx)
>>                          err = bpf_object__collect_map_relos(obj, shdr, data);
>> @@ -8954,8 +8989,9 @@ static int bpf_object__collect_st_ops_relos(struct bpf_object *obj,
>>                  }
>>
>>                  /* struct_ops BPF prog can be re-used between multiple
>> -                * .struct_ops as long as it's the same struct_ops struct
>> -                * definition and the same function pointer field
>> +                * .struct_ops & .struct_ops.link as long as it's the
>> +                * same struct_ops struct definition and the same
>> +                * function pointer field
>>                   */
>>                  if (prog->attach_btf_id != st_ops->type_id ||
>>                      prog->expected_attach_type != member_idx) {
>> --
>> 2.34.1
>>

  reply	other threads:[~2023-03-08  4:23 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-07 23:32 [PATCH bpf-next v4 0/9] Transit between BPF TCP congestion controls Kui-Feng Lee
2023-03-07 23:32 ` [PATCH bpf-next v4 1/9] bpf: Retire the struct_ops map kvalue->refcnt Kui-Feng Lee
2023-03-07 23:33 ` [PATCH bpf-next v4 2/9] bpf: Create links for BPF struct_ops maps Kui-Feng Lee
2023-03-08  0:37   ` Andrii Nakryiko
2023-03-08  1:11     ` Kui-Feng Lee
2023-03-07 23:33 ` [PATCH bpf-next v4 3/9] net: Update an existing TCP congestion control algorithm Kui-Feng Lee
2023-03-07 23:33 ` [PATCH bpf-next v4 4/9] bpf: Validate kdata of a struct_ops before transiting to READY Kui-Feng Lee
2023-03-07 23:33 ` [PATCH bpf-next v4 5/9] libbpf: Create a bpf_link in bpf_map__attach_struct_ops() Kui-Feng Lee
2023-03-08  0:46   ` Andrii Nakryiko
2023-03-08  3:33     ` Kui-Feng Lee
2023-03-07 23:33 ` [PATCH bpf-next v4 6/9] bpf: Update the struct_ops of a bpf_link Kui-Feng Lee
2023-03-08  0:49   ` Andrii Nakryiko
2023-03-08 16:27     ` Kui-Feng Lee
2023-03-07 23:33 ` [PATCH bpf-next v4 7/9] libbpf: Update a bpf_link with another struct_ops Kui-Feng Lee
2023-03-08  0:53   ` Andrii Nakryiko
2023-03-08  1:45     ` Kui-Feng Lee
2023-03-07 23:33 ` [PATCH bpf-next v4 8/9] libbpf: Use .struct_ops.link section to indicate a struct_ops with a link Kui-Feng Lee
2023-03-08  1:07   ` Andrii Nakryiko
2023-03-08  4:23     ` Kui-Feng Lee [this message]
2023-03-07 23:33 ` [PATCH bpf-next v4 9/9] selftests/bpf: Test switching TCP Congestion Control algorithms Kui-Feng Lee
2023-03-08  1:10   ` Andrii Nakryiko
2023-03-08 15:58     ` Kui-Feng Lee
2023-03-08 17:18       ` Andrii Nakryiko
2023-03-08 18:10         ` Kui-Feng Lee
2023-03-08 18:43           ` Andrii Nakryiko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7425b219-4b47-c3f1-844d-61e27d03af03@gmail.com \
    --to=sinquersw@gmail.com \
    --cc=andrii.nakryiko@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=kernel-team@meta.com \
    --cc=kuifeng@meta.com \
    --cc=martin.lau@linux.dev \
    --cc=sdf@google.com \
    --cc=song@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox