Skip to content

Commit

Permalink
extension_header
Browse files Browse the repository at this point in the history
  • Loading branch information
shankarseal committed Mar 8, 2024
1 parent f7bf6d0 commit dbac4a9
Show file tree
Hide file tree
Showing 41 changed files with 913 additions and 551 deletions.
33 changes: 25 additions & 8 deletions docs/eBpfExtensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,14 @@ initialized as follows:
* `NpiSpecificCharacteristics`: Pointer to structure of type `ebpf_extension_data_t`.
* The `data` field of this structure should point to a structure of type `ebpf_program_data_t`.

#### `ebpf_extension_header_t` Struct
This is a mandatory header that is common to all data structures needed by eBPF extensions to register with the eBPF framework.
* `version`: Version of the extension data structure.
* `size`: Size of the extension data structure.

#### `ebpf_program_data_t` Struct
The various fields of this structure should be set as follows:
* `header`: Version () and size.
* `program_info`: Pointer to `ebpf_program_info_t`.
* `program_type_specific_helper_function_addresses`: Pointer to `ebpf_helper_function_addresses_t`. This structure
provides the helper functions that are exclusive to this program type.
Expand All @@ -77,12 +83,14 @@ context structure and populates the returned data and context buffers.

#### `ebpf_program_info_t` Struct
The various fields of this structure should be set as follows:
* `program_type_descriptor`: Field of type `ebpf_program_type_descriptor_t`.
* `header`: Version and size.
* `program_type_descriptor`: Pointer to `ebpf_program_type_descriptor_t`.
* `count_of_helpers`: The number of helper functions that are implemented by this extension for the given program type.
* `helper_prototype`: Pointer to array of `ebpf_helper_function_prototype_t`.

#### `ebpf_program_type_descriptor_t` Struct
The various fields of this structure should be set as follows:
* `header`: Version and size.
* `name`: Friendly name of the program type.
* `context_descriptor`: Pointer of type `ebpf_context_descriptor_t`.
* `program_type`: GUID for the program type. This should be the same as the `NpiId` in `NPI_REGISTRATION_INSTANCE` as
Expand All @@ -94,6 +102,7 @@ field should be set to `0 (BPF_PROG_TYPE_UNSPEC)`.
#### `ebpf_context_descriptor_t` Struct
This structure (as the name signifies) provides a description of the context parameter that a hook passes when
invoking an eBPF program. The various fields of this struct are as follows.
* `header`: Version and size.
* `size`: Size of the context structure.
* `data`: Offset (in bytes) to the field in the context structure that is pointing to the beginning of context data.
* `end`: Offset (in bytes) to the field in the context structure that is pointing to the end of context data.
Expand Down Expand Up @@ -124,6 +133,7 @@ in the context descriptor.

#### `ebpf_helper_function_prototype_t` Struct
This structure is used to describe the prototypes of the various helper functions implemented by the extension.
* `header`: Version and size.
* `helper_id`: Integer signifying the helper function ID. (See section 2.6).
Helper function IDs for different program types need not be unique.
* `name`: Helper function name.
Expand Down Expand Up @@ -189,7 +199,14 @@ This optional function is used to populate the flat buffers representing the dat
returned to the application when the `bpf_prog_test_run_opts` call completes. In addition, the function frees any
resources allocated in the `ebpf_program_context_create_t` call.

### 2.2 Program Information NPI Client Attach and Detach Callbacks
### 2.2 Backward compatibility of the Extension data structures
All the extension data structures are versioned. New fields can be added to the end of a data structure to maintain backward compatibility
with the existing extensions. In such cases, the size field of the header will be updated but the version of the structure *will not change*.
If the change in data structure is such that it is no longer backward compatible (such as change field type or position),
then the version number will be updated. All previous versions of extension structure will continue to be supported.
The set of supported version numbers for the various extension structures are listed in `ebpf_windows.h`.

### 2.3 Program Information NPI Client Attach and Detach Callbacks
The eBPF Execution Context registers a Program Information NPI client module with the NMR for every eBPF program that
gets loaded. The Execution Context will use the program type GUID of the program as the NPI ID of the client module.
And as a result, upon eBPF program load, the associated Program Information NPI client module will attach with the
Expand All @@ -198,7 +215,7 @@ client or provider dispatch tables. Neither does the client's `NpiSpecificCharac
special processing is required in the client attach and detach callback handler on the provider module. An extension
must not unload until there are no more attached Program Information NPI clients.

