Skip to main content

route_verification_parse/
lex.rs

1use ::lex;
2
3use super::*;
4
5pub fn parse_lexed(lexed: lex::Ast) -> (Ir, Counts) {
6    let lex::Ast {
7        aut_nums,
8        as_sets,
9        route_sets,
10        peering_sets,
11        filter_sets,
12        as_routes,
13    } = lexed;
14    let (aut_nums, an_counts) = parse_lexed_aut_nums(aut_nums);
15    let (as_sets, as_counts) = parse_lexed_as_sets(as_sets);
16    let (route_sets, rs_counts) = parse_lexed_route_sets(route_sets);
17    let (peering_sets, ps_counts) = parse_lexed_peering_sets(peering_sets);
18    let (filter_sets, fs_counts) = parse_lexed_filter_sets(filter_sets);
19    let (as_routes, ar_counts) = parse_lexed_as_routes(as_routes);
20    let ir = Ir {
21        aut_nums,
22        as_sets,
23        route_sets,
24        peering_sets,
25        filter_sets,
26        as_routes,
27    };
28    let counts = an_counts + as_counts + rs_counts + ps_counts + fs_counts + ar_counts;
29    (ir, counts)
30}
31
32pub fn parse_lexed_aut_nums(lexed: Vec<lex::AutNum>) -> (BTreeMap<u32, AutNum>, Counts) {
33    par_process_map_counts(
34        lexed,
35        |(mut acc, mut counts), lexed| match parse_lexed_aut_num(lexed, &mut counts) {
36            Ok((num, aut_num)) => {
37                acc.insert(num, aut_num);
38                (acc, counts)
39            }
40            Err(e) => {
41                counts.parse_aut_num += 1;
42                error!("{e:?}");
43                (acc, counts)
44            }
45        },
46    )
47}
48
49pub fn parse_lexed_aut_num(aut_num: lex::AutNum, counts: &mut Counts) -> Result<(u32, AutNum)> {
50    let num = parse_aut_num_name(&aut_num.name).context(format!("parsing {aut_num:?}"))?;
51    let lex::AutNum {
52        name: _,
53        body,
54        n_import,
55        n_export,
56        imports,
57        exports,
58    } = aut_num;
59    let imports = parse_imports(imports, counts);
60    let exports = parse_imports(exports, counts);
61    Ok((
62        num,
63        AutNum {
64            body,
65            n_import,
66            n_export,
67            imports,
68            exports,
69        },
70    ))
71}
72
73pub fn parse_lexed_as_sets(lexed: Vec<lex::AsOrRouteSet>) -> (BTreeMap<String, AsSet>, Counts) {
74    par_process_map_counts(
75        lexed,
76        |(mut acc, mut counts), lexed| match parse_lexed_as_set(lexed) {
77            Ok((name, as_set)) => {
78                acc.insert(name, as_set);
79                (acc, counts)
80            }
81            Err(e) => {
82                counts.parse_as_set += 1;
83                error!("{e:?}");
84                (acc, counts)
85            }
86        },
87    )
88}
89
90pub fn parse_lexed_as_set(lexed: lex::AsOrRouteSet) -> Result<(String, AsSet)> {
91    if !is_as_set(&lexed.name) && !is_pseudo_set(&lexed.name) {
92        bail!("invalid AS Set name in {lexed:?}");
93    }
94    let max_length = lexed.members.len();
95    let mut members = Vec::with_capacity(max_length);
96    let mut set_members = Vec::with_capacity(max_length);
97    for member in lexed.members {
98        let member = parse_as_name(member)
99            .with_context(|| format!("parsing AS Set {}\n{}", lexed.name, lexed.body))?;
100        match member {
101            AsName::Any => return Ok((lexed.name, AsSet::new_any(lexed.body))),
102            AsName::Num(n) => members.push(n),
103            AsName::Set(set) => set_members.push(set),
104            AsName::Invalid(reason) => {
105                bail!("{reason} parsing AS Set {}\n{}", lexed.name, lexed.body)
106            }
107        }
108    }
109    let as_set = AsSet::new(lexed.body, members, set_members);
110    Ok((lexed.name, as_set))
111}
112
113pub fn parse_lexed_route_sets(
114    lexed: Vec<lex::AsOrRouteSet>,
115) -> (BTreeMap<String, RouteSet>, Counts) {
116    par_process_map_counts(
117        lexed,
118        |(mut acc, mut counts), lexed| match parse_lexed_route_set(lexed) {
119            Ok((name, route_set)) => {
120                acc.insert(name, route_set);
121                (acc, counts)
122            }
123            Err(e) => {
124                counts.parse_route_set += 1;
125                error!("{e:?}");
126                (acc, counts)
127            }
128        },
129    )
130}
131
132pub fn parse_lexed_route_set(lexed: lex::AsOrRouteSet) -> Result<(String, RouteSet)> {
133    if !is_route_set_name(&lexed.name) && !is_pseudo_set(&lexed.name) {
134        bail!(
135            "{} is an invalid route set name—parsing {lexed:?}",
136            lexed.name
137        );
138    }
139    let members = lexed
140        .members
141        .into_iter()
142        .map(|member| member.into())
143        .collect();
144
145    Ok((
146        lexed.name,
147        RouteSet {
148            body: lexed.body,
149            members,
150        },
151    ))
152}
153
154pub fn parse_lexed_peering_sets(
155    lexed: Vec<lex::PeeringSet>,
156) -> (BTreeMap<String, PeeringSet>, Counts) {
157    par_process_map_counts(
158        lexed,
159        |(mut acc, mut counts), lexed| match parse_lexed_peering_set(lexed) {
160            Ok((name, peering_set)) => {
161                acc.insert(name, peering_set);
162                (acc, counts)
163            }
164            Err(e) => {
165                counts.parse_peering_set += 1;
166                error!("{e:?}");
167                (acc, counts)
168            }
169        },
170    )
171}
172
173pub fn parse_lexed_peering_set(lexed: lex::PeeringSet) -> Result<(String, PeeringSet)> {
174    if !is_peering_set(&lexed.name) {
175        bail!(
176            "{} is an invalid peering set name—parsing {lexed:?}",
177            lexed.name
178        );
179    }
180    Ok((
181        lexed.name,
182        PeeringSet {
183            body: lexed.body,
184            peerings: lexed.peerings.into_iter().map(parse_mp_peering).collect(),
185        },
186    ))
187}
188
189pub fn parse_lexed_filter_sets(
190    lexed: Vec<lex::FilterSet>,
191) -> (BTreeMap<String, FilterSet>, Counts) {
192    par_process_map_counts(
193        lexed,
194        |(mut acc, mut counts), lexed| match parse_lexed_filter_set(lexed, &mut counts) {
195            Ok((name, filter_set)) => {
196                acc.insert(name, filter_set);
197                (acc, counts)
198            }
199            Err(e) => {
200                counts.parse_filter_set += 1;
201                error!("{e:?}");
202                (acc, counts)
203            }
204        },
205    )
206}
207
208pub fn parse_lexed_filter_set(
209    lexed: lex::FilterSet,
210    counts: &mut Counts,
211) -> Result<(String, FilterSet)> {
212    if !is_filter_set(&lexed.name) {
213        bail!(
214            "{} is an invalid filter set name—parsing {lexed:?}",
215            lexed.name
216        );
217    }
218    let filter_set = FilterSet {
219        body: lexed.body,
220        filters: lexed
221            .filters
222            .into_iter()
223            .map(|f| parse_filter(f, counts))
224            .collect(),
225    };
226    Ok((lexed.name, filter_set))
227}
228
229pub fn parse_lexed_as_routes(
230    as_routes: BTreeMap<String, Vec<String>>,
231) -> (BTreeMap<u32, Vec<IpNet>>, Counts) {
232    par_process_map_counts(
233        as_routes,
234        |(mut acc, mut counts), lexed| match parse_lexed_as_route(&lexed) {
235            Ok((num, routes)) => {
236                acc.insert(num, routes);
237                (acc, counts)
238            }
239            Err(e) => {
240                counts.parse_as_route += 1;
241                error!("Parsing routes for {lexed:?}: {e}.");
242                (acc, counts)
243            }
244        },
245    )
246}
247
248pub fn par_process_map_counts<I, In, F, K, V>(input: I, transform: F) -> (BTreeMap<K, V>, Counts)
249where
250    I: IntoParallelIterator<Item = In>,
251    F: Fn((BTreeMap<K, V>, Counts), In) -> (BTreeMap<K, V>, Counts) + Send + Sync,
252    K: Ord + Send + Sync,
253    V: Send + Sync,
254{
255    input
256        .into_par_iter()
257        .fold(|| (BTreeMap::new(), Counts::default()), transform)
258        .reduce(
259            || (BTreeMap::new(), Counts::default()),
260            |(mut map0, counts0), (map1, counts1)| {
261                map0.extend(map1);
262                (map0, counts0 + counts1)
263            },
264        )
265}
266
267pub fn parse_lexed_as_route((name, routes): &(String, Vec<String>)) -> Result<(u32, Vec<IpNet>)> {
268    let num = parse_aut_num_name(name)?;
269    let routes: Result<_> = routes.iter().map(|r| Ok(r.parse()?)).collect();
270    let mut routes: Vec<_> = routes?;
271    routes.sort_unstable();
272    Ok((num, routes))
273}