Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support context extensions #495

Merged
merged 1 commit into from
Mar 5, 2025
Merged

Conversation

amorenoz
Copy link
Contributor

@amorenoz amorenoz commented Feb 17, 2025

The retis context contains enough information to access common types such as the sk_buff pointer.

Sometimes this information cannot be easily available through the probe's arguments. In such cases, the context needs to be dynamically extended.

Well known types to sk_buff indirection can be implemented in the core so that it can be used in generic probes. However, this might be insufficient for some specific probes, for which a freplaced hook is available.

Note the hook is currently unused, the first user will be #493

@amorenoz amorenoz added the run-functional-tests Request functional tests to be run by CI label Feb 17, 2025
@amorenoz amorenoz force-pushed the idea_ctx_hook branch 2 times, most recently from 51184a3 to 3f4b1cc Compare February 17, 2025 20:47
@amorenoz amorenoz mentioned this pull request Feb 17, 2025
@amorenoz amorenoz changed the title core: add ctx_hooks RFC core: add ctx_hooks Feb 17, 2025
@atenart
Copy link
Contributor

atenart commented Feb 19, 2025

I find this quite clever and nice for many reasons! But I have some concerns:

  1. This changes the current behavior of supporting getting (and tracking) skbs from any struct nft_traceinfo * or struct nft_pktinfo * enabled function. Now only the targeted probe installed by the nft collector will access that indirect skb (e.g. retis collect -c skb,skb-tracking -p some_nft_function won't work anymore). IMO this is a key feature we want to keep (and extend): indirect accesses.
  2. In addition this makes the retrieval of getting such skbs depending on the nft collector being enabled.
  3. It makes things a bit scattered: the logic to get the above parameter offsets is in the core while it is (and will be) only
    used by the nft collector now.

Point 2 could be worked out by letting collectors install context hook even if not enabled (there's a slight subtility to get right wrt. the compatibility check collectors make — e.g. not loading the context probe in case the nft collector isn't explicitly enabled and the nft module isn't built-in or loaded).

Point 3 can be easily improved by moving the logic to be inside the collectors. This even raises the question to extend this to all types and let the collectors provide type offsets themselves (extending the logic added here wrt. the getters Retis provides).

Point 1 is more tricky. Context hooks should be added to the right list of probes (user defined, collector defined and core defined). Also multiple collectors could add a context hook to the same probe. I don't really see a problem with the later (a collector operates on his own types). For the former, maybe context hooks should be added to all probes. Or collectors should be able to inspect all probes after all are initialized?

Another way of seeing this would be context hooks are a nice addition for providing a way to do a really specialized thing that only applies to a specific probe; but that doesn't apply to indirect accesses of well known types and here for the nft example.

@amorenoz
Copy link
Contributor Author

I find this quite clever and nice for many reasons! But I have some concerns:

1. This changes the current behavior of supporting getting (and tracking) skbs from any  `struct nft_traceinfo *` or `struct nft_pktinfo *` enabled function. Now only the targeted probe installed by the `nft` collector will access that indirect skb (e.g. `retis collect -c skb,skb-tracking -p some_nft_function` won't work anymore). IMO this is a key feature we want to keep (and extend): indirect accesses.

Maybe we could have some built-in ctx "hooks" (they would not be hooks anymore) and them a way to freplace a custom one for collector-driven probes?

2. In addition this makes the retrieval of getting such skbs depending on the `nft` collector being enabled.

Probes with nft_pktinfo as an argument are exclusively in the netfilter subsystem.
I really don't see whey anyone would probe that module without enabling the nft collector.

3. It makes things a bit scattered: the logic to get the above parameter offsets is in the core while it is (and will be) only
   used by the nft collector now.

But it's not in the core anymore, is it? It lives in the nft collector.

Point 2 could be worked out by letting collectors install context hook even if not enabled (there's a slight subtility to get right wrt. the compatibility check collectors make — e.g. not loading the context probe in case the nft collector isn't explicitly enabled and the nft module isn't built-in or loaded).

Point 3 can be easily improved by moving the logic to be inside the collectors. This even raises the question to extend this to all types and let the collectors provide type offsets themselves (extending the logic added here wrt. the getters Retis provides).

Point 1 is more tricky. Context hooks should be added to the right list of probes (user defined, collector defined and core defined). Also multiple collectors could add a context hook to the same probe. I don't really see a problem with the later (a collector operates on his own types). For the former, maybe context hooks should be added to all probes. Or collectors should be able to inspect all probes after all are initialized?

Another way of seeing this would be context hooks are a nice addition for providing a way to do a really specialized thing that only applies to a specific probe; but that doesn't apply to indirect accesses of well known types and here for the nft example.

I think I agree. As I suggested above, we could have a built-in indirect-based skb extraction logic (only outside of retis_get_sk_buff), plus a custom hook.

@atenart
Copy link
Contributor

atenart commented Feb 25, 2025

2. In addition this makes the retrieval of getting such skbs depending on the `nft` collector being enabled.

Probes with nft_pktinfo as an argument are exclusively in the netfilter subsystem. I really don't see whey anyone would probe that module without enabling the nft collector.

I think doing retis -c skb,ct -p an_nft_func is a valid use case, users don't always want to get the information about the nft actions but only about the state of the skb in there, or even only want to "see" the skb. In the general case I don't think we'd want a strong link between enabling a collector and getting indirect access to a field; that last part should be transparent.

3. It makes things a bit scattered: the logic to get the above parameter offsets is in the core while it is (and will be) only
   used by the nft collector now.

But it's not in the core anymore, is it? It lives in the nft collector.

The offsets are, in retis/src/core/probe/kernel/inspect.rs.

Another way of seeing this would be context hooks are a nice addition for providing a way to do a really specialized thing that only applies to a specific probe; but that doesn't apply to indirect accesses of well known types and here for the nft example.

I think I agree. As I suggested above, we could have a built-in indirect-based skb extraction logic (only outside of retis_get_sk_buff), plus a custom hook.

Maybe we could have some built-in ctx "hooks" (they would not be hooks anymore) and them a way to freplace a custom one for collector-driven probes?

I'm not sure to get the "only outside of retis_get_sk_buff" part.

Except that, if I think I agree. Let me rephrase to be sure: we would keep the indirect access logic for common objects in the core and add context hooks (on targeted probes only) for specialized handling (here providing access to an skb ojbect from a specific ovs probe so that retis_get_sk_buff is aware of it upon later calls)?

@amorenoz
Copy link
Contributor Author

2. In addition this makes the retrieval of getting such skbs depending on the `nft` collector being enabled.

Probes with nft_pktinfo as an argument are exclusively in the netfilter subsystem. I really don't see whey anyone would probe that module without enabling the nft collector.

I think doing retis -c skb,ct -p an_nft_func is a valid use case, users don't always want to get the information about the nft actions but only about the state of the skb in there, or even only want to "see" the skb. In the general case I don't think we'd want a strong link between enabling a collector and getting indirect access to a field; that last part should be transparent.

3. It makes things a bit scattered: the logic to get the above parameter offsets is in the core while it is (and will be) only
   used by the nft collector now.

But it's not in the core anymore, is it? It lives in the nft collector.

The offsets are, in retis/src/core/probe/kernel/inspect.rs.

Ok, now I get what you were referring to.

Another way of seeing this would be context hooks are a nice addition for providing a way to do a really specialized thing that only applies to a specific probe; but that doesn't apply to indirect accesses of well known types and here for the nft example.

I think I agree. As I suggested above, we could have a built-in indirect-based skb extraction logic (only outside of retis_get_sk_buff), plus a custom hook.

Maybe we could have some built-in ctx "hooks" (they would not be hooks anymore) and them a way to freplace a custom one for collector-driven probes?

I'm not sure to get the "only outside of retis_get_sk_buff" part.

What I mean is: remove the part of retis_get_sk_buff that currently looks on other arbitrary symbols and performs indirections. It is both unnecessary (no need to run that code multiple times) and confusing IMO (it's the only retis_get_TYPE that does this quirks). Instead, create infrastructure to explicitly update the context once and before filtering is performed and put the built-in ctx-enrichment indirections there. That same infrastructure also calls the ctx-hook if available.

Except that, if I think I agree. Let me rephrase to be sure: we would keep the indirect access logic for common objects in the core and add context hooks (on targeted probes only) for specialized handling (here providing access to an skb ojbect from a specific ovs probe so that retis_get_sk_buff is aware of it upon later calls)?

@atenart
Copy link
Contributor

atenart commented Feb 26, 2025

  1. It makes things a bit scattered: the logic to get the above parameter offsets is in the core while it is (and will be) only
    used by the nft collector now.

But it's not in the core anymore, is it? It lives in the nft collector.

The offsets are, in retis/src/core/probe/kernel/inspect.rs.

Ok, now I get what you were referring to.

Side note: I have a plan to make this completely generic; it's just low priority.

Another way of seeing this would be context hooks are a nice addition for providing a way to do a really specialized thing that only applies to a specific probe; but that doesn't apply to indirect accesses of well known types and here for the nft example.

I think I agree. As I suggested above, we could have a built-in indirect-based skb extraction logic (only outside of retis_get_sk_buff), plus a custom hook.

Maybe we could have some built-in ctx "hooks" (they would not be hooks anymore) and them a way to freplace a custom one for collector-driven probes?

I'm not sure to get the "only outside of retis_get_sk_buff" part.

What I mean is: remove the part of retis_get_sk_buff that currently looks on other arbitrary symbols and performs indirections. It is both unnecessary (no need to run that code multiple times) and confusing IMO (it's the only retis_get_TYPE that does this quirks). Instead, create infrastructure to explicitly update the context once and before filtering is performed and put the built-in ctx-enrichment indirections there. That same infrastructure also calls the ctx-hook if available.

So we would make:

  • retis_get_sk_buff return either the skb from the probe args or the one found in the indirection logic.
  • Make an indirection function, which could be extended on targeted probes.

Right?

That's fine IMO. I think (without having a look at the code) a clean way to handle indirections would be to add extra registers (after REG_MAX) in our existing context arguments and reuse the offsets in our context to point to those. The logic would be unified, and that would allow multi-arg support later (e.g. handling multiple skbs in the same probe).

@amorenoz
Copy link
Contributor Author

  1. It makes things a bit scattered: the logic to get the above parameter offsets is in the core while it is (and will be) only
    used by the nft collector now.

But it's not in the core anymore, is it? It lives in the nft collector.

The offsets are, in retis/src/core/probe/kernel/inspect.rs.

Ok, now I get what you were referring to.

Side note: I have a plan to make this completely generic; it's just low priority.

Another way of seeing this would be context hooks are a nice addition for providing a way to do a really specialized thing that only applies to a specific probe; but that doesn't apply to indirect accesses of well known types and here for the nft example.

I think I agree. As I suggested above, we could have a built-in indirect-based skb extraction logic (only outside of retis_get_sk_buff), plus a custom hook.

Maybe we could have some built-in ctx "hooks" (they would not be hooks anymore) and them a way to freplace a custom one for collector-driven probes?

I'm not sure to get the "only outside of retis_get_sk_buff" part.

What I mean is: remove the part of retis_get_sk_buff that currently looks on other arbitrary symbols and performs indirections. It is both unnecessary (no need to run that code multiple times) and confusing IMO (it's the only retis_get_TYPE that does this quirks). Instead, create infrastructure to explicitly update the context once and before filtering is performed and put the built-in ctx-enrichment indirections there. That same infrastructure also calls the ctx-hook if available.

So we would make:

* `retis_get_sk_buff` return either the skb from the probe args or the one found in the indirection logic.

* Make an indirection function, which could be extended on targeted probes.

Right?

Yes.

That's fine IMO. I think (without having a look at the code) a clean way to handle indirections would be to add extra registers (after REG_MAX) in our existing context arguments and reuse the offsets in our context to point to those. The logic would be unified, and that would allow multi-arg support later (e.g. handling multiple skbs in the same probe).

Yest, that's a nice idea. I'll give it a try

@amorenoz
Copy link
Contributor Author

Probes with nft_pktinfo as an argument are exclusively in the netfilter subsystem. I really don't see whey anyone would probe that module without enabling the nft collector.

I think doing retis -c skb,ct -p an_nft_func is a valid use case, users don't always want to get the information about the nft actions but only about the state of the skb in there, or even only want to "see" the skb. In the general case I don't think we'd want a strong link between enabling a collector and getting indirect access to a field; that last part should be transparent.

Note this does not work today.

@atenart
Copy link
Contributor

atenart commented Feb 26, 2025

Probes with nft_pktinfo as an argument are exclusively in the netfilter subsystem. I really don't see whey anyone would probe that module without enabling the nft collector.

I think doing retis -c skb,ct -p an_nft_func is a valid use case, users don't always want to get the information about the nft actions but only about the state of the skb in there, or even only want to "see" the skb. In the general case I don't think we'd want a strong link between enabling a collector and getting indirect access to a field; that last part should be transparent.

Note this does not work today.

Nice finding. We should probably extend the collector known args with known indirections. E.g. if a collector knows sk_buff, add the current skb indirections.

@amorenoz
Copy link
Contributor Author

Probes with nft_pktinfo as an argument are exclusively in the netfilter subsystem. I really don't see whey anyone would probe that module without enabling the nft collector.

I think doing retis -c skb,ct -p an_nft_func is a valid use case, users don't always want to get the information about the nft actions but only about the state of the skb in there, or even only want to "see" the skb. In the general case I don't think we'd want a strong link between enabling a collector and getting indirect access to a field; that last part should be transparent.

Note this does not work today.

Nice finding. We should probably extend the collector known args with known indirections. E.g. if a collector knows sk_buff, add the current skb indirections.

Even so, I think it would still not work given the current implementation of indirection. It is very much focused on __nft_trace_packet, i.e: it required struct nft_traceinfo to be present.

@atenart
Copy link
Contributor

atenart commented Feb 26, 2025

Probes with nft_pktinfo as an argument are exclusively in the netfilter subsystem. I really don't see whey anyone would probe that module without enabling the nft collector.

I think doing retis -c skb,ct -p an_nft_func is a valid use case, users don't always want to get the information about the nft actions but only about the state of the skb in there, or even only want to "see" the skb. In the general case I don't think we'd want a strong link between enabling a collector and getting indirect access to a field; that last part should be transparent.

Note this does not work today.

Nice finding. We should probably extend the collector known args with known indirections. E.g. if a collector knows sk_buff, add the current skb indirections.

Even so, I think it would still not work given the current implementation of indirection. It is very much focused on __nft_trace_packet, i.e: it required struct nft_traceinfo to be present.

Right, this should be handled too; as part of another effort to add common indirections.

@vlrpl
Copy link
Contributor

vlrpl commented Feb 26, 2025

Probes with nft_pktinfo as an argument are exclusively in the netfilter subsystem. I really don't see whey anyone would probe that module without enabling the nft collector.

I think doing retis -c skb,ct -p an_nft_func is a valid use case, users don't always want to get the information about the nft actions but only about the state of the skb in there, or even only want to "see" the skb. In the general case I don't think we'd want a strong link between enabling a collector and getting indirect access to a field; that last part should be transparent.

Note this does not work today.

Nice finding. We should probably extend the collector known args with known indirections. E.g. if a collector knows sk_buff, add the current skb indirections.

Even so, I think it would still not work given the current implementation of indirection. It is very much focused on __nft_trace_packet, i.e: it required struct nft_traceinfo to be present.

Yes, it was, mostly because there was no plan/reason to support anything other than what was required to implement rule tracing.

@amorenoz amorenoz changed the title RFC core: add ctx_hooks Support context extensions Feb 28, 2025
@amorenoz amorenoz changed the title Support context extensions WIP: Support context extensions Feb 28, 2025
@amorenoz
Copy link
Contributor Author

The dynamic version of the context extension (ctx hooks) used in #493

Copy link
Contributor

@atenart atenart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks pretty good, I guess you can remove "WIP" from the PR title.

@atenart atenart added this to the v1.6 milestone Feb 28, 2025
@amorenoz amorenoz changed the title WIP: Support context extensions Support context extensions Mar 4, 2025
Ctx extensions allows extending the retis ctx in manual ways. For
example, by having a custom indirection logic to find the skb.

These extensions are run before filtering and are available to all
probes. However, collectors can implement their own logic to extend the
ctx via ctx_hooks.

Signed-off-by: Adrian Moreno <[email protected]>
Copy link
Contributor

@atenart atenart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@atenart atenart merged commit 3cab6a2 into retis-org:main Mar 5, 2025
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
run-functional-tests Request functional tests to be run by CI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants