Skip to main content

flowparser_sflow/counter_records/
mod.rs

1pub mod app_operations;
2pub mod app_resources;
3pub mod app_workers;
4pub mod broadcom_bst;
5pub mod broadcom_tables;
6pub mod energy;
7pub mod ethernet_interface;
8pub mod fans;
9pub mod generic_interface;
10pub mod host_adapters;
11pub mod host_cpu;
12pub mod host_descr;
13pub mod host_disk_io;
14pub mod host_memory;
15pub mod host_net_io;
16pub mod host_parent;
17pub mod http_counters;
18pub mod humidity;
19pub mod ib_counters;
20pub mod ieee80211_counters;
21pub mod jmx_runtime;
22pub mod jvm_statistics;
23pub mod lag_port_stats;
24pub mod memcache_counters;
25pub mod mib2_icmp_group;
26pub mod mib2_ip_group;
27pub mod mib2_tcp_group;
28pub mod mib2_udp_group;
29pub mod nvidia_gpu;
30pub mod of_port;
31pub mod ovs_dp_stats;
32pub mod port_name;
33pub mod processor;
34pub mod queue_length;
35pub mod radio_utilization;
36pub mod sfp;
37pub mod slow_path_counts;
38pub mod temperature;
39pub mod token_ring;
40pub mod vg_counters;
41pub mod virt_cpu;
42pub mod virt_disk_io;
43pub mod virt_memory;
44pub mod virt_net_io;
45pub mod virt_node;
46pub mod vlan;
47pub mod xen_vif;
48
49use nom::IResult;
50use nom::number::complete::be_u32;
51use serde::{Deserialize, Serialize};
52
53pub use app_operations::AppOperations;
54pub use app_resources::AppResources;
55pub use app_workers::AppWorkers;
56pub use broadcom_bst::{BroadcomBstDeviceBuffers, BroadcomBstPortBuffers};
57pub use broadcom_tables::BroadcomHwTables;
58pub use energy::Energy;
59pub use ethernet_interface::EthernetInterface;
60pub use fans::Fans;
61pub use generic_interface::GenericInterface;
62pub use host_adapters::HostAdapters;
63pub use host_cpu::HostCpu;
64pub use host_descr::{HostDescr, MachineType, OsName};
65pub use host_disk_io::HostDiskIo;
66pub use host_memory::HostMemory;
67pub use host_net_io::HostNetIo;
68pub use host_parent::HostParent;
69pub use http_counters::HttpCounters;
70pub use humidity::Humidity;
71pub use ib_counters::IbCounters;
72pub use ieee80211_counters::Ieee80211Counters;
73pub use jmx_runtime::JmxRuntime;
74pub use jvm_statistics::JvmStatistics;
75pub use lag_port_stats::LagPortStats;
76pub use memcache_counters::MemcacheCounters;
77pub use mib2_icmp_group::Mib2IcmpGroup;
78pub use mib2_ip_group::Mib2IpGroup;
79pub use mib2_tcp_group::Mib2TcpGroup;
80pub use mib2_udp_group::Mib2UdpGroup;
81pub use nvidia_gpu::NvidiaGpu;
82pub use of_port::OfPort;
83pub use ovs_dp_stats::OvsDpStats;
84pub use port_name::PortName;
85pub use processor::Processor;
86pub use queue_length::QueueLength;
87pub use radio_utilization::RadioUtilization;
88pub use sfp::Sfp;
89pub use slow_path_counts::SlowPathCounts;
90pub use temperature::Temperature;
91pub use token_ring::TokenRing;
92pub use vg_counters::VgCounters;
93pub use virt_cpu::{VirtCpu, VirtDomainState};
94pub use virt_disk_io::VirtDiskIo;
95pub use virt_memory::VirtMemory;
96pub use virt_net_io::VirtNetIo;
97pub use virt_node::VirtNode;
98pub use vlan::Vlan;
99pub use xen_vif::XenVif;
100
101/// A counter record within a counter sample.
102///
103/// Counter records contain periodic interface and system statistics
104/// reported by the sFlow agent.
105#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
106pub enum CounterRecord {
107    /// Generic interface counters (enterprise=0, format=1).
108    GenericInterface(GenericInterface),
109    /// Ethernet-specific interface counters (enterprise=0, format=2).
110    EthernetInterface(EthernetInterface),
111    /// Token Ring interface counters (enterprise=0, format=3).
112    TokenRing(TokenRing),
113    /// 100VG-AnyLAN counters (enterprise=0, format=4).
114    VgCounters(VgCounters),
115    /// VLAN counters (enterprise=0, format=5).
116    Vlan(Vlan),
117    /// IEEE 802.11 counters (enterprise=0, format=6).
118    Ieee80211Counters(Ieee80211Counters),
119    /// LAG port statistics (enterprise=0, format=7).
120    LagPortStats(LagPortStats),
121    /// Slow path counts (enterprise=0, format=8).
122    SlowPathCounts(SlowPathCounts),
123    /// InfiniBand counters (enterprise=0, format=9).
124    IbCounters(IbCounters),
125    /// SFP/optical transceiver counters (enterprise=0, format=10).
126    Sfp(Sfp),
127    /// Processor/CPU counters (enterprise=0, format=1001).
128    Processor(Processor),
129    /// Radio utilization counters (enterprise=0, format=1002).
130    RadioUtilization(RadioUtilization),
131    /// Queue length histogram (enterprise=0, format=1003).
132    QueueLength(QueueLength),
133    /// OpenFlow port mapping (enterprise=0, format=1004).
134    OfPort(OfPort),
135    /// Port name (enterprise=0, format=1005).
136    PortName(PortName),
137    /// Host description (enterprise=0, format=2000).
138    HostDescr(HostDescr),
139    /// Host network adapters (enterprise=0, format=2001).
140    HostAdapters(HostAdapters),
141    /// Host parent (virtualization) (enterprise=0, format=2002).
142    HostParent(HostParent),
143    /// Host CPU counters (enterprise=0, format=2003).
144    HostCpu(HostCpu),
145    /// Host memory counters (enterprise=0, format=2004).
146    HostMemory(HostMemory),
147    /// Host disk I/O counters (enterprise=0, format=2005).
148    HostDiskIo(HostDiskIo),
149    /// Host network I/O counters (enterprise=0, format=2006).
150    HostNetIo(HostNetIo),
151    /// Virtual node statistics (enterprise=0, format=2100).
152    VirtNode(VirtNode),
153    /// Virtual CPU statistics (enterprise=0, format=2101).
154    VirtCpu(VirtCpu),
155    /// Virtual memory statistics (enterprise=0, format=2102).
156    VirtMemory(VirtMemory),
157    /// Virtual disk I/O statistics (enterprise=0, format=2103).
158    VirtDiskIo(VirtDiskIo),
159    /// Virtual network I/O statistics (enterprise=0, format=2104).
160    VirtNetIo(VirtNetIo),
161    /// MIB-II IP group counters (enterprise=0, format=2007).
162    Mib2IpGroup(Mib2IpGroup),
163    /// MIB-II ICMP group counters (enterprise=0, format=2008).
164    Mib2IcmpGroup(Mib2IcmpGroup),
165    /// MIB-II TCP group counters (enterprise=0, format=2009).
166    Mib2TcpGroup(Mib2TcpGroup),
167    /// MIB-II UDP group counters (enterprise=0, format=2010).
168    Mib2UdpGroup(Mib2UdpGroup),
169    /// JMX runtime information (enterprise=0, format=2105).
170    JmxRuntime(JmxRuntime),
171    /// JVM statistics counters (enterprise=0, format=2106).
172    JvmStatistics(JvmStatistics),
173    /// HTTP method and status counters (enterprise=0, format=2201).
174    HttpCounters(HttpCounters),
175    /// Application operations counters (enterprise=0, format=2202).
176    AppOperations(AppOperations),
177    /// Application resource counters (enterprise=0, format=2203).
178    AppResources(AppResources),
179    /// Memcache counters (enterprise=0, format=2204).
180    MemcacheCounters(MemcacheCounters),
181    /// Application worker counters (enterprise=0, format=2206).
182    AppWorkers(AppWorkers),
183    /// Open vSwitch datapath statistics (enterprise=0, format=2207).
184    OvsDpStats(OvsDpStats),
185    /// Energy consumption counters (enterprise=0, format=3000).
186    Energy(Energy),
187    /// Temperature sensor counters (enterprise=0, format=3001).
188    Temperature(Temperature),
189    /// Humidity sensor counters (enterprise=0, format=3002).
190    Humidity(Humidity),
191    /// Fan status counters (enterprise=0, format=3003).
192    Fans(Fans),
193    /// Broadcom BST device buffer utilization (enterprise=4413, format=1).
194    BroadcomBstDeviceBuffers(BroadcomBstDeviceBuffers),
195    /// Broadcom BST port buffer utilization (enterprise=4413, format=2).
196    BroadcomBstPortBuffers(BroadcomBstPortBuffers),
197    /// Broadcom ASIC hardware table utilization (enterprise=4413, format=3).
198    BroadcomHwTables(BroadcomHwTables),
199    /// NVIDIA GPU counters via NVML (enterprise=5703, format=1).
200    NvidiaGpu(NvidiaGpu),
201    /// XenServer virtual interface metadata (enterprise=4300, format=2).
202    XenVif(XenVif),
203    /// Unrecognized counter record type, preserved as raw bytes.
204    Unknown {
205        /// Enterprise code from the record header.
206        enterprise: u32,
207        /// Format code from the record header.
208        format: u32,
209        /// Raw record data.
210        data: Vec<u8>,
211    },
212}
213
214pub(crate) fn parse_counter_records(
215    mut input: &[u8],
216    num_records: u32,
217) -> IResult<&[u8], Vec<CounterRecord>> {
218    // Cap capacity to prevent DoS: each record needs at least 8 bytes (format + length)
219    let cap = (num_records as usize).min(input.len() / 8);
220    let mut records = Vec::with_capacity(cap);
221
222    for _ in 0..num_records {
223        let (rest, data_format) = be_u32(input)?;
224        let enterprise = data_format >> 12;
225        let format = data_format & 0xFFF;
226
227        let (rest, record_length) = be_u32(rest)?;
228        let record_length = record_length as usize;
229
230        if rest.len() < record_length {
231            return Err(nom::Err::Error(nom::error::Error::new(
232                rest,
233                nom::error::ErrorKind::Eof,
234            )));
235        }
236
237        let record_data = &rest[..record_length];
238        let after_record = &rest[record_length..];
239
240        let record = if enterprise == 0 {
241            match format {
242                1 => {
243                    let (_, r) = generic_interface::parse_generic_interface(record_data)?;
244                    CounterRecord::GenericInterface(r)
245                }
246                2 => {
247                    let (_, r) = ethernet_interface::parse_ethernet_interface(record_data)?;
248                    CounterRecord::EthernetInterface(r)
249                }
250                3 => {
251                    let (_, r) = token_ring::parse_token_ring(record_data)?;
252                    CounterRecord::TokenRing(r)
253                }
254                4 => {
255                    let (_, r) = vg_counters::parse_vg_counters(record_data)?;
256                    CounterRecord::VgCounters(r)
257                }
258                5 => {
259                    let (_, r) = vlan::parse_vlan(record_data)?;
260                    CounterRecord::Vlan(r)
261                }
262                6 => {
263                    let (_, r) = ieee80211_counters::parse_ieee80211_counters(record_data)?;
264                    CounterRecord::Ieee80211Counters(r)
265                }
266                7 => {
267                    let (_, r) = lag_port_stats::parse_lag_port_stats(record_data)?;
268                    CounterRecord::LagPortStats(r)
269                }
270                8 => {
271                    let (_, r) = slow_path_counts::parse_slow_path_counts(record_data)?;
272                    CounterRecord::SlowPathCounts(r)
273                }
274                9 => {
275                    let (_, r) = ib_counters::parse_ib_counters(record_data)?;
276                    CounterRecord::IbCounters(r)
277                }
278                10 => {
279                    let (_, r) = sfp::parse_sfp(record_data)?;
280                    CounterRecord::Sfp(r)
281                }
282                1001 => {
283                    let (_, r) = processor::parse_processor(record_data)?;
284                    CounterRecord::Processor(r)
285                }
286                1003 => {
287                    let (_, r) = queue_length::parse_queue_length(record_data)?;
288                    CounterRecord::QueueLength(r)
289                }
290                1002 => {
291                    let (_, r) = radio_utilization::parse_radio_utilization(record_data)?;
292                    CounterRecord::RadioUtilization(r)
293                }
294                1004 => {
295                    let (_, r) = of_port::parse_of_port(record_data)?;
296                    CounterRecord::OfPort(r)
297                }
298                1005 => {
299                    let (_, r) = port_name::parse_port_name(record_data)?;
300                    CounterRecord::PortName(r)
301                }
302                2000 => {
303                    let (_, r) = host_descr::parse_host_descr(record_data)?;
304                    CounterRecord::HostDescr(r)
305                }
306                2001 => {
307                    let (_, r) = host_adapters::parse_host_adapters(record_data)?;
308                    CounterRecord::HostAdapters(r)
309                }
310                2002 => {
311                    let (_, r) = host_parent::parse_host_parent(record_data)?;
312                    CounterRecord::HostParent(r)
313                }
314                2003 => {
315                    let (_, r) = host_cpu::parse_host_cpu(record_data)?;
316                    CounterRecord::HostCpu(r)
317                }
318                2004 => {
319                    let (_, r) = host_memory::parse_host_memory(record_data)?;
320                    CounterRecord::HostMemory(r)
321                }
322                2005 => {
323                    let (_, r) = host_disk_io::parse_host_disk_io(record_data)?;
324                    CounterRecord::HostDiskIo(r)
325                }
326                2006 => {
327                    let (_, r) = host_net_io::parse_host_net_io(record_data)?;
328                    CounterRecord::HostNetIo(r)
329                }
330                2100 => {
331                    let (_, r) = virt_node::parse_virt_node(record_data)?;
332                    CounterRecord::VirtNode(r)
333                }
334                2101 => {
335                    let (_, r) = virt_cpu::parse_virt_cpu(record_data)?;
336                    CounterRecord::VirtCpu(r)
337                }
338                2102 => {
339                    let (_, r) = virt_memory::parse_virt_memory(record_data)?;
340                    CounterRecord::VirtMemory(r)
341                }
342                2103 => {
343                    let (_, r) = virt_disk_io::parse_virt_disk_io(record_data)?;
344                    CounterRecord::VirtDiskIo(r)
345                }
346                2104 => {
347                    let (_, r) = virt_net_io::parse_virt_net_io(record_data)?;
348                    CounterRecord::VirtNetIo(r)
349                }
350                2007 => {
351                    let (_, r) = mib2_ip_group::parse_mib2_ip_group(record_data)?;
352                    CounterRecord::Mib2IpGroup(r)
353                }
354                2008 => {
355                    let (_, r) = mib2_icmp_group::parse_mib2_icmp_group(record_data)?;
356                    CounterRecord::Mib2IcmpGroup(r)
357                }
358                2009 => {
359                    let (_, r) = mib2_tcp_group::parse_mib2_tcp_group(record_data)?;
360                    CounterRecord::Mib2TcpGroup(r)
361                }
362                2010 => {
363                    let (_, r) = mib2_udp_group::parse_mib2_udp_group(record_data)?;
364                    CounterRecord::Mib2UdpGroup(r)
365                }
366                2105 => {
367                    let (_, r) = jmx_runtime::parse_jmx_runtime(record_data)?;
368                    CounterRecord::JmxRuntime(r)
369                }
370                2106 => {
371                    let (_, r) = jvm_statistics::parse_jvm_statistics(record_data)?;
372                    CounterRecord::JvmStatistics(r)
373                }
374                2201 => {
375                    let (_, r) = http_counters::parse_http_counters(record_data)?;
376                    CounterRecord::HttpCounters(r)
377                }
378                2202 => {
379                    let (_, r) = app_operations::parse_app_operations(record_data)?;
380                    CounterRecord::AppOperations(r)
381                }
382                2203 => {
383                    let (_, r) = app_resources::parse_app_resources(record_data)?;
384                    CounterRecord::AppResources(r)
385                }
386                2204 => {
387                    let (_, r) = memcache_counters::parse_memcache_counters(record_data)?;
388                    CounterRecord::MemcacheCounters(r)
389                }
390                2206 => {
391                    let (_, r) = app_workers::parse_app_workers(record_data)?;
392                    CounterRecord::AppWorkers(r)
393                }
394                2207 => {
395                    let (_, r) = ovs_dp_stats::parse_ovs_dp_stats(record_data)?;
396                    CounterRecord::OvsDpStats(r)
397                }
398                3000 => {
399                    let (_, r) = energy::parse_energy(record_data)?;
400                    CounterRecord::Energy(r)
401                }
402                3001 => {
403                    let (_, r) = temperature::parse_temperature(record_data)?;
404                    CounterRecord::Temperature(r)
405                }
406                3002 => {
407                    let (_, r) = humidity::parse_humidity(record_data)?;
408                    CounterRecord::Humidity(r)
409                }
410                3003 => {
411                    let (_, r) = fans::parse_fans(record_data)?;
412                    CounterRecord::Fans(r)
413                }
414                _ => CounterRecord::Unknown {
415                    enterprise,
416                    format,
417                    data: record_data.to_vec(),
418                },
419            }
420        } else {
421            match (enterprise, format) {
422                (4300, 2) => {
423                    let (_, r) = xen_vif::parse_xen_vif(record_data)?;
424                    CounterRecord::XenVif(r)
425                }
426                (4413, 1) => {
427                    let (_, r) = broadcom_bst::parse_broadcom_bst_device_buffers(record_data)?;
428                    CounterRecord::BroadcomBstDeviceBuffers(r)
429                }
430                (4413, 2) => {
431                    let (_, r) = broadcom_bst::parse_broadcom_bst_port_buffers(record_data)?;
432                    CounterRecord::BroadcomBstPortBuffers(r)
433                }
434                (4413, 3) => {
435                    let (_, r) = broadcom_tables::parse_broadcom_hw_tables(record_data)?;
436                    CounterRecord::BroadcomHwTables(r)
437                }
438                (5703, 1) => {
439                    let (_, r) = nvidia_gpu::parse_nvidia_gpu(record_data)?;
440                    CounterRecord::NvidiaGpu(r)
441                }
442                _ => CounterRecord::Unknown {
443                    enterprise,
444                    format,
445                    data: record_data.to_vec(),
446                },
447            }
448        };
449
450        records.push(record);
451        input = after_record;
452    }
453
454    Ok((input, records))
455}