use std::num::NonZeroU64;
use std::sync::OnceLock;
use std::sync::atomic::{
AtomicU64,
Ordering::{Acquire, Relaxed, Release},
};
use std::time::Instant;
mod format;
use format::{fmt_ns, fmt_rate_per_sec};
const N_STAGES: usize = 74;
const N_EVENTS: usize = 221;
const HIST_BUCKETS: usize = 48;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(usize)]
pub enum Stage {
UdpRecv = 0,
FmpDecrypt = 1,
LinkDispatch = 2,
FspDecrypt = 3,
TunWrite = 4,
FspEncrypt = 5,
FmpEncrypt = 6,
UdpSend = 7,
ProcessPacket = 8,
EndpointDeliver = 9,
FspHandle = 10,
EndpointSend = 11,
EndpointCommandWait = 12,
FmpWorkerQueueWait = 13,
TransportQueueWait = 14,
EndpointEventWait = 15,
TransportPriorityQueueWait = 16,
TransportBulkQueueWait = 17,
EndpointPriorityEventWait = 18,
EndpointBulkEventWait = 19,
TransportChannelWait = 20,
TransportPriorityChannelWait = 21,
TransportBulkChannelWait = 22,
DecryptFallbackWait = 23,
DecryptFallbackPriorityWait = 24,
DecryptFallbackBulkWait = 25,
TransportRxLoopWait = 26,
TransportPriorityRxLoopWait = 27,
TransportBulkRxLoopWait = 28,
DecryptWorkerQueueWait = 29,
DecryptWorkerPriorityQueueWait = 30,
DecryptWorkerBulkQueueWait = 31,
EndpointPriorityCommandWait = 32,
EndpointBulkCommandWait = 33,
DecryptAuthenticatedSessionWait = 34,
DecryptAuthenticatedSessionPriorityWait = 35,
DecryptAuthenticatedSessionBulkWait = 36,
DecryptFspWorkerQueueWait = 37,
DecryptFspWorkerPriorityQueueWait = 38,
DecryptFspWorkerBulkQueueWait = 39,
FmpWorkerPriorityQueueWait = 40,
FmpWorkerBulkQueueWait = 41,
DecryptFspWorkerService = 42,
DecryptFspWorkerBulkInputHeadWait = 43,
DecryptFspWorkerBulkInputTailWait = 44,
FspAeadHelperQueueWait = 45,
FspAeadHelperCompletionWait = 46,
FmpWorkerFspSeal = 47,
FmpWorkerFmpSeal = 48,
FmpWorkerDispatch = 49,
DecryptWorkerBulkInputHeadWait = 50,
DecryptWorkerBulkInputTailWait = 51,
DecryptWorkerBulkItemService = 52,
FmpAeadHelperQueueWait = 53,
FmpAeadHelperCompletionWait = 54,
FmpAeadHelperPriorityCompletionWait = 55,
FmpAeadHelperBulkCompletionWait = 56,
FmpReceiveOrderWindowWait = 57,
FmpAeadHelperCompletionService = 58,
DecryptWorkerOutputFlush = 59,
FspAeadCompletionService = 60,
EndpointSendPrepare = 61,
EndpointSendPlan = 62,
EndpointSendCommit = 63,
DecryptAuthenticatedFmpReceiveWait = 64,
FspAeadWorkerOpenQueueWait = 65,
FspAeadWorkerOpenCompletionWait = 66,
DecryptDirectSessionCommitWait = 67,
DecryptDirectSessionDataWait = 68,
ConnectedUdpDrainRecv = 69,
ConnectedUdpFastPathDispatch = 70,
ConnectedUdpDrainRingWait = 71,
ConnectedUdpDrainPriorityRingWait = 72,
ConnectedUdpDrainBulkRingWait = 73,
}
impl Stage {
const fn name(self) -> &'static str {
match self {
Stage::UdpRecv => "udp_recv",
Stage::FmpDecrypt => "fmp_decrypt",
Stage::LinkDispatch => "link_dispatch",
Stage::FspDecrypt => "fsp_decrypt",
Stage::TunWrite => "tun_write",
Stage::FspEncrypt => "fsp_encrypt",
Stage::FmpEncrypt => "fmp_encrypt",
Stage::UdpSend => "udp_send",
Stage::ProcessPacket => "process_packet",
Stage::EndpointDeliver => "endpoint_deliver",
Stage::FspHandle => "fsp_handle",
Stage::EndpointSend => "endpoint_send",
Stage::EndpointCommandWait => "endpoint_command_wait",
Stage::FmpWorkerQueueWait => "fmp_worker_queue_wait",
Stage::TransportQueueWait => "transport_queue_wait",
Stage::EndpointEventWait => "endpoint_event_wait",
Stage::TransportPriorityQueueWait => "transport_priority_queue_wait",
Stage::TransportBulkQueueWait => "transport_bulk_queue_wait",
Stage::EndpointPriorityEventWait => "endpoint_priority_event_wait",
Stage::EndpointBulkEventWait => "endpoint_bulk_event_wait",
Stage::TransportChannelWait => "transport_channel_wait",
Stage::TransportPriorityChannelWait => "transport_priority_channel_wait",
Stage::TransportBulkChannelWait => "transport_bulk_channel_wait",
Stage::DecryptFallbackWait => "decrypt_fallback_wait",
Stage::DecryptFallbackPriorityWait => "decrypt_fallback_priority_wait",
Stage::DecryptFallbackBulkWait => "decrypt_fallback_bulk_wait",
Stage::TransportRxLoopWait => "transport_rx_loop_wait",
Stage::TransportPriorityRxLoopWait => "transport_priority_rx_loop_wait",
Stage::TransportBulkRxLoopWait => "transport_bulk_rx_loop_wait",
Stage::DecryptWorkerQueueWait => "decrypt_worker_queue_wait",
Stage::DecryptWorkerPriorityQueueWait => "decrypt_worker_priority_queue_wait",
Stage::DecryptWorkerBulkQueueWait => "decrypt_worker_bulk_queue_wait",
Stage::EndpointPriorityCommandWait => "endpoint_priority_command_wait",
Stage::EndpointBulkCommandWait => "endpoint_bulk_command_wait",
Stage::DecryptAuthenticatedSessionWait => "decrypt_authenticated_session_wait",
Stage::DecryptAuthenticatedSessionPriorityWait => {
"decrypt_authenticated_session_priority_wait"
}
Stage::DecryptAuthenticatedSessionBulkWait => "decrypt_authenticated_session_bulk_wait",
Stage::DecryptFspWorkerQueueWait => "decrypt_fsp_worker_queue_wait",
Stage::DecryptFspWorkerPriorityQueueWait => "decrypt_fsp_worker_priority_queue_wait",
Stage::DecryptFspWorkerBulkQueueWait => "decrypt_fsp_worker_bulk_queue_wait",
Stage::FmpWorkerPriorityQueueWait => "fmp_worker_priority_queue_wait",
Stage::FmpWorkerBulkQueueWait => "fmp_worker_bulk_queue_wait",
Stage::DecryptFspWorkerService => "decrypt_fsp_worker_service",
Stage::DecryptFspWorkerBulkInputHeadWait => "decrypt_fsp_worker_bulk_input_head_wait",
Stage::DecryptFspWorkerBulkInputTailWait => "decrypt_fsp_worker_bulk_input_tail_wait",
Stage::FspAeadHelperQueueWait => "fsp_aead_helper_queue_wait",
Stage::FspAeadHelperCompletionWait => "fsp_aead_helper_completion_wait",
Stage::FmpWorkerFspSeal => "fmp_worker_fsp_seal",
Stage::FmpWorkerFmpSeal => "fmp_worker_fmp_seal",
Stage::FmpWorkerDispatch => "fmp_worker_dispatch",
Stage::DecryptWorkerBulkInputHeadWait => "decrypt_worker_bulk_input_head_wait",
Stage::DecryptWorkerBulkInputTailWait => "decrypt_worker_bulk_input_tail_wait",
Stage::DecryptWorkerBulkItemService => "decrypt_worker_bulk_item_service",
Stage::FmpAeadHelperQueueWait => "fmp_aead_helper_queue_wait",
Stage::FmpAeadHelperCompletionWait => "fmp_aead_helper_completion_wait",
Stage::FmpAeadHelperPriorityCompletionWait => {
"fmp_aead_helper_priority_completion_wait"
}
Stage::FmpAeadHelperBulkCompletionWait => "fmp_aead_helper_bulk_completion_wait",
Stage::FmpReceiveOrderWindowWait => "fmp_receive_order_window_wait",
Stage::FmpAeadHelperCompletionService => "fmp_aead_helper_completion_service",
Stage::DecryptWorkerOutputFlush => "decrypt_worker_output_flush",
Stage::FspAeadCompletionService => "fsp_aead_completion_service",
Stage::EndpointSendPrepare => "endpoint_send_prepare",
Stage::EndpointSendPlan => "endpoint_send_plan",
Stage::EndpointSendCommit => "endpoint_send_commit",
Stage::DecryptAuthenticatedFmpReceiveWait => "decrypt_authenticated_fmp_receive_wait",
Stage::FspAeadWorkerOpenQueueWait => "fsp_aead_worker_open_queue_wait",
Stage::FspAeadWorkerOpenCompletionWait => "fsp_aead_worker_open_completion_wait",
Stage::DecryptDirectSessionCommitWait => "decrypt_direct_session_commit_wait",
Stage::DecryptDirectSessionDataWait => "decrypt_direct_session_data_wait",
Stage::ConnectedUdpDrainRecv => "connected_udp_drain_recv",
Stage::ConnectedUdpFastPathDispatch => "connected_udp_fast_path_dispatch",
Stage::ConnectedUdpDrainRingWait => "connected_udp_drain_ring_wait",
Stage::ConnectedUdpDrainPriorityRingWait => "connected_udp_drain_priority_ring_wait",
Stage::ConnectedUdpDrainBulkRingWait => "connected_udp_drain_bulk_ring_wait",
}
}
}
fn stage_from_index(idx: usize) -> Stage {
match idx {
0 => Stage::UdpRecv,
1 => Stage::FmpDecrypt,
2 => Stage::LinkDispatch,
3 => Stage::FspDecrypt,
4 => Stage::TunWrite,
5 => Stage::FspEncrypt,
6 => Stage::FmpEncrypt,
7 => Stage::UdpSend,
8 => Stage::ProcessPacket,
9 => Stage::EndpointDeliver,
10 => Stage::FspHandle,
11 => Stage::EndpointSend,
12 => Stage::EndpointCommandWait,
13 => Stage::FmpWorkerQueueWait,
14 => Stage::TransportQueueWait,
15 => Stage::EndpointEventWait,
16 => Stage::TransportPriorityQueueWait,
17 => Stage::TransportBulkQueueWait,
18 => Stage::EndpointPriorityEventWait,
19 => Stage::EndpointBulkEventWait,
20 => Stage::TransportChannelWait,
21 => Stage::TransportPriorityChannelWait,
22 => Stage::TransportBulkChannelWait,
23 => Stage::DecryptFallbackWait,
24 => Stage::DecryptFallbackPriorityWait,
25 => Stage::DecryptFallbackBulkWait,
26 => Stage::TransportRxLoopWait,
27 => Stage::TransportPriorityRxLoopWait,
28 => Stage::TransportBulkRxLoopWait,
29 => Stage::DecryptWorkerQueueWait,
30 => Stage::DecryptWorkerPriorityQueueWait,
31 => Stage::DecryptWorkerBulkQueueWait,
32 => Stage::EndpointPriorityCommandWait,
33 => Stage::EndpointBulkCommandWait,
34 => Stage::DecryptAuthenticatedSessionWait,
35 => Stage::DecryptAuthenticatedSessionPriorityWait,
36 => Stage::DecryptAuthenticatedSessionBulkWait,
37 => Stage::DecryptFspWorkerQueueWait,
38 => Stage::DecryptFspWorkerPriorityQueueWait,
39 => Stage::DecryptFspWorkerBulkQueueWait,
40 => Stage::FmpWorkerPriorityQueueWait,
41 => Stage::FmpWorkerBulkQueueWait,
42 => Stage::DecryptFspWorkerService,
43 => Stage::DecryptFspWorkerBulkInputHeadWait,
44 => Stage::DecryptFspWorkerBulkInputTailWait,
45 => Stage::FspAeadHelperQueueWait,
46 => Stage::FspAeadHelperCompletionWait,
47 => Stage::FmpWorkerFspSeal,
48 => Stage::FmpWorkerFmpSeal,
49 => Stage::FmpWorkerDispatch,
50 => Stage::DecryptWorkerBulkInputHeadWait,
51 => Stage::DecryptWorkerBulkInputTailWait,
52 => Stage::DecryptWorkerBulkItemService,
53 => Stage::FmpAeadHelperQueueWait,
54 => Stage::FmpAeadHelperCompletionWait,
55 => Stage::FmpAeadHelperPriorityCompletionWait,
56 => Stage::FmpAeadHelperBulkCompletionWait,
57 => Stage::FmpReceiveOrderWindowWait,
58 => Stage::FmpAeadHelperCompletionService,
59 => Stage::DecryptWorkerOutputFlush,
60 => Stage::FspAeadCompletionService,
61 => Stage::EndpointSendPrepare,
62 => Stage::EndpointSendPlan,
63 => Stage::EndpointSendCommit,
64 => Stage::DecryptAuthenticatedFmpReceiveWait,
65 => Stage::FspAeadWorkerOpenQueueWait,
66 => Stage::FspAeadWorkerOpenCompletionWait,
67 => Stage::DecryptDirectSessionCommitWait,
68 => Stage::DecryptDirectSessionDataWait,
69 => Stage::ConnectedUdpDrainRecv,
70 => Stage::ConnectedUdpFastPathDispatch,
71 => Stage::ConnectedUdpDrainRingWait,
72 => Stage::ConnectedUdpDrainPriorityRingWait,
73 => Stage::ConnectedUdpDrainBulkRingWait,
_ => unreachable!(),
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(usize)]
pub enum Event {
UdpSendConnected = 0,
UdpSendWildcard = 1,
UdpSendBackpressure = 2,
ConnectedUdpInstalled = 3,
ConnectedUdpActivationFailed = 4,
UdpSendBackpressureSleep = 5,
ConnectedUdpPeerCapSkipped = 6,
EncryptWorkerQueueFull = 7,
EncryptWorkerBulkDropped = 8,
UdpSendBulkDropped = 9,
DecryptWorkerQueueFull = 10,
DecryptWorkerBulkDropped = 11,
DecryptWorkerRegisterFull = 12,
DecryptWorkerPriorityDropped = 13,
DecryptFallbackBulkDropped = 14,
DecryptFallbackPriorityDropped = 15,
PendingTunDestinationDropped = 16,
PendingTunPacketDropped = 17,
PendingEndpointDestinationDropped = 18,
PendingEndpointPacketDropped = 19,
ConnectedUdpFdBudgetSkipped = 20,
EndpointEventBacklogHigh = 21,
EndpointCommandBulkDropped = 22,
TransportChannelBacklogHigh = 23,
TransportBulkDropped = 24,
EndpointEventBulkDropped = 25,
ConnectedUdpDirectDecrypt = 26,
ConnectedUdpDirectDecryptMiss = 27,
DecryptFallbackBacklogHigh = 28,
RxLoopSlowMaintenanceTimeout = 29,
RxLoopSlowMaintenanceSkipped = 30,
DecryptFallbackPressureDrain = 31,
DecryptFallbackPriorityGated = 32,
DecryptFspPriorityQueueFullFallback = 33,
DecryptFspBulkQueueFullFallback = 34,
DecryptFspWorkerReplayDropped = 35,
DecryptAuthenticatedSessionPriorityDropped = 36,
DecryptAuthenticatedSessionBulkDropped = 37,
FmpWorkerBatchFlush = 38,
FmpWorkerBatchPackets = 39,
FmpWorkerBatchFull = 40,
FmpWorkerBatchSingle = 41,
FmpWorkerBatchPriorityPackets = 42,
FmpWorkerBatchBulkPackets = 43,
UdpSendGsoBatch = 44,
UdpSendGsoPackets = 45,
UdpSendSendmmsgBatch = 46,
UdpSendSendmmsgPackets = 47,
DecryptWorkerBatchFlush = 48,
DecryptWorkerBatchPackets = 49,
DecryptWorkerBatchFull = 50,
DecryptWorkerBatchSingle = 51,
DecryptWorkerBatchPriorityPackets = 52,
DecryptWorkerBatchBulkPackets = 53,
UdpSendGsoBatchGe32 = 54,
UdpSendGsoBatchGe48 = 55,
UdpSendGsoBatchEq64 = 56,
UdpSendSendmmsgBatchGe32 = 57,
UdpSendSendmmsgBatchGe48 = 58,
UdpSendSendmmsgBatchEq64 = 59,
FmpSendGroup = 60,
FmpSendGroupPackets = 61,
FmpSendGroupSingle = 62,
EncryptWorkerPriorityQueueFull = 63,
EncryptWorkerBulkQueueFull = 64,
FmpWorkerDispatchBatch = 65,
FmpWorkerDispatchPackets = 66,
DecryptWorkerBulkInputWaitGe250us = 67,
DecryptWorkerBulkInputWaitGe500us = 68,
DecryptWorkerBulkInputWaitGe1ms = 69,
DecryptFspOwnerSame = 70,
DecryptFspOwnerMismatch = 71,
DecryptFspPathLocal = 72,
DecryptFspPathHandoff = 73,
DecryptFspPathHelper = 74,
DecryptFspPathFallback = 75,
DecryptFmpPreownerHelper = 76,
DecryptFmpPreownerHelperFallback = 77,
DecryptFmpPreownerWindowFallback = 78,
DecryptFmpPreownerInlineFallback = 79,
FmpWorkerDispatchFlowKeyed = 80,
FmpWorkerDispatchTargetOnly = 81,
FmpWorkerDispatchWorker0 = 82,
FmpWorkerDispatchWorker1 = 83,
FmpWorkerDispatchWorker2 = 84,
FmpWorkerDispatchWorker3 = 85,
FmpWorkerDispatchWorker4 = 86,
FmpWorkerDispatchWorker5 = 87,
FmpWorkerDispatchWorker6 = 88,
FmpWorkerDispatchWorker7 = 89,
FmpWorkerDispatchWorkerOther = 90,
FmpAeadCompletionReady = 91,
FmpAeadCompletionAccepted = 92,
FmpAeadCompletionAeadFailed = 93,
FmpAeadCompletionReplayDropped = 94,
FmpAeadCompletionReadyMulti = 95,
FspAeadCompletionReady = 96,
FspAeadCompletionAccepted = 97,
FspAeadCompletionAeadFailed = 98,
FspAeadCompletionReplayDropped = 99,
FspAeadCompletionReadyMulti = 100,
EndpointBulkFastPathPrepareFailed = 101,
EndpointBulkFastPathStageFull = 102,
EndpointBulkFastPathFeedbackFull = 103,
EndpointBulkFastPathAttempt = 104,
EndpointBulkFastPathDispatched = 105,
EndpointBulkFastPathLeaseMiss = 106,
EndpointBulkFastPathIneligible = 107,
LinuxWgBatchChunk = 108,
LinuxWgBatchChunkPackets = 109,
LinuxWgBatchChunkFull = 110,
LinuxWgBatchSenderWaitGe250us = 111,
LinuxWgBatchSenderWaitGe1ms = 112,
LinuxWgBatchSenderWaitGe4ms = 113,
FmpSendGroupSplitTarget = 114,
FmpSendGroupSplitLane = 115,
FmpSendGroupSplitBackpressure = 116,
FmpSendGroupSplitPacketCap = 117,
EndpointCommittedBulkDispatchBatch = 118,
EndpointCommittedBulkDispatchPackets = 119,
EndpointCommittedBulkDispatchMergedBatch = 120,
EndpointCommittedBulkDispatchMergedPackets = 121,
FspAeadCompletionStaleSession = 122,
FspAeadCompletionStaleOrder = 123,
FspAeadCompletionStaleTicket = 124,
FspAeadCompletionDuplicateTicket = 125,
FspAeadCompletionWindowExceeded = 126,
DecryptFspOpenWorkerWindowFallback = 127,
DecryptWorkerSelectPriority = 128,
DecryptWorkerSelectFmpCompletion = 129,
DecryptWorkerSelectFspCompletionPackets = 130,
DecryptWorkerSelectBulkPackets = 131,
DecryptWorkerDrainPriority = 132,
DecryptWorkerDrainAeadCompletionPackets = 133,
DecryptWorkerDrainBulkPackets = 134,
DecryptWorkerBulkInterleaveAeadCompletionPackets = 135,
DecryptWorkerBulkInterleaveBudgetExhausted = 136,
DecryptFspPathWorkerOpen = 137,
DecryptWorkerControlDropped = 138,
DecryptWorkerSelectControl = 139,
DecryptWorkerDrainControl = 140,
DecryptFspHelperCompletionBacklogFallback = 141,
DecryptFspHelperQueueFullFallback = 142,
DecryptFmpHelperCompletionBacklogFallback = 143,
DecryptFmpPreownerCompletionBacklogFallback = 144,
DecryptFspOpenWorkerCompletionBacklogFallback = 145,
FspAeadCompletionReplayDroppedHelper = 146,
FspAeadCompletionReplayDroppedHelperReturned = 147,
FspAeadCompletionReplayDroppedWorkerOpen = 148,
FspAeadCompletionReplayDroppedWorkerOpenReturned = 149,
FspAeadCompletionReplayDroppedDuplicate = 150,
FspAeadCompletionReplayDroppedTooOld = 151,
FspAeadCompletionReplayDroppedTooOldLagGe2xWindow = 152,
FspAeadCompletionReplayDroppedTooOldLagGe4xWindow = 153,
FspAeadCompletionReplayDroppedTooOldLagGe16xWindow = 154,
FspAeadCompletionReplayDroppedTooOldLagGe64xWindow = 155,
ConnectedUdpDirectDecryptBulkShed = 156,
DecryptFspOpenPoolQueueFullFallback = 157,
ConnectedUdpKernelDropped = 158,
ConnectedUdpPeerKernelDropped = 159,
DecryptFspPathWorkerOpenStriped = 160,
DecryptAuthenticatedBacklogHigh = 161,
EndpointEventBulkBacklogHigh = 162,
PacketBatchPoolFresh = 163,
PacketBatchPoolReuse = 164,
PacketBatchPoolReturn = 165,
PacketBatchPoolDiscard = 166,
PacketBufferPoolFresh = 167,
PacketBufferPoolReuse = 168,
PacketBufferPoolReturn = 169,
PacketBufferPoolDiscard = 170,
LinuxBulkUdpPaceWait = 171,
UdpKernelDropped = 172,
UdpSocketKernelDropped = 173,
UdpNamespaceRcvbufErrors = 174,
ConnectedUdpDrainBulkDropped = 175,
DecryptFspWorkerReplayDroppedDuplicate = 176,
DecryptFspWorkerReplayDroppedTooOld = 177,
DecryptFspWorkerReplayDroppedTooOldLagGe2xWindow = 178,
DecryptFspWorkerReplayDroppedTooOldLagGe4xWindow = 179,
DecryptFspWorkerReplayDroppedTooOldLagGe16xWindow = 180,
DecryptFspWorkerReplayDroppedTooOldLagGe64xWindow = 181,
DecryptFspPathLocalPriority = 182,
DecryptFspPathLocalBulk = 183,
DecryptFspPathHandoffPriority = 184,
DecryptFspPathHandoffBulk = 185,
DecryptFspPathHelperBulk = 186,
DecryptFspPathWorkerOpenBulk = 187,
FspAeadCompletionReturnedHelper = 188,
FspAeadCompletionReturnedWorkerOpen = 189,
DecryptFspOwnerHandoffDropped = 190,
FmpAeadCompletionReplayDroppedPrechecked = 191,
FmpAeadCompletionReplayDroppedDeferred = 192,
FmpAeadCompletionReplayDroppedDuplicate = 193,
FmpAeadCompletionReplayDroppedTooOld = 194,
FmpAeadCompletionReplayDroppedTooOldLagGe2xWindow = 195,
FmpAeadCompletionReplayDroppedTooOldLagGe4xWindow = 196,
FmpAeadCompletionReplayDroppedTooOldLagGe16xWindow = 197,
FmpAeadCompletionReplayDroppedTooOldLagGe64xWindow = 198,
DecryptFspMalformedDropped = 199,
FspAeadCompletionAeadFailedLocal = 200,
FspAeadCompletionAeadFailedHelper = 201,
FspAeadCompletionAeadFailedHelperReturned = 202,
FspAeadCompletionAeadFailedWorkerOpen = 203,
FspAeadCompletionAeadFailedWorkerOpenReturned = 204,
FspAeadCompletionEpochMismatch = 205,
FspAeadCompletionAeadFailedLocalOpen = 206,
FspAeadCompletionAeadFailedAcceptKbitMismatch = 207,
DecryptWorkerSelectFspCompletionBatch = 208,
DecryptWorkerDrainAeadCompletionBatch = 209,
DecryptWorkerBulkInterleaveAeadCompletionBatch = 210,
DecryptWorkerBatchWorker0 = 211,
DecryptWorkerBatchWorker1 = 212,
DecryptWorkerBatchWorker2 = 213,
DecryptWorkerBatchWorker3 = 214,
DecryptWorkerBatchWorker4 = 215,
DecryptWorkerBatchWorker5 = 216,
DecryptWorkerBatchWorker6 = 217,
DecryptWorkerBatchWorker7 = 218,
DecryptWorkerBatchWorkerOther = 219,
FspAeadCompletionStaleEpochWorkerOpen = 220,
}
impl Event {
const fn name(self) -> &'static str {
match self {
Event::UdpSendConnected => "udp_send_connected",
Event::UdpSendWildcard => "udp_send_wildcard",
Event::UdpSendBackpressure => "udp_send_backpressure",
Event::ConnectedUdpInstalled => "connected_udp_installed",
Event::ConnectedUdpActivationFailed => "connected_udp_activation_failed",
Event::UdpSendBackpressureSleep => "udp_send_backpressure_sleep",
Event::ConnectedUdpPeerCapSkipped => "connected_udp_peer_cap_skipped",
Event::EncryptWorkerQueueFull => "encrypt_worker_queue_full",
Event::EncryptWorkerBulkDropped => "encrypt_worker_bulk_dropped",
Event::UdpSendBulkDropped => "udp_send_bulk_dropped",
Event::DecryptWorkerQueueFull => "decrypt_worker_queue_full",
Event::DecryptWorkerBulkDropped => "decrypt_worker_bulk_dropped",
Event::DecryptWorkerRegisterFull => "decrypt_worker_register_full",
Event::DecryptWorkerPriorityDropped => "decrypt_worker_priority_dropped",
Event::DecryptFallbackBulkDropped => "decrypt_fallback_bulk_dropped",
Event::DecryptFallbackPriorityDropped => "decrypt_fallback_priority_dropped",
Event::PendingTunDestinationDropped => "pending_tun_destination_dropped",
Event::PendingTunPacketDropped => "pending_tun_packet_dropped",
Event::PendingEndpointDestinationDropped => "pending_endpoint_destination_dropped",
Event::PendingEndpointPacketDropped => "pending_endpoint_packet_dropped",
Event::ConnectedUdpFdBudgetSkipped => "connected_udp_fd_budget_skipped",
Event::EndpointEventBacklogHigh => "endpoint_event_backlog_high",
Event::EndpointCommandBulkDropped => "endpoint_command_bulk_dropped",
Event::TransportChannelBacklogHigh => "transport_channel_backlog_high",
Event::TransportBulkDropped => "transport_bulk_dropped",
Event::EndpointEventBulkDropped => "endpoint_event_bulk_dropped",
Event::ConnectedUdpDirectDecrypt => "connected_udp_direct_decrypt",
Event::ConnectedUdpDirectDecryptMiss => "connected_udp_direct_decrypt_miss",
Event::DecryptFallbackBacklogHigh => "decrypt_fallback_backlog_high",
Event::RxLoopSlowMaintenanceTimeout => "rx_loop_slow_maintenance_timeout",
Event::RxLoopSlowMaintenanceSkipped => "rx_loop_slow_maintenance_skipped",
Event::DecryptFallbackPressureDrain => "decrypt_fallback_pressure_drain",
Event::DecryptFallbackPriorityGated => "decrypt_fallback_priority_gated",
Event::DecryptFspPriorityQueueFullFallback => {
"decrypt_fsp_priority_queue_full_fallback"
}
Event::DecryptFspBulkQueueFullFallback => "decrypt_fsp_bulk_queue_full_fallback",
Event::DecryptFspWorkerReplayDropped => "decrypt_fsp_worker_replay_dropped",
Event::DecryptAuthenticatedSessionPriorityDropped => {
"decrypt_authenticated_session_priority_dropped"
}
Event::DecryptAuthenticatedSessionBulkDropped => {
"decrypt_authenticated_session_bulk_dropped"
}
Event::FmpWorkerBatchFlush => "fmp_worker_batch_flush",
Event::FmpWorkerBatchPackets => "fmp_worker_batch_packets",
Event::FmpWorkerBatchFull => "fmp_worker_batch_full",
Event::FmpWorkerBatchSingle => "fmp_worker_batch_single",
Event::FmpWorkerBatchPriorityPackets => "fmp_worker_batch_priority_packets",
Event::FmpWorkerBatchBulkPackets => "fmp_worker_batch_bulk_packets",
Event::UdpSendGsoBatch => "udp_send_gso_batch",
Event::UdpSendGsoPackets => "udp_send_gso_packets",
Event::UdpSendSendmmsgBatch => "udp_send_sendmmsg_batch",
Event::UdpSendSendmmsgPackets => "udp_send_sendmmsg_packets",
Event::DecryptWorkerBatchFlush => "decrypt_worker_batch_flush",
Event::DecryptWorkerBatchPackets => "decrypt_worker_batch_packets",
Event::DecryptWorkerBatchFull => "decrypt_worker_batch_full",
Event::DecryptWorkerBatchSingle => "decrypt_worker_batch_single",
Event::DecryptWorkerBatchPriorityPackets => "decrypt_worker_batch_priority_packets",
Event::DecryptWorkerBatchBulkPackets => "decrypt_worker_batch_bulk_packets",
Event::UdpSendGsoBatchGe32 => "udp_send_gso_batch_ge32",
Event::UdpSendGsoBatchGe48 => "udp_send_gso_batch_ge48",
Event::UdpSendGsoBatchEq64 => "udp_send_gso_batch_eq64",
Event::UdpSendSendmmsgBatchGe32 => "udp_send_sendmmsg_batch_ge32",
Event::UdpSendSendmmsgBatchGe48 => "udp_send_sendmmsg_batch_ge48",
Event::UdpSendSendmmsgBatchEq64 => "udp_send_sendmmsg_batch_eq64",
Event::FmpSendGroup => "fmp_send_group",
Event::FmpSendGroupPackets => "fmp_send_group_packets",
Event::FmpSendGroupSingle => "fmp_send_group_single",
Event::EncryptWorkerPriorityQueueFull => "encrypt_worker_priority_queue_full",
Event::EncryptWorkerBulkQueueFull => "encrypt_worker_bulk_queue_full",
Event::FmpWorkerDispatchBatch => "fmp_worker_dispatch_batch",
Event::FmpWorkerDispatchPackets => "fmp_worker_dispatch_packets",
Event::DecryptWorkerBulkInputWaitGe250us => "decrypt_worker_bulk_input_wait_ge250us",
Event::DecryptWorkerBulkInputWaitGe500us => "decrypt_worker_bulk_input_wait_ge500us",
Event::DecryptWorkerBulkInputWaitGe1ms => "decrypt_worker_bulk_input_wait_ge1ms",
Event::DecryptFspOwnerSame => "decrypt_fsp_owner_same",
Event::DecryptFspOwnerMismatch => "decrypt_fsp_owner_mismatch",
Event::DecryptFspPathLocal => "decrypt_fsp_path_local",
Event::DecryptFspPathHandoff => "decrypt_fsp_path_handoff",
Event::DecryptFspPathHelper => "decrypt_fsp_path_helper",
Event::DecryptFspPathFallback => "decrypt_fsp_path_fallback",
Event::DecryptFmpPreownerHelper => "decrypt_fmp_preowner_helper",
Event::DecryptFmpPreownerHelperFallback => "decrypt_fmp_preowner_helper_fallback",
Event::DecryptFmpPreownerWindowFallback => "decrypt_fmp_preowner_window_fallback",
Event::DecryptFmpPreownerInlineFallback => "decrypt_fmp_preowner_inline_fallback",
Event::FmpWorkerDispatchFlowKeyed => "fmp_worker_dispatch_flow_keyed",
Event::FmpWorkerDispatchTargetOnly => "fmp_worker_dispatch_target_only",
Event::FmpWorkerDispatchWorker0 => "fmp_worker_dispatch_worker0",
Event::FmpWorkerDispatchWorker1 => "fmp_worker_dispatch_worker1",
Event::FmpWorkerDispatchWorker2 => "fmp_worker_dispatch_worker2",
Event::FmpWorkerDispatchWorker3 => "fmp_worker_dispatch_worker3",
Event::FmpWorkerDispatchWorker4 => "fmp_worker_dispatch_worker4",
Event::FmpWorkerDispatchWorker5 => "fmp_worker_dispatch_worker5",
Event::FmpWorkerDispatchWorker6 => "fmp_worker_dispatch_worker6",
Event::FmpWorkerDispatchWorker7 => "fmp_worker_dispatch_worker7",
Event::FmpWorkerDispatchWorkerOther => "fmp_worker_dispatch_worker_other",
Event::FmpAeadCompletionReady => "fmp_aead_completion_ready",
Event::FmpAeadCompletionAccepted => "fmp_aead_completion_accepted",
Event::FmpAeadCompletionAeadFailed => "fmp_aead_completion_aead_failed",
Event::FmpAeadCompletionReplayDropped => "fmp_aead_completion_replay_dropped",
Event::FmpAeadCompletionReadyMulti => "fmp_aead_completion_ready_multi",
Event::FspAeadCompletionReady => "fsp_aead_completion_ready",
Event::FspAeadCompletionAccepted => "fsp_aead_completion_accepted",
Event::FspAeadCompletionAeadFailed => "fsp_aead_completion_aead_failed",
Event::FspAeadCompletionReplayDropped => "fsp_aead_completion_replay_dropped",
Event::FspAeadCompletionReadyMulti => "fsp_aead_completion_ready_multi",
Event::EndpointBulkFastPathPrepareFailed => "endpoint_bulk_fast_path_prepare_failed",
Event::EndpointBulkFastPathStageFull => "endpoint_bulk_fast_path_stage_full",
Event::EndpointBulkFastPathFeedbackFull => "endpoint_bulk_fast_path_feedback_full",
Event::EndpointBulkFastPathAttempt => "endpoint_bulk_fast_path_attempt",
Event::EndpointBulkFastPathDispatched => "endpoint_bulk_fast_path_dispatched",
Event::EndpointBulkFastPathLeaseMiss => "endpoint_bulk_fast_path_lease_miss",
Event::EndpointBulkFastPathIneligible => "endpoint_bulk_fast_path_ineligible",
Event::LinuxWgBatchChunk => "linux_wg_batch_chunk",
Event::LinuxWgBatchChunkPackets => "linux_wg_batch_chunk_packets",
Event::LinuxWgBatchChunkFull => "linux_wg_batch_chunk_full",
Event::LinuxWgBatchSenderWaitGe250us => "linux_wg_batch_sender_wait_ge250us",
Event::LinuxWgBatchSenderWaitGe1ms => "linux_wg_batch_sender_wait_ge1ms",
Event::LinuxWgBatchSenderWaitGe4ms => "linux_wg_batch_sender_wait_ge4ms",
Event::FmpSendGroupSplitTarget => "fmp_send_group_split_target",
Event::FmpSendGroupSplitLane => "fmp_send_group_split_lane",
Event::FmpSendGroupSplitBackpressure => "fmp_send_group_split_backpressure",
Event::FmpSendGroupSplitPacketCap => "fmp_send_group_split_packet_cap",
Event::EndpointCommittedBulkDispatchBatch => "endpoint_committed_bulk_dispatch_batch",
Event::EndpointCommittedBulkDispatchPackets => {
"endpoint_committed_bulk_dispatch_packets"
}
Event::EndpointCommittedBulkDispatchMergedBatch => {
"endpoint_committed_bulk_dispatch_merged_batch"
}
Event::EndpointCommittedBulkDispatchMergedPackets => {
"endpoint_committed_bulk_dispatch_merged_packets"
}
Event::FspAeadCompletionStaleSession => "fsp_aead_completion_stale_session",
Event::FspAeadCompletionStaleOrder => "fsp_aead_completion_stale_order",
Event::FspAeadCompletionStaleTicket => "fsp_aead_completion_stale_ticket",
Event::FspAeadCompletionDuplicateTicket => "fsp_aead_completion_duplicate_ticket",
Event::FspAeadCompletionWindowExceeded => "fsp_aead_completion_window_exceeded",
Event::DecryptFspOpenWorkerWindowFallback => "decrypt_fsp_open_worker_window_fallback",
Event::DecryptWorkerSelectPriority => "decrypt_worker_select_priority",
Event::DecryptWorkerSelectFmpCompletion => "decrypt_worker_select_fmp_completion",
Event::DecryptWorkerSelectFspCompletionPackets => {
"decrypt_worker_select_fsp_completion_packets"
}
Event::DecryptWorkerSelectBulkPackets => "decrypt_worker_select_bulk_packets",
Event::DecryptWorkerDrainPriority => "decrypt_worker_drain_priority",
Event::DecryptWorkerDrainAeadCompletionPackets => {
"decrypt_worker_drain_aead_completion_packets"
}
Event::DecryptWorkerDrainBulkPackets => "decrypt_worker_drain_bulk_packets",
Event::DecryptWorkerBulkInterleaveAeadCompletionPackets => {
"decrypt_worker_bulk_interleave_aead_completion_packets"
}
Event::DecryptWorkerBulkInterleaveBudgetExhausted => {
"decrypt_worker_bulk_interleave_budget_exhausted"
}
Event::DecryptFspPathWorkerOpen => "decrypt_fsp_path_worker_open",
Event::DecryptFspPathWorkerOpenStriped => "decrypt_fsp_path_worker_open_striped",
Event::DecryptWorkerControlDropped => "decrypt_worker_control_dropped",
Event::DecryptWorkerSelectControl => "decrypt_worker_select_control",
Event::DecryptWorkerDrainControl => "decrypt_worker_drain_control",
Event::DecryptFspHelperCompletionBacklogFallback => {
"decrypt_fsp_helper_completion_backlog_fallback"
}
Event::DecryptFspHelperQueueFullFallback => "decrypt_fsp_helper_queue_full_fallback",
Event::DecryptFmpHelperCompletionBacklogFallback => {
"decrypt_fmp_helper_completion_backlog_fallback"
}
Event::DecryptFmpPreownerCompletionBacklogFallback => {
"decrypt_fmp_preowner_completion_backlog_fallback"
}
Event::DecryptFspOpenWorkerCompletionBacklogFallback => {
"decrypt_fsp_open_worker_completion_backlog_fallback"
}
Event::FspAeadCompletionReplayDroppedHelper => {
"fsp_aead_completion_replay_dropped_helper"
}
Event::FspAeadCompletionReplayDroppedHelperReturned => {
"fsp_aead_completion_replay_dropped_helper_returned"
}
Event::FspAeadCompletionReplayDroppedWorkerOpen => {
"fsp_aead_completion_replay_dropped_worker_open"
}
Event::FspAeadCompletionReplayDroppedWorkerOpenReturned => {
"fsp_aead_completion_replay_dropped_worker_open_returned"
}
Event::FspAeadCompletionReplayDroppedDuplicate => {
"fsp_aead_completion_replay_dropped_duplicate"
}
Event::FspAeadCompletionReplayDroppedTooOld => {
"fsp_aead_completion_replay_dropped_too_old"
}
Event::FspAeadCompletionReplayDroppedTooOldLagGe2xWindow => {
"fsp_aead_completion_replay_dropped_too_old_lag_ge_2x_window"
}
Event::FspAeadCompletionReplayDroppedTooOldLagGe4xWindow => {
"fsp_aead_completion_replay_dropped_too_old_lag_ge_4x_window"
}
Event::FspAeadCompletionReplayDroppedTooOldLagGe16xWindow => {
"fsp_aead_completion_replay_dropped_too_old_lag_ge_16x_window"
}
Event::FspAeadCompletionReplayDroppedTooOldLagGe64xWindow => {
"fsp_aead_completion_replay_dropped_too_old_lag_ge_64x_window"
}
Event::ConnectedUdpDirectDecryptBulkShed => "connected_udp_direct_decrypt_bulk_shed",
Event::DecryptFspOpenPoolQueueFullFallback => {
"decrypt_fsp_open_pool_queue_full_fallback"
}
Event::ConnectedUdpKernelDropped => "connected_udp_kernel_dropped",
Event::ConnectedUdpPeerKernelDropped => "connected_udp_peer_kernel_dropped",
Event::DecryptAuthenticatedBacklogHigh => "decrypt_authenticated_backlog_high",
Event::EndpointEventBulkBacklogHigh => "endpoint_event_bulk_backlog_high",
Event::PacketBatchPoolFresh => "packet_batch_pool_fresh",
Event::PacketBatchPoolReuse => "packet_batch_pool_reuse",
Event::PacketBatchPoolReturn => "packet_batch_pool_return",
Event::PacketBatchPoolDiscard => "packet_batch_pool_discard",
Event::PacketBufferPoolFresh => "packet_buffer_pool_fresh",
Event::PacketBufferPoolReuse => "packet_buffer_pool_reuse",
Event::PacketBufferPoolReturn => "packet_buffer_pool_return",
Event::PacketBufferPoolDiscard => "packet_buffer_pool_discard",
Event::LinuxBulkUdpPaceWait => "linux_bulk_udp_pace_wait",
Event::UdpKernelDropped => "udp_kernel_dropped",
Event::UdpSocketKernelDropped => "udp_socket_kernel_dropped",
Event::UdpNamespaceRcvbufErrors => "udp_namespace_rcvbuf_errors",
Event::ConnectedUdpDrainBulkDropped => "connected_udp_drain_bulk_dropped",
Event::DecryptFspWorkerReplayDroppedDuplicate => {
"decrypt_fsp_worker_replay_dropped_duplicate"
}
Event::DecryptFspWorkerReplayDroppedTooOld => {
"decrypt_fsp_worker_replay_dropped_too_old"
}
Event::DecryptFspWorkerReplayDroppedTooOldLagGe2xWindow => {
"decrypt_fsp_worker_replay_dropped_too_old_lag_ge_2x_window"
}
Event::DecryptFspWorkerReplayDroppedTooOldLagGe4xWindow => {
"decrypt_fsp_worker_replay_dropped_too_old_lag_ge_4x_window"
}
Event::DecryptFspWorkerReplayDroppedTooOldLagGe16xWindow => {
"decrypt_fsp_worker_replay_dropped_too_old_lag_ge_16x_window"
}
Event::DecryptFspWorkerReplayDroppedTooOldLagGe64xWindow => {
"decrypt_fsp_worker_replay_dropped_too_old_lag_ge_64x_window"
}
Event::DecryptFspPathLocalPriority => "decrypt_fsp_path_local_priority",
Event::DecryptFspPathLocalBulk => "decrypt_fsp_path_local_bulk",
Event::DecryptFspPathHandoffPriority => "decrypt_fsp_path_handoff_priority",
Event::DecryptFspPathHandoffBulk => "decrypt_fsp_path_handoff_bulk",
Event::DecryptFspPathHelperBulk => "decrypt_fsp_path_helper_bulk",
Event::DecryptFspPathWorkerOpenBulk => "decrypt_fsp_path_worker_open_bulk",
Event::FspAeadCompletionReturnedHelper => "fsp_aead_completion_returned_helper",
Event::FspAeadCompletionReturnedWorkerOpen => {
"fsp_aead_completion_returned_worker_open"
}
Event::DecryptFspOwnerHandoffDropped => "decrypt_fsp_owner_handoff_dropped",
Event::FmpAeadCompletionReplayDroppedPrechecked => {
"fmp_aead_completion_replay_dropped_prechecked"
}
Event::FmpAeadCompletionReplayDroppedDeferred => {
"fmp_aead_completion_replay_dropped_deferred"
}
Event::FmpAeadCompletionReplayDroppedDuplicate => {
"fmp_aead_completion_replay_dropped_duplicate"
}
Event::FmpAeadCompletionReplayDroppedTooOld => {
"fmp_aead_completion_replay_dropped_too_old"
}
Event::FmpAeadCompletionReplayDroppedTooOldLagGe2xWindow => {
"fmp_aead_completion_replay_dropped_too_old_lag_ge_2x_window"
}
Event::FmpAeadCompletionReplayDroppedTooOldLagGe4xWindow => {
"fmp_aead_completion_replay_dropped_too_old_lag_ge_4x_window"
}
Event::FmpAeadCompletionReplayDroppedTooOldLagGe16xWindow => {
"fmp_aead_completion_replay_dropped_too_old_lag_ge_16x_window"
}
Event::FmpAeadCompletionReplayDroppedTooOldLagGe64xWindow => {
"fmp_aead_completion_replay_dropped_too_old_lag_ge_64x_window"
}
Event::DecryptFspMalformedDropped => "decrypt_fsp_malformed_dropped",
Event::FspAeadCompletionAeadFailedLocal => "fsp_aead_completion_aead_failed_local",
Event::FspAeadCompletionAeadFailedHelper => "fsp_aead_completion_aead_failed_helper",
Event::FspAeadCompletionAeadFailedHelperReturned => {
"fsp_aead_completion_aead_failed_helper_returned"
}
Event::FspAeadCompletionAeadFailedWorkerOpen => {
"fsp_aead_completion_aead_failed_worker_open"
}
Event::FspAeadCompletionAeadFailedWorkerOpenReturned => {
"fsp_aead_completion_aead_failed_worker_open_returned"
}
Event::FspAeadCompletionEpochMismatch => "fsp_aead_completion_epoch_mismatch",
Event::FspAeadCompletionAeadFailedLocalOpen => {
"fsp_aead_completion_aead_failed_local_open"
}
Event::FspAeadCompletionAeadFailedAcceptKbitMismatch => {
"fsp_aead_completion_aead_failed_accept_kbit_mismatch"
}
Event::DecryptWorkerSelectFspCompletionBatch => {
"decrypt_worker_select_fsp_completion_batch"
}
Event::DecryptWorkerDrainAeadCompletionBatch => {
"decrypt_worker_drain_aead_completion_batch"
}
Event::DecryptWorkerBulkInterleaveAeadCompletionBatch => {
"decrypt_worker_bulk_interleave_aead_completion_batch"
}
Event::DecryptWorkerBatchWorker0 => "decrypt_worker_batch_worker0",
Event::DecryptWorkerBatchWorker1 => "decrypt_worker_batch_worker1",
Event::DecryptWorkerBatchWorker2 => "decrypt_worker_batch_worker2",
Event::DecryptWorkerBatchWorker3 => "decrypt_worker_batch_worker3",
Event::DecryptWorkerBatchWorker4 => "decrypt_worker_batch_worker4",
Event::DecryptWorkerBatchWorker5 => "decrypt_worker_batch_worker5",
Event::DecryptWorkerBatchWorker6 => "decrypt_worker_batch_worker6",
Event::DecryptWorkerBatchWorker7 => "decrypt_worker_batch_worker7",
Event::DecryptWorkerBatchWorkerOther => "decrypt_worker_batch_worker_other",
Event::FspAeadCompletionStaleEpochWorkerOpen => {
"fsp_aead_completion_stale_epoch_worker_open"
}
}
}
}
fn event_from_index(idx: usize) -> Event {
match idx {
0 => Event::UdpSendConnected,
1 => Event::UdpSendWildcard,
2 => Event::UdpSendBackpressure,
3 => Event::ConnectedUdpInstalled,
4 => Event::ConnectedUdpActivationFailed,
5 => Event::UdpSendBackpressureSleep,
6 => Event::ConnectedUdpPeerCapSkipped,
7 => Event::EncryptWorkerQueueFull,
8 => Event::EncryptWorkerBulkDropped,
9 => Event::UdpSendBulkDropped,
10 => Event::DecryptWorkerQueueFull,
11 => Event::DecryptWorkerBulkDropped,
12 => Event::DecryptWorkerRegisterFull,
13 => Event::DecryptWorkerPriorityDropped,
14 => Event::DecryptFallbackBulkDropped,
15 => Event::DecryptFallbackPriorityDropped,
16 => Event::PendingTunDestinationDropped,
17 => Event::PendingTunPacketDropped,
18 => Event::PendingEndpointDestinationDropped,
19 => Event::PendingEndpointPacketDropped,
20 => Event::ConnectedUdpFdBudgetSkipped,
21 => Event::EndpointEventBacklogHigh,
22 => Event::EndpointCommandBulkDropped,
23 => Event::TransportChannelBacklogHigh,
24 => Event::TransportBulkDropped,
25 => Event::EndpointEventBulkDropped,
26 => Event::ConnectedUdpDirectDecrypt,
27 => Event::ConnectedUdpDirectDecryptMiss,
28 => Event::DecryptFallbackBacklogHigh,
29 => Event::RxLoopSlowMaintenanceTimeout,
30 => Event::RxLoopSlowMaintenanceSkipped,
31 => Event::DecryptFallbackPressureDrain,
32 => Event::DecryptFallbackPriorityGated,
33 => Event::DecryptFspPriorityQueueFullFallback,
34 => Event::DecryptFspBulkQueueFullFallback,
35 => Event::DecryptFspWorkerReplayDropped,
36 => Event::DecryptAuthenticatedSessionPriorityDropped,
37 => Event::DecryptAuthenticatedSessionBulkDropped,
38 => Event::FmpWorkerBatchFlush,
39 => Event::FmpWorkerBatchPackets,
40 => Event::FmpWorkerBatchFull,
41 => Event::FmpWorkerBatchSingle,
42 => Event::FmpWorkerBatchPriorityPackets,
43 => Event::FmpWorkerBatchBulkPackets,
44 => Event::UdpSendGsoBatch,
45 => Event::UdpSendGsoPackets,
46 => Event::UdpSendSendmmsgBatch,
47 => Event::UdpSendSendmmsgPackets,
48 => Event::DecryptWorkerBatchFlush,
49 => Event::DecryptWorkerBatchPackets,
50 => Event::DecryptWorkerBatchFull,
51 => Event::DecryptWorkerBatchSingle,
52 => Event::DecryptWorkerBatchPriorityPackets,
53 => Event::DecryptWorkerBatchBulkPackets,
54 => Event::UdpSendGsoBatchGe32,
55 => Event::UdpSendGsoBatchGe48,
56 => Event::UdpSendGsoBatchEq64,
57 => Event::UdpSendSendmmsgBatchGe32,
58 => Event::UdpSendSendmmsgBatchGe48,
59 => Event::UdpSendSendmmsgBatchEq64,
60 => Event::FmpSendGroup,
61 => Event::FmpSendGroupPackets,
62 => Event::FmpSendGroupSingle,
63 => Event::EncryptWorkerPriorityQueueFull,
64 => Event::EncryptWorkerBulkQueueFull,
65 => Event::FmpWorkerDispatchBatch,
66 => Event::FmpWorkerDispatchPackets,
67 => Event::DecryptWorkerBulkInputWaitGe250us,
68 => Event::DecryptWorkerBulkInputWaitGe500us,
69 => Event::DecryptWorkerBulkInputWaitGe1ms,
70 => Event::DecryptFspOwnerSame,
71 => Event::DecryptFspOwnerMismatch,
72 => Event::DecryptFspPathLocal,
73 => Event::DecryptFspPathHandoff,
74 => Event::DecryptFspPathHelper,
75 => Event::DecryptFspPathFallback,
76 => Event::DecryptFmpPreownerHelper,
77 => Event::DecryptFmpPreownerHelperFallback,
78 => Event::DecryptFmpPreownerWindowFallback,
79 => Event::DecryptFmpPreownerInlineFallback,
80 => Event::FmpWorkerDispatchFlowKeyed,
81 => Event::FmpWorkerDispatchTargetOnly,
82 => Event::FmpWorkerDispatchWorker0,
83 => Event::FmpWorkerDispatchWorker1,
84 => Event::FmpWorkerDispatchWorker2,
85 => Event::FmpWorkerDispatchWorker3,
86 => Event::FmpWorkerDispatchWorker4,
87 => Event::FmpWorkerDispatchWorker5,
88 => Event::FmpWorkerDispatchWorker6,
89 => Event::FmpWorkerDispatchWorker7,
90 => Event::FmpWorkerDispatchWorkerOther,
91 => Event::FmpAeadCompletionReady,
92 => Event::FmpAeadCompletionAccepted,
93 => Event::FmpAeadCompletionAeadFailed,
94 => Event::FmpAeadCompletionReplayDropped,
95 => Event::FmpAeadCompletionReadyMulti,
96 => Event::FspAeadCompletionReady,
97 => Event::FspAeadCompletionAccepted,
98 => Event::FspAeadCompletionAeadFailed,
99 => Event::FspAeadCompletionReplayDropped,
100 => Event::FspAeadCompletionReadyMulti,
101 => Event::EndpointBulkFastPathPrepareFailed,
102 => Event::EndpointBulkFastPathStageFull,
103 => Event::EndpointBulkFastPathFeedbackFull,
104 => Event::EndpointBulkFastPathAttempt,
105 => Event::EndpointBulkFastPathDispatched,
106 => Event::EndpointBulkFastPathLeaseMiss,
107 => Event::EndpointBulkFastPathIneligible,
108 => Event::LinuxWgBatchChunk,
109 => Event::LinuxWgBatchChunkPackets,
110 => Event::LinuxWgBatchChunkFull,
111 => Event::LinuxWgBatchSenderWaitGe250us,
112 => Event::LinuxWgBatchSenderWaitGe1ms,
113 => Event::LinuxWgBatchSenderWaitGe4ms,
114 => Event::FmpSendGroupSplitTarget,
115 => Event::FmpSendGroupSplitLane,
116 => Event::FmpSendGroupSplitBackpressure,
117 => Event::FmpSendGroupSplitPacketCap,
118 => Event::EndpointCommittedBulkDispatchBatch,
119 => Event::EndpointCommittedBulkDispatchPackets,
120 => Event::EndpointCommittedBulkDispatchMergedBatch,
121 => Event::EndpointCommittedBulkDispatchMergedPackets,
122 => Event::FspAeadCompletionStaleSession,
123 => Event::FspAeadCompletionStaleOrder,
124 => Event::FspAeadCompletionStaleTicket,
125 => Event::FspAeadCompletionDuplicateTicket,
126 => Event::FspAeadCompletionWindowExceeded,
127 => Event::DecryptFspOpenWorkerWindowFallback,
128 => Event::DecryptWorkerSelectPriority,
129 => Event::DecryptWorkerSelectFmpCompletion,
130 => Event::DecryptWorkerSelectFspCompletionPackets,
131 => Event::DecryptWorkerSelectBulkPackets,
132 => Event::DecryptWorkerDrainPriority,
133 => Event::DecryptWorkerDrainAeadCompletionPackets,
134 => Event::DecryptWorkerDrainBulkPackets,
135 => Event::DecryptWorkerBulkInterleaveAeadCompletionPackets,
136 => Event::DecryptWorkerBulkInterleaveBudgetExhausted,
137 => Event::DecryptFspPathWorkerOpen,
138 => Event::DecryptWorkerControlDropped,
139 => Event::DecryptWorkerSelectControl,
140 => Event::DecryptWorkerDrainControl,
141 => Event::DecryptFspHelperCompletionBacklogFallback,
142 => Event::DecryptFspHelperQueueFullFallback,
143 => Event::DecryptFmpHelperCompletionBacklogFallback,
144 => Event::DecryptFmpPreownerCompletionBacklogFallback,
145 => Event::DecryptFspOpenWorkerCompletionBacklogFallback,
146 => Event::FspAeadCompletionReplayDroppedHelper,
147 => Event::FspAeadCompletionReplayDroppedHelperReturned,
148 => Event::FspAeadCompletionReplayDroppedWorkerOpen,
149 => Event::FspAeadCompletionReplayDroppedWorkerOpenReturned,
150 => Event::FspAeadCompletionReplayDroppedDuplicate,
151 => Event::FspAeadCompletionReplayDroppedTooOld,
152 => Event::FspAeadCompletionReplayDroppedTooOldLagGe2xWindow,
153 => Event::FspAeadCompletionReplayDroppedTooOldLagGe4xWindow,
154 => Event::FspAeadCompletionReplayDroppedTooOldLagGe16xWindow,
155 => Event::FspAeadCompletionReplayDroppedTooOldLagGe64xWindow,
156 => Event::ConnectedUdpDirectDecryptBulkShed,
157 => Event::DecryptFspOpenPoolQueueFullFallback,
158 => Event::ConnectedUdpKernelDropped,
159 => Event::ConnectedUdpPeerKernelDropped,
160 => Event::DecryptFspPathWorkerOpenStriped,
161 => Event::DecryptAuthenticatedBacklogHigh,
162 => Event::EndpointEventBulkBacklogHigh,
163 => Event::PacketBatchPoolFresh,
164 => Event::PacketBatchPoolReuse,
165 => Event::PacketBatchPoolReturn,
166 => Event::PacketBatchPoolDiscard,
167 => Event::PacketBufferPoolFresh,
168 => Event::PacketBufferPoolReuse,
169 => Event::PacketBufferPoolReturn,
170 => Event::PacketBufferPoolDiscard,
171 => Event::LinuxBulkUdpPaceWait,
172 => Event::UdpKernelDropped,
173 => Event::UdpSocketKernelDropped,
174 => Event::UdpNamespaceRcvbufErrors,
175 => Event::ConnectedUdpDrainBulkDropped,
176 => Event::DecryptFspWorkerReplayDroppedDuplicate,
177 => Event::DecryptFspWorkerReplayDroppedTooOld,
178 => Event::DecryptFspWorkerReplayDroppedTooOldLagGe2xWindow,
179 => Event::DecryptFspWorkerReplayDroppedTooOldLagGe4xWindow,
180 => Event::DecryptFspWorkerReplayDroppedTooOldLagGe16xWindow,
181 => Event::DecryptFspWorkerReplayDroppedTooOldLagGe64xWindow,
182 => Event::DecryptFspPathLocalPriority,
183 => Event::DecryptFspPathLocalBulk,
184 => Event::DecryptFspPathHandoffPriority,
185 => Event::DecryptFspPathHandoffBulk,
186 => Event::DecryptFspPathHelperBulk,
187 => Event::DecryptFspPathWorkerOpenBulk,
188 => Event::FspAeadCompletionReturnedHelper,
189 => Event::FspAeadCompletionReturnedWorkerOpen,
190 => Event::DecryptFspOwnerHandoffDropped,
191 => Event::FmpAeadCompletionReplayDroppedPrechecked,
192 => Event::FmpAeadCompletionReplayDroppedDeferred,
193 => Event::FmpAeadCompletionReplayDroppedDuplicate,
194 => Event::FmpAeadCompletionReplayDroppedTooOld,
195 => Event::FmpAeadCompletionReplayDroppedTooOldLagGe2xWindow,
196 => Event::FmpAeadCompletionReplayDroppedTooOldLagGe4xWindow,
197 => Event::FmpAeadCompletionReplayDroppedTooOldLagGe16xWindow,
198 => Event::FmpAeadCompletionReplayDroppedTooOldLagGe64xWindow,
199 => Event::DecryptFspMalformedDropped,
200 => Event::FspAeadCompletionAeadFailedLocal,
201 => Event::FspAeadCompletionAeadFailedHelper,
202 => Event::FspAeadCompletionAeadFailedHelperReturned,
203 => Event::FspAeadCompletionAeadFailedWorkerOpen,
204 => Event::FspAeadCompletionAeadFailedWorkerOpenReturned,
205 => Event::FspAeadCompletionEpochMismatch,
206 => Event::FspAeadCompletionAeadFailedLocalOpen,
207 => Event::FspAeadCompletionAeadFailedAcceptKbitMismatch,
208 => Event::DecryptWorkerSelectFspCompletionBatch,
209 => Event::DecryptWorkerDrainAeadCompletionBatch,
210 => Event::DecryptWorkerBulkInterleaveAeadCompletionBatch,
211 => Event::DecryptWorkerBatchWorker0,
212 => Event::DecryptWorkerBatchWorker1,
213 => Event::DecryptWorkerBatchWorker2,
214 => Event::DecryptWorkerBatchWorker3,
215 => Event::DecryptWorkerBatchWorker4,
216 => Event::DecryptWorkerBatchWorker5,
217 => Event::DecryptWorkerBatchWorker6,
218 => Event::DecryptWorkerBatchWorker7,
219 => Event::DecryptWorkerBatchWorkerOther,
220 => Event::FspAeadCompletionStaleEpochWorkerOpen,
_ => unreachable!(),
}
}
static TOTAL_NS: [AtomicU64; N_STAGES] = [const { AtomicU64::new(0) }; N_STAGES];
static COUNT: [AtomicU64; N_STAGES] = [const { AtomicU64::new(0) }; N_STAGES];
static MAX_NS: [AtomicU64; N_STAGES] = [const { AtomicU64::new(0) }; N_STAGES];
static HIST: [AtomicU64; N_STAGES * HIST_BUCKETS] =
[const { AtomicU64::new(0) }; N_STAGES * HIST_BUCKETS];
static EVENTS: [AtomicU64; N_EVENTS] = [const { AtomicU64::new(0) }; N_EVENTS];
static TRACE_EPOCH: OnceLock<Instant> = OnceLock::new();
#[doc(hidden)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct TraceStamp(NonZeroU64);
impl TraceStamp {
fn now() -> Self {
let elapsed = trace_elapsed_ns().saturating_add(1).max(1);
Self(NonZeroU64::new(elapsed).unwrap_or(NonZeroU64::MAX))
}
fn elapsed_ns(self) -> u64 {
trace_elapsed_ns().saturating_sub(self.0.get().saturating_sub(1))
}
}
fn trace_epoch() -> Instant {
*TRACE_EPOCH.get_or_init(Instant::now)
}
fn trace_elapsed_ns() -> u64 {
Instant::now()
.saturating_duration_since(trace_epoch())
.as_nanos()
.min(u64::MAX as u128) as u64
}
pub(crate) fn enabled() -> bool {
static ENABLED: OnceLock<bool> = OnceLock::new();
*ENABLED.get_or_init(|| {
["FIPS_PERF", "FIPS_PIPELINE_TRACE", "NVPN_PIPELINE_TRACE"]
.into_iter()
.any(|key| {
std::env::var(key)
.map(|s| s == "1" || s.eq_ignore_ascii_case("true"))
.unwrap_or(false)
})
})
}
#[inline]
pub(crate) fn stamp() -> Option<TraceStamp> {
if enabled() {
Some(TraceStamp::now())
} else {
None
}
}
#[cfg(test)]
pub(crate) fn test_stamp() -> TraceStamp {
TraceStamp::now()
}
pub fn record(stage: Stage, elapsed_ns: u64) {
record_count(stage, elapsed_ns, 1);
}
pub fn record_count(stage: Stage, elapsed_ns: u64, count: u64) {
if !enabled() {
return;
}
if count == 0 {
return;
}
let elapsed_ns = elapsed_ns.max(1);
let bucket = bucket_for_ns(elapsed_ns);
record_count_sample(stage, elapsed_ns, count, bucket);
}
#[inline]
pub(crate) fn record_since_count(stage: Stage, start: Option<TraceStamp>, count: u64) {
if !enabled() || count == 0 {
return;
}
let Some(start) = start else {
return;
};
let elapsed_ns = start.elapsed_ns().max(1);
let bucket = bucket_for_ns(elapsed_ns);
record_count_sample(stage, elapsed_ns, count, bucket);
}
#[inline]
fn record_count_sample(stage: Stage, elapsed_ns: u64, count: u64, bucket: usize) {
let idx = stage as usize;
TOTAL_NS[idx].fetch_add(elapsed_ns.saturating_mul(count), Relaxed);
MAX_NS[idx].fetch_max(elapsed_ns, Relaxed);
HIST[(idx * HIST_BUCKETS) + bucket].fetch_add(count, Relaxed);
COUNT[idx].fetch_add(count, Release);
}
#[inline]
pub(crate) fn record_since_split_count(
total_stage: Stage,
priority_stage: Stage,
bulk_stage: Stage,
start: Option<TraceStamp>,
total_count: u64,
priority_count: u64,
bulk_count: u64,
) {
debug_assert_eq!(
priority_count.saturating_add(bulk_count),
total_count,
"queue wait split counts should add up to the aggregate count"
);
if !enabled() || total_count == 0 {
return;
}
let Some(start) = start else {
return;
};
let elapsed_ns = start.elapsed_ns().max(1);
let bucket = bucket_for_ns(elapsed_ns);
record_count_sample(total_stage, elapsed_ns, total_count, bucket);
if priority_count > 0 {
record_count_sample(priority_stage, elapsed_ns, priority_count, bucket);
}
if bulk_count > 0 {
record_count_sample(bulk_stage, elapsed_ns, bulk_count, bucket);
}
}
#[inline]
pub fn record_event(event: Event) {
record_event_count(event, 1);
}
pub fn record_event_count(event: Event, count: u64) {
if !enabled() || count == 0 {
return;
}
record_event_count_sample(event, count);
}
#[inline]
pub(crate) fn record_udp_kernel_drops(drops: u64) {
record_event_count(Event::UdpKernelDropped, drops);
}
#[inline]
pub(crate) fn record_udp_socket_kernel_drops(drops: u64) {
record_event_count(Event::UdpSocketKernelDropped, drops);
}
#[inline]
pub(crate) fn record_udp_namespace_rcvbuf_errors(drops: u64) {
record_event_count(Event::UdpNamespaceRcvbufErrors, drops);
}
#[inline]
#[cfg(target_os = "linux")]
pub(crate) fn record_connected_udp_peer_kernel_drops(drops: u64) {
record_event_count(Event::ConnectedUdpPeerKernelDropped, drops);
}
#[inline]
#[cfg(target_os = "linux")]
pub(crate) fn record_linux_bulk_udp_pace_wait() {
record_event(Event::LinuxBulkUdpPaceWait);
}
#[inline]
pub(crate) fn record_encrypt_worker_queue_full(priority: bool) {
record_event(Event::EncryptWorkerQueueFull);
record_event(if priority {
Event::EncryptWorkerPriorityQueueFull
} else {
Event::EncryptWorkerBulkQueueFull
});
}
#[inline]
pub(crate) fn record_fmp_worker_batch(
packets: usize,
priority_packets: usize,
bulk_packets: usize,
max_batch: usize,
) {
if !enabled() || packets == 0 {
return;
}
debug_assert_eq!(
packets,
priority_packets.saturating_add(bulk_packets),
"FMP worker batch lane counts should cover every packet"
);
record_event_count_sample(Event::FmpWorkerBatchFlush, 1);
record_event_count_sample(Event::FmpWorkerBatchPackets, packets as u64);
record_event_count_sample(
Event::FmpWorkerBatchPriorityPackets,
priority_packets as u64,
);
record_event_count_sample(Event::FmpWorkerBatchBulkPackets, bulk_packets as u64);
if packets >= max_batch.max(1) {
record_event_count_sample(Event::FmpWorkerBatchFull, 1);
}
if packets == 1 {
record_event_count_sample(Event::FmpWorkerBatchSingle, 1);
}
}
#[inline]
pub(crate) fn record_fmp_send_groups(groups: usize, packets: usize, single_groups: usize) {
if !enabled() || groups == 0 || packets == 0 {
return;
}
debug_assert!(
single_groups <= groups,
"single-packet send groups cannot exceed total groups"
);
record_event_count_sample(Event::FmpSendGroup, groups as u64);
record_event_count_sample(Event::FmpSendGroupPackets, packets as u64);
if single_groups > 0 {
record_event_count_sample(Event::FmpSendGroupSingle, single_groups as u64);
}
}
#[inline]
pub(crate) fn record_fmp_send_group_split_target() {
record_fmp_send_group_split(Event::FmpSendGroupSplitTarget);
}
#[inline]
pub(crate) fn record_fmp_send_group_split_lane() {
record_fmp_send_group_split(Event::FmpSendGroupSplitLane);
}
#[inline]
pub(crate) fn record_fmp_send_group_split_backpressure() {
record_fmp_send_group_split(Event::FmpSendGroupSplitBackpressure);
}
#[inline]
#[cfg(target_os = "linux")]
pub(crate) fn record_fmp_send_group_split_packet_cap() {
record_fmp_send_group_split(Event::FmpSendGroupSplitPacketCap);
}
#[inline]
fn record_fmp_send_group_split(event: Event) {
if !enabled() {
return;
}
record_event_count_sample(event, 1);
}
#[inline]
pub(crate) fn record_endpoint_committed_bulk_dispatch(
packets: usize,
merged_batches: usize,
merged_packets: usize,
) {
if !enabled() || packets == 0 {
return;
}
record_event_count_sample(Event::EndpointCommittedBulkDispatchBatch, 1);
record_event_count_sample(Event::EndpointCommittedBulkDispatchPackets, packets as u64);
if merged_batches > 0 {
record_event_count_sample(
Event::EndpointCommittedBulkDispatchMergedBatch,
merged_batches as u64,
);
}
if merged_packets > 0 {
record_event_count_sample(
Event::EndpointCommittedBulkDispatchMergedPackets,
merged_packets as u64,
);
}
}
#[inline]
pub(crate) fn record_fmp_worker_dispatch(elapsed_ns: u64, packets: usize) {
if !enabled() || packets == 0 {
return;
}
let packets_u64 = packets as u64;
let per_packet_ns = elapsed_ns.max(1).saturating_div(packets_u64).max(1);
record_count_sample(
Stage::FmpWorkerDispatch,
per_packet_ns,
packets_u64,
bucket_for_ns(per_packet_ns),
);
record_event_count_sample(Event::FmpWorkerDispatchBatch, 1);
record_event_count_sample(Event::FmpWorkerDispatchPackets, packets_u64);
}
#[inline]
pub(crate) fn record_fmp_worker_dispatch_target(worker_idx: usize, flow_keyed: bool) {
if !enabled() {
return;
}
record_event_count_sample(
if flow_keyed {
Event::FmpWorkerDispatchFlowKeyed
} else {
Event::FmpWorkerDispatchTargetOnly
},
1,
);
let worker_event = match worker_idx {
0 => Event::FmpWorkerDispatchWorker0,
1 => Event::FmpWorkerDispatchWorker1,
2 => Event::FmpWorkerDispatchWorker2,
3 => Event::FmpWorkerDispatchWorker3,
4 => Event::FmpWorkerDispatchWorker4,
5 => Event::FmpWorkerDispatchWorker5,
6 => Event::FmpWorkerDispatchWorker6,
7 => Event::FmpWorkerDispatchWorker7,
_ => Event::FmpWorkerDispatchWorkerOther,
};
record_event_count_sample(worker_event, 1);
}
#[inline]
#[cfg(target_os = "linux")]
pub(crate) fn record_linux_wg_batch_chunk(packets: usize, chunk_size: usize) {
if !enabled() || packets == 0 {
return;
}
record_event_count_sample(Event::LinuxWgBatchChunk, 1);
record_event_count_sample(Event::LinuxWgBatchChunkPackets, packets as u64);
if packets >= chunk_size.max(1) {
record_event_count_sample(Event::LinuxWgBatchChunkFull, 1);
}
}
#[inline]
#[cfg(target_os = "linux")]
pub(crate) fn record_linux_wg_batch_sender_wait(elapsed_ns: u64) {
if !enabled() {
return;
}
record_wait_threshold(Event::LinuxWgBatchSenderWaitGe250us, elapsed_ns, 1, 250_000);
record_wait_threshold(Event::LinuxWgBatchSenderWaitGe1ms, elapsed_ns, 1, 1_000_000);
record_wait_threshold(Event::LinuxWgBatchSenderWaitGe4ms, elapsed_ns, 1, 4_000_000);
}
#[inline]
pub(crate) fn record_decrypt_worker_bulk_input_wait(start: Option<TraceStamp>, count: u64) {
if !enabled() || count == 0 {
return;
}
let Some(start) = start else {
return;
};
let elapsed_ns = start.elapsed_ns().max(1);
let bucket = bucket_for_ns(elapsed_ns);
record_count_sample(
Stage::DecryptWorkerBulkInputHeadWait,
elapsed_ns,
count,
bucket,
);
record_wait_threshold(
Event::DecryptWorkerBulkInputWaitGe250us,
elapsed_ns,
count,
250_000,
);
record_wait_threshold(
Event::DecryptWorkerBulkInputWaitGe500us,
elapsed_ns,
count,
500_000,
);
record_wait_threshold(
Event::DecryptWorkerBulkInputWaitGe1ms,
elapsed_ns,
count,
1_000_000,
);
}
#[inline]
fn record_wait_threshold(event: Event, elapsed_ns: u64, count: u64, threshold_ns: u64) {
if elapsed_ns >= threshold_ns {
record_event_count_sample(event, count);
}
}
#[inline]
pub(crate) fn record_decrypt_worker_batch(
packets: usize,
priority_packets: usize,
bulk_packets: usize,
max_batch: usize,
) {
if !enabled() || packets == 0 {
return;
}
debug_assert_eq!(
packets,
priority_packets.saturating_add(bulk_packets),
"decrypt worker batch lane counts should cover every packet"
);
record_event_count_sample(Event::DecryptWorkerBatchFlush, 1);
record_event_count_sample(Event::DecryptWorkerBatchPackets, packets as u64);
record_event_count_sample(
Event::DecryptWorkerBatchPriorityPackets,
priority_packets as u64,
);
record_event_count_sample(Event::DecryptWorkerBatchBulkPackets, bulk_packets as u64);
if packets >= max_batch.max(1) {
record_event_count_sample(Event::DecryptWorkerBatchFull, 1);
}
if packets == 1 {
record_event_count_sample(Event::DecryptWorkerBatchSingle, 1);
}
}
#[inline]
pub(crate) fn record_decrypt_worker_batch_target(worker_idx: usize, packets: usize) {
if !enabled() || packets == 0 {
return;
}
let worker_event = match worker_idx {
0 => Event::DecryptWorkerBatchWorker0,
1 => Event::DecryptWorkerBatchWorker1,
2 => Event::DecryptWorkerBatchWorker2,
3 => Event::DecryptWorkerBatchWorker3,
4 => Event::DecryptWorkerBatchWorker4,
5 => Event::DecryptWorkerBatchWorker5,
6 => Event::DecryptWorkerBatchWorker6,
7 => Event::DecryptWorkerBatchWorker7,
_ => Event::DecryptWorkerBatchWorkerOther,
};
record_event_count_sample(worker_event, packets as u64);
}
#[inline]
pub(crate) fn record_decrypt_worker_select_priority() {
record_event(Event::DecryptWorkerSelectPriority);
}
#[inline]
pub(crate) fn record_decrypt_worker_select_control() {
record_event(Event::DecryptWorkerSelectControl);
}
#[inline]
pub(crate) fn record_decrypt_worker_select_fmp_completion() {
record_event(Event::DecryptWorkerSelectFmpCompletion);
}
#[inline]
pub(crate) fn record_decrypt_worker_select_fsp_completion(packets: usize) {
record_event(Event::DecryptWorkerSelectFspCompletionBatch);
record_event_count(
Event::DecryptWorkerSelectFspCompletionPackets,
packets as u64,
);
}
#[inline]
pub(crate) fn record_decrypt_worker_select_bulk(packets: usize) {
record_event_count(Event::DecryptWorkerSelectBulkPackets, packets as u64);
}
#[inline]
pub(crate) fn record_decrypt_worker_drain_priority() {
record_event(Event::DecryptWorkerDrainPriority);
}
#[inline]
pub(crate) fn record_decrypt_worker_drain_control() {
record_event(Event::DecryptWorkerDrainControl);
}
#[inline]
pub(crate) fn record_decrypt_worker_drain_aead_completion(messages: usize, packets: usize) {
record_event_count(
Event::DecryptWorkerDrainAeadCompletionBatch,
messages as u64,
);
record_event_count(
Event::DecryptWorkerDrainAeadCompletionPackets,
packets as u64,
);
}
#[inline]
pub(crate) fn record_decrypt_worker_drain_bulk(packets: usize) {
record_event_count(Event::DecryptWorkerDrainBulkPackets, packets as u64);
}
#[inline]
pub(crate) fn record_decrypt_worker_bulk_interleave_aead_completion(
messages: usize,
packets: usize,
) {
record_event_count(
Event::DecryptWorkerBulkInterleaveAeadCompletionBatch,
messages as u64,
);
record_event_count(
Event::DecryptWorkerBulkInterleaveAeadCompletionPackets,
packets as u64,
);
}
#[inline]
pub(crate) fn record_decrypt_worker_bulk_interleave_budget_exhausted() {
record_event(Event::DecryptWorkerBulkInterleaveBudgetExhausted);
}
#[inline]
pub(crate) fn record_fmp_aead_completion_drain(
ready: usize,
accepted: usize,
aead_failures: usize,
replay_drops: usize,
) {
if !enabled() || ready == 0 {
return;
}
record_event_count_sample(Event::FmpAeadCompletionReady, ready as u64);
if accepted > 0 {
record_event_count_sample(Event::FmpAeadCompletionAccepted, accepted as u64);
}
if aead_failures > 0 {
record_event_count_sample(Event::FmpAeadCompletionAeadFailed, aead_failures as u64);
}
if replay_drops > 0 {
record_event_count_sample(Event::FmpAeadCompletionReplayDropped, replay_drops as u64);
}
if ready > 1 {
record_event_count_sample(Event::FmpAeadCompletionReadyMulti, 1);
}
}
#[inline]
pub(crate) fn record_fsp_aead_completion_drain(
ready: usize,
accepted: usize,
aead_failures: usize,
epoch_mismatches: usize,
stale_epoch_worker_open_failures: usize,
replay_drops: usize,
) {
if !enabled() || ready == 0 {
return;
}
record_event_count_sample(Event::FspAeadCompletionReady, ready as u64);
if accepted > 0 {
record_event_count_sample(Event::FspAeadCompletionAccepted, accepted as u64);
}
if aead_failures > 0 {
record_event_count_sample(Event::FspAeadCompletionAeadFailed, aead_failures as u64);
}
if epoch_mismatches > 0 {
record_event_count_sample(
Event::FspAeadCompletionEpochMismatch,
epoch_mismatches as u64,
);
}
if stale_epoch_worker_open_failures > 0 {
record_event_count_sample(
Event::FspAeadCompletionStaleEpochWorkerOpen,
stale_epoch_worker_open_failures as u64,
);
}
if replay_drops > 0 {
record_event_count_sample(Event::FspAeadCompletionReplayDropped, replay_drops as u64);
}
if ready > 1 {
record_event_count_sample(Event::FspAeadCompletionReadyMulti, 1);
}
}
#[inline]
pub(crate) fn record_fsp_aead_completion_source_replay_drops(
helper: usize,
helper_returned: usize,
worker_open: usize,
worker_open_returned: usize,
) {
if !enabled() {
return;
}
if helper > 0 {
record_event_count_sample(Event::FspAeadCompletionReplayDroppedHelper, helper as u64);
}
if helper_returned > 0 {
record_event_count_sample(
Event::FspAeadCompletionReplayDroppedHelperReturned,
helper_returned as u64,
);
}
if worker_open > 0 {
record_event_count_sample(
Event::FspAeadCompletionReplayDroppedWorkerOpen,
worker_open as u64,
);
}
if worker_open_returned > 0 {
record_event_count_sample(
Event::FspAeadCompletionReplayDroppedWorkerOpenReturned,
worker_open_returned as u64,
);
}
}
#[inline]
pub(crate) fn record_fsp_aead_completion_source_aead_failures(
local: usize,
helper: usize,
helper_returned: usize,
worker_open: usize,
worker_open_returned: usize,
) {
if !enabled() {
return;
}
if local > 0 {
record_event_count_sample(Event::FspAeadCompletionAeadFailedLocal, local as u64);
}
if helper > 0 {
record_event_count_sample(Event::FspAeadCompletionAeadFailedHelper, helper as u64);
}
if helper_returned > 0 {
record_event_count_sample(
Event::FspAeadCompletionAeadFailedHelperReturned,
helper_returned as u64,
);
}
if worker_open > 0 {
record_event_count_sample(
Event::FspAeadCompletionAeadFailedWorkerOpen,
worker_open as u64,
);
}
if worker_open_returned > 0 {
record_event_count_sample(
Event::FspAeadCompletionAeadFailedWorkerOpenReturned,
worker_open_returned as u64,
);
}
}
#[inline]
pub(crate) fn record_fsp_aead_completion_local_open_aead_failure() {
record_event(Event::FspAeadCompletionAeadFailedLocalOpen);
}
#[inline]
pub(crate) fn record_fsp_aead_completion_accept_kbit_mismatch() {
record_event(Event::FspAeadCompletionAeadFailedAcceptKbitMismatch);
}
#[inline]
pub(crate) fn record_fmp_aead_completion_replay_drop_mode(deferred: bool) {
if !enabled() {
return;
}
record_event(if deferred {
Event::FmpAeadCompletionReplayDroppedDeferred
} else {
Event::FmpAeadCompletionReplayDroppedPrechecked
});
}
#[inline]
pub(crate) fn record_fmp_aead_completion_replay_drop_reason(
reason: crate::noise::ReplayRejection,
counter_lag: u64,
) {
if !enabled() {
return;
}
let event = match reason {
crate::noise::ReplayRejection::Duplicate => Event::FmpAeadCompletionReplayDroppedDuplicate,
crate::noise::ReplayRejection::TooOld => Event::FmpAeadCompletionReplayDroppedTooOld,
};
record_event(event);
if reason == crate::noise::ReplayRejection::TooOld {
record_fmp_aead_completion_too_old_lag_buckets(counter_lag);
}
}
#[inline]
pub(crate) fn record_fsp_aead_completion_replay_drop_reason(
reason: crate::noise::ReplayRejection,
counter_lag: u64,
) {
if !enabled() {
return;
}
let event = match reason {
crate::noise::ReplayRejection::Duplicate => Event::FspAeadCompletionReplayDroppedDuplicate,
crate::noise::ReplayRejection::TooOld => Event::FspAeadCompletionReplayDroppedTooOld,
};
record_event(event);
if reason == crate::noise::ReplayRejection::TooOld {
record_fsp_aead_completion_too_old_lag_buckets(counter_lag);
}
}
#[inline]
pub(crate) fn record_decrypt_fsp_worker_replay_drop_reason(
reason: crate::noise::ReplayRejection,
counter_lag: u64,
) {
if !enabled() {
return;
}
let event = match reason {
crate::noise::ReplayRejection::Duplicate => Event::DecryptFspWorkerReplayDroppedDuplicate,
crate::noise::ReplayRejection::TooOld => Event::DecryptFspWorkerReplayDroppedTooOld,
};
record_event(event);
if reason == crate::noise::ReplayRejection::TooOld {
record_decrypt_fsp_worker_too_old_lag_buckets(counter_lag);
}
}
#[inline]
fn record_fmp_aead_completion_too_old_lag_buckets(counter_lag: u64) {
let window = crate::noise::REPLAY_WINDOW_SIZE as u64;
if counter_lag >= window.saturating_mul(2) {
record_event(Event::FmpAeadCompletionReplayDroppedTooOldLagGe2xWindow);
}
if counter_lag >= window.saturating_mul(4) {
record_event(Event::FmpAeadCompletionReplayDroppedTooOldLagGe4xWindow);
}
if counter_lag >= window.saturating_mul(16) {
record_event(Event::FmpAeadCompletionReplayDroppedTooOldLagGe16xWindow);
}
if counter_lag >= window.saturating_mul(64) {
record_event(Event::FmpAeadCompletionReplayDroppedTooOldLagGe64xWindow);
}
}
#[inline]
fn record_fsp_aead_completion_too_old_lag_buckets(counter_lag: u64) {
let window = crate::noise::REPLAY_WINDOW_SIZE as u64;
if counter_lag >= window.saturating_mul(2) {
record_event(Event::FspAeadCompletionReplayDroppedTooOldLagGe2xWindow);
}
if counter_lag >= window.saturating_mul(4) {
record_event(Event::FspAeadCompletionReplayDroppedTooOldLagGe4xWindow);
}
if counter_lag >= window.saturating_mul(16) {
record_event(Event::FspAeadCompletionReplayDroppedTooOldLagGe16xWindow);
}
if counter_lag >= window.saturating_mul(64) {
record_event(Event::FspAeadCompletionReplayDroppedTooOldLagGe64xWindow);
}
}
#[inline]
fn record_decrypt_fsp_worker_too_old_lag_buckets(counter_lag: u64) {
let window = crate::noise::REPLAY_WINDOW_SIZE as u64;
if counter_lag >= window.saturating_mul(2) {
record_event(Event::DecryptFspWorkerReplayDroppedTooOldLagGe2xWindow);
}
if counter_lag >= window.saturating_mul(4) {
record_event(Event::DecryptFspWorkerReplayDroppedTooOldLagGe4xWindow);
}
if counter_lag >= window.saturating_mul(16) {
record_event(Event::DecryptFspWorkerReplayDroppedTooOldLagGe16xWindow);
}
if counter_lag >= window.saturating_mul(64) {
record_event(Event::DecryptFspWorkerReplayDroppedTooOldLagGe64xWindow);
}
}
#[inline]
#[cfg(target_os = "linux")]
pub(crate) fn record_udp_send_gso_batch(packets: usize) {
record_udp_send_batch(Event::UdpSendGsoBatch, Event::UdpSendGsoPackets, packets);
record_udp_send_batch_tail_buckets(
packets,
Event::UdpSendGsoBatchGe32,
Event::UdpSendGsoBatchGe48,
Event::UdpSendGsoBatchEq64,
);
}
#[inline]
#[cfg(target_os = "linux")]
pub(crate) fn record_udp_send_sendmmsg_batch(packets: usize) {
record_udp_send_batch(
Event::UdpSendSendmmsgBatch,
Event::UdpSendSendmmsgPackets,
packets,
);
record_udp_send_batch_tail_buckets(
packets,
Event::UdpSendSendmmsgBatchGe32,
Event::UdpSendSendmmsgBatchGe48,
Event::UdpSendSendmmsgBatchEq64,
);
}
#[inline]
#[cfg(target_os = "linux")]
fn record_udp_send_batch(batch_event: Event, packet_event: Event, packets: usize) {
if !enabled() || packets == 0 {
return;
}
record_event_count_sample(batch_event, 1);
record_event_count_sample(packet_event, packets as u64);
}
#[inline]
#[cfg(target_os = "linux")]
fn record_udp_send_batch_tail_buckets(
packets: usize,
ge32_event: Event,
ge48_event: Event,
eq64_event: Event,
) {
if !enabled() || packets == 0 {
return;
}
let (ge32, ge48, eq64) = udp_send_batch_tail_bucket_flags(packets);
if ge32 {
record_event_count_sample(ge32_event, 1);
}
if ge48 {
record_event_count_sample(ge48_event, 1);
}
if eq64 {
record_event_count_sample(eq64_event, 1);
}
}
#[inline]
#[cfg(target_os = "linux")]
fn udp_send_batch_tail_bucket_flags(packets: usize) -> (bool, bool, bool) {
(packets >= 32, packets >= 48, packets >= 64)
}
#[inline]
fn record_event_count_sample(event: Event, count: u64) {
EVENTS[event as usize].fetch_add(count, Relaxed);
}
pub struct Timer {
stage: Stage,
start: Option<Instant>,
}
impl Timer {
#[inline]
pub fn start(stage: Stage) -> Self {
let start = if enabled() {
Some(Instant::now())
} else {
None
};
Self { stage, start }
}
}
impl Drop for Timer {
fn drop(&mut self) {
if let Some(t0) = self.start {
let ns = t0.elapsed().as_nanos() as u64;
record(self.stage, ns);
}
}
}
pub fn maybe_spawn_reporter() {
if !enabled() {
return;
}
static STARTED: OnceLock<()> = OnceLock::new();
if STARTED.set(()).is_err() {
return;
}
let interval = std::env::var("FIPS_PERF_INTERVAL_SECS")
.ok()
.and_then(|s| s.parse::<u64>().ok())
.unwrap_or(5)
.max(1);
tokio::spawn(async move {
let mut prev_total = [0u64; N_STAGES];
let mut prev_count = [0u64; N_STAGES];
let mut prev_hist = [0u64; N_STAGES * HIST_BUCKETS];
let mut prev_events = [0u64; N_EVENTS];
loop {
tokio::time::sleep(std::time::Duration::from_secs(interval)).await;
let mut line = format!("[pipe {}s]", interval);
for i in 0..N_STAGES {
let c = COUNT[i].load(Acquire);
let dc = c.saturating_sub(prev_count[i]);
if dc == 0 {
continue;
}
let t = TOTAL_NS[i].load(Relaxed);
let dt = t.saturating_sub(prev_total[i]);
prev_total[i] = t;
prev_count[i] = c;
let base = i * HIST_BUCKETS;
let mut hist_delta = [0u64; HIST_BUCKETS];
for (bucket, delta) in hist_delta.iter_mut().enumerate().take(HIST_BUCKETS) {
let idx = base + bucket;
let current = HIST[idx].load(Relaxed);
*delta = current.saturating_sub(prev_hist[idx]);
prev_hist[idx] = current;
}
let stage = stage_from_index(i);
let avg_ns = if dc > 0 { dt / dc } else { 0 };
let rate_per_sec = fmt_rate_per_sec(dc, interval);
let p50 = percentile_ns(&hist_delta, dc, 50);
let p95 = percentile_ns(&hist_delta, dc, 95);
let p99 = percentile_ns(&hist_delta, dc, 99);
let approx_max = interval_max_ns(&hist_delta);
let lifetime_max = MAX_NS[i].load(Relaxed);
line.push_str(&format!(
" {}={}/s avg={} p50<={} p95<={} p99<={} max<={} allmax={}",
stage.name(),
rate_per_sec,
fmt_ns(avg_ns),
fmt_ns(p50),
fmt_ns(p95),
fmt_ns(p99),
fmt_ns(approx_max),
fmt_ns(lifetime_max),
));
}
for i in 0..N_EVENTS {
let current = EVENTS[i].load(Relaxed);
let delta = current.saturating_sub(prev_events[i]);
prev_events[i] = current;
if delta == 0 {
continue;
}
let event = event_from_index(i);
let rate_per_sec = fmt_rate_per_sec(delta, interval);
line.push_str(&format!(
" {}={}/s total={}",
event.name(),
rate_per_sec,
current
));
}
eprintln!("{}", line);
}
});
}
fn bucket_for_ns(ns: u64) -> usize {
if ns <= 1 {
return 0;
}
((u64::BITS - (ns - 1).leading_zeros()) as usize).min(HIST_BUCKETS - 1)
}
fn bucket_upper_ns(bucket: usize) -> u64 {
if bucket == 0 {
1
} else if bucket >= 63 {
u64::MAX
} else {
1u64 << bucket
}
}
fn percentile_ns(hist_delta: &[u64; HIST_BUCKETS], total: u64, pct: u64) -> u64 {
let observed_total = hist_delta.iter().copied().sum::<u64>();
let total = total.min(observed_total);
if total == 0 {
return 0;
}
let target = total.saturating_mul(pct).saturating_add(99) / 100;
let mut seen = 0u64;
for (idx, count) in hist_delta.iter().enumerate() {
seen = seen.saturating_add(*count);
if seen >= target {
return bucket_upper_ns(idx);
}
}
interval_max_ns(hist_delta)
}
fn interval_max_ns(hist_delta: &[u64; HIST_BUCKETS]) -> u64 {
for idx in (0..HIST_BUCKETS).rev() {
if hist_delta[idx] != 0 {
return bucket_upper_ns(idx);
}
}
0
}
#[cfg(test)]
mod tests;