Skip to content

Commit 84ef2c8

Browse files
committed
Helpers on bgp::path_selection
1 parent 0e791ba commit 84ef2c8

File tree

1 file changed

+136
-2
lines changed

1 file changed

+136
-2
lines changed

src/bgp/path_selection.rs

+136-2
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ pub trait OrdStrat {
135135
}
136136

137137
/// Decision process strategy as described in RFC 4271.
138-
#[derive(Debug)]
138+
#[derive(Copy, Clone, Debug)]
139139
pub struct Rfc4271;
140140
impl OrdStrat for Rfc4271 {
141141
fn step_c<OS>(a: &OrdRoute<OS>, b: &OrdRoute<OS>) -> cmp::Ordering {
@@ -170,7 +170,7 @@ impl OrdStrat for Rfc4271 {
170170
}
171171

172172
/// Decision process strategy skipping comparison of Multi Exit Discriminator.
173-
#[derive(Debug)]
173+
#[derive(Copy, Clone, Debug)]
174174
pub struct SkipMed;
175175

176176
impl OrdStrat for SkipMed {
@@ -449,6 +449,96 @@ impl fmt::Display for DecisionErrorType {
449449
}
450450
}
451451

452+
453+
//------------ Helpers -------------------------------------------------------
454+
455+
pub fn preferred<'a, OS: OrdStrat>(
456+
a: OrdRoute<'a, OS>, b: OrdRoute<'a, OS>
457+
) -> OrdRoute<'a, OS> {
458+
cmp::min(a,b)
459+
}
460+
461+
pub fn best<'a, OS: 'a + OrdStrat, I>(it: I)-> Option<I::Item>
462+
where
463+
I: Iterator<Item = &'a OrdRoute<'a, OS>>
464+
{
465+
it.min()
466+
}
467+
468+
469+
// XXX would this be convenient?
470+
pub fn best_alt<'a, OS: OrdStrat>(
471+
_pamaps: impl Iterator<Item = &'a PaMap>,
472+
_tiebreakers: impl Iterator<Item = TiebreakerInfo>
473+
) -> Option<OrdRoute<'a, OS>> {
474+
unimplemented!()
475+
}
476+
477+
pub fn best_backup_vec<'a, OS: OrdStrat>(
478+
it: impl Iterator<Item = &'a OrdRoute<'a, OS>>
479+
) -> (Option<&'a OrdRoute<'a, OS>>, Option<&'a OrdRoute<'a, OS>>)
480+
{
481+
let mut sorted = it.collect::<Vec<_>>();
482+
sorted.sort();
483+
let mut iter = sorted.into_iter();
484+
485+
let best = iter.next();
486+
let backup = iter.next();
487+
488+
(best, backup)
489+
}
490+
491+
pub fn best_backup<'a, OS: OrdStrat>(
492+
it: impl Iterator<Item = &'a OrdRoute<'a, OS>>
493+
) -> (Option<&'a OrdRoute<'a, OS>>, Option<&'a OrdRoute<'a, OS>>)
494+
{
495+
let mut best = None;
496+
let mut backup = None;
497+
498+
for c in it {
499+
match best.take() {
500+
None => { best = Some(c); continue }
501+
Some(cur_best) => {
502+
if c < cur_best {
503+
// c is preferred over current
504+
best = Some(c);
505+
backup = Some(cur_best);
506+
continue;
507+
}
508+
// put it back in
509+
best = Some(cur_best);
510+
511+
// c is not better than best, now check backup
512+
if let Some(bkup) = backup.take() {
513+
if c < bkup {
514+
// c is preferred over backup
515+
backup = Some(c);
516+
continue;
517+
}
518+
backup = Some(bkup);
519+
}
520+
}
521+
}
522+
}
523+
524+
(best, backup)
525+
}
526+
527+
/*
528+
pub fn best_multistrat<'a, OS1: OrdStrat, OS2: OrdStrat, I>(it: I)
529+
-> (Option<&'a OrdRoute<'a, OS1>>, Option<&'a OrdRoute<'a, OS2>>)
530+
where
531+
I: Iterator<Item = &'a OrdRoute<'a, OS1>>,
532+
I::Item: Copy
533+
{
534+
let res1 = best(it);
535+
let it2 = it.copied().map(|r| r.into_strat());
536+
let res2 = best::<'a, OS2, _>(it2);
537+
538+
(res1, res2)
539+
}
540+
*/
541+
452542
//------------ Tests ---------------------------------------------------------
453543

454544
#[cfg(test)]
@@ -508,4 +598,48 @@ mod tests {
508598
assert!(b == c);
509599
assert!(a == c);
510600
}
601+
602+
603+
#[test]
604+
fn helpers() {
605+
606+
let tiebreakers = TiebreakerInfo {
607+
source: RouteSource::Ebgp,
608+
degree_of_preference: None,
609+
local_asn: Asn::from_u32(100),
610+
bgp_identifier: [0, 0, 0, 0].into(),
611+
peer_addr: "::".parse().unwrap(),
612+
};
613+
614+
let mut a_pamap = PaMap::empty();
615+
a_pamap.set(Origin(OriginType::Egp));
616+
a_pamap.set(HopPath::from([10, 20, 30]));
617+
a_pamap.set(MultiExitDisc(100));
618+
619+
let mut b_pamap = PaMap::empty();
620+
b_pamap.set(Origin(OriginType::Egp));
621+
b_pamap.set(HopPath::from([10, 25, 30]));
622+
b_pamap.set(MultiExitDisc(50));
623+
624+
let mut c_pamap = PaMap::empty();
625+
c_pamap.set(Origin(OriginType::Egp));
626+
c_pamap.set(HopPath::from([80, 90, 100]));
627+
628+
let candidates = [
629+
OrdRoute::rfc4271(&a_pamap, tiebreakers).unwrap(),
630+
OrdRoute::rfc4271(&b_pamap, tiebreakers).unwrap(),
631+
OrdRoute::rfc4271(&c_pamap, tiebreakers).unwrap(),
632+
];
633+
634+
let best1 = best(candidates.iter());
635+
let (best2, backup2) = best_backup_vec(candidates.iter());
636+
let (best3, backup3) = best_backup(candidates.iter());
637+
638+
assert_eq!(best1, best2);
639+
assert_eq!(best2, best3);
640+
assert_eq!(backup2, backup3);
641+
assert_ne!(best2, backup2);
642+
assert_ne!(best3, backup3);
643+
}
644+
511645
}

0 commit comments

Comments
 (0)