1use std::sync::atomic::{AtomicUsize, Ordering};
6use std::time::Duration;
7
8use diagnostics_traits::{InspectableValue, Inspector};
9
10use crate::parse::{
11 IncomingResponseToRequestErrorCounters, SelectingIncomingMessageErrorCounters, SoftParseErrors,
12};
13
14#[derive(Default, Debug)]
16pub(crate) struct Counter(AtomicUsize);
17
18impl Counter {
19 pub(crate) fn increment(&self) {
20 let _: usize = self.0.fetch_add(1, Ordering::Relaxed);
21 }
22
23 pub(crate) fn load(&self) -> usize {
24 self.0.load(Ordering::Relaxed)
25 }
26}
27
28impl InspectableValue for Counter {
29 fn record<I: diagnostics_traits::Inspector>(&self, name: &str, inspector: &mut I) {
30 inspector.record_uint(name, u64::try_from(self.load()).unwrap_or(u64::MAX));
31 }
32}
33
34pub(crate) fn record_optional_duration_secs(
35 inspector: &mut impl Inspector,
36 name: &str,
37 value: Option<Duration>,
38) {
39 match value {
40 Some(value) => inspector.record_uint(name, value.as_secs()),
41 None => inspector.record_display(name, "Unset"),
42 }
43}
44
45#[derive(Debug, Default)]
47pub(crate) struct MessagingRelatedCounters {
48 pub(crate) send_message: Counter,
50 pub(crate) recv_message: Counter,
52 pub(crate) recv_message_fatal_socket_error: Counter,
55 pub(crate) recv_message_non_fatal_socket_error: Counter,
58 pub(crate) recv_time_out: Counter,
61 pub(crate) recv_wrong_xid: Counter,
64 pub(crate) recv_wrong_chaddr: Counter,
67 pub(crate) recv_failed_dhcp_parse: Counter,
70 pub(crate) recv_ack_no_addr_lease_time: Counter,
73 pub(crate) recv_illegal_option: Counter,
76}
77
78impl MessagingRelatedCounters {
79 fn record(&self, inspector: &mut impl Inspector) {
80 let Self {
81 send_message,
82 recv_message,
83 recv_message_fatal_socket_error,
84 recv_message_non_fatal_socket_error,
85 recv_time_out,
86 recv_wrong_xid,
87 recv_wrong_chaddr,
88 recv_failed_dhcp_parse,
89 recv_ack_no_addr_lease_time,
90 recv_illegal_option,
91 } = self;
92 inspector.record_inspectable_value("SendMessage", send_message);
93 inspector.record_inspectable_value("RecvMessage", recv_message);
94 inspector.record_inspectable_value(
95 "RecvMessageFatalSocketError",
96 recv_message_fatal_socket_error,
97 );
98 inspector.record_inspectable_value(
99 "RecvMessageNonFatalSocketError",
100 recv_message_non_fatal_socket_error,
101 );
102 inspector.record_inspectable_value("RecvTimeOut", recv_time_out);
103 inspector.record_inspectable_value("RecvWrongXid", recv_wrong_xid);
104 inspector.record_inspectable_value("RecvWrongChaddr", recv_wrong_chaddr);
105 inspector.record_inspectable_value("RecvFailedDhcpParse", recv_failed_dhcp_parse);
106 inspector.record_inspectable_value("NoLeaseTime", recv_ack_no_addr_lease_time);
107 inspector.record_inspectable_value("IllegallyIncludedOption", recv_illegal_option);
108 }
109
110 pub(crate) fn increment_soft_errors(&self, soft_errors: SoftParseErrors) {
111 let SoftParseErrors { illegal_option } = soft_errors;
112 if illegal_option {
113 self.recv_illegal_option.increment()
114 }
115 }
116}
117
118#[derive(Debug, Default)]
120pub(crate) struct InitCounters {
121 pub(crate) entered: Counter,
123}
124
125impl InitCounters {
126 fn record(&self, inspector: &mut impl Inspector) {
127 let Self { entered } = self;
128 inspector.record_inspectable_value("Entered", entered);
129 }
130}
131
132#[derive(Debug, Default)]
134pub(crate) struct SelectingCounters {
135 pub(crate) entered: Counter,
137 pub(crate) messaging: MessagingRelatedCounters,
139 pub(crate) recv_error: SelectingIncomingMessageErrorCounters,
142}
143
144impl SelectingCounters {
145 fn record(&self, inspector: &mut impl Inspector) {
146 let Self { entered, messaging, recv_error } = self;
147 inspector.record_inspectable_value("Entered", entered);
148 messaging.record(inspector);
149 recv_error.record(inspector);
150 }
151}
152
153#[derive(Debug, Default)]
155pub(crate) struct RequestingCounters {
156 pub(crate) entered: Counter,
158 pub(crate) messaging: MessagingRelatedCounters,
160 pub(crate) recv_error: IncomingResponseToRequestErrorCounters,
163 pub(crate) recv_nak: Counter,
166}
167
168impl RequestingCounters {
169 fn record(&self, inspector: &mut impl Inspector) {
170 let Self { entered, messaging, recv_error, recv_nak } = self;
171 inspector.record_inspectable_value("Entered", entered);
172 messaging.record(inspector);
173 recv_error.record(inspector);
174 inspector.record_inspectable_value("RecvNak", recv_nak);
175 }
176}
177
178#[derive(Debug, Default)]
180pub(crate) struct BoundCounters {
181 pub(crate) entered: Counter,
183 pub(crate) assigned: Counter,
185}
186
187impl BoundCounters {
188 fn record(&self, inspector: &mut impl Inspector) {
189 let Self { entered, assigned } = self;
190 inspector.record_inspectable_value("Entered", entered);
191 inspector.record_inspectable_value("Assigned", assigned);
192 }
193}
194
195#[derive(Debug, Default)]
197pub(crate) struct RenewingCounters {
198 pub(crate) entered: Counter,
200 pub(crate) messaging: MessagingRelatedCounters,
202 pub(crate) recv_error: IncomingResponseToRequestErrorCounters,
205 pub(crate) recv_nak: Counter,
208}
209
210impl RenewingCounters {
211 fn record(&self, inspector: &mut impl Inspector) {
212 let Self { entered, messaging, recv_error, recv_nak } = self;
213 inspector.record_inspectable_value("Entered", entered);
214 messaging.record(inspector);
215 recv_error.record(inspector);
216 inspector.record_inspectable_value("RecvNak", recv_nak);
217 }
218}
219
220#[derive(Debug, Default)]
222pub(crate) struct RebindingCounters {
223 pub(crate) entered: Counter,
225 pub(crate) messaging: MessagingRelatedCounters,
227 pub(crate) recv_error: IncomingResponseToRequestErrorCounters,
230 pub(crate) recv_nak: Counter,
233}
234
235impl RebindingCounters {
236 fn record(&self, inspector: &mut impl Inspector) {
237 let Self { entered, messaging, recv_error, recv_nak } = self;
238 inspector.record_inspectable_value("Entered", entered);
239 messaging.record(inspector);
240 recv_error.record(inspector);
241 inspector.record_inspectable_value("RecvNak", recv_nak);
242 }
243}
244
245#[derive(Debug, Default)]
247pub(crate) struct WaitingToRestartCounters {
248 pub(crate) entered: Counter,
250}
251
252impl WaitingToRestartCounters {
253 fn record(&self, inspector: &mut impl Inspector) {
254 let Self { entered } = self;
255 inspector.record_inspectable_value("Entered", entered);
256 }
257}
258
259#[derive(Default, Debug)]
261pub struct Counters {
262 pub(crate) init: InitCounters,
263 pub(crate) selecting: SelectingCounters,
264 pub(crate) requesting: RequestingCounters,
265 pub(crate) bound: BoundCounters,
266 pub(crate) renewing: RenewingCounters,
267 pub(crate) rebinding: RebindingCounters,
268 pub(crate) waiting_to_restart: WaitingToRestartCounters,
269}
270
271impl Counters {
272 pub fn record(&self, inspector: &mut impl Inspector) {
274 let Self { init, selecting, requesting, bound, renewing, rebinding, waiting_to_restart } =
275 self;
276 inspector.record_child("Init", |inspector| {
277 init.record(inspector);
278 });
279 inspector.record_child("Selecting", |inspector| {
280 selecting.record(inspector);
281 });
282 inspector.record_child("Requesting", |inspector| {
283 requesting.record(inspector);
284 });
285 inspector.record_child("Bound", |inspector| {
286 bound.record(inspector);
287 });
288 inspector.record_child("Renewing", |inspector| {
289 renewing.record(inspector);
290 });
291 inspector.record_child("Rebinding", |inspector| {
292 rebinding.record(inspector);
293 });
294 inspector.record_child("WaitingToRestart", |inspector| {
295 waiting_to_restart.record(inspector);
296 });
297 }
298}