sflow_parser/models/
record_flows.rs

1//! Flow record data structures
2//!
3//! These represent the actual packet data captured in flow samples.
4//! Enterprise = 0 (sFlow.org standard formats)
5
6use std::net::{Ipv4Addr, Ipv6Addr};
7
8/// Header protocol types for sampled headers
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub enum HeaderProtocol {
12    EthernetIso88023 = 1,
13    Iso88024TokenBus = 2,
14    Iso88025TokenRing = 3,
15    Fddi = 4,
16    FrameRelay = 5,
17    X25 = 6,
18    Ppp = 7,
19    Smds = 8,
20    Aal5 = 9,
21    Aal5Ip = 10,
22    Ipv4 = 11,
23    Ipv6 = 12,
24    Mpls = 13,
25    Pos = 14,
26    Ieee80211Mac = 15,
27    Ieee80211Ampdu = 16,
28    Ieee80211Amsdu = 17,
29}
30
31impl HeaderProtocol {
32    /// Convert from u32 value to HeaderProtocol enum
33    pub fn from_u32(value: u32) -> Option<Self> {
34        match value {
35            1 => Some(HeaderProtocol::EthernetIso88023),
36            2 => Some(HeaderProtocol::Iso88024TokenBus),
37            3 => Some(HeaderProtocol::Iso88025TokenRing),
38            4 => Some(HeaderProtocol::Fddi),
39            5 => Some(HeaderProtocol::FrameRelay),
40            6 => Some(HeaderProtocol::X25),
41            7 => Some(HeaderProtocol::Ppp),
42            8 => Some(HeaderProtocol::Smds),
43            9 => Some(HeaderProtocol::Aal5),
44            10 => Some(HeaderProtocol::Aal5Ip),
45            11 => Some(HeaderProtocol::Ipv4),
46            12 => Some(HeaderProtocol::Ipv6),
47            13 => Some(HeaderProtocol::Mpls),
48            14 => Some(HeaderProtocol::Pos),
49            15 => Some(HeaderProtocol::Ieee80211Mac),
50            16 => Some(HeaderProtocol::Ieee80211Ampdu),
51            17 => Some(HeaderProtocol::Ieee80211Amsdu),
52            _ => None,
53        }
54    }
55}
56
57impl std::fmt::Display for HeaderProtocol {
58    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59        match self {
60            HeaderProtocol::EthernetIso88023 => write!(f, "Ethernet (ISO 802.3)"),
61            HeaderProtocol::Iso88024TokenBus => write!(f, "ISO 802.4 Token Bus"),
62            HeaderProtocol::Iso88025TokenRing => write!(f, "ISO 802.5 Token Ring"),
63            HeaderProtocol::Fddi => write!(f, "FDDI"),
64            HeaderProtocol::FrameRelay => write!(f, "Frame Relay"),
65            HeaderProtocol::X25 => write!(f, "X.25"),
66            HeaderProtocol::Ppp => write!(f, "PPP"),
67            HeaderProtocol::Smds => write!(f, "SMDS"),
68            HeaderProtocol::Aal5 => write!(f, "AAL5"),
69            HeaderProtocol::Aal5Ip => write!(f, "AAL5 IP"),
70            HeaderProtocol::Ipv4 => write!(f, "IPv4"),
71            HeaderProtocol::Ipv6 => write!(f, "IPv6"),
72            HeaderProtocol::Mpls => write!(f, "MPLS"),
73            HeaderProtocol::Pos => write!(f, "POS"),
74            HeaderProtocol::Ieee80211Mac => write!(f, "IEEE 802.11 MAC"),
75            HeaderProtocol::Ieee80211Ampdu => write!(f, "IEEE 802.11 A-MPDU"),
76            HeaderProtocol::Ieee80211Amsdu => write!(f, "IEEE 802.11 A-MSDU"),
77        }
78    }
79}
80
81/// Sampled Header - Format (0,1)
82///
83/// Raw packet header captured from the wire
84///
85/// # XDR Definition (sFlow v5)
86///
87/// ```text
88/// /* Raw Packet Header */
89/// /* opaque = flow_data; enterprise = 0; format = 1 */
90///
91/// struct sampled_header {
92///     header_protocol protocol;  /* Format of sampled header */
93///     unsigned int frame_length; /* Original length of packet before sampling */
94///     unsigned int stripped;     /* Number of octets removed from packet */
95///     opaque header<>;           /* Header bytes */
96/// }
97/// ```
98#[derive(Debug, Clone, PartialEq, Eq)]
99#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
100pub struct SampledHeader {
101    /// Protocol of the sampled packet
102    pub protocol: HeaderProtocol,
103
104    /// Original length of the packet (before sampling)
105    pub frame_length: u32,
106
107    /// Number of bytes stripped from the packet before sampling
108    pub stripped: u32,
109
110    /// Raw header bytes
111    pub header: Vec<u8>,
112}
113
114/// Sampled Ethernet Frame - Format (0,2)
115///
116/// Ethernet frame header information
117///
118/// # XDR Definition (sFlow v5)
119///
120/// ```text
121/// /* Ethernet Frame Data */
122/// /* opaque = flow_data; enterprise = 0; format = 2 */
123///
124/// struct sampled_ethernet {
125///     unsigned int length;   /* The length of the MAC packet received on the
126///                               network, excluding lower layer encapsulations
127///                               and framing bits but including FCS octets */
128///     mac src_mac;           /* Source MAC address */
129///     mac dst_mac;           /* Destination MAC address */
130///     unsigned int type;     /* Ethernet packet type */
131/// }
132/// ```
133#[derive(Debug, Clone, PartialEq, Eq)]
134#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
135pub struct SampledEthernet {
136    /// Length of MAC packet in bytes
137    pub length: u32,
138
139    /// Source MAC address
140    pub src_mac: crate::models::MacAddress,
141
142    /// Destination MAC address
143    pub dst_mac: crate::models::MacAddress,
144
145    /// Ethernet type (spec: type)
146    pub eth_type: u32,
147}
148
149/// Sampled IPv4 - Format (0,3)
150///
151/// IPv4 packet header information
152///
153/// # XDR Definition (sFlow v5)
154///
155/// ```text
156/// /* Packet IP version 4 data */
157/// /* opaque = flow_data; enterprise = 0; format = 3 */
158///
159/// struct sampled_ipv4 {
160///     unsigned int length;     /* Length of IP packet excluding lower layer encapsulations */
161///     unsigned int protocol;   /* IP Protocol type (e.g., TCP = 6, UDP = 17) */
162///     ip_v4 src_ip;            /* Source IP Address */
163///     ip_v4 dst_ip;            /* Destination IP Address */
164///     unsigned int src_port;   /* TCP/UDP source port number or equivalent */
165///     unsigned int dst_port;   /* TCP/UDP destination port number or equivalent */
166///     unsigned int tcp_flags;  /* TCP flags */
167///     unsigned int tos;        /* IP type of service */
168/// }
169/// ```
170#[derive(Debug, Clone, PartialEq, Eq)]
171#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
172pub struct SampledIpv4 {
173    /// Length of IP packet in bytes
174    pub length: u32,
175
176    /// IP Protocol (TCP=6, UDP=17, etc.)
177    pub protocol: u32,
178
179    /// Source IP address
180    pub src_ip: Ipv4Addr,
181
182    /// Destination IP address
183    pub dst_ip: Ipv4Addr,
184
185    /// Source port (for TCP/UDP)
186    pub src_port: u32,
187
188    /// Destination port (for TCP/UDP)
189    pub dst_port: u32,
190
191    /// TCP flags
192    pub tcp_flags: u32,
193
194    /// Type of Service
195    pub tos: u32,
196}
197
198/// Sampled IPv6 - Format (0,4)
199///
200/// IPv6 packet header information
201///
202/// # XDR Definition (sFlow v5)
203///
204/// ```text
205/// /* Packet IP Version 6 Data */
206/// /* opaque = flow_data; enterprise = 0; format = 4 */
207///
208/// struct sampled_ipv6 {
209///     unsigned int length;     /* Length of IP packet excluding lower layer encapsulations */
210///     unsigned int protocol;   /* IP next header (e.g., TCP = 6, UDP = 17) */
211///     ip_v6 src_ip;            /* Source IP Address */
212///     ip_v6 dst_ip;            /* Destination IP Address */
213///     unsigned int src_port;   /* TCP/UDP source port number or equivalent */
214///     unsigned int dst_port;   /* TCP/UDP destination port number or equivalent */
215///     unsigned int tcp_flags;  /* TCP flags */
216///     unsigned int priority;   /* IP priority */
217/// }
218/// ```
219#[derive(Debug, Clone, PartialEq, Eq)]
220#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
221pub struct SampledIpv6 {
222    /// Length of IP packet in bytes
223    pub length: u32,
224
225    /// IP Protocol (TCP=6, UDP=17, etc.)
226    pub protocol: u32,
227
228    /// Source IP address
229    pub src_ip: Ipv6Addr,
230
231    /// Destination IP address
232    pub dst_ip: Ipv6Addr,
233
234    /// Source port (for TCP/UDP)
235    pub src_port: u32,
236
237    /// Destination port (for TCP/UDP)
238    pub dst_port: u32,
239
240    /// TCP flags
241    pub tcp_flags: u32,
242
243    /// Priority (traffic class)
244    pub priority: u32,
245}
246
247/// Extended Switch Data - Format (0,1001)
248///
249/// Layer 2 switching information
250///
251/// # XDR Definition ([sFlow v5](https://sflow.org/sflow_version_5.txt))
252///
253/// ```text
254/// /* Extended Switch Data */
255/// /* opaque = flow_data; enterprise = 0; format = 1001 */
256///
257/// struct extended_switch {
258///     unsigned int src_vlan;     /* The 802.1Q VLAN id of incoming frame,
259///                                   0xffffffff if unknown */
260///     unsigned int src_priority; /* The 802.1p priority of incoming frame,
261///                                   0xffffffff if unknown */
262///     unsigned int dst_vlan;     /* The 802.1Q VLAN id of outgoing frame,
263///                                   0xffffffff if unknown */
264///     unsigned int dst_priority; /* The 802.1p priority of outgoing frame,
265///                                   0xffffffff if unknown */
266/// }
267/// ```
268///
269/// **ERRATUM:** The specification was updated to clarify that 0xffffffff indicates unknown values.
270#[derive(Debug, Clone, PartialEq, Eq)]
271#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
272pub struct ExtendedSwitch {
273    /// Source VLAN ID
274    /// **ERRATUM:** 0xffffffff if unknown
275    pub src_vlan: u32,
276
277    /// Source priority (802.1p)
278    /// **ERRATUM:** 0xffffffff if unknown
279    pub src_priority: u32,
280
281    /// Destination VLAN ID
282    /// **ERRATUM:** 0xffffffff if unknown
283    pub dst_vlan: u32,
284
285    /// Destination priority (802.1p)
286    /// **ERRATUM:** 0xffffffff if unknown
287    pub dst_priority: u32,
288}
289
290/// Extended Router Data - Format (0,1002)
291///
292/// Layer 3 routing information
293///
294/// # XDR Definition ([sFlow v5](https://sflow.org/sflow_version_5.txt))
295///
296/// ```text
297/// /* Extended Router Data */
298/// /* opaque = flow_data; enterprise = 0; format = 1002 */
299///
300/// struct extended_router {
301///     next_hop nexthop;          /* IP address of immediate next hop router */
302///     unsigned int src_mask_len; /* Source address prefix mask (number of bits) */
303///     unsigned int dst_mask_len; /* Destination address prefix mask (number of bits) */
304/// }
305/// ```
306///
307/// **ERRATUM:** The specification was clarified to specify "immediate" next hop router.
308#[derive(Debug, Clone, PartialEq, Eq)]
309#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
310pub struct ExtendedRouter {
311    /// IP address of immediate next hop router (spec: nexthop)
312    /// **ERRATUM:** Clarified as "immediate" next hop router
313    pub next_hop: crate::models::core::Address,
314
315    /// Source subnet mask bits
316    pub src_mask_len: u32,
317
318    /// Destination subnet mask bits
319    pub dst_mask_len: u32,
320}
321
322/// AS Path Type
323#[derive(Debug, Clone, Copy, PartialEq, Eq)]
324#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
325pub enum AsPathType {
326    AsSet = 1,
327    AsSequence = 2,
328}
329
330/// AS Path Segment
331#[derive(Debug, Clone, PartialEq, Eq)]
332#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
333pub struct AsPathSegment {
334    pub path_type: u32,
335    pub path_length: u32,
336    pub path: Vec<u32>,
337}
338
339/// Extended Gateway Data - Format (0,1003)
340///
341/// BGP routing information
342///
343/// # XDR Definition ([sFlow v5](https://sflow.org/sflow_version_5.txt))
344///
345/// ```text
346/// /* Extended Gateway Data */
347/// /* opaque = flow_data; enterprise = 0; format = 1003 */
348///
349/// struct extended_gateway {
350///     next_hop nexthop;           /* Address of the border router */
351///     unsigned int as;            /* Autonomous system number of router */
352///     unsigned int src_as;        /* Autonomous system number of source */
353///     unsigned int src_peer_as;   /* Autonomous system number of source peer */
354///     as_path_type dst_as_path<>; /* AS path to the destination */
355///     unsigned int communities<>; /* Communities associated with this route */
356///     unsigned int localpref;     /* LocalPref associated with this route */
357/// }
358/// ```
359#[derive(Debug, Clone, PartialEq, Eq)]
360#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
361pub struct ExtendedGateway {
362    /// IP address of the border router (spec: nexthop)
363    pub next_hop: crate::models::core::Address,
364
365    /// Autonomous system number (spec: as)
366    pub as_number: u32,
367
368    /// Source AS
369    pub src_as: u32,
370
371    /// Source peer AS
372    pub src_peer_as: u32,
373
374    /// Autonomous system path to the destination
375    pub dst_as_path: Vec<AsPathSegment>,
376
377    /// Communities associated with this route
378    pub communities: Vec<u32>,
379
380    /// Local preference (spec: localpref)
381    pub local_pref: u32,
382}
383
384/// Extended User Data - Format (0,1004)
385///
386/// Application-level user information
387///
388/// # XDR Definition ([sFlow v5](https://sflow.org/sflow_version_5.txt))
389///
390/// ```text
391/// /* Extended User Data */
392/// /* opaque = flow_data; enterprise = 0; format = 1004 */
393///
394/// struct extended_user {
395///     charset src_charset;   /* Character set for src_user */
396///     opaque src_user<>;     /* User ID associated with packet source */
397///     charset dst_charset;   /* Character set for dst_user */
398///     opaque dst_user<>;     /* User ID associated with packet destination */
399/// }
400/// ```
401#[derive(Debug, Clone, PartialEq, Eq)]
402#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
403pub struct ExtendedUser {
404    /// Source character set (MIBEnum)
405    pub src_charset: u32,
406
407    /// Source user ID
408    pub src_user: String,
409
410    /// Destination character set (MIBEnum)
411    pub dst_charset: u32,
412
413    /// Destination user ID
414    pub dst_user: String,
415}
416
417/// URL Direction
418#[derive(Debug, Clone, Copy, PartialEq, Eq)]
419#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
420pub enum UrlDirection {
421    Source = 1,
422    Destination = 2,
423}
424
425/// Extended URL Data - Format (0,1005)
426///
427/// HTTP request information
428///
429/// # XDR Definition ([sFlow v5](https://sflow.org/sflow_version_5.txt))
430///
431/// ```text
432/// /* Extended URL Data */
433/// /* opaque = flow_data; enterprise = 0; format = 1005 */
434///
435/// struct extended_url {
436///     url_direction direction; /* Direction of connection */
437///     string url<>;            /* The HTTP request-line (see RFC 2616) */
438///     string host<>;           /* The host field from the HTTP header */
439/// }
440/// ```
441#[derive(Debug, Clone, PartialEq, Eq)]
442#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
443pub struct ExtendedUrl {
444    /// Direction (source or destination)
445    pub direction: u32,
446
447    /// URL string (HTTP request-line)
448    pub url: String,
449
450    /// Host header from HTTP request
451    pub host: String,
452}
453
454/// Extended MPLS Data - Format (0,1006)
455///
456/// MPLS label stack information
457///
458/// # XDR Definition ([sFlow v5](https://sflow.org/sflow_version_5.txt))
459///
460/// ```text
461/// /* Extended MPLS Data */
462/// /* opaque = flow_data; enterprise = 0; format = 1006 */
463///
464/// struct extended_mpls {
465///     next_hop nexthop;     /* Address of the next hop */
466///     label_stack in_stack; /* Label stack of received packet */
467///     label_stack out_stack;/* Label stack for transmitted packet */
468/// }
469/// ```
470#[derive(Debug, Clone, PartialEq, Eq)]
471#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
472pub struct ExtendedMpls {
473    /// Next hop address (spec: nexthop)
474    pub next_hop: crate::models::core::Address,
475
476    /// Input label stack
477    pub in_stack: Vec<u32>,
478
479    /// Output label stack
480    pub out_stack: Vec<u32>,
481}
482
483/// Extended NAT Data - Format (0,1007)
484///
485/// Network Address Translation information
486///
487/// # XDR Definition ([sFlow v5](https://sflow.org/sflow_version_5.txt))
488///
489/// ```text
490/// /* Extended NAT Data */
491/// /* opaque = flow_data; enterprise = 0; format = 1007 */
492///
493/// struct extended_nat {
494///     address src_address; /* Source address */
495///     address dst_address; /* Destination address */
496/// }
497/// ```
498#[derive(Debug, Clone, PartialEq, Eq)]
499#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
500pub struct ExtendedNat {
501    /// Source address type
502    pub src_address: crate::models::core::Address,
503
504    /// Destination address type
505    pub dst_address: crate::models::core::Address,
506}
507
508/// Extended MPLS Tunnel - Format (0,1008)
509///
510/// MPLS tunnel information
511///
512/// # XDR Definition ([sFlow v5](https://sflow.org/sflow_version_5.txt))
513///
514/// ```text
515/// /* Extended MPLS Tunnel */
516/// /* opaque = flow_data; enterprise = 0; format = 1008 */
517///
518/// struct extended_mpls_tunnel {
519///     string tunnel_lsp_name<>; /* Tunnel name */
520///     unsigned int tunnel_id;   /* Tunnel ID */
521///     unsigned int tunnel_cos;  /* Tunnel COS value */
522/// }
523/// ```
524#[derive(Debug, Clone, PartialEq, Eq)]
525#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
526pub struct ExtendedMplsTunnel {
527    /// Tunnel LSP name
528    pub tunnel_lsp_name: String,
529
530    /// Tunnel ID
531    pub tunnel_id: u32,
532
533    /// Tunnel COS value
534    pub tunnel_cos: u32,
535}
536
537/// Extended MPLS VC - Format (0,1009)
538///
539/// MPLS Virtual Circuit information
540///
541/// # XDR Definition ([sFlow v5](https://sflow.org/sflow_version_5.txt))
542///
543/// ```text
544/// /* Extended MPLS VC */
545/// /* opaque = flow_data; enterprise = 0; format = 1009 */
546///
547/// struct extended_mpls_vc {
548///     string vc_instance_name<>; /* VC instance name */
549///     unsigned int vll_vc_id;    /* VLL/VC instance ID */
550///     unsigned int vc_label_cos; /* VC Label COS value */
551/// }
552/// ```
553#[derive(Debug, Clone, PartialEq, Eq)]
554#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
555pub struct ExtendedMplsVc {
556    /// VC instance name
557    pub vc_instance_name: String,
558
559    /// VC ID
560    pub vll_vc_id: u32,
561
562    /// VC label
563    pub vc_label: u32,
564
565    /// VC COS
566    pub vc_cos: u32,
567}
568
569/// Extended MPLS FEC - Format (0,1010)
570///
571/// MPLS Forwarding Equivalence Class information
572///
573/// # XDR Definition ([sFlow v5](https://sflow.org/sflow_version_5.txt))
574///
575/// ```text
576/// /* Extended MPLS FEC */
577/// /* opaque = flow_data; enterprise = 0; format = 1010 */
578///
579/// struct extended_mpls_FTN {
580///     string mplsFTNDescr<>;  /* FEC description */
581///     unsigned int mplsFTNMask; /* FEC mask */
582/// }
583/// ```
584#[derive(Debug, Clone, PartialEq, Eq)]
585#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
586pub struct ExtendedMplsFec {
587    /// FEC address prefix
588    pub fec_addr_prefix: crate::models::core::Address,
589
590    /// FEC prefix length
591    pub fec_prefix_len: u32,
592}
593
594/// Extended MPLS LVP FEC - Format (0,1011)
595///
596/// MPLS LDP FEC information
597///
598/// # XDR Definition ([sFlow v5](https://sflow.org/sflow_version_5.txt))
599///
600/// ```text
601/// /* Extended MPLS LVP FEC */
602/// /* opaque = flow_data; enterprise = 0; format = 1011 */
603///
604/// struct extended_mpls_LDP_FEC {
605///     unsigned int mplsFecAddrPrefixLength; /* FEC address prefix length */
606/// }
607/// ```
608#[derive(Debug, Clone, PartialEq, Eq)]
609#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
610pub struct ExtendedMplsLvpFec {
611    /// FEC address prefix length
612    pub mpls_fec_addr_prefix_length: u32,
613}
614
615/// Extended VLAN Tunnel - Format (0,1012)
616///
617/// VLAN tunnel information for nested VLAN tags
618///
619/// # XDR Definition ([sFlow v5](https://sflow.org/sflow_version_5.txt))
620///
621/// ```text
622/// /* Extended VLAN tunnel information */
623/// /* opaque = flow_data; enterprise = 0; format = 1012 */
624///
625/// struct extended_vlantunnel {
626///     unsigned int stack<>; /* List of stripped 802.1Q TPID/TCI layers */
627/// }
628/// ```
629#[derive(Debug, Clone, PartialEq, Eq)]
630#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
631pub struct ExtendedVlanTunnel {
632    /// List of stripped 802.1Q TPID/TCI layers
633    pub stack: Vec<u32>,
634}
635
636/// Extended 802.11 Payload - Format (0,1013)
637///
638/// Unencrypted 802.11 payload data
639///
640/// # XDR Definition ([sFlow 802.11](https://sflow.org/sflow_80211.txt))
641///
642/// ```text
643/// /* Extended 80211 Payload */
644/// /* opaque = flow_data; enterprise = 0; format = 1013 */
645///
646/// struct extended_80211_payload {
647///     cipher_suite ciphersuite; /* encryption scheme used for this packet */
648///     opaque data<>;            /* unencrypted bytes from the payload */
649/// }
650/// ```
651#[derive(Debug, Clone, PartialEq, Eq)]
652#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
653pub struct Extended80211Payload {
654    /// Cipher suite (OUI + Suite Type) (spec: ciphersuite)
655    pub cipher_suite: u32,
656
657    /// Unencrypted payload data
658    pub data: Vec<u8>,
659}
660
661/// Extended 802.11 RX - Format (0,1014)
662///
663/// 802.11 receive information
664///
665/// # XDR Definition ([sFlow 802.11](https://sflow.org/sflow_80211.txt))
666///
667/// ```text
668/// /* Extended 802.11 RX */
669/// /* opaque = flow_data; enterprise = 0; format = 1014 */
670///
671/// struct extended_80211_rx {
672///     string ssid<32>;           /* SSID string */
673///     mac bssid;                 /* BSSID */
674///     ieee80211_version version; /* version */
675///     unsigned int channel;      /* channel number */
676///     unsigned hyper speed;      /* speed */
677///     unsigned int rsni;         /* received signal to noise ratio */
678///     unsigned int rcpi;         /* received channel power */
679///     duration_us packet_duration; /* time packet occupied RF medium */
680/// }
681/// ```
682#[derive(Debug, Clone, PartialEq, Eq)]
683#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
684pub struct Extended80211Rx {
685    /// SSID string (max 32 bytes)
686    pub ssid: String,
687
688    /// BSSID (MAC address)
689    pub bssid: crate::models::MacAddress,
690
691    /// IEEE 802.11 version (a=1, b=2, g=3, n=4)
692    pub version: u32,
693
694    /// Channel number
695    pub channel: u32,
696
697    /// Speed in bits per second
698    pub speed: u64,
699
700    /// Received signal to noise ratio (RSNI)
701    pub rsni: u32,
702
703    /// Received channel power indicator (RCPI)
704    pub rcpi: u32,
705
706    /// Packet duration in microseconds
707    pub packet_duration: u32,
708}
709
710/// Extended 802.11 TX - Format (0,1015)
711///
712/// 802.11 transmit information
713///
714/// # XDR Definition ([sFlow 802.11](https://sflow.org/sflow_80211.txt))
715///
716/// ```text
717/// /* Extended 802.11 TX */
718/// /* opaque = flow_data; enterprise = 0; format = 1015 */
719///
720/// struct extended_80211_tx {
721///     string ssid<32>;             /* SSID string */
722///     mac bssid;                   /* BSSID */
723///     ieee80211_version version;   /* version */
724///     unsigned int transmissions;  /* number of transmissions */
725///     duration_us packet_duration; /* time packet occupied RF medium */
726///     duration_us retrans_duration;/* time failed attempts occupied RF */
727///     unsigned int channel;        /* channel number */
728///     unsigned hyper speed;        /* speed */
729///     unsigned int power;          /* transmit power in mW */
730/// }
731/// ```
732#[derive(Debug, Clone, PartialEq, Eq)]
733#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
734pub struct Extended80211Tx {
735    /// SSID string (max 32 bytes)
736    pub ssid: String,
737
738    /// BSSID (MAC address)
739    pub bssid: crate::models::MacAddress,
740
741    /// IEEE 802.11 version (a=1, b=2, g=3, n=4)
742    pub version: u32,
743
744    /// Number of transmissions (0=unknown, 1=success on first attempt, n>1 = n-1 retransmissions)
745    pub transmissions: u32,
746
747    /// Packet duration in microseconds (successful transmission)
748    pub packet_duration: u32,
749
750    /// Retransmission duration in microseconds (failed attempts)
751    pub retrans_duration: u32,
752
753    /// Channel number
754    pub channel: u32,
755
756    /// Speed in bits per second
757    pub speed: u64,
758
759    /// Transmit power in milliwatts
760    pub power: u32,
761}
762
763/// PDU (Protocol Data Unit) in 802.11 aggregation
764///
765/// # XDR Definition ([sFlow 802.11](https://sflow.org/sflow_80211.txt))
766///
767/// ```text
768/// struct pdu {
769///     flow_record flow_records<>;
770/// }
771/// ```
772#[derive(Debug, Clone, PartialEq, Eq)]
773#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
774pub struct Pdu {
775    /// Flow records for this PDU
776    pub flow_records: Vec<crate::models::FlowRecord>,
777}
778
779/// Extended 802.11 Aggregation - Format (0,1016)
780///
781/// 802.11 frame aggregation information
782///
783/// # XDR Definition ([sFlow 802.11](https://sflow.org/sflow_80211.txt))
784///
785/// ```text
786/// /* Extended 802.11 Aggregation Data */
787/// /* opaque = flow_data; enterprise = 0; format = 1016 */
788///
789/// struct extended_80211_aggregation {
790///     pdu pdus<>; /* Array of PDUs in the aggregation */
791/// }
792/// ```
793#[derive(Debug, Clone, PartialEq, Eq)]
794#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
795pub struct Extended80211Aggregation {
796    /// Array of PDUs in the aggregation
797    pub pdus: Vec<Pdu>,
798}
799
800/// Extended OpenFlow v1 - Format (0,1017) - **DEPRECATED**
801///
802/// OpenFlow 1.0 forwarding information
803///
804/// **Note:** This format was defined in an early draft of the sFlow OpenFlow specification
805/// but was deprecated and removed from the final specification. It is included here for
806/// backward compatibility with legacy implementations.
807///
808/// # XDR Definition ([sFlow OpenFlow Draft](https://sflow.org/draft-sflow-openflow.txt))
809///
810/// ```text
811/// /* Extended OpenFlow 1.0 Data */
812/// /* opaque = flow_data; enterprise = 0; format = 1017 */
813///
814/// struct extended_openflow_v1 {
815///     unsigned hyper flow_cookie;  /* Flow cookie set by controller */
816///     wildcards flow_match;        /* Bit array of wildcarded fields */
817///     actions flow_actions;        /* Bit array of actions applied */
818/// }
819/// ```
820#[derive(Debug, Clone, PartialEq, Eq)]
821#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
822pub struct ExtendedOpenFlowV1 {
823    /// Flow cookie set by the OpenFlow controller
824    pub flow_cookie: u64,
825
826    /// Bit array describing the fields in the packet header that are used to form the flow key
827    /// See OpenFlow 1.0 ofp_match for the definition of wildcards
828    pub flow_match: u32,
829
830    /// Bit array describing fields that may have been altered by the flow action
831    /// The ofp_action_type enum is used to determine the bit positions
832    pub flow_actions: u32,
833}
834
835/// Extended L2 Tunnel Egress - Format (0,1021)
836///
837/// Layer 2 tunnel egress information - reports outer Ethernet headers
838/// that will be added on egress when encapsulating packets
839///
840/// # XDR Definition ([sFlow Tunnels](https://sflow.org/sflow_tunnels.txt))
841///
842/// ```text
843/// /* opaque = flow_data; enterprise = 0; format = 1021 */
844/// struct extended_L2_tunnel_egress {
845///     sampled_ethernet header;
846/// }
847/// ```
848#[derive(Debug, Clone, PartialEq, Eq)]
849#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
850pub struct ExtendedL2TunnelEgress {
851    /// Outer Ethernet header that will be added on egress
852    pub header: SampledEthernet,
853}
854
855/// Extended L2 Tunnel Ingress - Format (0,1022)
856///
857/// Layer 2 tunnel ingress information - reports outer Ethernet headers
858/// that were present on ingress and removed during decapsulation
859///
860/// # XDR Definition ([sFlow Tunnels](https://sflow.org/sflow_tunnels.txt))
861///
862/// ```text
863/// /* opaque = flow_data; enterprise = 0; format = 1022 */
864/// struct extended_L2_tunnel_ingress {
865///     sampled_ethernet header;
866/// }
867/// ```
868#[derive(Debug, Clone, PartialEq, Eq)]
869#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
870pub struct ExtendedL2TunnelIngress {
871    /// Outer Ethernet header that was present on ingress
872    pub header: SampledEthernet,
873}
874
875/// Extended IPv4 Tunnel Egress - Format (0,1023)
876///
877/// IPv4 tunnel egress information - reports outer IPv4 headers
878/// that will be added on egress when encapsulating packets
879///
880/// # XDR Definition ([sFlow Tunnels](https://sflow.org/sflow_tunnels.txt))
881///
882/// ```text
883/// /* opaque = flow_data; enterprise = 0; format = 1023 */
884/// struct extended_ipv4_tunnel_egress {
885///     sampled_ipv4 header;
886/// }
887/// ```
888#[derive(Debug, Clone, PartialEq, Eq)]
889#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
890pub struct ExtendedIpv4TunnelEgress {
891    /// Outer IPv4 header that will be added on egress
892    pub header: SampledIpv4,
893}
894
895/// Extended IPv4 Tunnel Ingress - Format (0,1024)
896///
897/// IPv4 tunnel ingress information - reports outer IPv4 headers
898/// that were present on ingress and removed during decapsulation
899///
900/// # XDR Definition ([sFlow Tunnels](https://sflow.org/sflow_tunnels.txt))
901///
902/// ```text
903/// /* opaque = flow_data; enterprise = 0; format = 1024 */
904/// struct extended_ipv4_tunnel_ingress {
905///     sampled_ipv4 header;
906/// }
907/// ```
908#[derive(Debug, Clone, PartialEq, Eq)]
909#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
910pub struct ExtendedIpv4TunnelIngress {
911    /// Outer IPv4 header that was present on ingress
912    pub header: SampledIpv4,
913}
914
915/// Extended IPv6 Tunnel Egress - Format (0,1025)
916///
917/// IPv6 tunnel egress information - reports outer IPv6 headers
918/// that will be added on egress when encapsulating packets
919///
920/// # XDR Definition ([sFlow Tunnels](https://sflow.org/sflow_tunnels.txt))
921///
922/// ```text
923/// /* opaque = flow_data; enterprise = 0; format = 1025 */
924/// struct extended_ipv6_tunnel_egress {
925///     sampled_ipv6 header;
926/// }
927/// ```
928#[derive(Debug, Clone, PartialEq, Eq)]
929#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
930pub struct ExtendedIpv6TunnelEgress {
931    /// Outer IPv6 header that will be added on egress
932    pub header: SampledIpv6,
933}
934
935/// Extended IPv6 Tunnel Ingress - Format (0,1026)
936///
937/// IPv6 tunnel ingress information - reports outer IPv6 headers
938/// that were present on ingress and removed during decapsulation
939///
940/// # XDR Definition ([sFlow Tunnels](https://sflow.org/sflow_tunnels.txt))
941///
942/// ```text
943/// /* opaque = flow_data; enterprise = 0; format = 1026 */
944/// struct extended_ipv6_tunnel_ingress {
945///     sampled_ipv6 header;
946/// }
947/// ```
948#[derive(Debug, Clone, PartialEq, Eq)]
949#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
950pub struct ExtendedIpv6TunnelIngress {
951    /// Outer IPv6 header that was present on ingress
952    pub header: SampledIpv6,
953}
954
955/// Extended Decapsulate Egress - Format (0,1027)
956///
957/// Indicates the end of a tunnel and points to the start of the inner header
958/// Used when a packet is sampled before decapsulation on ingress
959///
960/// # XDR Definition ([sFlow Tunnels](https://sflow.org/sflow_tunnels.txt))
961///
962/// ```text
963/// /* opaque = flow_data; enterprise = 0; format = 1027 */
964/// struct extended_decapsulate_egress {
965///     unsigned int inner_header_offset;
966/// }
967/// ```
968#[derive(Debug, Clone, PartialEq, Eq)]
969#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
970pub struct ExtendedDecapsulateEgress {
971    /// Offset in bytes to the inner header within the sampled packet header
972    pub inner_header_offset: u32,
973}
974
975/// Extended Decapsulate Ingress - Format (0,1028)
976///
977/// Indicates the start of a tunnel
978/// Used when a packet is sampled after encapsulation on egress
979///
980/// # XDR Definition ([sFlow Tunnels](https://sflow.org/sflow_tunnels.txt))
981///
982/// ```text
983/// /* opaque = flow_data; enterprise = 0; format = 1028 */
984/// struct extended_decapsulate_ingress {
985///     unsigned int inner_header_offset;
986/// }
987/// ```
988#[derive(Debug, Clone, PartialEq, Eq)]
989#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
990pub struct ExtendedDecapsulateIngress {
991    /// Offset in bytes to the inner header within the sampled packet header
992    pub inner_header_offset: u32,
993}
994
995/// Extended VNI Egress - Format (0,1029)
996///
997/// Virtual Network Identifier for egress traffic
998/// The VNI may be explicitly included in the tunneling protocol or implicit
999///
1000/// # XDR Definition ([sFlow Tunnels](https://sflow.org/sflow_tunnels.txt))
1001///
1002/// ```text
1003/// /* opaque_flow_data; enterprise = 0; format = 1029 */
1004/// struct extended_vni_egress {
1005///     unsigned int vni;
1006/// }
1007/// ```
1008#[derive(Debug, Clone, PartialEq, Eq)]
1009#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1010pub struct ExtendedVniEgress {
1011    /// Virtual Network Identifier
1012    pub vni: u32,
1013}
1014
1015/// Extended VNI Ingress - Format (0,1030)
1016///
1017/// Virtual Network Identifier for ingress traffic
1018/// The VNI may be explicitly included in the tunneling protocol or implicit
1019/// in the encapsulation (e.g., VXLAN uses UDP port 4789).
1020///
1021/// # XDR Definition ([sFlow Tunnel](https://sflow.org/sflow_tunnels.txt))
1022///
1023/// ```text
1024/// /* VNI ingress */
1025/// /* opaque = flow_data; enterprise = 0; format = 1030 */
1026///
1027/// struct extended_vni_ingress {
1028///     unsigned int vni;  /* VNI associated with ingress packet */
1029/// }
1030/// ```
1031#[derive(Debug, Clone, PartialEq, Eq)]
1032#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1033pub struct ExtendedVniIngress {
1034    /// Virtual Network Identifier
1035    pub vni: u32,
1036}
1037
1038/// Drop reason codes for discarded packets
1039///
1040/// # XDR Definition ([sFlow Drops](https://sflow.org/sflow_drops.txt))
1041///
1042/// ```text
1043/// /* The drop_reason enumeration may be expanded over time.
1044///    sFlow collectors must be prepared to receive discard_packet
1045///    structures with unrecognized drop_reason values.
1046///
1047///    This document expands on the discard reason codes 0-262 defined
1048///    in the sFlow Version 5 [1] interface typedef and this expanded list
1049///    should be regarded as an expansion of the reason codes in the
1050///    interface typdef and are valid anywhere the typedef is referenced.
1051///
1052///    Codes 263-288 are defined in Devlink Trap [2]. Drop reason / group
1053///    names from the Devlink Trap document are preserved where they define
1054///    new reason codes, or referenced as comments where they map to existing
1055///    codes.
1056///
1057///    Codes 289-303 are reasons that have yet to be upstreamed to Devlink Trap,
1058///    but the intent is that they will eventually be upstreamed and documented as
1059///    part of the Linux API [2], and so they have been reserved.
1060///
1061///    The authoritative list of drop reasons will be maintained
1062///    at sflow.org */
1063///
1064/// enum drop_reason {
1065///    net_unreachable      = 0,
1066///    host_unreachable     = 1,
1067///    protocol_unreachable = 2,
1068///    port_unreachable     = 3,
1069///    frag_needed          = 4,
1070///    src_route_failed     = 5,
1071///    dst_net_unknown      = 6, /* ipv4_lpm_miss, ipv6_lpm_miss */
1072///    dst_host_unknown     = 7,
1073///    src_host_isolated    = 8,
1074///    dst_net_prohibited   = 9, /* reject_route */
1075///    dst_host_prohibited  = 10,
1076///    dst_net_tos_unreachable  = 11,
1077///    dst_host_tos_unreacheable = 12,
1078///    comm_admin_prohibited = 13,
1079///    host_precedence_violation = 14,
1080///    precedence_cutoff    = 15,
1081///    unknown              = 256,
1082///    ttl_exceeded         = 257, /* ttl_value_is_too_small */
1083///    acl                  = 258, /* ingress_flow_action_drop,
1084///                                   egress_flow_action_drop
1085///                                   group acl_drops */
1086///    no_buffer_space      = 259, /* tail_drop */
1087///    red                  = 260, /* early_drop */
1088///    traffic_shaping      = 261,
1089///    pkt_too_big          = 262, /* mtu_value_is_too_small */
1090///    src_mac_is_multicast = 263,
1091///    vlan_tag_mismatch    = 264,
1092///    ingress_vlan_filter  = 265,
1093///    ingress_spanning_tree_filter = 266,
1094///    port_list_is_empty   = 267,
1095///    port_loopback_filter = 268,
1096///    blackhole_route      = 269,
1097///    non_ip               = 270,
1098///    uc_dip_over_mc_dmac  = 271,
1099///    dip_is_loopback_address = 272,
1100///    sip_is_mc            = 273,
1101///    sip_is_loopback_address = 274,
1102///    ip_header_corrupted  = 275,
1103///    ipv4_sip_is_limited_bc = 276,
1104///    ipv6_mc_dip_reserved_scope = 277,
1105///    ipv6_mc_dip_interface_local_scope = 278,
1106///    unresolved_neigh     = 279,
1107///    mc_reverse_path_forwarding = 280,
1108///    non_routable_packet  = 281,
1109///    decap_error          = 282,
1110///    overlay_smac_is_mc   = 283,
1111///    unknown_l2           = 284, /* group l2_drops */
1112///    unknown_l3           = 285, /* group l3_drops */
1113///    unknown_l3_exception = 286, /* group l3_exceptions */
1114///    unknown_buffer       = 287, /* group buffer_drops */
1115///    unknown_tunnel       = 288, /* group tunnel_drops */
1116///    unknown_l4           = 289,
1117///    sip_is_unspecified   = 290,
1118///    mlag_port_isolation  = 291,
1119///    blackhole_arp_neigh  = 292,
1120///    src_mac_is_dmac      = 293,
1121///    dmac_is_reserved     = 294,
1122///    sip_is_class_e       = 295,
1123///    mc_dmac_mismatch     = 296,
1124///    sip_is_dip           = 297,
1125///    dip_is_local_network = 298,
1126///    dip_is_link_local    = 299,
1127///    overlay_smac_is_dmac = 300,
1128///    egress_vlan_filter   = 301,
1129///    uc_reverse_path_forwarding = 302,
1130///    split_horizon        = 303
1131/// }
1132/// ```
1133#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1134#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1135#[repr(u32)]
1136pub enum DropReason {
1137    NetUnreachable = 0,
1138    HostUnreachable = 1,
1139    ProtocolUnreachable = 2,
1140    PortUnreachable = 3,
1141    FragNeeded = 4,
1142    SrcRouteFailed = 5,
1143    DstNetUnknown = 6,
1144    DstHostUnknown = 7,
1145    SrcHostIsolated = 8,
1146    DstNetProhibited = 9,
1147    DstHostProhibited = 10,
1148    DstNetTosUnreachable = 11,
1149    DstHostTosUnreachable = 12,
1150    CommAdminProhibited = 13,
1151    HostPrecedenceViolation = 14,
1152    PrecedenceCutoff = 15,
1153    Unknown = 256,
1154    TtlExceeded = 257,
1155    Acl = 258,
1156    NoBufferSpace = 259,
1157    Red = 260,
1158    TrafficShaping = 261,
1159    PktTooBig = 262,
1160    SrcMacIsMulticast = 263,
1161    VlanTagMismatch = 264,
1162    IngressVlanFilter = 265,
1163    IngressSpanningTreeFilter = 266,
1164    PortListIsEmpty = 267,
1165    PortLoopbackFilter = 268,
1166    BlackholeRoute = 269,
1167    NonIp = 270,
1168    UcDipOverMcDmac = 271,
1169    DipIsLoopbackAddress = 272,
1170    SipIsMc = 273,
1171    SipIsLoopbackAddress = 274,
1172    IpHeaderCorrupted = 275,
1173    Ipv4SipIsLimitedBc = 276,
1174    Ipv6McDipReservedScope = 277,
1175    Ipv6McDipInterfaceLocalScope = 278,
1176    UnresolvedNeigh = 279,
1177    McReversePathForwarding = 280,
1178    NonRoutablePacket = 281,
1179    DecapError = 282,
1180    OverlaySmacIsMc = 283,
1181    UnknownL2 = 284,
1182    UnknownL3 = 285,
1183    UnknownL3Exception = 286,
1184    UnknownBuffer = 287,
1185    UnknownTunnel = 288,
1186    UnknownL4 = 289,
1187    SipIsUnspecified = 290,
1188    MlagPortIsolation = 291,
1189    BlackholeArpNeigh = 292,
1190    SrcMacIsDmac = 293,
1191    DmacIsReserved = 294,
1192    SipIsClassE = 295,
1193    McDmacMismatch = 296,
1194    SipIsDip = 297,
1195    DipIsLocalNetwork = 298,
1196    DipIsLinkLocal = 299,
1197    OverlaySmacIsDmac = 300,
1198    EgressVlanFilter = 301,
1199    UcReversePathForwarding = 302,
1200    SplitHorizon = 303,
1201}
1202
1203impl DropReason {
1204    /// Convert from u32 value to DropReason enum
1205    ///
1206    /// This is a mechanical mapping of u32 values to enum variants
1207    /// defined in the sFlow specification. The function is tested
1208    /// with representative samples rather than exhaustively.
1209    pub fn from_u32(value: u32) -> Option<Self> {
1210        match value {
1211            0 => Some(DropReason::NetUnreachable),
1212            1 => Some(DropReason::HostUnreachable),
1213            2 => Some(DropReason::ProtocolUnreachable),
1214            3 => Some(DropReason::PortUnreachable),
1215            4 => Some(DropReason::FragNeeded),
1216            5 => Some(DropReason::SrcRouteFailed),
1217            6 => Some(DropReason::DstNetUnknown),
1218            7 => Some(DropReason::DstHostUnknown),
1219            8 => Some(DropReason::SrcHostIsolated),
1220            9 => Some(DropReason::DstNetProhibited),
1221            10 => Some(DropReason::DstHostProhibited),
1222            11 => Some(DropReason::DstNetTosUnreachable),
1223            12 => Some(DropReason::DstHostTosUnreachable),
1224            13 => Some(DropReason::CommAdminProhibited),
1225            14 => Some(DropReason::HostPrecedenceViolation),
1226            15 => Some(DropReason::PrecedenceCutoff),
1227            256 => Some(DropReason::Unknown),
1228            257 => Some(DropReason::TtlExceeded),
1229            258 => Some(DropReason::Acl),
1230            259 => Some(DropReason::NoBufferSpace),
1231            260 => Some(DropReason::Red),
1232            261 => Some(DropReason::TrafficShaping),
1233            262 => Some(DropReason::PktTooBig),
1234            263 => Some(DropReason::SrcMacIsMulticast),
1235            264 => Some(DropReason::VlanTagMismatch),
1236            265 => Some(DropReason::IngressVlanFilter),
1237            266 => Some(DropReason::IngressSpanningTreeFilter),
1238            267 => Some(DropReason::PortListIsEmpty),
1239            268 => Some(DropReason::PortLoopbackFilter),
1240            269 => Some(DropReason::BlackholeRoute),
1241            270 => Some(DropReason::NonIp),
1242            271 => Some(DropReason::UcDipOverMcDmac),
1243            272 => Some(DropReason::DipIsLoopbackAddress),
1244            273 => Some(DropReason::SipIsMc),
1245            274 => Some(DropReason::SipIsLoopbackAddress),
1246            275 => Some(DropReason::IpHeaderCorrupted),
1247            276 => Some(DropReason::Ipv4SipIsLimitedBc),
1248            277 => Some(DropReason::Ipv6McDipReservedScope),
1249            278 => Some(DropReason::Ipv6McDipInterfaceLocalScope),
1250            279 => Some(DropReason::UnresolvedNeigh),
1251            280 => Some(DropReason::McReversePathForwarding),
1252            281 => Some(DropReason::NonRoutablePacket),
1253            282 => Some(DropReason::DecapError),
1254            283 => Some(DropReason::OverlaySmacIsMc),
1255            284 => Some(DropReason::UnknownL2),
1256            285 => Some(DropReason::UnknownL3),
1257            286 => Some(DropReason::UnknownL3Exception),
1258            287 => Some(DropReason::UnknownBuffer),
1259            288 => Some(DropReason::UnknownTunnel),
1260            289 => Some(DropReason::UnknownL4),
1261            290 => Some(DropReason::SipIsUnspecified),
1262            291 => Some(DropReason::MlagPortIsolation),
1263            292 => Some(DropReason::BlackholeArpNeigh),
1264            293 => Some(DropReason::SrcMacIsDmac),
1265            294 => Some(DropReason::DmacIsReserved),
1266            295 => Some(DropReason::SipIsClassE),
1267            296 => Some(DropReason::McDmacMismatch),
1268            297 => Some(DropReason::SipIsDip),
1269            298 => Some(DropReason::DipIsLocalNetwork),
1270            299 => Some(DropReason::DipIsLinkLocal),
1271            300 => Some(DropReason::OverlaySmacIsDmac),
1272            301 => Some(DropReason::EgressVlanFilter),
1273            302 => Some(DropReason::UcReversePathForwarding),
1274            303 => Some(DropReason::SplitHorizon),
1275            _ => None,
1276        }
1277    }
1278}
1279
1280/// Extended Egress Queue - Format (0,1036)
1281///
1282/// Selected egress queue for the sampled packet
1283///
1284/// # XDR Definition ([sFlow Drops](https://sflow.org/sflow_drops.txt))
1285///
1286/// ```text
1287/// /* Selected egress queue */
1288/// /* Output port number must be provided in enclosing structure */
1289/// /* opaque = flow_data; enterprise = 0; format = 1036 */
1290/// struct extended_egress_queue {
1291///   unsigned int queue;  /* eqress queue number selected for sampled packet */
1292/// }
1293/// ```
1294#[derive(Debug, Clone, PartialEq, Eq)]
1295#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1296pub struct ExtendedEgressQueue {
1297    /// Egress queue number selected for sampled packet
1298    pub queue: u32,
1299}
1300
1301/// Extended ACL - Format (0,1037)
1302///
1303/// ACL information about the rule that matched this packet
1304///
1305/// # XDR Definition ([sFlow Drops](https://sflow.org/sflow_drops.txt))
1306///
1307/// ```text
1308/// /* ACL information */
1309/// /* Information about ACL rule that matched this packet
1310/// /* opaque = flow_data; enterprise = 0; format = 1037 */
1311/// struct extended_acl {
1312///   unsigned int number; /* access list number */
1313///   string name<>; /* access list name */
1314///   unsigned int direction; /* unknown = 0, ingress = 1, egress = 2 */
1315/// }
1316/// ```
1317#[derive(Debug, Clone, PartialEq, Eq)]
1318#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1319pub struct ExtendedAcl {
1320    /// Access list number
1321    pub number: u32,
1322
1323    /// Access list name
1324    pub name: String,
1325
1326    /// Direction: unknown = 0, ingress = 1, egress = 2
1327    pub direction: u32,
1328}
1329
1330/// Extended Function - Format (0,1038)
1331///
1332/// Name of the function in software network stack that discarded the packet
1333///
1334/// # XDR Definition ([sFlow Drops](https://sflow.org/sflow_drops.txt))
1335///
1336/// ```text
1337/// /* Software function */
1338/// /* Name of the function in software network stack that discarded the packet */
1339/// /* opaque = flow_data; enterprise = 0; format = 1038 */
1340/// struct extended_function {
1341///   string symbol<>;
1342/// }
1343/// ```
1344#[derive(Debug, Clone, PartialEq, Eq)]
1345#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1346pub struct ExtendedFunction {
1347    /// Function symbol name
1348    pub symbol: String,
1349}
1350
1351/// Extended Transit - Format (0,1039)
1352///
1353/// Delay for sampled packet traversing switch
1354///
1355/// # XDR Definition ([sFlow Transit](https://sflow.org/sflow_transit.txt))
1356///
1357/// ```text
1358/// /* Delay for sampled packet traversing switch */
1359/// /* opaque = flow_data; enterprise = 0; format = 1039 */
1360/// struct extended_transit {
1361///   unsigned int delay; /* transit delay in nanoseconds
1362///                          0xffffffff indicates value >= 0xffffffff */
1363/// }
1364/// ```
1365#[derive(Debug, Clone, PartialEq, Eq)]
1366#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1367pub struct ExtendedTransit {
1368    /// Transit delay in nanoseconds (0xffffffff indicates value >= 0xffffffff)
1369    pub delay: u32,
1370}
1371
1372/// Extended Queue - Format (0,1040)
1373///
1374/// Queue depth for sampled packet traversing switch
1375///
1376/// # XDR Definition ([sFlow Transit](https://sflow.org/sflow_transit.txt))
1377///
1378/// ```text
1379/// /* Queue depth for sampled packet traversing switch */
1380/// /* extended_egress_queue structure must be included */
1381/// /* opaque = flow_data; enterprise = 0; format = 1040 */
1382/// struct extended_queue {
1383///   unsigned int depth;   /* queue depth in bytes */
1384/// }
1385/// ```
1386#[derive(Debug, Clone, PartialEq, Eq)]
1387#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1388pub struct ExtendedQueue {
1389    /// Queue depth in bytes
1390    pub depth: u32,
1391}
1392
1393/// Extended Socket IPv4 - Format (0,2100)
1394///
1395/// IPv4 socket information for application transactions
1396///
1397/// # XDR Definition ([sFlow Host](https://sflow.org/sflow_host.txt))
1398///
1399/// ```text
1400/// /* IPv4 Socket */
1401/// /* opaque = flow_data; enterprise = 0; format = 2100 */
1402///
1403/// struct extended_socket_ipv4 {
1404///     unsigned int protocol;     /* IP Protocol type (e.g., TCP = 6, UDP = 17) */
1405///     ip_v4 local_ip;            /* local IP address */
1406///     ip_v4 remote_ip;           /* remote IP address */
1407///     unsigned int local_port;   /* TCP/UDP local port number or equivalent */
1408///     unsigned int remote_port;  /* TCP/UDP remote port number or equivalent */
1409/// }
1410/// ```
1411#[derive(Debug, Clone, PartialEq, Eq)]
1412#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1413pub struct ExtendedSocketIpv4 {
1414    /// IP Protocol type (e.g., TCP = 6, UDP = 17)
1415    pub protocol: u32,
1416
1417    /// Local IP address
1418    pub local_ip: std::net::Ipv4Addr,
1419
1420    /// Remote IP address
1421    pub remote_ip: std::net::Ipv4Addr,
1422
1423    /// TCP/UDP local port number
1424    pub local_port: u32,
1425
1426    /// TCP/UDP remote port number
1427    pub remote_port: u32,
1428}
1429
1430/// Extended Socket IPv6 - Format (0,2101)
1431///
1432/// IPv6 socket information for application transactions
1433///
1434/// # XDR Definition ([sFlow Host](https://sflow.org/sflow_host.txt))
1435///
1436/// ```text
1437/// /* IPv6 Socket */
1438/// /* opaque = flow_data; enterprise = 0; format = 2101 */
1439///
1440/// struct extended_socket_ipv6 {
1441///     unsigned int protocol;     /* IP Protocol type (e.g., TCP = 6, UDP = 17) */
1442///     ip_v6 local_ip;            /* local IP address */
1443///     ip_v6 remote_ip;           /* remote IP address */
1444///     unsigned int local_port;   /* TCP/UDP local port number or equivalent */
1445///     unsigned int remote_port;  /* TCP/UDP remote port number or equivalent */
1446/// }
1447/// ```
1448#[derive(Debug, Clone, PartialEq, Eq)]
1449#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1450pub struct ExtendedSocketIpv6 {
1451    /// IP Protocol type (e.g., TCP = 6, UDP = 17)
1452    pub protocol: u32,
1453
1454    /// Local IP address
1455    pub local_ip: std::net::Ipv6Addr,
1456
1457    /// Remote IP address
1458    pub remote_ip: std::net::Ipv6Addr,
1459
1460    /// TCP/UDP local port number
1461    pub local_port: u32,
1462
1463    /// TCP/UDP remote port number
1464    pub remote_port: u32,
1465}
1466
1467/// HTTP method enumeration
1468///
1469/// # XDR Definition ([sFlow HTTP](https://sflow.org/sflow_http.txt))
1470///
1471/// ```text
1472/// /* The http_method enumeration may be expanded over time.
1473///    Applications receiving sFlow must be prepared to receive
1474///    http_request structures with unknown http_method values */
1475///
1476/// enum http_method {
1477///   OTHER    = 0;
1478///   OPTIONS  = 1;
1479///   GET      = 2;
1480///   HEAD     = 3;
1481///   POST     = 4;
1482///   PUT      = 5;
1483///   DELETE   = 6;
1484///   TRACE    = 7;
1485///   CONNECT  = 8;
1486/// }
1487/// ```
1488#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1489#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1490#[repr(u32)]
1491pub enum HttpMethod {
1492    Other = 0,
1493    Options = 1,
1494    Get = 2,
1495    Head = 3,
1496    Post = 4,
1497    Put = 5,
1498    Delete = 6,
1499    Trace = 7,
1500    Connect = 8,
1501}
1502
1503impl From<u32> for HttpMethod {
1504    fn from(value: u32) -> Self {
1505        match value {
1506            1 => HttpMethod::Options,
1507            2 => HttpMethod::Get,
1508            3 => HttpMethod::Head,
1509            4 => HttpMethod::Post,
1510            5 => HttpMethod::Put,
1511            6 => HttpMethod::Delete,
1512            7 => HttpMethod::Trace,
1513            8 => HttpMethod::Connect,
1514            _ => HttpMethod::Other,
1515        }
1516    }
1517}
1518
1519impl std::fmt::Display for HttpMethod {
1520    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1521        match self {
1522            HttpMethod::Other => write!(f, "OTHER"),
1523            HttpMethod::Options => write!(f, "OPTIONS"),
1524            HttpMethod::Get => write!(f, "GET"),
1525            HttpMethod::Head => write!(f, "HEAD"),
1526            HttpMethod::Post => write!(f, "POST"),
1527            HttpMethod::Put => write!(f, "PUT"),
1528            HttpMethod::Delete => write!(f, "DELETE"),
1529            HttpMethod::Trace => write!(f, "TRACE"),
1530            HttpMethod::Connect => write!(f, "CONNECT"),
1531        }
1532    }
1533}
1534
1535/// Extended Proxy Socket IPv4 - Format (0,2102)
1536///
1537/// IPv4 socket information for proxy connections
1538///
1539/// # XDR Definition ([sFlow HTTP](https://sflow.org/sflow_http.txt))
1540///
1541/// ```text
1542/// /* Proxy socket IPv4 */
1543/// /* opaque = flow_data; enterprise=0; format=2102 */
1544/// struct extended_proxy_socket_ipv4 {
1545///   extended_socket_ipv4 socket;
1546/// }
1547/// ```
1548#[derive(Debug, Clone, PartialEq, Eq)]
1549#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1550pub struct ExtendedProxySocketIpv4 {
1551    /// Socket information
1552    pub socket: ExtendedSocketIpv4,
1553}
1554
1555/// Extended Proxy Socket IPv6 - Format (0,2103)
1556///
1557/// IPv6 socket information for proxy connections
1558///
1559/// # XDR Definition ([sFlow HTTP](https://sflow.org/sflow_http.txt))
1560///
1561/// ```text
1562/// /* Proxy socket IPv6 */
1563/// /* opaque = flow_data; enterprise=0; format=2103 */
1564/// struct extended_proxy_socket_ipv6 {
1565///   extended_socket_ipv6 socket;
1566/// }
1567/// ```
1568#[derive(Debug, Clone, PartialEq, Eq)]
1569#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1570pub struct ExtendedProxySocketIpv6 {
1571    /// Socket information
1572    pub socket: ExtendedSocketIpv6,
1573}
1574
1575/// Application operation context
1576///
1577/// # XDR Definition ([sFlow Application](https://sflow.org/sflow_application.txt))
1578///
1579/// ```text
1580/// struct context {
1581///     application application;
1582///     operation operation;
1583///     attributes attributes;
1584/// }
1585/// ```
1586#[derive(Debug, Clone, PartialEq, Eq)]
1587#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1588pub struct AppContext {
1589    /// Application name (e.g., "payment", "mail.smtp", "db.oracle")
1590    pub application: String,
1591
1592    /// Operation name (e.g., "get.customer.name", "upload.photo")
1593    pub operation: String,
1594
1595    /// Operation attributes as name=value pairs (e.g., "cc=visa&loc=mobile")
1596    pub attributes: String,
1597}
1598
1599/// Application operation status
1600///
1601/// # XDR Definition ([sFlow Application](https://sflow.org/sflow_application.txt))
1602#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1603#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1604#[repr(u32)]
1605pub enum AppStatus {
1606    Success = 0,
1607    Other = 1,
1608    Timeout = 2,
1609    InternalError = 3,
1610    BadRequest = 4,
1611    Forbidden = 5,
1612    TooLarge = 6,
1613    NotImplemented = 7,
1614    NotFound = 8,
1615    Unavailable = 9,
1616    Unauthorized = 10,
1617}
1618
1619impl From<u32> for AppStatus {
1620    fn from(value: u32) -> Self {
1621        match value {
1622            0 => AppStatus::Success,
1623            1 => AppStatus::Other,
1624            2 => AppStatus::Timeout,
1625            3 => AppStatus::InternalError,
1626            4 => AppStatus::BadRequest,
1627            5 => AppStatus::Forbidden,
1628            6 => AppStatus::TooLarge,
1629            7 => AppStatus::NotImplemented,
1630            8 => AppStatus::NotFound,
1631            9 => AppStatus::Unavailable,
1632            10 => AppStatus::Unauthorized,
1633            _ => AppStatus::Other,
1634        }
1635    }
1636}
1637
1638/// Application Operation - Format (0,2202)
1639///
1640/// Sampled application operation information
1641///
1642/// # XDR Definition ([sFlow Application](https://sflow.org/sflow_application.txt))
1643///
1644/// ```text
1645/// /* Sampled Application Operation */
1646/// /* opaque = flow_data; enterprise = 0; format = 2202 */
1647///
1648/// struct app_operation {
1649///     context context;             /* attributes describing the operation */
1650///     utf8string<64> status_descr; /* additional text describing status */
1651///     unsigned hyper req_bytes;    /* size of request body (exclude headers) */
1652///     unsigned hyper resp_bytes;   /* size of response body (exclude headers) */
1653///     unsigned int uS;             /* duration of the operation (microseconds) */
1654///     status status;               /* status code */
1655/// }
1656/// ```
1657#[derive(Debug, Clone, PartialEq, Eq)]
1658#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1659pub struct AppOperation {
1660    /// Operation context
1661    pub context: AppContext,
1662
1663    /// Additional status description
1664    pub status_descr: String,
1665
1666    /// Size of request body in bytes (excluding headers)
1667    pub req_bytes: u64,
1668
1669    /// Size of response body in bytes (excluding headers)
1670    pub resp_bytes: u64,
1671
1672    /// Duration of the operation in microseconds
1673    pub duration_us: u32,
1674
1675    /// Operation status code
1676    pub status: AppStatus,
1677}
1678
1679/// Application Parent Context - Format (0,2203)
1680///
1681/// Parent context for sampled client operations
1682///
1683/// # XDR Definition ([sFlow Application](https://sflow.org/sflow_application.txt))
1684///
1685/// ```text
1686/// /* Optional parent context information for sampled client operation */
1687/// /* opaque = flow_data; enterprise = 0; format = 2203 */
1688///
1689/// struct app_parent_context {
1690///     context context;
1691/// }
1692/// ```
1693#[derive(Debug, Clone, PartialEq, Eq)]
1694#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1695pub struct AppParentContext {
1696    /// Parent operation context
1697    pub context: AppContext,
1698}
1699
1700/// Application Initiator - Format (0,2204)
1701///
1702/// Actor initiating the request (e.g., customer sending a payment)
1703///
1704/// # XDR Definition ([sFlow Application](https://sflow.org/sflow_application.txt))
1705///
1706/// ```text
1707/// /* Actor initiating the request */
1708/// /* e.g. customer sending a payment */
1709/// /* opaque = flow_data; enterprise = 0; format = 2204 */
1710///
1711/// app_initiator {
1712///    actor actor;
1713/// }
1714/// ```
1715#[derive(Debug, Clone, PartialEq, Eq)]
1716#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1717pub struct AppInitiator {
1718    /// Business level identifier (e.g., customer id, vendor id)
1719    pub actor: String,
1720}
1721
1722/// Application Target - Format (0,2205)
1723///
1724/// Actor targeted by the request (e.g., recipient of payment)
1725///
1726/// # XDR Definition ([sFlow Application](https://sflow.org/sflow_application.txt))
1727///
1728/// ```text
1729/// /* Actor targetted by the request */
1730/// /* e.g. recipient of payment */
1731/// /* opaque = flow_data; enterprise = 0; format = 2205 */
1732///
1733/// app_target {
1734///    actor actor;
1735/// }
1736/// ```
1737#[derive(Debug, Clone, PartialEq, Eq)]
1738#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1739pub struct AppTarget {
1740    /// Business level identifier (e.g., customer id, vendor id)
1741    pub actor: String,
1742}
1743
1744/// HTTP Request - Format (0,2206)
1745///
1746/// HTTP request information
1747///
1748/// # XDR Definition ([sFlow HTTP](https://sflow.org/sflow_http.txt))
1749///
1750/// ```text
1751/// /* HTTP protocol version number */
1752/// /* Encoded as major_number * 1000 + minor_number */
1753/// /* e.g. HTTP1.1 is encoded as 1001 */
1754/// typedef unsigned int version;
1755///
1756/// /* HTTP request */
1757/// /* opaque = flow_data; enterprise = 0; format = 2206 */
1758/// struct http_request {
1759///   http_method method;        /* method */
1760///   version protocol;          /* HTTP protocol version */
1761///   string<255> uri;           /* URI exactly as it came from the client */
1762///   string<64> host;           /* Host value from request header */
1763///   string<255> referer;       /* Referer value from request header */
1764///   string<128> useragent;     /* User-Agent value from request header */
1765///   string<64> xff;            /* X-Forwarded-For value
1766///                                 from request header */
1767///   string<32> authuser;       /* RFC 1413 identity of user*/
1768///   string<64> mime-type;      /* Mime-Type of response */
1769///   unsigned hyper req_bytes;  /* Content-Length of request */
1770///   unsigned hyper resp_bytes; /* Content-Length of response */
1771///   unsigned int uS;           /* duration of the operation
1772///                                 (in microseconds) */
1773///   int status;                /* HTTP status code */
1774/// }
1775/// ```
1776#[derive(Debug, Clone, PartialEq, Eq)]
1777#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1778pub struct HttpRequest {
1779    /// HTTP method
1780    pub method: HttpMethod,
1781
1782    /// HTTP protocol version (major * 1000 + minor, e.g., HTTP/1.1 = 1001)
1783    pub protocol: u32,
1784
1785    /// URI exactly as it came from the client
1786    pub uri: String,
1787
1788    /// Host value from request header
1789    pub host: String,
1790
1791    /// Referer value from request header
1792    pub referer: String,
1793
1794    /// User-Agent value from request header
1795    pub useragent: String,
1796
1797    /// X-Forwarded-For value from request header
1798    pub xff: String,
1799
1800    /// RFC 1413 identity of user
1801    pub authuser: String,
1802
1803    /// MIME type of response
1804    pub mime_type: String,
1805
1806    /// Content-Length of request
1807    pub req_bytes: u64,
1808
1809    /// Content-Length of response
1810    pub resp_bytes: u64,
1811
1812    /// Duration of the operation in microseconds
1813    pub duration_us: u32,
1814
1815    /// HTTP status code
1816    pub status: i32,
1817}
1818
1819/// Extended Proxy Request - Format (0,2207)
1820///
1821/// Rewritten URI for proxy requests
1822///
1823/// # XDR Definition ([sFlow HTTP](https://sflow.org/sflow_http.txt))
1824///
1825/// ```text
1826/// /* Rewritten URI */
1827/// /* Only include if host or uri are modified */
1828/// /* opaque = flow_data; enterprise = 0; format = 2207 */
1829/// struct extended_proxy_request {
1830///   string<255> uri;           /* URI in request to downstream server */
1831///   string<64>  host;          /* Host in request to downstream server */
1832/// }
1833/// ```
1834#[derive(Debug, Clone, PartialEq, Eq)]
1835#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1836pub struct ExtendedProxyRequest {
1837    /// URI in request to downstream server
1838    pub uri: String,
1839
1840    /// Host in request to downstream server
1841    pub host: String,
1842}