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

Proposal for multiple load of native programs. #3566

Merged

Conversation

saxena-anurag
Copy link
Contributor

Description

This PR contains the proposal for implementing multiple load of native programs. The proposal captures the 2 options that were discussed in the triage meeting.

Testing

NA

Documentation

This PR adds documentation.

Installation

NA

docs/MultipleLoadNativeModule.md Outdated Show resolved Hide resolved
docs/MultipleLoadNativeModule.md Outdated Show resolved Hide resolved
docs/MultipleLoadNativeModule.md Show resolved Hide resolved
docs/MultipleLoadNativeModule.md Outdated Show resolved Hide resolved
1. Installer installs the service entry. We need to ensure the service name is unique. Two native modules with same name but in different locations should be installed as 2 different services. Installer also populates the client module ID registry key with a random GUID.
2. The app that loads the program will pass the service name to ebpfapi (TBD: How does app know the service name for its service). We can still use the existing `bpf_object__open` API, and the API can take the service name instead of file name as input.

**Note**: If we want to continue using existing APIs without any change, it causes a limitation that with this approach, **every user** of native module will need to implement the installer logic.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I didn't follow this sentence, can you elaborate? What is a "user" here?
The native module installer (setup.exe or whatever) needs to implement it. Calling apps don't, nor do their installers per se.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated to "application / product"

Copy link
Collaborator

@dthaler dthaler May 24, 2024

Choose a reason for hiding this comment

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

As I noted in my comment, this sentence doesn't make sense as worded. In option 2, calling apps don't implement the installer at all. Only the installer of the native module does. The native module and the application can come from two separate organizations and have different installers. One solution would be to just delete note 1.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have updated (re-written) that note. If it still looks incorrect, I can remove that point altogether.

1. Installer installs the service entry. We need to ensure the service name is unique. Two native modules with same
name but in different locations should be installed as 2 different services. Installer also populates the client module
ID registry key with a random GUID.
2. The app that loads the program will pass the service name to ebpfapi (TBD: How does app know the service name for its
Copy link
Collaborator

Choose a reason for hiding this comment

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

This TBD could be addressed the same way as in lines 32-40, based on passing the file name in option 2.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed this TBD

Comment on lines 104 to 105
1. One limitation with option 2 is that all existing applications that are using native eBPF programs need to now
also have an explicit installer / un-installer for the native programs that are they are using. This installer can
Copy link
Collaborator

@dthaler dthaler May 24, 2024

Choose a reason for hiding this comment

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

I disagree with this sentence. My feedback on option 2 was that the applications using the native program do NOT install the native program. They only load it after it was installed by the same mechanism that got the native program on the machine in the first place. E.g. that could be L3AFD or a script or whatever else. It's also possible that the installer of the app and the installer of the native program are the same program, but they're logically two separate things which is why this sentence makes no sense to me. An app installer can have a dependency on another components installer, just like multiple programs depend on say the .NET Framework being installed first, but that doesn't mean that multiple programs' installers all know the details of how to install the .NET Framework. That's not how it works.

Copy link
Contributor Author

@saxena-anurag saxena-anurag May 24, 2024

Choose a reason for hiding this comment

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

I will update it to reflect the point that installer and app are different, and the installer can install both the app and the native programs.

Had one question regarding the end-to-end workflow if we go with option 2. Does the below workflow look sufficient to satisfy all our requirements?

  1. An installer installs the eBPF program on the machine. It can use a new ebpfapi API (e.g. ebpf_get_service_name_from_file_name()) to generate the service name from the file name with path.
  2. When an app wants to load an eBPF program, it will provide the file name (with absolute or relative path) to bpf_object__open(). ebpfapi.dll will use the same API as above to internally generate the same service name.
  3. In the load step, ebpfapi.dll checks if the corresponding service is present -- if present, it will proceed with the load of program, else it will fail the load call.
  4. In the case a program is shared between multiple apps / products, common installation will need to be managed by the products that are using the shared eBPF program and is outside the scope of eBPF framework.
  5. With the above approach of providing an API to consistently generate a service name for a file name, there is no need for any central database in eBPF that stores "file name --> service name" mapping. Existing _open() / _load() APIs will still take file name as input, and ebpfapi can regenerate the corresponding service name when needed.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes that all looks right to me. I think the main advantage of option 1 over option 2 (as you pointed out to me in chat) is that option 1 doesn't require any custom install steps, just a simple file copy, whereas option 2 requires the native driver installer to also create the service. So as is, L3AFD for instance would work with option 1 but L3AFD would require changes for option 2. Feel free to call out this advantage since you thought it was important and I agreed that's a good thing.

Copy link
Contributor Author

@saxena-anurag saxena-anurag May 29, 2024

Choose a reason for hiding this comment

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

@Alan-Jowett as per today's discussion in the triage meeting, for option 2, if the proposal is that ebpfapi exposes APIs for installers that helps install / uninstall the drivers, does it become similar to the approach in the below draft PR that adds 2 new APIs ebpf_initialize_native_program_state() and ebpf_uninitialize_native_program_state() for creating / deleting the service?

#3556

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated doc with what was discussed in the triage meeting.

either be a separate entity (in the cases where the native eBPF program is a common program shared between multiple
applications / products), or it can be integrated with the application that loads the program (in the cases where the
native eBPF program is exclusively owned by that application / product).
2. Since this approach requires multiple components to generate the service name for the sys file, one option can be to
Copy link
Collaborator

Choose a reason for hiding this comment

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

I disagree with this sentence too as noted in my comment on line 99. How the service name can be generated based on the file path is completely orthogonal to whether to use option 1 or option 2.

docs/MultipleLoadNativeModule.md Outdated Show resolved Hide resolved
docs/MultipleLoadNativeModule.md Outdated Show resolved Hide resolved
Co-authored-by: Dave Thaler <dthaler1968@gmail.com>
@Alan-Jowett Alan-Jowett enabled auto-merge June 17, 2024 21:05
@mtfriesen
Copy link
Collaborator

Adding a breadcrumb link to #2667.

@Alan-Jowett Alan-Jowett added this pull request to the merge queue Jun 18, 2024
Merged via the queue into microsoft:main with commit 5ad0297 Jun 18, 2024
84 of 86 checks passed
@saxena-anurag saxena-anurag deleted the user/anusa/proposal_for_multiple_load branch July 22, 2024 20:30
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.

4 participants