// Copyright (c) eBPF for Windows contributors // SPDX-License-Identifier: MIT #include "net_ebpf_ext.h" #include #include TRACELOGGING_DEFINE_PROVIDER( net_ebpf_ext_tracelog_provider, "NetEbpfExtProvider", // {f2f2ca01-ad02-4a07-9e90-95a2334f3692} (0xf2f2ca01, 0xad02, 0x4a07, 0x9e, 0x90, 0x95, 0xa2, 0x33, 0x4f, 0x36, 0x92)); static bool _net_ebpf_ext_trace_initiated = false; NTSTATUS net_ebpf_ext_trace_initiate() { NTSTATUS status = STATUS_SUCCESS; if (_net_ebpf_ext_trace_initiated) { goto Exit; } status = TraceLoggingRegister(net_ebpf_ext_tracelog_provider); if (status != STATUS_SUCCESS) { goto Exit; } else { _net_ebpf_ext_trace_initiated = true; } Exit: return status; } // Prevent tail call optimization of the call to TraceLoggingUnregister to resolve verifier stop C4/DD // "An attempt was made to unload a driver without calling EtwUnregister". #pragma optimize("", off) void net_ebpf_ext_trace_terminate() { if (_net_ebpf_ext_trace_initiated) { TraceLoggingUnregister(net_ebpf_ext_tracelog_provider); _net_ebpf_ext_trace_initiated = false; } } #pragma optimize("", on) #define KEYWORD_BASE NET_EBPF_EXT_TRACELOG_KEYWORD_BASE #define KEYWORD_BIND NET_EBPF_EXT_TRACELOG_KEYWORD_BIND #define KEYWORD_EXT NET_EBPF_EXT_TRACELOG_KEYWORD_EXTENSION #define KEYWORD_SOCK_ADDR NET_EBPF_EXT_TRACELOG_KEYWORD_SOCK_ADDR #define KEYWORD_SOCK_OPS NET_EBPF_EXT_TRACELOG_KEYWORD_SOCK_OPS #define KEYWORD_XDP NET_EBPF_EXT_TRACELOG_KEYWORD_XDP #define CASE_BASE case _NET_EBPF_EXT_TRACELOG_KEYWORD_BASE #define CASE_BIND case _NET_EBPF_EXT_TRACELOG_KEYWORD_BIND #define CASE_EXT case _NET_EBPF_EXT_TRACELOG_KEYWORD_EXTENSION #define CASE_SOCK_ADDR case _NET_EBPF_EXT_TRACELOG_KEYWORD_SOCK_ADDR #define CASE_SOCK_OPS case _NET_EBPF_EXT_TRACELOG_KEYWORD_SOCK_OPS #define CASE_XDP case _NET_EBPF_EXT_TRACELOG_KEYWORD_XDP #define LEVEL_LOG_ALWAYS NET_EBPF_EXT_TRACELOG_LEVEL_LOG_ALWAYS #define LEVEL_CRITICAL NET_EBPF_EXT_TRACELOG_LEVEL_CRITICAL #define LEVEL_ERROR NET_EBPF_EXT_TRACELOG_LEVEL_ERROR #define LEVEL_WARNING NET_EBPF_EXT_TRACELOG_LEVEL_WARNING #define LEVEL_INFO NET_EBPF_EXT_TRACELOG_LEVEL_INFO #define LEVEL_VERBOSE NET_EBPF_EXT_TRACELOG_LEVEL_VERBOSE #define CASE_LOG_ALWAYS case _NET_EBPF_EXT_TRACELOG_LEVEL_LOG_ALWAYS #define CASE_CRITICAL case _NET_EBPF_EXT_TRACELOG_LEVEL_CRITICAL #define CASE_LEVEL_ERROR case _NET_EBPF_EXT_TRACELOG_LEVEL_ERROR #define CASE_WARNING case _NET_EBPF_EXT_TRACELOG_LEVEL_WARNING #define CASE_INFO case _NET_EBPF_EXT_TRACELOG_LEVEL_INFO #define CASE_VERBOSE case _NET_EBPF_EXT_TRACELOG_LEVEL_VERBOSE #define NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE_KEYWORD_SWITCH(api_name, status) \ switch (keyword) { \ CASE_BASE: \ _NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE(KEYWORD_BASE, api_name, status); \ break; \ CASE_EXT: \ _NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE(KEYWORD_EXT, api_name, status); \ break; \ CASE_BIND: \ _NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE(KEYWORD_BIND, api_name, status); \ break; \ CASE_SOCK_ADDR: \ _NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE(KEYWORD_SOCK_ADDR, api_name, status); \ break; \ CASE_SOCK_OPS: \ _NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE(KEYWORD_SOCK_OPS, api_name, status); \ break; \ CASE_XDP: \ _NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE(KEYWORD_XDP, api_name, status); \ break; \ default: \ ebpf_assert(!"Invalid keyword"); \ break; \ } #pragma warning(push) #pragma warning(disable : 6262) // Function uses 'N' bytes of stack. Consider moving some data to heap. __declspec(noinline) void net_ebpf_ext_log_ntstatus_api_failure( net_ebpf_ext_tracelog_keyword_t keyword, _In_z_ const char* api_name, NTSTATUS status) { NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE_KEYWORD_SWITCH(api_name, status); } #define NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE_MESSAGE_STRING_KEYWORD_SWITCH(api_name, status, message, string_value) \ switch (keyword) { \ CASE_BASE: \ _NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE_MESSAGE_STRING(KEYWORD_BASE, api_name, status, message, string_value); \ break; \ CASE_EXT: \ _NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE_MESSAGE_STRING(KEYWORD_EXT, api_name, status, message, string_value); \ break; \ CASE_BIND: \ _NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE_MESSAGE_STRING(KEYWORD_BIND, api_name, status, message, string_value); \ break; \ CASE_SOCK_ADDR: \ _NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE_MESSAGE_STRING( \ KEYWORD_SOCK_ADDR, api_name, status, message, string_value); \ break; \ CASE_SOCK_OPS: \ _NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE_MESSAGE_STRING( \ KEYWORD_SOCK_OPS, api_name, status, message, string_value); \ break; \ CASE_XDP: \ _NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE_MESSAGE_STRING(KEYWORD_XDP, api_name, status, message, string_value); \ break; \ default: \ ebpf_assert(!"Invalid keyword"); \ break; \ } __declspec(noinline) void net_ebpf_ext_log_ntstatus_api_failure_message_string( net_ebpf_ext_tracelog_keyword_t keyword, _In_z_ const char* api_name, NTSTATUS status, _In_z_ const char* message, _In_z_ const char* string_value) { NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE_MESSAGE_STRING_KEYWORD_SWITCH(api_name, status, message, string_value); } #define NET_EBPF_EXT_LOG_MESSAGE_KEYWORD_SWITCH(trace_level, message) \ switch (keyword) { \ CASE_BASE: \ _NET_EBPF_EXT_LOG_MESSAGE(trace_level, KEYWORD_BASE, message); \ break; \ CASE_BIND: \ _NET_EBPF_EXT_LOG_MESSAGE(trace_level, KEYWORD_BIND, message); \ break; \ CASE_EXT: \ _NET_EBPF_EXT_LOG_MESSAGE(trace_level, KEYWORD_EXT, message); \ break; \ CASE_SOCK_ADDR: \ _NET_EBPF_EXT_LOG_MESSAGE(trace_level, KEYWORD_SOCK_ADDR, message); \ break; \ CASE_SOCK_OPS: \ _NET_EBPF_EXT_LOG_MESSAGE(trace_level, KEYWORD_SOCK_OPS, message); \ break; \ CASE_XDP: \ _NET_EBPF_EXT_LOG_MESSAGE(trace_level, KEYWORD_XDP, message); \ break; \ default: \ ebpf_assert(!"Invalid keyword"); \ break; \ } __declspec(noinline) void net_ebpf_ext_log_message( net_ebpf_ext_tracelog_level_t trace_level, net_ebpf_ext_tracelog_keyword_t keyword, _In_z_ const char* message) { switch (trace_level) { CASE_LOG_ALWAYS: NET_EBPF_EXT_LOG_MESSAGE_KEYWORD_SWITCH(LEVEL_LOG_ALWAYS, message); break; CASE_CRITICAL: NET_EBPF_EXT_LOG_MESSAGE_KEYWORD_SWITCH(LEVEL_CRITICAL, message); break; CASE_LEVEL_ERROR: NET_EBPF_EXT_LOG_MESSAGE_KEYWORD_SWITCH(LEVEL_ERROR, message); break; CASE_WARNING: NET_EBPF_EXT_LOG_MESSAGE_KEYWORD_SWITCH(LEVEL_WARNING, message); break; CASE_INFO: NET_EBPF_EXT_LOG_MESSAGE_KEYWORD_SWITCH(LEVEL_INFO, message); break; CASE_VERBOSE: NET_EBPF_EXT_LOG_MESSAGE_KEYWORD_SWITCH(LEVEL_VERBOSE, message); break; default: ebpf_assert(!"Invalid trace level"); break; } } #define NET_EBPF_EXT_LOG_MESSAGE_STRING_KEYWORD_SWITCH(trace_level, message, string_value) \ switch (keyword) { \ CASE_BASE: \ _NET_EBPF_EXT_LOG_MESSAGE_STRING(trace_level, KEYWORD_BASE, message, string_value); \ break; \ CASE_BIND: \ _NET_EBPF_EXT_LOG_MESSAGE_STRING(trace_level, KEYWORD_BIND, message, string_value); \ break; \ CASE_EXT: \ _NET_EBPF_EXT_LOG_MESSAGE_STRING(trace_level, KEYWORD_EXT, message, string_value); \ break; \ CASE_SOCK_ADDR: \ _NET_EBPF_EXT_LOG_MESSAGE_STRING(trace_level, KEYWORD_SOCK_ADDR, message, string_value); \ break; \ CASE_SOCK_OPS: \ _NET_EBPF_EXT_LOG_MESSAGE_STRING(trace_level, KEYWORD_SOCK_OPS, message, string_value); \ break; \ CASE_XDP: \ _NET_EBPF_EXT_LOG_MESSAGE_STRING(trace_level, KEYWORD_XDP, message, string_value); \ break; \ default: \ ebpf_assert(!"Invalid keyword"); \ break; \ } __declspec(noinline) void net_ebpf_ext_log_message_string( net_ebpf_ext_tracelog_level_t trace_level, net_ebpf_ext_tracelog_keyword_t keyword, _In_z_ const char* message, _In_z_ const char* string_value) { switch (trace_level) { CASE_LOG_ALWAYS: NET_EBPF_EXT_LOG_MESSAGE_STRING_KEYWORD_SWITCH(LEVEL_LOG_ALWAYS, message, string_value); break; CASE_CRITICAL: NET_EBPF_EXT_LOG_MESSAGE_STRING_KEYWORD_SWITCH(LEVEL_CRITICAL, message, string_value); break; CASE_LEVEL_ERROR: NET_EBPF_EXT_LOG_MESSAGE_STRING_KEYWORD_SWITCH(LEVEL_ERROR, message, string_value); break; CASE_WARNING: NET_EBPF_EXT_LOG_MESSAGE_STRING_KEYWORD_SWITCH(LEVEL_WARNING, message, string_value); break; CASE_INFO: NET_EBPF_EXT_LOG_MESSAGE_STRING_KEYWORD_SWITCH(LEVEL_INFO, message, string_value); break; CASE_VERBOSE: NET_EBPF_EXT_LOG_MESSAGE_STRING_KEYWORD_SWITCH(LEVEL_VERBOSE, message, string_value); break; default: ebpf_assert(!"Invalid trace level"); break; } } #define NET_EBPF_EXT_LOG_MESSAGE_NTSTATUS_KEYWORD_SWITCH(trace_level, message, status) \ switch (keyword) { \ CASE_BASE: \ _NET_EBPF_EXT_LOG_MESSAGE_NTSTATUS(trace_level, KEYWORD_BASE, message, status); \ break; \ CASE_BIND: \ _NET_EBPF_EXT_LOG_MESSAGE_NTSTATUS(trace_level, KEYWORD_BIND, message, status); \ break; \ CASE_EXT: \ _NET_EBPF_EXT_LOG_MESSAGE_NTSTATUS(trace_level, KEYWORD_EXT, message, status); \ break; \ CASE_SOCK_ADDR: \ _NET_EBPF_EXT_LOG_MESSAGE_NTSTATUS(trace_level, KEYWORD_SOCK_ADDR, message, status); \ break; \ CASE_SOCK_OPS: \ _NET_EBPF_EXT_LOG_MESSAGE_NTSTATUS(trace_level, KEYWORD_SOCK_OPS, message, status); \ break; \ CASE_XDP: \ _NET_EBPF_EXT_LOG_MESSAGE_NTSTATUS(trace_level, KEYWORD_XDP, message, status); \ break; \ default: \ ebpf_assert(!"Invalid keyword"); \ break; \ } __declspec(noinline) void net_ebpf_ext_log_message_ntstatus( net_ebpf_ext_tracelog_level_t trace_level, net_ebpf_ext_tracelog_keyword_t keyword, _In_z_ const char* message, NTSTATUS status) { switch (trace_level) { CASE_LOG_ALWAYS: NET_EBPF_EXT_LOG_MESSAGE_NTSTATUS_KEYWORD_SWITCH(LEVEL_LOG_ALWAYS, message, status); break; CASE_CRITICAL: NET_EBPF_EXT_LOG_MESSAGE_NTSTATUS_KEYWORD_SWITCH(LEVEL_CRITICAL, message, status); break; CASE_LEVEL_ERROR: NET_EBPF_EXT_LOG_MESSAGE_NTSTATUS_KEYWORD_SWITCH(LEVEL_ERROR, message, status); break; CASE_WARNING: NET_EBPF_EXT_LOG_MESSAGE_NTSTATUS_KEYWORD_SWITCH(LEVEL_WARNING, message, status); break; CASE_INFO: NET_EBPF_EXT_LOG_MESSAGE_NTSTATUS_KEYWORD_SWITCH(LEVEL_INFO, message, status); break; CASE_VERBOSE: NET_EBPF_EXT_LOG_MESSAGE_NTSTATUS_KEYWORD_SWITCH(LEVEL_VERBOSE, message, status); break; default: ebpf_assert(!"Invalid trace level"); break; } } #define NET_EBPF_EXT_LOG_MESSAGE_BOOL_KEYWORD_SWITCH(trace_level, message, value) \ switch (keyword) { \ CASE_BASE: \ _NET_EBPF_EXT_LOG_MESSAGE_BOOL(trace_level, KEYWORD_BASE, message, value); \ break; \ CASE_BIND: \ _NET_EBPF_EXT_LOG_MESSAGE_BOOL(trace_level, KEYWORD_BIND, message, value); \ break; \ CASE_EXT: \ _NET_EBPF_EXT_LOG_MESSAGE_BOOL(trace_level, KEYWORD_EXT, message, value); \ break; \ CASE_SOCK_ADDR: \ _NET_EBPF_EXT_LOG_MESSAGE_BOOL(trace_level, KEYWORD_SOCK_ADDR, message, value); \ break; \ CASE_SOCK_OPS: \ _NET_EBPF_EXT_LOG_MESSAGE_BOOL(trace_level, KEYWORD_SOCK_OPS, message, value); \ break; \ CASE_XDP: \ _NET_EBPF_EXT_LOG_MESSAGE_BOOL(trace_level, KEYWORD_XDP, message, value); \ break; \ default: \ ebpf_assert(!"Invalid keyword"); \ break; \ } __declspec(noinline) void net_ebpf_ext_log_message_bool( net_ebpf_ext_tracelog_level_t trace_level, net_ebpf_ext_tracelog_keyword_t keyword, _In_z_ const char* message, bool value) { switch (trace_level) { CASE_LOG_ALWAYS: NET_EBPF_EXT_LOG_MESSAGE_BOOL_KEYWORD_SWITCH(LEVEL_LOG_ALWAYS, message, value); break; CASE_CRITICAL: NET_EBPF_EXT_LOG_MESSAGE_BOOL_KEYWORD_SWITCH(LEVEL_CRITICAL, message, value); break; CASE_LEVEL_ERROR: NET_EBPF_EXT_LOG_MESSAGE_BOOL_KEYWORD_SWITCH(LEVEL_ERROR, message, value); break; CASE_WARNING: NET_EBPF_EXT_LOG_MESSAGE_BOOL_KEYWORD_SWITCH(LEVEL_WARNING, message, value); break; CASE_INFO: NET_EBPF_EXT_LOG_MESSAGE_BOOL_KEYWORD_SWITCH(LEVEL_INFO, message, value); break; CASE_VERBOSE: NET_EBPF_EXT_LOG_MESSAGE_BOOL_KEYWORD_SWITCH(LEVEL_VERBOSE, message, value); break; default: ebpf_assert(!"Invalid trace level"); break; } } #define NET_EBPF_EXT_LOG_MESSAGE_POINTER_KEYWORD_SWITCH(trace_level, message, value) \ switch (keyword) { \ CASE_BASE: \ _NET_EBPF_EXT_LOG_MESSAGE_POINTER(trace_level, KEYWORD_BASE, message, value); \ break; \ CASE_BIND: \ _NET_EBPF_EXT_LOG_MESSAGE_POINTER(trace_level, KEYWORD_BIND, message, value); \ break; \ CASE_EXT: \ _NET_EBPF_EXT_LOG_MESSAGE_POINTER(trace_level, KEYWORD_EXT, message, value); \ break; \ CASE_SOCK_ADDR: \ _NET_EBPF_EXT_LOG_MESSAGE_POINTER(trace_level, KEYWORD_SOCK_ADDR, message, value); \ break; \ CASE_SOCK_OPS: \ _NET_EBPF_EXT_LOG_MESSAGE_POINTER(trace_level, KEYWORD_SOCK_OPS, message, value); \ break; \ CASE_XDP: \ _NET_EBPF_EXT_LOG_MESSAGE_POINTER(trace_level, KEYWORD_XDP, message, value); \ break; \ default: \ ebpf_assert(!"Invalid keyword"); \ break; \ } __declspec(noinline) void net_ebpf_ext_log_message_pointer( net_ebpf_ext_tracelog_level_t trace_level, net_ebpf_ext_tracelog_keyword_t keyword, _In_z_ const char* message, _In_opt_ const void* value) { switch (trace_level) { CASE_LOG_ALWAYS: NET_EBPF_EXT_LOG_MESSAGE_POINTER_KEYWORD_SWITCH(LEVEL_LOG_ALWAYS, message, value); break; CASE_CRITICAL: NET_EBPF_EXT_LOG_MESSAGE_POINTER_KEYWORD_SWITCH(LEVEL_CRITICAL, message, value); break; CASE_LEVEL_ERROR: NET_EBPF_EXT_LOG_MESSAGE_POINTER_KEYWORD_SWITCH(LEVEL_ERROR, message, value); break; CASE_WARNING: NET_EBPF_EXT_LOG_MESSAGE_POINTER_KEYWORD_SWITCH(LEVEL_WARNING, message, value); break; CASE_INFO: NET_EBPF_EXT_LOG_MESSAGE_POINTER_KEYWORD_SWITCH(LEVEL_INFO, message, value); break; CASE_VERBOSE: NET_EBPF_EXT_LOG_MESSAGE_POINTER_KEYWORD_SWITCH(LEVEL_VERBOSE, message, value); break; default: ebpf_assert(!"Invalid trace level"); break; } } #define NET_EBPF_EXT_LOG_MESSAGE_UINT32_KEYWORD_SWITCH(trace_level, message, status) \ switch (keyword) { \ CASE_BASE: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT32(trace_level, KEYWORD_BASE, message, status); \ break; \ CASE_BIND: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT32(trace_level, KEYWORD_BIND, message, status); \ break; \ CASE_EXT: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT32(trace_level, KEYWORD_EXT, message, status); \ break; \ CASE_SOCK_ADDR: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT32(trace_level, KEYWORD_SOCK_ADDR, message, status); \ break; \ CASE_SOCK_OPS: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT32(trace_level, KEYWORD_SOCK_OPS, message, status); \ break; \ CASE_XDP: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT32(trace_level, KEYWORD_XDP, message, status); \ break; \ default: \ ebpf_assert(!"Invalid keyword"); \ break; \ } __declspec(noinline) void net_ebpf_ext_log_message_uint32( net_ebpf_ext_tracelog_level_t trace_level, net_ebpf_ext_tracelog_keyword_t keyword, _In_z_ const char* message, uint32_t value) { switch (trace_level) { CASE_LOG_ALWAYS: NET_EBPF_EXT_LOG_MESSAGE_UINT32_KEYWORD_SWITCH(LEVEL_LOG_ALWAYS, message, value); break; CASE_CRITICAL: NET_EBPF_EXT_LOG_MESSAGE_UINT32_KEYWORD_SWITCH(LEVEL_CRITICAL, message, value); break; CASE_LEVEL_ERROR: NET_EBPF_EXT_LOG_MESSAGE_UINT32_KEYWORD_SWITCH(LEVEL_ERROR, message, value); break; CASE_WARNING: NET_EBPF_EXT_LOG_MESSAGE_UINT32_KEYWORD_SWITCH(LEVEL_WARNING, message, value); break; CASE_INFO: NET_EBPF_EXT_LOG_MESSAGE_UINT32_KEYWORD_SWITCH(LEVEL_INFO, message, value); break; CASE_VERBOSE: NET_EBPF_EXT_LOG_MESSAGE_UINT32_KEYWORD_SWITCH(LEVEL_VERBOSE, message, value); break; default: ebpf_assert(!"Invalid trace level"); break; } } #define NET_EBPF_EXT_LOG_MESSAGE_UINT64_KEYWORD_SWITCH(trace_level, message, status) \ switch (keyword) { \ CASE_BASE: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT64(trace_level, KEYWORD_BASE, message, status); \ break; \ CASE_BIND: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT64(trace_level, KEYWORD_BIND, message, status); \ break; \ CASE_EXT: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT64(trace_level, KEYWORD_EXT, message, status); \ break; \ CASE_SOCK_ADDR: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT64(trace_level, KEYWORD_SOCK_ADDR, message, status); \ break; \ CASE_SOCK_OPS: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT64(trace_level, KEYWORD_SOCK_OPS, message, status); \ break; \ CASE_XDP: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT64(trace_level, KEYWORD_XDP, message, status); \ break; \ default: \ ebpf_assert(!"Invalid keyword"); \ break; \ } __declspec(noinline) void net_ebpf_ext_log_message_uint64( net_ebpf_ext_tracelog_level_t trace_level, net_ebpf_ext_tracelog_keyword_t keyword, _In_z_ const char* message, uint64_t value) { switch (trace_level) { CASE_LOG_ALWAYS: NET_EBPF_EXT_LOG_MESSAGE_UINT64_KEYWORD_SWITCH(LEVEL_LOG_ALWAYS, message, value); break; CASE_CRITICAL: NET_EBPF_EXT_LOG_MESSAGE_UINT64_KEYWORD_SWITCH(LEVEL_CRITICAL, message, value); break; CASE_LEVEL_ERROR: NET_EBPF_EXT_LOG_MESSAGE_UINT64_KEYWORD_SWITCH(LEVEL_ERROR, message, value); break; CASE_WARNING: NET_EBPF_EXT_LOG_MESSAGE_UINT64_KEYWORD_SWITCH(LEVEL_WARNING, message, value); break; CASE_INFO: NET_EBPF_EXT_LOG_MESSAGE_UINT64_KEYWORD_SWITCH(LEVEL_INFO, message, value); break; CASE_VERBOSE: NET_EBPF_EXT_LOG_MESSAGE_UINT64_KEYWORD_SWITCH(LEVEL_VERBOSE, message, value); break; default: ebpf_assert(!"Invalid trace level"); break; } } #define NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE_UINT64_UINT64_KEYWORD_SWITCH(api_name, status, value1, value2) \ switch (keyword) { \ CASE_BASE: \ _NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE_UINT64_UINT64(KEYWORD_BASE, api_name, status, value1, value2); \ break; \ CASE_EXT: \ _NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE_UINT64_UINT64(KEYWORD_EXT, api_name, status, value1, value2); \ break; \ CASE_BIND: \ _NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE_UINT64_UINT64(KEYWORD_BIND, api_name, status, value1, value2); \ break; \ CASE_SOCK_ADDR: \ _NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE_UINT64_UINT64(KEYWORD_SOCK_ADDR, api_name, status, value1, value2); \ break; \ CASE_SOCK_OPS: \ _NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE_UINT64_UINT64(KEYWORD_SOCK_OPS, api_name, status, value1, value2); \ break; \ CASE_XDP: \ _NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE_UINT64_UINT64(KEYWORD_XDP, api_name, status, value1, value2); \ break; \ default: \ ebpf_assert(!"Invalid keyword"); \ break; \ } __declspec(noinline) void net_ebpf_ext_log_ntstatus_api_failure_uint64_uint64( net_ebpf_ext_tracelog_keyword_t keyword, _In_z_ const char* api_name, NTSTATUS status, uint64_t value1, uint64_t value2) { NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE_UINT64_UINT64_KEYWORD_SWITCH(api_name, status, value1, value2); } #define NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64_KEYWORD_SWITCH(trace_level, message, value1, value2) \ switch (keyword) { \ CASE_BASE: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64(trace_level, KEYWORD_BASE, message, value1, value2); \ break; \ CASE_EXT: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64(trace_level, KEYWORD_EXT, message, value1, value2); \ break; \ CASE_BIND: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64(trace_level, KEYWORD_BIND, message, value1, value2); \ break; \ CASE_SOCK_ADDR: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64(trace_level, KEYWORD_SOCK_ADDR, message, value1, value2); \ break; \ CASE_SOCK_OPS: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64(trace_level, KEYWORD_SOCK_OPS, message, value1, value2); \ break; \ CASE_XDP: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64(trace_level, KEYWORD_XDP, message, value1, value2); \ break; \ default: \ ebpf_assert(!"Invalid keyword"); \ break; \ } __declspec(noinline) void net_ebpf_ext_log_message_uint64_uint64( net_ebpf_ext_tracelog_level_t trace_level, net_ebpf_ext_tracelog_keyword_t keyword, _In_z_ const char* message, uint64_t value1, uint64_t value2) { switch (trace_level) { CASE_LOG_ALWAYS: NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64_KEYWORD_SWITCH(LEVEL_LOG_ALWAYS, message, value1, value2); break; CASE_CRITICAL: NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64_KEYWORD_SWITCH(LEVEL_CRITICAL, message, value1, value2); break; CASE_LEVEL_ERROR: NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64_KEYWORD_SWITCH(LEVEL_ERROR, message, value1, value2); break; CASE_WARNING: NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64_KEYWORD_SWITCH(LEVEL_WARNING, message, value1, value2); break; CASE_INFO: NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64_KEYWORD_SWITCH(LEVEL_INFO, message, value1, value2); break; CASE_VERBOSE: NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64_KEYWORD_SWITCH(LEVEL_VERBOSE, message, value1, value2); break; default: ebpf_assert(!"Invalid trace level"); break; } } #define NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64_UINT64_KEYWORD_SWITCH(trace_level, message, value1, value2, value3) \ switch (keyword) { \ CASE_BASE: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64_UINT64(trace_level, KEYWORD_BASE, message, value1, value2, value3); \ break; \ CASE_EXT: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64_UINT64(trace_level, KEYWORD_EXT, message, value1, value2, value3); \ break; \ CASE_BIND: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64_UINT64(trace_level, KEYWORD_BIND, message, value1, value2, value3); \ break; \ CASE_SOCK_ADDR: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64_UINT64( \ trace_level, KEYWORD_SOCK_ADDR, message, value1, value2, value3); \ break; \ CASE_SOCK_OPS: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64_UINT64( \ trace_level, KEYWORD_SOCK_OPS, message, value1, value2, value3); \ break; \ CASE_XDP: \ _NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64_UINT64(trace_level, KEYWORD_XDP, message, value1, value2, value3); \ break; \ default: \ ebpf_assert(!"Invalid keyword"); \ break; \ } __declspec(noinline) void net_ebpf_ext_log_message_uint64_uint64_uint64( net_ebpf_ext_tracelog_level_t trace_level, net_ebpf_ext_tracelog_keyword_t keyword, _In_z_ const char* message, uint64_t value1, uint64_t value2, uint64_t value3) { switch (trace_level) { CASE_LOG_ALWAYS: NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64_UINT64_KEYWORD_SWITCH(LEVEL_LOG_ALWAYS, message, value1, value2, value3); break; CASE_CRITICAL: NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64_UINT64_KEYWORD_SWITCH(LEVEL_CRITICAL, message, value1, value2, value3); break; CASE_LEVEL_ERROR: NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64_UINT64_KEYWORD_SWITCH(LEVEL_ERROR, message, value1, value2, value3); break; CASE_WARNING: NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64_UINT64_KEYWORD_SWITCH(LEVEL_WARNING, message, value1, value2, value3); break; CASE_INFO: NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64_UINT64_KEYWORD_SWITCH(LEVEL_INFO, message, value1, value2, value3); break; CASE_VERBOSE: NET_EBPF_EXT_LOG_MESSAGE_UINT64_UINT64_UINT64_KEYWORD_SWITCH(LEVEL_VERBOSE, message, value1, value2, value3); break; default: ebpf_assert(!"Invalid trace level"); break; } } #pragma warning(pop)