-
Notifications
You must be signed in to change notification settings - Fork 287
Add support for extensible maps. #4869
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
base: main
Are you sure you want to change the base?
Changes from all commits
3bfc155
912cc62
b26ae77
9b408d1
a45ac14
14bd9bb
0cf4579
8baea8c
3a76764
9211235
4a275a9
9b92684
91886cd
6924483
3756d5b
5ac337a
c0c7cf8
ea1b288
8ac47a5
ea3afd6
248683e
17fa874
98e8c73
23786d2
7a0caa1
2b09b19
0c0273e
053dba6
5b97b69
01b9fdc
2396181
5e26bdb
a66d544
b5d316c
834ab3d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,8 +1,8 @@ | ||||||
| # eBPF extensions | ||||||
|
|
||||||
| ## 1 Overview | ||||||
| An "eBPF extension" is a Windows kernel driver or component that implements eBPF hooks or helper functions. The design | ||||||
| of eBPF for Windows is such that an extension providing an implementation for hooks and helper functions can be | ||||||
| An "eBPF extension" is a Windows kernel driver or component that implements eBPF hooks, helper functions and extensible maps. The design | ||||||
| of eBPF for Windows is such that an extension providing an implementation for hooks, helper functions and maps can be | ||||||
| developed and deployed without the need to modify either the eBPF execution context or the eBPF verifier. | ||||||
|
|
||||||
| ## 1.1 Windows Network Module Registrar | ||||||
|
|
@@ -24,9 +24,10 @@ and the various aspects of developing NMR modules as described in | |||||
| [NMR documentation](https://docs.microsoft.com/en-us/windows-hardware/drivers/network/network-module-registrar2). | ||||||
|
|
||||||
| ## 1.3 NPI Contracts for eBPF Extensions | ||||||
| eBPF Extensions need to implement *provider modules* for two types of NPIs. They are the **Program Information NPI** | ||||||
| provider and the **Hook NPI** provider. The following section explains when an extension must implement these | ||||||
| providers. | ||||||
| eBPF Extensions need to implement *provider modules* for three types of NPIs. They are the **Program Information NPI** | ||||||
| provider, **Hook NPI** provider and **Map Information NPI**. | ||||||
| **Map Information NPI** is optional and only needs to be implemented if an extension want to add support for a | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
grammar |
||||||
| program type specific map. The following section explains when an extension must implement these providers. | ||||||
|
|
||||||
| ### 1.3.1 eBPF Program Information NPI Provider | ||||||
| The eBPF Program Information NPI contract is used to provide information about an eBPF program type. Program types | ||||||
|
|
@@ -44,12 +45,19 @@ several attach types. The eBPF extension must register a separate Hook NPI provi | |||||
| supports for an eBPF hook. Note that, there can be more than one attach types for a given program type. If an extension | ||||||
| is adding a new attach type for an existing program type, then it only needs to implement the Hook NPI Provider. | ||||||
|
|
||||||
| ### 1.3.3 eBPF Map Information NPI Provider | ||||||
| The Map Info NPI contract is used by extension to provide an implementation for a map type that is not already | ||||||
| implemented by the eBPF runtime. An example for this can be *BPF_MAP_TYPE_XSKMAP*. The eBPF extension must register | ||||||
| a separate Map Info NPI provider module for each map type it implements. | ||||||
|
|
||||||
| ## 2 Authoring an eBPF Extension | ||||||
| The steps for authoring an eBPF extension are: | ||||||
| 1. Register the NPI provider. | ||||||
| 2. Author any program type specific Helper Functions. | ||||||
| 3. Author any extensible maps. | ||||||
| 3. Invoke eBPF programs from hook(s). | ||||||
| 4. Register program and attach types. | ||||||
| 5. Register extensible map types, if any. | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As before, should this say "program type specific map types" rather than "extensible map types"? |
||||||
|
|
||||||
| The following sections describe these steps in detail. | ||||||
|
|
||||||
|
|
@@ -571,7 +579,95 @@ of time a batch is open and must not change IRQL between calling batch begin and | |||||
| the number of times the program has been invoked, so callers should limit the number of calls within a batch to | ||||||
| prevent long delays in batch end. | ||||||
|
|
||||||
| ### 2.7 Authoring Helper Functions | ||||||
| ### 2.7 Map Information NPI Provider Registration | ||||||
| When registering itself to the NMR, the Map Info NPI provider should have the | ||||||
| [`NPI_REGISTRATION_INSTANCE`](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/netioddk/ns-netioddk-_npi_registration_instance) | ||||||
| initialized as follows: | ||||||
| * `NpiId`: This should be set to `EBPF_MAP_INFO_EXTENSION_IID` defined in `ebpf_extension_uuids.h`. | ||||||
| * `ModuleId`: This can be set to any provider chosen GUID. | ||||||
| * `NpiSpecificCharacteristics`: Pointer to structure of type `ebpf_map_provider_data_t`. | ||||||
|
|
||||||
| typedef struct _ebpf_map_provider_data | ||||||
| { | ||||||
| ebpf_extension_header_t header; | ||||||
| size_t supported_map_type_count; // Number of supported map types | ||||||
| _Field_size_(supported_map_type_count) const uint32_t* supported_map_types; // Array of supported map types | ||||||
| ebpf_map_provider_dispatch_table_t* dispatch_table; | ||||||
| } ebpf_map_provider_data_t; | ||||||
|
|
||||||
| #### `ebpf_map_provider_data_t` Struct | ||||||
| This structure is used to specify all the extensible map types that the extension supports. It contains the following fields: | ||||||
| * `supported_map_type_count` | ||||||
| * `supported_map_types` | ||||||
| * `dispatch_table` | ||||||
|
|
||||||
| The `supported_map_type_count` field contains the number of extensible maps that the extension supports. | ||||||
| The `supported_map_types` is a pointer to an array containing the map types of the extensible maps that the extension supports. | ||||||
| The `dispatch_table` is a pointer to the provider dispatch table that the extension provides for operations on the supported maps. | ||||||
|
|
||||||
| #### Map ID | ||||||
| eBPF-for-Windows runtime supports some global map types. eBPF-for-Windows has reserved the map IDs 1 to 4095 (BPF_MAP_TYPE_MAX) for the global map types implemented in eBPF Core. Extensions need to use a map ID > BPF_MAP_TYPE_MAX for any extensible map they implement. | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Also I think "Map ID" is the wrong term, since that's the ID for a specific map instance. I think you mean Map Type ID. |
||||||
|
|
||||||
| Note: Though this is not required, extensions *can* register their map types by creating a pull request to eBPF-for-Windows | ||||||
| repo and updating `ebpf_map_type_t` enum in ebpf_structs.h. This helps in any map type collision with another extension. | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| #### `ebpf_map_provider_dispatch_table_t` Struct | ||||||
| ``` | ||||||
| typedef struct _ebpf_map_provider_dispatch_table | ||||||
| { | ||||||
| ebpf_extension_header_t header; | ||||||
| _Notnull_ ebpf_map_create_t create_map_function; | ||||||
| _Notnull_ ebpf_map_delete_t delete_map_function; | ||||||
| _Notnull_ ebpf_map_associate_program_type_t associate_program_function; | ||||||
| ebpf_map_find_element_t find_element_function; | ||||||
| ebpf_map_update_element_t update_element_function; | ||||||
| ebpf_map_delete_element_t delete_element_function; | ||||||
| ebpf_map_get_next_key_and_value_t get_next_key_and_value_function; | ||||||
| } ebpf_map_provider_dispatch_table_t; | ||||||
| ``` | ||||||
| This the dispatch table that the extension needs to implement and provide to eBPF runtime. It contains the following fields: | ||||||
| 1. `create_map_function` - Called by eBPF runtime to create the map. | ||||||
| 2. `delete_map_function` - Called by eBPF runtime to delete the map. | ||||||
| 3. `associate_program_function` - Called by eBPF runtime to validate if a specific map can be associated with the supplied program type. eBPFCore invokes this function before an extensible map is associated with a program. | ||||||
| 4. `find_element_function` - Function to find an entry. | ||||||
| 5. `update_element_function` - Function to update an entry. | ||||||
| 5. `delete_element_function` - Function to delete an entry. | ||||||
| 6. `get_next_key_and_value_function` - Function to get the next key and value. | ||||||
|
|
||||||
| When `create_map_function` is invoked, the extension will allocate a map, and return a pointer to it (called `map_context`) back to the eBPF runtime. When any of the APIs are invoked for this map, the extension will get this `map_context` back as an input parameter. | ||||||
|
|
||||||
| #### `ebpf_map_client_data_t` Struct | ||||||
| `ebpf_map_client_data_t` is the client data that is provided by eBPFCore to the extension when it attaches to the NMR provider. It is defined as below: | ||||||
|
|
||||||
| ``` | ||||||
| typedef struct _ebpf_map_client_data | ||||||
| { | ||||||
| ebpf_extension_header_t header; ///< Standard extension header containing version and size information. | ||||||
| uint64_t map_context_offset; ///< Offset within the map structure where the provider context data is stored. | ||||||
| ebpf_map_client_dispatch_table_t* dispatch_table; ///< Pointer to client dispatch table. | ||||||
| } ebpf_map_client_data_t; | ||||||
| ``` | ||||||
|
|
||||||
| `map_context_offset` is provided by eBPFCore to the extension to get to the extension specific map context when the | ||||||
| extensible map is being used in a helper function. This value is constant for all the bindings from eBPFCore to the | ||||||
| extension for all extensible map types and instances. | ||||||
|
|
||||||
| `dispatch_table` is the client dispatch table provided by eBPFCore to the extension. It is defined as below: | ||||||
| ``` | ||||||
| typedef struct _ebpf_map_client_dispatch_table | ||||||
| { | ||||||
| ebpf_extension_header_t header; | ||||||
| epoch_allocate_with_tag_t epoch_allocate_with_tag; | ||||||
| epoch_allocate_cache_aligned_with_tag_t epoch_allocate_cache_aligned_with_tag; | ||||||
| epoch_free_t epoch_free; | ||||||
| epoch_free_cache_aligned_t epoch_free_cache_aligned; | ||||||
| } ebpf_map_client_dispatch_table_t; | ||||||
| ``` | ||||||
| The client dispatch table provides *epoch based memory management* APIs that extension can use for allocating | ||||||
| memory when implementing extensible maps. | ||||||
| See [Epoch based memory management](https://github.com/microsoft/ebpf-for-windows/blob/main/docs/EpochBasedMemoryManagement.md) for more details on this topic. | ||||||
|
|
||||||
| ### 2.8 Authoring Helper Functions | ||||||
| An extension can provide an implementation of helper functions that can be invoked by the eBPF programs. The helper | ||||||
| functions can be of two types: | ||||||
| 1. Program-Type specific: These helper functions can only be invoked by eBPF programs of a given program type. Usually, | ||||||
|
|
@@ -597,7 +693,15 @@ The helper function ID for a general helper function must be in the range 0 - 65 | |||||
| The parameter and return types for these helper functions must adhere to the `ebpf_argument_type_t` and | ||||||
| `ebpf_return_type_t` enums. | ||||||
|
|
||||||
| ### 2.8 Registering Program Types and Attach Types - eBPF Store | ||||||
| ### 2.9 Helper functions that use extensible maps. | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| If the extension is implementing a helper function that takes an extensible map as input, when the helper function is | ||||||
| invoked, it will **not** get the map context that it had passed earlier to eBPFCore. It will instead get a pointer to | ||||||
| a separate map structure that eBPFCore maintains. Using this pointer, and the `map_context_offset` provided in the | ||||||
| `map_client_data`, extensions will need to get their map context. `MAP_CONTEXT()` macro is provied in `ebpf_extensions.h` | ||||||
| for extensions to get their map context. Extensions should validate that the map context they got back is NULL or not, | ||||||
| and handle it appropriately. | ||||||
|
|
||||||
| ### 2.9 Registering Program Types and Attach Types - eBPF Store | ||||||
| The eBPF execution context loads an eBPF program from an ELF file that has program section(s) with section names. The | ||||||
| prefix to these names determines the program type. For example, the section name `"xdp"` implies that the corresponding | ||||||
| program type is `BPF_PROG_TYPE_XDP`. | ||||||
|
|
@@ -622,9 +726,10 @@ To operate on the eBPF store, the user mode application needs to link with eBPFA | |||||
| _In_reads_(program_info_count) const ebpf_program_info_t* program_info, uint32_t program_info_count); | ||||||
| ``` | ||||||
|
|
||||||
| ### 2.9 eBPF Sample Driver | ||||||
| ### 2.10 eBPF Sample Driver | ||||||
| The eBPF for Windows project provides a | ||||||
| [sample extension driver](https://github.com/microsoft/ebpf-for-windows/tree/8f46b4020f79c32f994d3a59671ce8782e4b4cf0/tests/sample/ext) | ||||||
| as an example for how to implement an extension. This simple extension exposes a new program type, and implements a | ||||||
| hook for it with a single attach type. It implements simple NPI provider modules for the two NPIs. It also implements | ||||||
| three program-type specific helper functions. | ||||||
| The extension also implements two extensible maps, and implements a provider module for the two maps that it implements. | ||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -6,6 +6,9 @@ | |||||
| #include "ebpf_structs.h" | ||||||
| #include "ebpf_windows.h" | ||||||
|
|
||||||
| #define EBPF_MAP_FLAG_HELPER 0x01 /* Called by an eBPF program. */ | ||||||
| #define EBPF_MAP_FIND_FLAG_DELETE 0x02 /* Perform a find and delete. */ | ||||||
|
|
||||||
| typedef ebpf_result_t (*_ebpf_extension_dispatch_function)(); | ||||||
|
|
||||||
| typedef struct _ebpf_extension_dispatch_table | ||||||
|
|
@@ -130,3 +133,201 @@ typedef struct _ebpf_execution_context_state | |||||
|
|
||||||
| #define EBPF_CONTEXT_HEADER uint64_t context_header[8] | ||||||
| #define EBPF_CONTEXT_HEADER_SIZE (sizeof(uint64_t) * 8) | ||||||
|
|
||||||
| /** | ||||||
| * @brief Create an eBPF map. | ||||||
| * | ||||||
| * @param[in] map_type The type of map to create. | ||||||
| * @param[in] key_size The size of the key in bytes. | ||||||
| * @param[in] value_size The size of the value in bytes. | ||||||
| * @param[in] max_entries The maximum number of entries in the map. | ||||||
| * @param[out] map_context The created map context. | ||||||
| * | ||||||
| * @retval EBPF_SUCCESS The operation was successful. | ||||||
| * @retval EBPF_NO_MEMORY Unable to allocate memory. | ||||||
| * @retval EBPF_INVALID_ARGUMENT One or more parameters are incorrect. | ||||||
| */ | ||||||
| typedef ebpf_result_t (*ebpf_map_create_t)( | ||||||
| _In_ void* binding_context, | ||||||
| uint32_t map_type, | ||||||
| uint32_t key_size, | ||||||
| uint32_t value_size, | ||||||
| uint32_t max_entries, | ||||||
| _Outptr_ void** map_context); | ||||||
|
|
||||||
| /** | ||||||
| * @brief Delete an eBPF map. | ||||||
| * | ||||||
| * @param[in] map_context The map context to delete. | ||||||
| */ | ||||||
| typedef void (*ebpf_map_delete_t)(_In_ _Post_invalid_ void* map_context); | ||||||
|
|
||||||
| /** | ||||||
| * @brief Find an element in the eBPF map. | ||||||
| * | ||||||
| * @param[in] map The eBPF map to search. | ||||||
| * @param[in] key_size The size of the key in bytes. Set to 0 in case of a helper function call. | ||||||
| * @param[in] key Optionally, the key to search for. | ||||||
| * @param[in] value_size The size of the value in bytes. Set to 0 in case of a helper function call. | ||||||
| * @param[out] value Pointer to the value associated with the key. | ||||||
| * @param[in] flags Find flags. | ||||||
| * | ||||||
| * @retval EBPF_SUCCESS The operation was successful. | ||||||
| * @retval EBPF_OBJECT_NOT_FOUND The key was not found in the map. | ||||||
| */ | ||||||
| typedef ebpf_result_t (*ebpf_map_find_element_t)( | ||||||
| _In_ void* map, | ||||||
| size_t key_size, | ||||||
| _In_reads_opt_(key_size) const uint8_t* key, | ||||||
| _Outptr_ uint8_t** value, | ||||||
| uint32_t flags); | ||||||
|
|
||||||
| /** | ||||||
| * @brief Update an element in the eBPF map. | ||||||
| * | ||||||
| * @param[in] map The eBPF map to update. | ||||||
| * @param[in] key_size The size of the key in bytes. Set to 0 in case of a helper function call. | ||||||
| * @param[in] key Optionally, the key to update. | ||||||
| * @param[in] value_size The size of the value in bytes. Set to 0 in case of a helper function call. | ||||||
| * @param[in] value Optionally, the value to associate with the key. | ||||||
| * @param[in] option Update option. | ||||||
| * @param[in] flags Update flags. | ||||||
| * | ||||||
| * @retval EBPF_SUCCESS The operation was successful. | ||||||
| * @retval EBPF_OBJECT_NOT_FOUND The key was not found in the map. | ||||||
| * @retval EBPF_INVALID_ARGUMENT One or more parameters are incorrect. | ||||||
| * @retval EBPF_NO_MEMORY Unable to allocate memory. | ||||||
| */ | ||||||
| typedef ebpf_result_t (*ebpf_map_update_element_t)( | ||||||
| _In_ void* map, | ||||||
| size_t key_size, | ||||||
| _In_reads_opt_(key_size) const uint8_t* key, | ||||||
| size_t value_size, | ||||||
| _In_reads_opt_(value_size) const uint8_t* value, | ||||||
| ebpf_map_option_t option, | ||||||
| uint32_t flags); | ||||||
|
|
||||||
| /** | ||||||
| * @brief Delete an element from the eBPF map. | ||||||
| * @param[in] map The eBPF map to delete from. | ||||||
| * @param[in] key_size The size of the key in bytes. Set to 0 in case of a helper function call. | ||||||
| * @param[in] key Optionally, the key to delete. If the key is not found, the map is unchanged. If the key is found, the | ||||||
| * associated value is deleted. | ||||||
| * @param[in] flags Delete flags. | ||||||
| * @retval EBPF_SUCCESS The operation was successful. | ||||||
| * @retval EBPF_OBJECT_NOT_FOUND The key was not found in the map. | ||||||
| * @retval EBPF_INVALID_ARGUMENT One or more parameters are incorrect. | ||||||
| * @retval EBPF_NO_MEMORY Unable to allocate memory. | ||||||
| */ | ||||||
| typedef ebpf_result_t (*ebpf_map_delete_element_t)( | ||||||
| _In_ void* map, size_t key_size, _In_reads_opt_(key_size) const uint8_t* key, uint32_t flags); | ||||||
|
|
||||||
| /** | ||||||
| * @brief Get the next key and value in the eBPF map. | ||||||
| * | ||||||
| * @param[in] map The eBPF map to query. | ||||||
| * @param[in] previous_key The previous key. If NULL, get the first key. | ||||||
| * @param[out] next_key The next key in the map. | ||||||
| * | ||||||
| * @retval EBPF_SUCCESS The operation was successful. | ||||||
| * @retval EBPF_OBJECT_NOT_FOUND No more keys in the map. | ||||||
| * @retval EBPF_INVALID_ARGUMENT One or more parameters are incorrect. | ||||||
| */ | ||||||
| typedef ebpf_result_t (*ebpf_map_get_next_key_and_value_t)( | ||||||
| _In_ void* map, | ||||||
| size_t key_size, | ||||||
| _In_reads_opt_(key_size) const uint8_t* previous_key, | ||||||
| _Out_writes_(key_size) uint8_t* next_key, | ||||||
| _Outptr_opt_ uint8_t** next_value); | ||||||
|
|
||||||
| /** | ||||||
| * @brief Get the next key in the eBPF map. | ||||||
| * | ||||||
| * @param[in] map The eBPF map to query. | ||||||
| * @param[in] program_type The program type. | ||||||
| * | ||||||
| * @retval EBPF_SUCCESS The operation was successful. | ||||||
| * @retval EBPF_OPERATION_NOT_SUPPORTED The operation is not supported. | ||||||
| */ | ||||||
| typedef ebpf_result_t (*ebpf_map_associate_program_type_t)( | ||||||
| _In_ void* map, _In_ const ebpf_program_type_t* program_type); | ||||||
|
|
||||||
| /** | ||||||
| * Dispatch table implemented by the eBPF extension to provide map operations. | ||||||
| * This table is used to provide map operations to the eBPF core. | ||||||
| */ | ||||||
| typedef struct _ebpf_map_provider_dispatch_table | ||||||
| { | ||||||
| ebpf_extension_header_t header; | ||||||
| _Notnull_ ebpf_map_create_t create_map_function; | ||||||
| _Notnull_ ebpf_map_delete_t delete_map_function; | ||||||
| _Notnull_ ebpf_map_associate_program_type_t associate_program_function; | ||||||
| ebpf_map_find_element_t find_element_function; | ||||||
| ebpf_map_update_element_t update_element_function; | ||||||
| ebpf_map_delete_element_t delete_element_function; | ||||||
| ebpf_map_get_next_key_and_value_t get_next_key_and_value_function; | ||||||
| } ebpf_map_provider_dispatch_table_t; | ||||||
|
|
||||||
| /** | ||||||
| * @brief Allocate memory under epoch control. | ||||||
| * @param[in] size Size of memory to allocate | ||||||
| * @param[in] tag Pool tag to use. | ||||||
| * @returns Pointer to memory block allocated, or null on failure. | ||||||
| */ | ||||||
| typedef _Ret_writes_maybenull_(size) void* (*epoch_allocate_with_tag_t)(size_t size, uint32_t tag); | ||||||
|
|
||||||
| /** | ||||||
| * @brief Allocate cache aligned memory under epoch control. | ||||||
| * @param[in] size Size of memory to allocate | ||||||
| * @param[in] tag Pool tag to use. | ||||||
| * @returns Pointer to memory block allocated, or null on failure. | ||||||
| */ | ||||||
| typedef _Ret_writes_maybenull_(size) void* (*epoch_allocate_cache_aligned_with_tag_t)(size_t size, uint32_t tag); | ||||||
|
|
||||||
| /** | ||||||
| * @brief Free memory under epoch control. | ||||||
| * @param[in] memory Allocation to be freed once epoch ends. | ||||||
| */ | ||||||
| typedef void (*epoch_free_t)(_In_opt_ void* memory); | ||||||
|
|
||||||
| /** | ||||||
| * @brief Free memory under epoch control. | ||||||
| * @param[in] memory Allocation to be freed once epoch ends. | ||||||
| */ | ||||||
| typedef void (*epoch_free_cache_aligned_t)(_In_opt_ void* pointer); | ||||||
|
|
||||||
| typedef ebpf_result_t (*ebpf_get_map_context_t)(_In_ const void* map, _Outptr_ void** map_context); | ||||||
|
|
||||||
| /** | ||||||
| * Dispatch table implemented by the eBPF runtime to provide RCU / epoch operations. | ||||||
| */ | ||||||
| typedef struct _ebpf_map_client_dispatch_table | ||||||
| { | ||||||
| ebpf_extension_header_t header; | ||||||
| epoch_allocate_with_tag_t epoch_allocate_with_tag; | ||||||
| epoch_allocate_cache_aligned_with_tag_t epoch_allocate_cache_aligned_with_tag; | ||||||
| epoch_free_t epoch_free; | ||||||
| epoch_free_cache_aligned_t epoch_free_cache_aligned; | ||||||
| } ebpf_map_client_dispatch_table_t; | ||||||
|
|
||||||
| /** | ||||||
| * @brief Extensible map provider data. | ||||||
| */ | ||||||
| typedef struct _ebpf_map_provider_data | ||||||
| { | ||||||
| ebpf_extension_header_t header; | ||||||
| uint32_t map_type; // Extensible map type implemented by the provider. | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| ebpf_map_provider_dispatch_table_t* dispatch_table; | ||||||
| } ebpf_map_provider_data_t; | ||||||
|
|
||||||
| /** | ||||||
| * @brief Extensible map client data. | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Update to match PR #4882 |
||||||
| */ | ||||||
| typedef struct _ebpf_map_client_data | ||||||
| { | ||||||
| ebpf_extension_header_t header; ///< Standard extension header containing version and size information. | ||||||
| uint64_t map_context_offset; ///< Offset within the map structure where the provider context data is stored. | ||||||
| ebpf_map_client_dispatch_table_t* dispatch_table; ///< Pointer to client dispatch table. | ||||||
| } ebpf_map_client_data_t; | ||||||
|
|
||||||
| #define MAP_CONTEXT(map_pointer, offset) ((void**)(((uint8_t*)(map_pointer)) + (offset))) | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To verify: So an extension can implement an extensible map but it cannot implement a non-extensible map? I'll observe that this document never defines the term "extensible map", so either define it or remove that term entirely. Line 30 says "program type specific map", should this line use that language?