use std::collections::HashSet;
use std::iter::repeat_n;
use crate::{
builder::*,
event::{EventQueue, ModelParams, SimpleTimingModel},
interactive::InteractiveNetwork,
network::Network,
ospf::global::GlobalOspf,
policies::{FwPolicy, Policy},
record::{ConvergenceRecording, ConvergenceTrace, RecordNetwork},
topology_zoo::TopologyZoo,
types::{SinglePrefix as P, StepUpdate, ASN},
};
use pretty_assertions::assert_eq;
#[test]
fn roland_pacificwave() {
let queue = SimpleTimingModel::<P>::new(ModelParams::new(1.0, 1.0, 2.0, 5.0, 0.5));
let mut net = TopologyZoo::Pacificwave.build(queue, ASN(65500), ASN(1));
let prefix = P::from(1);
let _external_routers = net
.build_external_routers(ASN(65500), ASN(1), HighestDegreeRouters::new(3))
.unwrap();
let route_reflectors = net
.build_ibgp_route_reflection(HighestDegreeRouters::new(2))
.unwrap();
net.build_ebgp_sessions().unwrap();
net.build_link_weights(UniformWeights::new(10.0, 100.0))
.unwrap();
let advertisements = net
.build_advertisements(
prefix,
UniquePreference::new().internal_asn(ASN(65500)),
ASN(0),
)
.unwrap();
let policies = Vec::from_iter(
route_reflectors
.into_values()
.flatten()
.map(|r| FwPolicy::LoopFree(r, prefix)),
);
let most_preferred = advertisements.iter().min_by_key(|(_, x)| *x).unwrap().0;
for _ in 0..1_000 {
let mut net = net.clone();
let mut recording = net
.record(|net| net.withdraw_route(most_preferred, prefix))
.unwrap();
let state = recording.state();
policies.iter().for_each(|p| {
let _ = p.check(state);
});
while let Some((_, _, state)) = recording.step() {
policies.iter().for_each(|p| {
let _ = p.check(state);
});
}
}
}
#[test]
fn roland_pacificwave_manual() {
let queue = SimpleTimingModel::<P>::new(ModelParams::new(1.0, 1.0, 2.0, 5.0, 0.5));
let mut net: Network<_, _, GlobalOspf> =
TopologyZoo::Pacificwave.build(queue, ASN(65500), ASN(1));
let prefix = P::from(1);
let _external_routers = net
.build_external_routers(ASN(65500), ASN(1), HighestDegreeRouters::new(3))
.unwrap();
let route_reflectors = net
.build_ibgp_route_reflection(HighestDegreeRouters::new(2))
.unwrap();
net.build_ebgp_sessions().unwrap();
net.build_link_weights(UniformWeights::new(10.0, 100.0))
.unwrap();
let advertisements = net
.build_advertisements(
prefix,
UniquePreference::new().internal_asn(ASN(65500)),
ASN(0),
)
.unwrap();
let policies = Vec::from_iter(
route_reflectors
.into_values()
.flatten()
.map(|r| FwPolicy::LoopFree(r, prefix)),
);
let mut t = net.clone();
let fw_state_before = t.get_forwarding_state();
let most_preferred = advertisements.iter().min_by_key(|(_, x)| *x).unwrap().0;
t.manual_simulation();
t.withdraw_route(most_preferred, prefix).unwrap();
let fw_state_after = t.get_forwarding_state();
let diff = fw_state_before.diff(&fw_state_after);
let trace = vec![(diff, Some(0.0).into())];
let mut fw_state = net.get_forwarding_state();
let fw_state_ref = net.get_forwarding_state();
let t0 = net.queue().get_time().unwrap_or_default();
for i in 0..1_000 {
println!("iteration {i}");
assert_eq!(fw_state, fw_state_ref);
let mut t = t.clone();
let mut trace = trace.clone();
while let Some((step, event)) = t.simulate_step().unwrap() {
match step {
StepUpdate::Unchanged => {}
StepUpdate::Multiple => unreachable!("OSPF events should be disabled"),
StepUpdate::Single(delta) => {
trace.push((
vec![(event.router(), delta.old, delta.new)],
net.queue().get_time().map(|x| x - t0).into(),
));
}
}
}
let mut recording = ConvergenceRecording::new(fw_state, trace);
let state = recording.state();
policies.iter().for_each(|p| {
let _ = p.check(state);
});
while let Some((_, _, state)) = recording.step() {
policies.iter().for_each(|p| {
let _ = p.check(state);
});
}
fw_state = recording.into_initial_fw_state();
}
}
#[test]
fn roland_arpanet() {
let queue = SimpleTimingModel::<P>::new(ModelParams::new(1.0, 1.0, 2.0, 5.0, 0.5));
let mut net = TopologyZoo::Arpanet196912.build(queue, ASN(65500), ASN(1));
let prefix = P::from(1);
let _external_routers = net
.build_external_routers(ASN(65500), ASN(1), HighestDegreeRouters::new(3))
.unwrap();
let route_reflectors = net
.build_ibgp_route_reflection(HighestDegreeRouters::new(2))
.unwrap();
net.build_ebgp_sessions().unwrap();
net.build_link_weights(UniformWeights::new(10.0, 100.0))
.unwrap();
let advertisements = net
.build_advertisements(
prefix,
UniquePreference::new().internal_asn(ASN(65500)),
ASN(0),
)
.unwrap();
let policies = Vec::from_iter(
route_reflectors
.into_values()
.flatten()
.map(|r| FwPolicy::LoopFree(r, prefix)),
);
let most_preferred = advertisements.iter().min_by_key(|(_, x)| *x).unwrap().0;
for _ in 0..1_000 {
let mut net = net.clone();
let mut recording = net
.record(|net| net.withdraw_route(most_preferred, prefix))
.unwrap();
let state = recording.state();
policies.iter().for_each(|p| {
let _ = p.check(state);
});
while let Some((_, _, state)) = recording.step() {
policies.iter().for_each(|p| {
let _ = p.check(state);
});
}
}
}
#[test]
fn roland_arpanet_manual() {
let queue = SimpleTimingModel::<P>::new(ModelParams::new(1.0, 1.0, 2.0, 5.0, 0.5));
let mut net: Network<_, _, GlobalOspf> =
TopologyZoo::Arpanet196912.build(queue, ASN(65500), ASN(1));
let prefix = P::from(0);
let _external_routers = net
.build_external_routers(ASN(65500), ASN(1), HighestDegreeRouters::new(3))
.unwrap();
let route_reflectors = net
.build_ibgp_route_reflection(HighestDegreeRouters::new(2))
.unwrap();
net.build_ebgp_sessions().unwrap();
net.build_link_weights(UniformWeights::new(10.0, 100.0))
.unwrap();
let advertisements = net
.build_advertisements(
prefix,
UniquePreference::new().internal_asn(ASN(65500)),
ASN(0),
)
.unwrap();
let policies = Vec::from_iter(
route_reflectors
.into_values()
.flatten()
.map(|r| FwPolicy::LoopFree(r, prefix)),
);
let mut t = net.clone();
t.manual_simulation();
let fw_state_before = t.get_forwarding_state();
let most_preferred = advertisements.iter().min_by_key(|(_, x)| *x).unwrap().0;
t.withdraw_route(most_preferred, prefix).unwrap();
let fw_state_after = t.get_forwarding_state();
let diff = fw_state_before.diff(&fw_state_after);
let t0 = t.queue().get_time().unwrap_or_default();
let trace = vec![(diff, Some(0.0).into())];
let mut fw_state = net.get_forwarding_state();
let fw_state_ref = net.get_forwarding_state();
for i in 0..1_000 {
println!("iteration {i}");
assert_eq!(fw_state, fw_state_ref);
let mut t = t.clone();
let mut trace = trace.clone();
while let Some((step, event)) = t.simulate_step().unwrap() {
match step {
StepUpdate::Unchanged => {}
StepUpdate::Multiple => unreachable!("OSPF events should be disabled"),
StepUpdate::Single(delta) => {
trace.push((
vec![(event.router(), delta.old, delta.new)],
net.queue().get_time().map(|x| x - t0).into(),
));
}
}
}
let mut recording = ConvergenceRecording::new(fw_state, trace);
let state = recording.state();
policies.iter().for_each(|p| {
let _ = p.check(state);
});
while recording.step().is_some() {
policies.iter().for_each(|p| {
let _ = p.check(recording.state());
});
}
while recording.back().is_some() {}
fw_state = recording.into_initial_fw_state();
}
}
#[test]
fn roland_arpanet_complete() {
let queue = SimpleTimingModel::<P>::new(ModelParams::new(
1.0, 1.0, 2.0, 5.0, 0.5, ));
let prefix = P::from(0);
let topology = TopologyZoo::Arpanet196912;
let mut net = topology.build(queue, ASN(65500), ASN(1));
let _external_routers = net
.build_external_routers(ASN(65500), ASN(1), HighestDegreeRouters::new(3))
.unwrap();
let route_reflectors = net
.build_ibgp_route_reflection(HighestDegreeRouters::new(2))
.unwrap();
net.build_ebgp_sessions().unwrap();
net.build_link_weights(UniformWeights::new(10.0, 100.0))
.unwrap();
let advertisements = net
.build_advertisements(
prefix,
UniquePreference::new().internal_asn(ASN(65500)),
ASN(0),
)
.unwrap();
let iters = 1_000;
let workers = 1;
let mut t = net.clone();
t.manual_simulation();
let t0 = t.queue().get_time().unwrap_or_default();
let fw_state_before = t.get_forwarding_state();
let most_preferred = advertisements.iter().min_by_key(|(_, x)| *x).unwrap().0;
t.withdraw_route(most_preferred, prefix).unwrap();
let fw_state_after = t.get_forwarding_state();
let diff = fw_state_before.diff(&fw_state_after);
let trace = vec![(diff, Some(0.0).into())];
let sample_func = |(mut t, mut trace): (Network<P, SimpleTimingModel<P>>, ConvergenceTrace)| {
while let Some((step, event)) = t.simulate_step().unwrap() {
match step {
StepUpdate::Unchanged => {}
StepUpdate::Multiple => unreachable!("OSPF events should be disabled"),
StepUpdate::Single(delta) => {
trace.push((
vec![(event.router(), delta.old, delta.new)],
net.queue().get_time().map(|x| x - t0).into(),
));
}
}
}
trace
};
let mut traces: HashSet<ConvergenceTrace> = HashSet::new();
traces.extend(
repeat_n(&(t.clone(), trace.clone()), workers)
.cloned()
.map(|(t, trace)| {
repeat_n(&(t, trace), iters / workers)
.cloned()
.map(sample_func)
.collect::<HashSet<_>>()
})
.collect::<Vec<_>>()
.into_iter()
.flatten(),
);
traces.extend(
repeat_n(&(t.clone(), trace), iters - iters / workers * workers)
.cloned()
.map(sample_func),
);
let transient_policies: Vec<_> = route_reflectors
.values()
.flatten()
.map(|&x| FwPolicy::LoopFree(x, prefix))
.collect();
let mut fw_state = net.get_forwarding_state();
for trace in traces.into_iter() {
let mut recording = ConvergenceRecording::new(fw_state, trace);
transient_policies.iter().for_each(|x| {
_ = x.check(recording.state());
});
while recording.step().is_some() {
transient_policies.iter().for_each(|x| {
_ = x.check(recording.state());
});
}
while recording.back().is_some() {}
fw_state = recording.into_initial_fw_state();
}
}