### 2.3 Hook NPI Provider Registration
### 2.4 Hook NPI Provider Registration
When registering itself to the NMR, the Hook 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:
Expand All @@ -220,7 +237,7 @@ requested attach type is supported by the Hook NPI provider. If not, the eBPF pr
The `bpf_attach_type` field should contain the equivalent bpf attach type integer. If there is no equivalent bpf
attach type, this field should be set to `0 (BPF_ATTACH_TYPE_UNSPEC)`.

### 2.4 Hook NPI Client Attach and Detach Callbacks
### 2.5 Hook NPI Client Attach and Detach Callbacks
The eBPF Execution Context registers a Hook NPI client module with the NMR for each program that is attached to a hook.
The attach type GUID is used as the NPI of the client module. And as a result, when an eBPF program gets attached to
a hook, the associated Hook NPI client module will attach to the corresponding Hook NPI provider module in the
Expand All @@ -246,7 +263,7 @@ Upon
[client detach callback](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/netioddk/nc-netioddk-npi_provider_detach_client_fn)
the provider must free the per-client context passed in via `ProviderBindingContext` parameter.

### 2.5 Invoking an eBPF program from Hook NPI Provider
### 2.6 Invoking an eBPF program from Hook NPI Provider
To invoke an eBPF program, the extension uses the dispatch table supplied by the Hook NPI client during attaching.
The client dispatch table contains the functions, with the following type prototypes:

Expand Down Expand Up @@ -330,7 +347,7 @@ 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.6 Authoring Helper Functions
### 2.7 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,
Expand All @@ -356,7 +373,7 @@ 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.7 Registering Program Types and Attach Types - eBPF Store
### 2.8 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_test"` implies that the corresponding
program type is `EBPF_PROGRAM_TYPE_XDP_TEST`.
Expand All @@ -381,7 +398,7 @@ 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.8 eBPF Sample Driver
### 2.9 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
Expand Down
11 changes: 3 additions & 8 deletions include/ebpf_extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,13 @@ typedef struct _ebpf_extension_program_dispatch_table

typedef struct _ebpf_extension_data
{
uint16_t version;
size_t size;
ebpf_extension_header_t header;
const void* data;
} ebpf_extension_data_t;

typedef struct _ebpf_attach_provider_data
{
ebpf_extension_header_t header;
ebpf_program_type_t supported_program_type;
bpf_attach_type_t bpf_attach_type;
enum bpf_link_type link_type;
Expand All @@ -118,9 +118,4 @@ typedef struct _ebpf_execution_context_state
const void* next_program;
uint32_t count;
} tail_call_state;
} ebpf_execution_context_state_t;

#define EBPF_ATTACH_CLIENT_DATA_VERSION 0
#define EBPF_ATTACH_PROVIDER_DATA_VERSION 1
#define EBPF_PROGRAM_INFORMATION_PROVIDER_DATA_VERSION 0
#define EBPF_MAX_GENERAL_HELPER_FUNCTION 0xFFFF
} ebpf_execution_context_state_t;
63 changes: 46 additions & 17 deletions include/ebpf_program_attach_type_guids.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,69 +21,98 @@ extern "C"
__declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_XDP = {
0x85e0d8ef, 0x579e, 0x4931, {0xb0, 0x72, 0x8e, 0xe2, 0x26, 0xbb, 0x2e, 0x9d}};

#define EBPF_ATTACH_TYPE_BIND_GUID \
{ \
0xb9707e04, 0x8127, 0x4c72, { 0x83, 0x3e, 0x05, 0xb1, 0xfb, 0x43, 0x94, 0x96 } \
}
/** @brief Attach type for handling socket bind() requests.
*
* Program type: \ref EBPF_PROGRAM_TYPE_BIND
*/
__declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_BIND = {
0xb9707e04, 0x8127, 0x4c72, {0x83, 0x3e, 0x05, 0xb1, 0xfb, 0x43, 0x94, 0x96}};
__declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_BIND = EBPF_ATTACH_TYPE_BIND_GUID;

