Skip to content

pkg/btf : Add some optimisation over the BTF resolution to reduce the amount of steps#4464

Draft
tdaudi wants to merge 7 commits intocilium:mainfrom
tdaudi:pr/tdaudi/optimize-resolve-algo
Draft

pkg/btf : Add some optimisation over the BTF resolution to reduce the amount of steps#4464
tdaudi wants to merge 7 commits intocilium:mainfrom
tdaudi:pr/tdaudi/optimize-resolve-algo

Conversation

@tdaudi
Copy link
Copy Markdown
Contributor

@tdaudi tdaudi commented Jan 2, 2026

This PR improve the ResolveBTFPath algorithm to reduce the amount of steps to reach data.

Before explaining what the PR did, let's recap how the original algo works

Lets take an example with the following resolve :

resolve: a.b.c
# In C, it will be *a->b.c to get the data

It will produce the following steps

[
   { IsInitialized: 1, IsPointer: 1, Offset: 20 },
   { IsInitialized: 1, IsPointer: 0, Offset: 23 },
   { IsInitialized: 1, IsPointer: 1, Offset: 100 }
]

There is one step that is not a pointer. This can be compacted with the next steps

This PR will take the above config as an input, and return as follow

[
   { IsInitialized: 1, IsPointer: 1, Offset: 20 },
   { IsInitialized: 1, IsPointer: 1, Offset: 123 }
]

One step is saved, so this mean we can push one more step in the BTFArg config without touching the BPF code.

This PR introduce some changes on top of the ResolveBTFPath to compact all the resolution steps to push as much elements as possible in the array.
If the user defines too many entries, it will produces an error only if there are no more space (aka no non-pointer entries) in the BTFArg array.

For better consitency, the resolveBTFPath wrapper should be placed along
with the main algorithm.

This commit does :
- moves the generic.resolveBTFPath in pkg/btf
- Rename the main function algo into private and put the wrapper into
  public.

Note: in `buildResolveBTFConfig`, we should never use the wrapper because
we want to have the very same behaviour as `buildManualBTFConfig` which
does not have the upper layer of the wrapper.

Signed-off-by: Tristan d'Audibert <tdaudibe@isovalent.com>
@netlify
Copy link
Copy Markdown

netlify Bot commented Jan 2, 2026

Deploy Preview for tetragon ready!

Name Link
🔨 Latest commit d066e1c
🔍 Latest deploy log https://app.netlify.com/projects/tetragon/deploys/6957fbcdd02b1900099a6b12
😎 Deploy Preview https://deploy-preview-4464--tetragon.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

tdaudi added 6 commits January 2, 2026 18:22
To be able to recall ResolveBTFPath from a specific index, we need to
keep track of the value of "i". Like this, when the path is resolved, we
can make the optimisation and restart at a specific index.

Signed-off-by: Tristan d'Audibert <tdaudibe@isovalent.com>
The `ResolveBTFPath` should be self-sufficient in term of limitation
validation.
Until now the function could have crashed if the given `pathToFound` was
longer than `api.MaxBTFArgDepth`.

Furthermore, introducing `ErrMaxBTFDepth`. This error is different than the
others because it's not directly related to BTF. So because of this
separate error, we can distinguish it from the others.

Signed-off-by: Tristan d'Audibert <tdaudibe@isovalent.com>
When an error fires, this will allow more control on the algorithm for
optimisation.

Signed-off-by: Tristan d'Audibert <tdaudibe@isovalent.com>
This commit does several things :
- When `member.Name == pathToFound[*i]`, add the Offset rather than
  overwriting it. This allows to increment the value with the previous
  one. This is important if we want to concatenate the values btfArg
  because the algorithm will go over already existing elements.
     - It will do `btfArg[*i] + 0` when the value has never been defined
     - It will do `btfArg[*i] + N` to concatenate the offset
- When anonymous struct/union is encounter, the algorithm do not need
  to update btfArg[*i] if `member.Name != pathToFound[*i]`. In the
  original code, this was overwritten so even though the code was
  useless, it was not possible to see that.
- Simplify and move isNotLastChild to the end of the function. This
  ensure the logic is applied for every cases.

This commit does not break the tests :

```bash
 $ go test -exec "sudo" ./pkg/sensors/tracing/ -run TestUprobeResolve
ok  	github.com/cilium/tetragon/pkg/sensors/tracing	0.065s
```

```bash
 $ go test -exec "sudo" ./pkg/btf/ -run TestResolveBTFPath
ok  	github.com/cilium/tetragon/pkg/btf	0.090s
```

Signed-off-by: Tristan d'Audibert <tdaudibe@isovalent.com>
Concatenate all non-ptr entries in the `btfArg` array to reduce the
amount of iterations needed and also allow more pointer resolution.

It always concatenate downwards, because the ptr dereference comes after
the offset calculation on the bpf side

For example, for the following input :
[
  { IsInitialized: 1, IsPointer: 1, Offset: 20 },
  { IsInitialized: 1, IsPointer: 0, Offset: 10 },
  { IsInitialized: 1, IsPointer: 0, Offset: 22 },
  { IsInitialized: 1, IsPointer: 1, Offset: 100 }
]

You will have the following output
[
  { IsInitialized: 1, IsPointer: 1, Offset: 20 },
  { IsInitialized: 1, IsPointer: 1, Offset: 132 }
]

Signed-off-by: Tristan d'Audibert <tdaudibe@isovalent.com>
The test try to resolve a longer path than api.MaxBTFArgDepth. Normally,
the test should fail as there is only one entry for every step. But
because we concatenated every non-ptr arguments, we can reach a deeper
path without changing the BPF logic.

In this test path, there are 12 logical steps but 10 only ptrs. So we can
concatenated by 2 which gives space for 2 more ptrs.

Signed-off-by: Tristan d'Audibert <tdaudibe@isovalent.com>
@tdaudi tdaudi force-pushed the pr/tdaudi/optimize-resolve-algo branch from d066e1c to b318a64 Compare January 2, 2026 17:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant