1use mesh::Cell;
7use mesh::MeshPayload;
8use nvme_spec::Command;
9use nvme_spec::Completion;
10use std::time::Duration;
11
12#[derive(Debug, Clone, MeshPayload)]
14pub enum QueueFaultBehavior<T> {
15 Update(T),
17 Drop,
19 Delay(Duration),
21 Panic(String),
23 CustomPayload(Vec<u8>),
25}
26
27#[derive(Clone, MeshPayload)]
28pub enum PciFaultBehavior {
30 Delay(Duration),
32 Default,
34}
35
36#[derive(MeshPayload, Clone)]
37pub struct PciFaultConfig {
39 pub controller_management_fault_enable: PciFaultBehavior,
41}
42
43#[derive(MeshPayload, Clone)]
44pub struct AdminQueueFaultConfig {
46 pub admin_submission_queue_faults: Vec<(CommandMatch, QueueFaultBehavior<Command>)>,
48 pub admin_completion_queue_faults: Vec<(CommandMatch, QueueFaultBehavior<Completion>)>,
50}
51
52#[derive(Clone, MeshPayload, PartialEq)]
53pub struct CommandMatch {
55 pub command: Command,
57 pub mask: [u8; 64],
59}
60
61#[derive(MeshPayload, Clone)]
62pub struct FaultConfiguration {
64 pub fault_active: Cell<bool>,
66 pub admin_fault: AdminQueueFaultConfig,
68 pub pci_fault: PciFaultConfig,
70}
71
72impl FaultConfiguration {
73 pub fn new(fault_active: Cell<bool>) -> Self {
75 Self {
76 fault_active,
77 admin_fault: AdminQueueFaultConfig::new(),
78 pci_fault: PciFaultConfig::new(),
79 }
80 }
81
82 pub fn with_pci_fault(mut self, pci_fault: PciFaultConfig) -> Self {
84 self.pci_fault = pci_fault;
85 self
86 }
87
88 pub fn with_admin_queue_fault(mut self, admin_fault: AdminQueueFaultConfig) -> Self {
90 self.admin_fault = admin_fault;
91 self
92 }
93}
94
95impl PciFaultConfig {
96 pub fn new() -> Self {
98 Self {
99 controller_management_fault_enable: PciFaultBehavior::Default,
100 }
101 }
102
103 pub fn with_cc_enable_fault(mut self, behaviour: PciFaultBehavior) -> Self {
105 self.controller_management_fault_enable = behaviour;
106 self
107 }
108}
109
110impl AdminQueueFaultConfig {
111 pub fn new() -> Self {
113 Self {
114 admin_submission_queue_faults: vec![],
115 admin_completion_queue_faults: vec![],
116 }
117 }
118
119 pub fn with_submission_queue_fault(
124 mut self,
125 pattern: CommandMatch,
126 behaviour: QueueFaultBehavior<Command>,
127 ) -> Self {
128 if self
129 .admin_submission_queue_faults
130 .iter()
131 .any(|(c, _)| (pattern == *c))
132 {
133 panic!(
134 "Duplicate submission queue fault for Compare {:?} and Mask {:?}",
135 pattern.command, pattern.mask
136 );
137 }
138
139 self.admin_submission_queue_faults
140 .push((pattern, behaviour));
141 self
142 }
143
144 pub fn with_completion_queue_fault(
149 mut self,
150 pattern: CommandMatch,
151 behaviour: QueueFaultBehavior<Completion>,
152 ) -> Self {
153 if self
154 .admin_completion_queue_faults
155 .iter()
156 .any(|(c, _)| (pattern == *c))
157 {
158 panic!(
159 "Duplicate completion queue fault for Compare {:?} and Mask {:?}",
160 pattern.command, pattern.mask
161 );
162 }
163
164 self.admin_completion_queue_faults
165 .push((pattern, behaviour));
166 self
167 }
168}