#define EBPF_ATTACH_TYPE_CGROUP_INET4_CONNECT_GUID \
{ \
0xa82e37b1, 0xaee7, 0x11ec, { 0x9a, 0x30, 0x18, 0x60, 0x24, 0x89, 0xbe, 0xee } \
}
/** @brief The programs attached to the INET4_CONNECT hook will be invoked for
* connect() calls on TCP or UDP sockets or when a UDP socket sends a packet to
* a unique remote address/port tuple.
*
* Program type: \ref EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR
*/
__declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_INET4_CONNECT = {
0xa82e37b1, 0xaee7, 0x11ec, {0x9a, 0x30, 0x18, 0x60, 0x24, 0x89, 0xbe, 0xee}};
__declspec(selectany)
ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_INET4_CONNECT = EBPF_ATTACH_TYPE_CGROUP_INET4_CONNECT_GUID;

#define EBPF_ATTACH_TYPE_CGROUP_INET6_CONNECT_GUID \
{ \
0xa82e37b2, 0xaee7, 0x11ec, { 0x9a, 0x30, 0x18, 0x60, 0x24, 0x89, 0xbe, 0xee } \
}
/** @brief The programs attached to the INET6_CONNECT hook will be invoked for
* connect() calls on TCP or UDP sockets or when a UDP socket sends a packet to
* a unique remote address/port tuple.
*
* Program type: \ref EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR
*/
__declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_INET6_CONNECT = {
0xa82e37b2, 0xaee7, 0x11ec, {0x9a, 0x30, 0x18, 0x60, 0x24, 0x89, 0xbe, 0xee}};
__declspec(selectany)
ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_INET6_CONNECT = EBPF_ATTACH_TYPE_CGROUP_INET6_CONNECT_GUID;

#define EBPF_ATTACH_TYPE_CGROUP_INET4_RECV_ACCEPT_GUID \
{ \
0xa82e37b3, 0xaee7, 0x11ec, { 0x9a, 0x30, 0x18, 0x60, 0x24, 0x89, 0xbe, 0xee } \
}
/** @brief The programs attached to the INET4_RECV_ACCEPT hook will get invoked for
* TCP accept() calls or for the first unicast UDP packet from a unique remote
* address/port tuple.
*
* Program type: \ref EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR
*/
__declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_INET4_RECV_ACCEPT = {
0xa82e37b3, 0xaee7, 0x11ec, {0x9a, 0x30, 0x18, 0x60, 0x24, 0x89, 0xbe, 0xee}};
__declspec(selectany)
ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_INET4_RECV_ACCEPT = EBPF_ATTACH_TYPE_CGROUP_INET4_RECV_ACCEPT_GUID;

#define EBPF_ATTACH_TYPE_CGROUP_INET6_RECV_ACCEPT_GUID \
{ \
0xa82e37b4, 0xaee7, 0x11ec, { 0x9a, 0x30, 0x18, 0x60, 0x24, 0x89, 0xbe, 0xee } \
}
/** @brief The programs attached to the INET6_RECV_ACCEPT hook will get invoked for
* TCP accept() calls or for the first unicast UDP packet from a unique remote
* address/port tuple.
*
* Program type: \ref EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR
*/
__declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_INET6_RECV_ACCEPT = {
0xa82e37b4, 0xaee7, 0x11ec, {0x9a, 0x30, 0x18, 0x60, 0x24, 0x89, 0xbe, 0xee}};
__declspec(selectany)
ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_INET6_RECV_ACCEPT = EBPF_ATTACH_TYPE_CGROUP_INET6_RECV_ACCEPT_GUID;

#define EBPF_ATTACH_TYPE_CGROUP_SOCK_OPS_GUID \
{ \
0x837d02cd, 0x3251, 0x4632, { 0x8d, 0x94, 0x60, 0xd3, 0xb4, 0x57, 0x69, 0xf2 } \
}
/** @brief Attach type for handling socket event notifications.
*
* Program type: \ref EBPF_PROGRAM_TYPE_SOCK_OPS
*/
__declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_SOCK_OPS = {
0x837d02cd, 0x3251, 0x4632, {0x8d, 0x94, 0x60, 0xd3, 0xb4, 0x57, 0x69, 0xf2}};
__declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_SOCK_OPS = EBPF_ATTACH_TYPE_CGROUP_SOCK_OPS_GUID;

#define EBPF_ATTACH_TYPE_SAMPLE_GUID \
{ \
0xf788ef4b, 0x207d, 0x4dc3, { 0x85, 0xcf, 0x0f, 0x2e, 0xa1, 0x07, 0x21, 0x3c } \
}

