Skip to main content

flowparser_sflow/flow_records/
extended_gateway.rs

1use nom::IResult;
2use nom::number::complete::be_u32;
3use serde::{Deserialize, Serialize};
4
5use crate::datagram::{AddressType, parse_address};
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8pub struct AsPathSegment {
9    pub segment_type: u32,
10    pub values: Vec<u32>,
11}
12
13#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
14pub struct ExtendedGateway {
15    pub next_hop: AddressType,
16    pub as_number: u32,
17    pub src_as: u32,
18    pub src_peer_as: u32,
19    pub as_path_segments: Vec<AsPathSegment>,
20    pub communities: Vec<u32>,
21}
22
23fn parse_as_path_segment(input: &[u8]) -> IResult<&[u8], AsPathSegment> {
24    let (input, segment_type) = be_u32(input)?;
25    let (input, count) = be_u32(input)?;
26    // Cap capacity: each value is 4 bytes
27    let cap = (count as usize).min(input.len() / 4);
28    let mut values = Vec::with_capacity(cap);
29    let mut input = input;
30    for _ in 0..count {
31        let (rest, val) = be_u32(input)?;
32        values.push(val);
33        input = rest;
34    }
35    Ok((
36        input,
37        AsPathSegment {
38            segment_type,
39            values,
40        },
41    ))
42}
43
44pub(crate) fn parse_extended_gateway(input: &[u8]) -> IResult<&[u8], ExtendedGateway> {
45    let (input, next_hop) = parse_address(input)?;
46    let (input, as_number) = be_u32(input)?;
47    let (input, src_as) = be_u32(input)?;
48    let (input, src_peer_as) = be_u32(input)?;
49    let (input, as_path_count) = be_u32(input)?;
50
51    // Cap capacity: each segment needs at least 8 bytes (type + count)
52    let cap = (as_path_count as usize).min(input.len() / 8);
53    let mut as_path_segments = Vec::with_capacity(cap);
54    let mut input = input;
55    for _ in 0..as_path_count {
56        let (rest, segment) = parse_as_path_segment(input)?;
57        as_path_segments.push(segment);
58        input = rest;
59    }
60
61    let (input, communities_count) = be_u32(input)?;
62    // Cap capacity: each community is 4 bytes
63    let cap = (communities_count as usize).min(input.len() / 4);
64    let mut communities = Vec::with_capacity(cap);
65    let mut input = input;
66    for _ in 0..communities_count {
67        let (rest, val) = be_u32(input)?;
68        communities.push(val);
69        input = rest;
70    }
71
72    Ok((
73        input,
74        ExtendedGateway {
75            next_hop,
76            as_number,
77            src_as,
78            src_peer_as,
79            as_path_segments,
80            communities,
81        },
82    ))
83}