1use net_types::ip::{Ip, Ipv4, Ipv6};
8use netstack3_base::{Counter, CounterRepr, Inspectable, Inspector, InspectorExt};
9use packet_formats::icmp::{
10 Icmpv4DestUnreachableCode, Icmpv4ParameterProblemCode, Icmpv4TimeExceededCode,
11 Icmpv6DestUnreachableCode, Icmpv6ParameterProblemCode, Icmpv6TimeExceededCode,
12};
13
14pub trait IcmpCountersIpExt: Ip {
16 type DestUnreachableCounters<C: CounterRepr>: Inspectable + Default;
18 type TimeExceededCounters<C: CounterRepr>: Inspectable + Default;
20 type ParameterProblemCounters<C: CounterRepr>: Inspectable + Default;
22}
23
24impl IcmpCountersIpExt for Ipv4 {
25 type DestUnreachableCounters<C: CounterRepr> = Icmpv4DestUnreachableCounters<C>;
26 type TimeExceededCounters<C: CounterRepr> = Icmpv4TimeExceededCounters<C>;
27 type ParameterProblemCounters<C: CounterRepr> = Icmpv4ParameterProblemCounters<C>;
28}
29
30impl IcmpCountersIpExt for Ipv6 {
31 type DestUnreachableCounters<C: CounterRepr> = Icmpv6DestUnreachableCounters<C>;
32 type TimeExceededCounters<C: CounterRepr> = Icmpv6TimeExceededCounters<C>;
33 type ParameterProblemCounters<C: CounterRepr> = Icmpv6ParameterProblemCounters<C>;
34}
35
36#[derive(Default)]
38pub struct IcmpTxCounters<I: IcmpCountersIpExt> {
39 pub reply: Counter,
41 pub protocol_unreachable: Counter,
43 pub address_unreachable: Counter,
45 pub port_unreachable: Counter,
47 pub net_unreachable: Counter,
49 pub time_exceeded: I::TimeExceededCounters<Counter>,
51 pub packet_too_big: Counter,
53 pub parameter_problem: I::ParameterProblemCounters<Counter>,
55 pub dest_unreachable: I::DestUnreachableCounters<Counter>,
57 pub error: Counter,
59}
60
61impl<I: IcmpCountersIpExt> Inspectable for IcmpTxCounters<I> {
62 fn record<II: Inspector>(&self, inspector: &mut II) {
63 let IcmpTxCounters {
64 reply,
65 protocol_unreachable,
66 address_unreachable,
67 port_unreachable,
68 net_unreachable,
69 time_exceeded,
70 packet_too_big,
71 parameter_problem,
72 dest_unreachable,
73 error,
74 } = self;
75 inspector.record_counter("Reply", reply);
76 inspector.record_counter("ProtocolUnreachable", protocol_unreachable);
77 inspector.record_counter("PortUnreachable", port_unreachable);
78 inspector.record_counter("AddressUnreachable", address_unreachable);
79 inspector.record_counter("NetUnreachable", net_unreachable);
80
81 inspector.record_inspectable("TimeExceeded", time_exceeded);
82 inspector.record_counter("PacketTooBig", packet_too_big);
83 inspector.record_inspectable("ParameterProblem", parameter_problem);
84 inspector.record_inspectable("DestUnreachable", dest_unreachable);
85 inspector.record_counter("Error", error);
86 }
87}
88
89#[derive(Default)]
91pub struct IcmpRxCounters<I: IcmpCountersIpExt> {
92 pub error: Counter,
94 pub error_delivered_to_transport_layer: Counter,
96 pub error_delivered_to_socket: Counter,
98 pub echo_request: Counter,
100 pub echo_reply: Counter,
102 pub timestamp_request: Counter,
104 pub dest_unreachable: I::DestUnreachableCounters<Counter>,
106 pub time_exceeded: I::TimeExceededCounters<Counter>,
108 pub parameter_problem: I::ParameterProblemCounters<Counter>,
110 pub packet_too_big: Counter,
112 pub queue_full: Counter,
115}
116
117impl<I: IcmpCountersIpExt> Inspectable for IcmpRxCounters<I> {
118 fn record<II: Inspector>(&self, inspector: &mut II) {
119 let IcmpRxCounters {
120 error,
121 error_delivered_to_transport_layer,
122 error_delivered_to_socket,
123 echo_request,
124 echo_reply,
125 timestamp_request,
126 dest_unreachable,
127 time_exceeded,
128 parameter_problem,
129 packet_too_big,
130 queue_full,
131 } = self;
132 inspector.record_counter("EchoRequest", echo_request);
133 inspector.record_counter("EchoReply", echo_reply);
134 inspector.record_counter("TimestampRequest", timestamp_request);
135 inspector.record_inspectable("DestUnreachable", dest_unreachable);
136 inspector.record_inspectable("TimeExceeded", time_exceeded);
137 inspector.record_inspectable("ParameterProblem", parameter_problem);
138 inspector.record_counter("PacketTooBig", packet_too_big);
139 inspector.record_counter("Error", error);
140 inspector
141 .record_counter("ErrorDeliveredToTransportLayer", error_delivered_to_transport_layer);
142 inspector.record_counter("ErrorDeliveredToSocket", error_delivered_to_socket);
143 inspector.record_counter("DroppedQueueFull", queue_full);
144 }
145}
146
147#[derive(Default)]
152pub struct Icmpv4DestUnreachableCounters<C: CounterRepr> {
153 pub dest_network_unreachable: C,
155 pub dest_host_unreachable: C,
157 pub dest_protocol_unreachable: C,
159 pub dest_port_unreachable: C,
161 pub fragmentation_required: C,
163 pub source_route_failed: C,
165 pub dest_network_unknown: C,
167 pub dest_host_unknown: C,
169 pub source_host_isolated: C,
171 pub network_administratively_prohibited: C,
173 pub host_administratively_prohibited: C,
175 pub network_unreachable_for_tos: C,
177 pub host_unreachable_for_tos: C,
179 pub comm_administratively_prohibited: C,
181 pub host_precedence_violation: C,
183 pub precedence_cutoff_in_effect: C,
185}
186
187impl Icmpv4DestUnreachableCounters<Counter> {
188 pub(crate) fn increment_code(&self, code: Icmpv4DestUnreachableCode) {
189 use Icmpv4DestUnreachableCode::*;
190 let counter = match code {
191 DestNetworkUnreachable => &self.dest_network_unreachable,
192 DestHostUnreachable => &self.dest_host_unreachable,
193 DestProtocolUnreachable => &self.dest_protocol_unreachable,
194 DestPortUnreachable => &self.dest_port_unreachable,
195 FragmentationRequired => &self.fragmentation_required,
196 SourceRouteFailed => &self.source_route_failed,
197 DestNetworkUnknown => &self.dest_network_unknown,
198 DestHostUnknown => &self.dest_host_unknown,
199 SourceHostIsolated => &self.source_host_isolated,
200 NetworkAdministrativelyProhibited => &self.network_administratively_prohibited,
201 HostAdministrativelyProhibited => &self.host_administratively_prohibited,
202 NetworkUnreachableForToS => &self.network_unreachable_for_tos,
203 HostUnreachableForToS => &self.host_unreachable_for_tos,
204 CommAdministrativelyProhibited => &self.comm_administratively_prohibited,
205 HostPrecedenceViolation => &self.host_precedence_violation,
206 PrecedenceCutoffInEffect => &self.precedence_cutoff_in_effect,
207 };
208 counter.increment()
209 }
210}
211
212impl<C: CounterRepr> Inspectable for Icmpv4DestUnreachableCounters<C> {
213 fn record<I: Inspector>(&self, inspector: &mut I) {
214 let Icmpv4DestUnreachableCounters {
215 dest_network_unreachable,
216 dest_host_unreachable,
217 dest_protocol_unreachable,
218 dest_port_unreachable,
219 fragmentation_required,
220 source_route_failed,
221 dest_network_unknown,
222 dest_host_unknown,
223 source_host_isolated,
224 network_administratively_prohibited,
225 host_administratively_prohibited,
226 network_unreachable_for_tos,
227 host_unreachable_for_tos,
228 comm_administratively_prohibited,
229 host_precedence_violation,
230 precedence_cutoff_in_effect,
231 } = self;
232 inspector.record_counter("DestNetworkUnreachable", dest_network_unreachable);
233 inspector.record_counter("DestHostUnreachable", dest_host_unreachable);
234 inspector.record_counter("DestProtocolUnreachable", dest_protocol_unreachable);
235 inspector.record_counter("DestPortUnreachable", dest_port_unreachable);
236 inspector.record_counter("FragmentationRequired", fragmentation_required);
237 inspector.record_counter("SourceRouteFailed", source_route_failed);
238 inspector.record_counter("DestNetworkUnknown", dest_network_unknown);
239 inspector.record_counter("DestHostUnknown", dest_host_unknown);
240 inspector.record_counter("SourceHostIsolated", source_host_isolated);
241 inspector.record_counter(
242 "NetworkAdministrativelyProhibited",
243 network_administratively_prohibited,
244 );
245 inspector
246 .record_counter("HostAdministrativelyProhibited", host_administratively_prohibited);
247 inspector.record_counter("NetworkUnreachableForTos", network_unreachable_for_tos);
248 inspector.record_counter("HostUnreachableForTos", host_unreachable_for_tos);
249 inspector
250 .record_counter("CommAdministrativelyProhibited", comm_administratively_prohibited);
251 inspector.record_counter("HostPrecedenceViolation", host_precedence_violation);
252 inspector.record_counter("PrecedenceCutoffInEffect", precedence_cutoff_in_effect);
253 }
254}
255
256#[derive(Default)]
261pub struct Icmpv6DestUnreachableCounters<C: CounterRepr> {
262 pub no_route: C,
264 pub comm_administratively_prohibited: C,
266 pub beyond_scope: C,
268 pub addr_unreachable: C,
270 pub port_unreachable: C,
272 pub src_addr_failed_policy: C,
274 pub reject_route: C,
276}
277
278impl Icmpv6DestUnreachableCounters<Counter> {
279 pub(crate) fn increment_code(&self, code: Icmpv6DestUnreachableCode) {
280 use Icmpv6DestUnreachableCode::*;
281 let counter = match code {
282 NoRoute => &self.no_route,
283 CommAdministrativelyProhibited => &self.comm_administratively_prohibited,
284 BeyondScope => &self.beyond_scope,
285 AddrUnreachable => &self.addr_unreachable,
286 PortUnreachable => &self.port_unreachable,
287 SrcAddrFailedPolicy => &self.src_addr_failed_policy,
288 RejectRoute => &self.reject_route,
289 };
290 counter.increment();
291 }
292}
293
294impl<C: CounterRepr> Inspectable for Icmpv6DestUnreachableCounters<C> {
295 fn record<I: Inspector>(&self, inspector: &mut I) {
296 let Icmpv6DestUnreachableCounters {
297 no_route,
298 comm_administratively_prohibited,
299 beyond_scope,
300 addr_unreachable,
301 port_unreachable,
302 src_addr_failed_policy,
303 reject_route,
304 } = self;
305 inspector.record_counter("NoRoute", no_route);
306 inspector.record_counter(
307 "CommunicationAdministrativelyProhibited",
308 comm_administratively_prohibited,
309 );
310 inspector.record_counter("BeyondScope", beyond_scope);
311 inspector.record_counter("AddrUnreachable", addr_unreachable);
312 inspector.record_counter("PortUnreachable", port_unreachable);
313 inspector.record_counter("SrcAddrFailedPolicy", src_addr_failed_policy);
314 inspector.record_counter("RejectRoute", reject_route);
315 }
316}
317
318#[derive(Default)]
323pub struct Icmpv4TimeExceededCounters<C: CounterRepr> {
324 pub ttl_expired: C,
326 pub fragment_reassembly_time_exceeded: C,
328}
329
330impl Icmpv4TimeExceededCounters<Counter> {
331 pub(crate) fn increment_code(&self, code: Icmpv4TimeExceededCode) {
332 use Icmpv4TimeExceededCode::*;
333 let counter = match code {
334 TtlExpired => &self.ttl_expired,
335 FragmentReassemblyTimeExceeded => &self.fragment_reassembly_time_exceeded,
336 };
337 counter.increment();
338 }
339}
340
341impl<C: CounterRepr> Inspectable for Icmpv4TimeExceededCounters<C> {
342 fn record<I: Inspector>(&self, inspector: &mut I) {
343 let Icmpv4TimeExceededCounters { ttl_expired, fragment_reassembly_time_exceeded } = self;
344 inspector.record_counter("TtlExpired", ttl_expired);
345 inspector
346 .record_counter("FragmentReassemblyTimeExceeded", fragment_reassembly_time_exceeded);
347 }
348}
349
350#[derive(Default)]
355pub struct Icmpv6TimeExceededCounters<C: CounterRepr> {
356 pub hop_limit_exceeded: C,
358 pub fragment_reassembly_time_exceeded: C,
360}
361
362impl Icmpv6TimeExceededCounters<Counter> {
363 pub(crate) fn increment_code(&self, code: Icmpv6TimeExceededCode) {
364 use Icmpv6TimeExceededCode::*;
365 let counter = match code {
366 HopLimitExceeded => &self.hop_limit_exceeded,
367 FragmentReassemblyTimeExceeded => &self.fragment_reassembly_time_exceeded,
368 };
369 counter.increment();
370 }
371}
372
373impl<C: CounterRepr> Inspectable for Icmpv6TimeExceededCounters<C> {
374 fn record<I: Inspector>(&self, inspector: &mut I) {
375 let Icmpv6TimeExceededCounters { hop_limit_exceeded, fragment_reassembly_time_exceeded } =
376 self;
377 inspector.record_counter("HopLimitExceeded", hop_limit_exceeded);
378 inspector
379 .record_counter("FragmentReassemblyTimeExceeded", fragment_reassembly_time_exceeded);
380 }
381}
382
383#[derive(Default)]
388pub struct Icmpv4ParameterProblemCounters<C: CounterRepr> {
389 pub pointer_indicates_error: C,
391 pub missing_required_option: C,
393 pub bad_length: C,
395}
396
397impl Icmpv4ParameterProblemCounters<Counter> {
398 pub(crate) fn increment_code(&self, code: Icmpv4ParameterProblemCode) {
399 use Icmpv4ParameterProblemCode::*;
400 let counter = match code {
401 PointerIndicatesError => &self.pointer_indicates_error,
402 MissingRequiredOption => &self.missing_required_option,
403 BadLength => &self.bad_length,
404 };
405 counter.increment()
406 }
407}
408
409impl<C: CounterRepr> Inspectable for Icmpv4ParameterProblemCounters<C> {
410 fn record<I: Inspector>(&self, inspector: &mut I) {
411 let Icmpv4ParameterProblemCounters {
412 pointer_indicates_error,
413 missing_required_option,
414 bad_length,
415 } = self;
416 inspector.record_counter("PointerIndicatesError", pointer_indicates_error);
417 inspector.record_counter("MissingRequiredOption", missing_required_option);
418 inspector.record_counter("BadLength", bad_length);
419 }
420}
421
422#[derive(Default)]
427pub struct Icmpv6ParameterProblemCounters<C = Counter> {
428 pub erroneous_header_field: C,
430 pub unrecognized_next_header_type: C,
432 pub unrecognized_ipv6_option: C,
434}
435
436impl Icmpv6ParameterProblemCounters<Counter> {
437 pub(crate) fn increment_code(&self, code: Icmpv6ParameterProblemCode) {
438 use Icmpv6ParameterProblemCode::*;
439 let counter = match code {
440 ErroneousHeaderField => &self.erroneous_header_field,
441 UnrecognizedNextHeaderType => &self.unrecognized_next_header_type,
442 UnrecognizedIpv6Option => &self.unrecognized_ipv6_option,
443 };
444 counter.increment()
445 }
446}
447
448impl<C: CounterRepr> Inspectable for Icmpv6ParameterProblemCounters<C> {
449 fn record<I: Inspector>(&self, inspector: &mut I) {
450 let Icmpv6ParameterProblemCounters {
451 erroneous_header_field,
452 unrecognized_next_header_type,
453 unrecognized_ipv6_option,
454 } = self;
455 inspector.record_counter("ErroneousHeaderField", erroneous_header_field);
456 inspector.record_counter("UnrecognizedNextHeaderType", unrecognized_next_header_type);
457 inspector.record_counter("UnrecognizedIpv6Option", unrecognized_ipv6_option);
458 }
459}