/** @brief Attach type implemented by eBPF Sample Extension driver, used for testing.
*
* Program type: \ref EBPF_PROGRAM_TYPE_SAMPLE
* Program type: \ref EBPF_ATTACH_TYPE_SAMPLE
*/
__declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_SAMPLE = {
0xf788ef4b, 0x207d, 0x4dc3, {0x85, 0xcf, 0x0f, 0x2e, 0xa1, 0x07, 0x21, 0x3c}};
__declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_SAMPLE = EBPF_ATTACH_TYPE_SAMPLE_GUID;

#define EBPF_ATTACH_TYPE_XDP_TEST_GUID \
{ \
0x0dccc15d, 0xa5f9, 0x4dc1, { 0xac, 0x79, 0xfa, 0x25, 0xee, 0xf2, 0x15, 0xc3 } \
}
/** @brief Attach type for handling incoming packets as early as possible.
*
* Program type: \ref EBPF_PROGRAM_TYPE_XDP_TEST
*/
__declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_XDP_TEST = {
0x0dccc15d, 0xa5f9, 0x4dc1, {0xac, 0x79, 0xfa, 0x25, 0xee, 0xf2, 0x15, 0xc3}};
__declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_XDP_TEST = EBPF_ATTACH_TYPE_XDP_TEST_GUID;

//
// Program Types.
Expand Down
21 changes: 10 additions & 11 deletions include/ebpf_program_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,15 @@

#include "ebpf_base.h"
#include "ebpf_result.h"

#include <guiddef.h>
#if !defined(NO_CRT) && !defined(_NO_CRT_STDIO_INLINE)
#include <stdint.h>
#else
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef unsigned short wchar_t;
#endif
#include "ebpf_windows.h"

#define EBPF_MAX_PROGRAM_DESCRIPTOR_NAME_LENGTH 256
#define EBPF_MAX_HELPER_FUNCTION_NAME_LENGTH 256

typedef struct _ebpf_program_type_descriptor
{
ebpf_extension_header_t header;
// The following fields are available in version EBPF_PROGRAM_TYPE_DESCRIPTOR_VERSION_0 and later.
const char* name;
const ebpf_context_descriptor_t* context_descriptor;
GUID program_type;
Expand All @@ -29,6 +22,8 @@ typedef struct _ebpf_program_type_descriptor

typedef struct _ebpf_helper_function_prototype
{
ebpf_extension_header_t header;
// The following fields are available in version EBPF_HELPER_FUNCTION_PROTOTYPE_VERSION_0 and later.
uint32_t helper_id;
const char* name;
ebpf_return_type_t return_type;
Expand All @@ -37,7 +32,8 @@ typedef struct _ebpf_helper_function_prototype

typedef struct _ebpf_program_info
{
ebpf_program_type_descriptor_t program_type_descriptor;
ebpf_extension_header_t header;
const ebpf_program_type_descriptor_t* program_type_descriptor;
uint32_t count_of_program_type_specific_helpers;
const ebpf_helper_function_prototype_t* program_type_specific_helper_prototype;
uint32_t count_of_global_helpers;
Expand All @@ -46,6 +42,7 @@ typedef struct _ebpf_program_info

typedef struct _ebpf_helper_function_addresses
{
ebpf_extension_header_t header;
uint32_t helper_function_count;
uint64_t* helper_function_address;
} ebpf_helper_function_addresses_t;
Expand All @@ -66,6 +63,7 @@ typedef void (*ebpf_program_context_destroy_t)(

typedef struct _ebpf_program_data
{
ebpf_extension_header_t header;
const ebpf_program_info_t* program_info; ///< Pointer to program information.
const ebpf_helper_function_addresses_t*
program_type_specific_helper_function_addresses; ///< Pointer to program type specific helper function
Expand All @@ -79,6 +77,7 @@ typedef struct _ebpf_program_data

typedef struct _ebpf_program_section_info
{
ebpf_extension_header_t header;
const wchar_t* section_name;
const GUID* program_type;
const GUID* attach_type;
Expand Down
10 changes: 0 additions & 10 deletions include/ebpf_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,6 @@

#include "ebpf_windows.h"

#if !defined(NO_CRT) && !defined(_NO_CRT_STDIO_INLINE)
#include <stdbool.h>
#include <stdint.h>
#else
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
#endif

#define MAX_TAIL_CALL_CNT 33

#define BPF_ENUM_TO_STRING(X) #X
Expand Down

0 comments on commit dbac4a9

Please sign in to comment.