Skip to content

Commit 7a932f2

Browse files
committed
implement Extended Queue Length records
1 parent 425dd8d commit 7a932f2

File tree

8 files changed

+392
-137
lines changed

8 files changed

+392
-137
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ Each sample contains one or more flow records (for flow samples) or counter reco
9090
| 0 | 1016 | Extended 802.11 Aggregation | [sFlow 802.11](https://sflow.org/sflow_80211.txt) ||
9191
| 0 | 1017 | Extended OpenFlow v1 (deprecated) | [sFlow OpenFlow Draft](https://sflow.org/draft-sflow-openflow.txt) | ✅ 🪦 |
9292
| 0 | 1018 | Extended Fibre Channel | [RFC 4625](https://datatracker.ietf.org/doc/html/rfc4625) ||
93-
| 0 | 1019 | Extended Queue Length | [sFlow Discussion](http://groups.google.com/group/sflow/browse_thread/thread/773d27b17a81600c) | |
93+
| 0 | 1019 | Extended Queue Length | [sFlow Discussion](http://groups.google.com/group/sflow/browse_thread/thread/773d27b17a81600c) | |
9494
| 0 | 1020 | Extended NAT Port | [sFlow Port NAT](https://sflow.org/sflow_pnat.txt) ||
9595
| 0 | 1021 | Extended L2 Tunnel Egress | [sFlow Tunnel](https://sflow.org/sflow_tunnels.txt) ||
9696
| 0 | 1022 | Extended L2 Tunnel Ingress | [sFlow Tunnel](https://sflow.org/sflow_tunnels.txt) ||
@@ -151,7 +151,7 @@ Each sample contains one or more flow records (for flow samples) or counter reco
151151
| 0 | 10 | Optical SFP/QSFP | [sFlow Optics](https://sflow.org/sflow_optics.txt) ||
152152
| 0 | 1001 | Processor | [sFlow v5](https://sflow.org/sflow_version_5.txt) ||
153153
| 0 | 1002 | Radio Utilization | [sFlow 802.11](https://sflow.org/sflow_80211.txt) ||
154-
| 0 | 1003 | Queue Length | [sFlow Discussion](http://groups.google.com/group/sflow/browse_thread/thread/773d27b17a81600c) | |
154+
| 0 | 1003 | Queue Length | [sFlow Discussion](http://groups.google.com/group/sflow/browse_thread/thread/773d27b17a81600c) | |
155155
| 0 | 1004 | OpenFlow Port | [sFlow OpenFlow](https://sflow.org/sflow_openflow.txt) ||
156156
| 0 | 1005 | OpenFlow Port Name | [sFlow OpenFlow](https://sflow.org/sflow_openflow.txt) ||
157157
| 0 | 2000 | Host Description | [sFlow Host](https://sflow.org/sflow_host.txt) ||

src/models/core.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,8 @@ pub enum FlowData {
302302
ExtendedOpenFlowV1(crate::models::record_flows::ExtendedOpenFlowV1),
303303
/// Extended Fiber Channel - Format (0,1018)
304304
ExtendedFc(crate::models::record_flows::ExtendedFc),
305+
/// Extended Queue Length - Format (0,1019)
306+
ExtendedQueueLength(crate::models::record_flows::ExtendedQueueLength),
305307
/// Extended NAT Port - Format (0,1020)
306308
ExtendedNatPort(crate::models::record_flows::ExtendedNatPort),
307309
/// Extended InfiniBand BTH - Format (0,1033)
@@ -420,6 +422,8 @@ pub enum CounterData {
420422
Processor(crate::models::record_counters::ProcessorCounters),
421423
/// Radio Utilization - Format (0,1002)
422424
RadioUtilization(crate::models::record_counters::RadioUtilization),
425+
/// Queue Length - Format (0,1003)
426+
QueueLength(crate::models::record_counters::QueueLength),
423427
/// OpenFlow Port - Format (0,1004)
424428
OpenFlowPort(crate::models::record_counters::OpenFlowPort),
425429
/// OpenFlow Port Name - Format (0,1005)

src/models/record_counters.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,96 @@ pub struct RadioUtilization {
671671
pub on_channel_busy_time: u32,
672672
}
673673

674+
/// Queue Length - Format (0,1003)
675+
///
676+
/// Histogram of queue lengths experienced by packets when they are enqueued
677+
///
678+
/// # XDR Definition ([sFlow Discussion](http://groups.google.com/group/sflow/browse_thread/thread/773d27b17a81600c))
679+
///
680+
/// ```text
681+
/// /* Queue length counters
682+
/// Histogram of queue lengths experienced by packets when they are
683+
/// enqueued (ie queue length immediately before packet is enqueued)
684+
/// thus giving the queue lengths experienced by each packet.
685+
/// Queue length is measured in segments occupied by the enqueued
686+
/// packets.
687+
/// Queue length counter records for each of the queues for a
688+
/// port must be exported with the generic interface counters
689+
/// record, if_counters, for the port.*/
690+
///
691+
/// /* Queue length histogram counters
692+
/// opaque = counter_data; enterprise = 0; format = 1003 */
693+
///
694+
/// struct queue_length {
695+
/// unsigned int queueIndex; /* persistent index of queue within port */
696+
/// unsigned int segmentSize; /* size of queue segment in bytes */
697+
/// unsigned int queueSegments; /* total number of segments allocated
698+
/// (ie available) to this queue. */
699+
/// unsigned int queueLength0; /* queue is empty when a packet is
700+
/// enqueued. */
701+
/// unsigned int queueLength1; /* queue length == 1 segment when a
702+
/// packet is enqueued. */
703+
/// unsigned int queueLength2; /* queue length == 2 segments when a
704+
/// packet is enqueued. */
705+
/// unsigned int queueLength4; /* 2 segments > queue length <= 4
706+
/// segments when a packet is enqueued. */
707+
/// unsigned int queueLength8; /* 4 segments > queue length <= 8
708+
/// segments when packet is enqueued. */
709+
/// unsigned int queueLength32; /* 8 segments > queue length <= 32
710+
/// segments when packet is enqueued. */
711+
/// unsigned int queueLength128; /* 32 segments > queue length <= 128
712+
/// segments when packet is enqueued. */
713+
/// unsigned int queueLength1024; /* 128 segments > queue length <= 1024
714+
/// segments when packet is enqueued. */
715+
/// unsigned int queueLengthMore; /* queue length > 1024 segments when
716+
/// packet is enqueued. */
717+
/// unsigned int dropped; /* count of packets intended for this queue
718+
/// that are dropped on enqueuing. */
719+
/// }
720+
/// ```
721+
#[derive(Debug, Clone, PartialEq, Eq)]
722+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
723+
pub struct QueueLength {
724+
/// Persistent index of queue within port
725+
pub queue_index: u32,
726+
727+
/// Size of queue segment in bytes
728+
pub segment_size: u32,
729+
730+
/// Total number of segments allocated (available) to this queue
731+
pub queue_segments: u32,
732+
733+
/// Queue is empty when a packet is enqueued
734+
pub queue_length_0: u32,
735+
736+
/// Queue length == 1 segment when a packet is enqueued
737+
pub queue_length_1: u32,
738+
739+
/// Queue length == 2 segments when a packet is enqueued
740+
pub queue_length_2: u32,
741+
742+
/// 2 segments > queue length <= 4 segments when a packet is enqueued
743+
pub queue_length_4: u32,
744+
745+
/// 4 segments > queue length <= 8 segments when packet is enqueued
746+
pub queue_length_8: u32,
747+
748+
/// 8 segments > queue length <= 32 segments when packet is enqueued
749+
pub queue_length_32: u32,
750+
751+
/// 32 segments > queue length <= 128 segments when packet is enqueued
752+
pub queue_length_128: u32,
753+
754+
/// 128 segments > queue length <= 1024 segments when packet is enqueued
755+
pub queue_length_1024: u32,
756+
757+
/// Queue length > 1024 segments when packet is enqueued
758+
pub queue_length_more: u32,
759+
760+
/// Count of packets intended for this queue that are dropped on enqueuing
761+
pub dropped: u32,
762+
}
763+
674764
/// OpenFlow Port - Format (0,1004)
675765
///
676766
/// OpenFlow port statistics

src/models/record_flows.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,6 +1092,43 @@ pub struct ExtendedFc {
10921092
pub metric: u32,
10931093
}
10941094

1095+
/// Extended Queue Length - Format (0,1019)
1096+
///
1097+
/// Queue length experienced by the sampled packet
1098+
///
1099+
/// # XDR Definition ([sFlow Discussion](http://groups.google.com/group/sflow/browse_thread/thread/773d27b17a81600c))
1100+
///
1101+
/// ```text
1102+
/// /* Extended queue length data
1103+
/// Used to indicate the queue length experienced by the sampled packet.
1104+
/// If the extended_queue_length record is exported, queue_length counter
1105+
/// records must also be exported with the if_counter record.*/
1106+
///
1107+
/// /* opaque = flow_data; enterprise = 0; format = 1019 */
1108+
///
1109+
/// struct extended_queue_length
1110+
/// {
1111+
/// unsigned int queueIndex; /* persistent index within port of queue
1112+
/// used to enqueue sampled packet.
1113+
/// The ifIndex of the port can be inferred
1114+
/// from the data source. */
1115+
/// unsigned int queueLength; /* length of queue, in segments,
1116+
/// experienced by the packet (ie queue length
1117+
/// immediately before the sampled packet is
1118+
/// enqueued). */
1119+
/// }
1120+
/// ```
1121+
#[derive(Debug, Clone, PartialEq, Eq)]
1122+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1123+
pub struct ExtendedQueueLength {
1124+
/// Persistent index within port of queue used to enqueue sampled packet
1125+
pub queue_index: u32,
1126+
1127+
/// Length of queue, in segments, experienced by the packet
1128+
/// (queue length immediately before the sampled packet is enqueued)
1129+
pub queue_length: u32,
1130+
}
1131+
10951132
/// Extended L2 Tunnel Egress - Format (0,1021)
10961133
///
10971134
/// Layer 2 tunnel egress information - reports outer Ethernet headers

src/parsers/parser_counters.rs

Lines changed: 56 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,27 @@ impl<R: Read> Parser<R> {
290290
})
291291
}
292292

293+
/// Parse Queue Length - Format (0,1003)
294+
pub(super) fn parse_queue_length(
295+
&mut self,
296+
) -> Result<crate::models::record_counters::QueueLength> {
297+
Ok(crate::models::record_counters::QueueLength {
298+
queue_index: self.read_u32()?,
299+
segment_size: self.read_u32()?,
300+
queue_segments: self.read_u32()?,
301+
queue_length_0: self.read_u32()?,
302+
queue_length_1: self.read_u32()?,
303+
queue_length_2: self.read_u32()?,
304+
queue_length_4: self.read_u32()?,
305+
queue_length_8: self.read_u32()?,
306+
queue_length_32: self.read_u32()?,
307+
queue_length_128: self.read_u32()?,
308+
queue_length_1024: self.read_u32()?,
309+
queue_length_more: self.read_u32()?,
310+
dropped: self.read_u32()?,
311+
})
312+
}
313+
293314
/// Parse OpenFlow Port - Format (0,1004)
294315
pub(super) fn parse_openflow_port(
295316
&mut self,
@@ -556,33 +577,6 @@ impl<R: Read> Parser<R> {
556577
})
557578
}
558579

559-
/// Parse Temperature - Format (0,3001)
560-
pub(super) fn parse_temperature(
561-
&mut self,
562-
) -> Result<crate::models::record_counters::Temperature> {
563-
Ok(crate::models::record_counters::Temperature {
564-
minimum: self.read_i32()?,
565-
maximum: self.read_i32()?,
566-
errors: self.read_u32()?,
567-
})
568-
}
569-
570-
/// Parse Humidity - Format (0,3002)
571-
pub(super) fn parse_humidity(&mut self) -> Result<crate::models::record_counters::Humidity> {
572-
Ok(crate::models::record_counters::Humidity {
573-
relative: self.read_i32()?,
574-
})
575-
}
576-
577-
/// Parse Fans - Format (0,3003)
578-
pub(super) fn parse_fans(&mut self) -> Result<crate::models::record_counters::Fans> {
579-
Ok(crate::models::record_counters::Fans {
580-
total: self.read_u32()?,
581-
failed: self.read_u32()?,
582-
speed: self.read_u32()?,
583-
})
584-
}
585-
586580
/// Parse Virtual Node - Format (0,2100)
587581
pub(super) fn parse_virtual_node(
588582
&mut self,
@@ -839,6 +833,33 @@ impl<R: Read> Parser<R> {
839833
})
840834
}
841835

836+
/// Parse Temperature - Format (0,3001)
837+
pub(super) fn parse_temperature(
838+
&mut self,
839+
) -> Result<crate::models::record_counters::Temperature> {
840+
Ok(crate::models::record_counters::Temperature {
841+
minimum: self.read_i32()?,
842+
maximum: self.read_i32()?,
843+
errors: self.read_u32()?,
844+
})
845+
}
846+
847+
/// Parse Humidity - Format (0,3002)
848+
pub(super) fn parse_humidity(&mut self) -> Result<crate::models::record_counters::Humidity> {
849+
Ok(crate::models::record_counters::Humidity {
850+
relative: self.read_i32()?,
851+
})
852+
}
853+
854+
/// Parse Fans - Format (0,3003)
855+
pub(super) fn parse_fans(&mut self) -> Result<crate::models::record_counters::Fans> {
856+
Ok(crate::models::record_counters::Fans {
857+
total: self.read_u32()?,
858+
failed: self.read_u32()?,
859+
speed: self.read_u32()?,
860+
})
861+
}
862+
842863
/// Parse Broadcom Device Buffer Utilization - Format (4413,1)
843864
pub(super) fn parse_broadcom_device_buffers(
844865
&mut self,
@@ -976,6 +997,7 @@ impl<R: Read> Parser<R> {
976997
1002 => Ok(CounterData::RadioUtilization(
977998
parser.parse_radio_utilization()?,
978999
)),
1000+
1003 => Ok(CounterData::QueueLength(parser.parse_queue_length()?)),
9791001
1004 => Ok(CounterData::OpenFlowPort(parser.parse_openflow_port()?)),
9801002
1005 => Ok(CounterData::OpenFlowPortName(
9811003
parser.parse_openflow_port_name()?,
@@ -993,27 +1015,28 @@ impl<R: Read> Parser<R> {
9931015
2008 => Ok(CounterData::Mib2IcmpGroup(parser.parse_mib2_icmp_group()?)),
9941016
2009 => Ok(CounterData::Mib2TcpGroup(parser.parse_mib2_tcp_group()?)),
9951017
2010 => Ok(CounterData::Mib2UdpGroup(parser.parse_mib2_udp_group()?)),
996-
3000 => Ok(CounterData::Energy(parser.parse_energy()?)),
997-
3001 => Ok(CounterData::Temperature(parser.parse_temperature()?)),
998-
3002 => Ok(CounterData::Humidity(parser.parse_humidity()?)),
999-
3003 => Ok(CounterData::Fans(parser.parse_fans()?)),
10001018
2100 => Ok(CounterData::VirtualNode(parser.parse_virtual_node()?)),
10011019
2101 => Ok(CounterData::VirtualCpu(parser.parse_virtual_cpu()?)),
10021020
2102 => Ok(CounterData::VirtualMemory(parser.parse_virtual_memory()?)),
10031021
2103 => Ok(CounterData::VirtualDiskIo(parser.parse_virtual_disk_io()?)),
10041022
2104 => Ok(CounterData::VirtualNetIo(parser.parse_virtual_net_io()?)),
10051023
2105 => Ok(CounterData::JvmRuntime(parser.parse_jvm_runtime()?)),
10061024
2106 => Ok(CounterData::JvmStatistics(parser.parse_jvm_statistics()?)),
1025+
// DEPRECATED
10071026
2200 => Ok(CounterData::MemcacheCountersDeprecated(
10081027
parser.parse_memcache_counters_deprecated()?,
10091028
)),
10101029
2201 => Ok(CounterData::HttpCounters(parser.parse_http_counters()?)),
1030+
2202 => Ok(CounterData::AppOperations(parser.parse_app_operations()?)),
1031+
2203 => Ok(CounterData::AppResources(parser.parse_app_resources()?)),
10111032
2204 => Ok(CounterData::MemcacheCounters(
10121033
parser.parse_memcache_counters()?,
10131034
)),
1014-
2202 => Ok(CounterData::AppOperations(parser.parse_app_operations()?)),
1015-
2203 => Ok(CounterData::AppResources(parser.parse_app_resources()?)),
10161035
2206 => Ok(CounterData::AppWorkers(parser.parse_app_workers()?)),
1036+
3000 => Ok(CounterData::Energy(parser.parse_energy()?)),
1037+
3001 => Ok(CounterData::Temperature(parser.parse_temperature()?)),
1038+
3002 => Ok(CounterData::Humidity(parser.parse_humidity()?)),
1039+
3003 => Ok(CounterData::Fans(parser.parse_fans()?)),
10171040
_ => Ok(CounterData::Unknown { format, data }),
10181041
}
10191042
} else if format.enterprise() == 4413 {

0 commit comments

Comments
 (0)