1use alloc::collections::BinaryHeap;
8use alloc::vec::Vec;
9use core::fmt::Debug;
10use core::hash::Hash;
11use core::time::Duration;
12use netstack3_hashmap::HashMap;
13
14use packet::Buf;
15
16use crate::InstantContext as _;
17use crate::testutil::{
18 FakeInstant, FakeTimerId, InstantAndData, WithFakeFrameContext, WithFakeTimerContext,
19};
20
21pub struct FakeNetwork<Spec: FakeNetworkSpec, CtxId, Links> {
26 links: Links,
27 current_time: FakeInstant,
28 pending_frames: BinaryHeap<PendingFrame<CtxId, Spec::RecvMeta>>,
29 contexts: HashMap<CtxId, Spec::Context>,
33}
34
35#[derive(Debug)]
37pub struct PendingFrameData<CtxId, Meta> {
38 pub dst_context: CtxId,
40 pub meta: Meta,
42 pub frame: Vec<u8>,
44}
45
46pub type PendingFrame<CtxId, Meta> = InstantAndData<PendingFrameData<CtxId, Meta>>;
48
49pub trait FakeNetworkSpec: Sized {
51 type Context: WithFakeTimerContext<Self::TimerId>;
53 type TimerId: Clone;
55 type SendMeta;
58 type RecvMeta;
61
62 fn handle_frame(ctx: &mut Self::Context, recv: Self::RecvMeta, data: Buf<Vec<u8>>);
64 fn handle_timer(ctx: &mut Self::Context, dispatch: Self::TimerId, timer: FakeTimerId);
70 fn process_queues(ctx: &mut Self::Context) -> bool;
76
77 fn fake_frames(ctx: &mut Self::Context) -> &mut impl WithFakeFrameContext<Self::SendMeta>;
79
80 fn new_network<CtxId, Links, I>(contexts: I, links: Links) -> FakeNetwork<Self, CtxId, Links>
82 where
83 CtxId: Eq + Hash + Copy + Debug,
84 I: IntoIterator<Item = (CtxId, Self::Context)>,
85 Links: FakeNetworkLinks<Self::SendMeta, Self::RecvMeta, CtxId>,
86 {
87 FakeNetwork::new(contexts, links)
88 }
89}
90
91pub trait FakeNetworkLinks<SendMeta, RecvMeta, CtxId> {
99 fn map_link(&self, ctx: CtxId, meta: SendMeta) -> Vec<(CtxId, RecvMeta, Option<Duration>)>;
102}
103
104impl<SendMeta, RecvMeta, CtxId, F: Fn(CtxId, SendMeta) -> Vec<(CtxId, RecvMeta, Option<Duration>)>>
105 FakeNetworkLinks<SendMeta, RecvMeta, CtxId> for F
106{
107 fn map_link(&self, ctx: CtxId, meta: SendMeta) -> Vec<(CtxId, RecvMeta, Option<Duration>)> {
108 (self)(ctx, meta)
109 }
110}
111
112#[derive(Debug)]
114pub struct StepResult {
115 pub timers_fired: usize,
117 pub frames_sent: usize,
119 pub contexts_with_queued_frames: usize,
121}
122
123impl StepResult {
124 fn new_idle() -> Self {
125 Self { timers_fired: 0, frames_sent: 0, contexts_with_queued_frames: 0 }
126 }
127
128 pub fn is_idle(&self) -> bool {
130 return self.timers_fired == 0
131 && self.frames_sent == 0
132 && self.contexts_with_queued_frames == 0;
133 }
134}
135
136impl<Spec, CtxId, Links> FakeNetwork<Spec, CtxId, Links>
137where
138 CtxId: Eq + Hash,
139 Spec: FakeNetworkSpec,
140{
141 pub fn context<K: Into<CtxId>>(&mut self, context: K) -> &mut Spec::Context {
143 self.contexts.get_mut(&context.into()).unwrap()
144 }
145
146 pub fn with_context<K: Into<CtxId>, O, F: FnOnce(&mut Spec::Context) -> O>(
148 &mut self,
149 context: K,
150 f: F,
151 ) -> O {
152 f(self.context(context))
153 }
154}
155
156impl<Spec, CtxId, Links> FakeNetwork<Spec, CtxId, Links>
157where
158 Spec: FakeNetworkSpec,
159 CtxId: Eq + Hash + Copy + Debug,
160 Links: FakeNetworkLinks<Spec::SendMeta, Spec::RecvMeta, CtxId>,
161{
162 pub fn new<I: IntoIterator<Item = (CtxId, Spec::Context)>>(contexts: I, links: Links) -> Self {
175 let mut contexts = contexts.into_iter().collect::<HashMap<_, _>>();
176 let latest_time = contexts
186 .iter()
187 .map(|(_, ctx)| ctx.with_fake_timer_ctx(|ctx| ctx.instant.time))
188 .max()
189 .unwrap_or_else(FakeInstant::default);
193
194 assert!(
195 !contexts
196 .iter()
197 .any(|(_, ctx)| { !ctx.with_fake_timer_ctx(|ctx| ctx.timers.is_empty()) }),
198 "can't start network with contexts that already have timers set"
199 );
200
201 for (_, ctx) in contexts.iter_mut() {
204 ctx.with_fake_timer_ctx_mut(|ctx| ctx.instant.time = latest_time);
205 }
206
207 Self { contexts, current_time: latest_time, pending_frames: BinaryHeap::new(), links }
208 }
209
210 pub fn iter_pending_frames(
212 &self,
213 ) -> impl Iterator<Item = &PendingFrame<CtxId, Spec::RecvMeta>> {
214 self.pending_frames.iter()
215 }
216
217 #[track_caller]
219 pub fn assert_no_pending_frames(&self)
220 where
221 Spec::RecvMeta: Debug,
222 {
223 assert!(self.pending_frames.is_empty(), "pending frames: {:?}", self.pending_frames);
224 }
225
226 pub fn drop_pending_frames(&mut self) {
228 self.pending_frames.clear();
229 }
230
231 pub fn step(&mut self) -> StepResult
264 where
265 Spec::TimerId: Debug,
266 {
267 self.step_with(|_, meta, buf| Some((meta, buf)))
268 }
269
270 pub fn step_with<
274 F: FnMut(
275 &mut Spec::Context,
276 Spec::RecvMeta,
277 Buf<Vec<u8>>,
278 ) -> Option<(Spec::RecvMeta, Buf<Vec<u8>>)>,
279 >(
280 &mut self,
281 filter_map_frame: F,
282 ) -> StepResult
283 where
284 Spec::TimerId: Debug,
285 {
286 let mut ret = StepResult::new_idle();
287 for (_, ctx) in self.contexts.iter_mut() {
290 if Spec::process_queues(ctx) {
291 ret.contexts_with_queued_frames += 1;
292 }
293 }
294
295 self.collect_frames();
296
297 let next_step = if let Some(t) = self.next_step() {
298 t
299 } else {
300 return ret;
301 };
302
303 assert!(next_step >= self.current_time);
306
307 self.current_time = next_step;
309 for (_, ctx) in self.contexts.iter_mut() {
310 ctx.with_fake_timer_ctx_mut(|ctx| ctx.instant.time = next_step);
311 }
312
313 ret.frames_sent = self.dispatch_pending_frames(filter_map_frame);
314
315 for (_, ctx) in self.contexts.iter_mut() {
317 let mut timers = Vec::<(Spec::TimerId, FakeTimerId)>::new();
321 ctx.with_fake_timer_ctx_mut(|ctx| {
322 while let Some(InstantAndData(t, timer)) = ctx.timers.peek() {
323 if *t > ctx.now() {
326 break;
327 }
328 timers.push((timer.dispatch_id.clone(), timer.timer_id()));
329 assert_ne!(ctx.timers.pop(), None);
330 }
331 });
332
333 for (dispatch_id, timer_id) in timers {
334 Spec::handle_timer(ctx, dispatch_id, timer_id);
335 ret.timers_fired += 1;
336 }
337 }
338 ret
339 }
340
341 pub fn step_deliver_frames(&mut self) -> StepResult
348 where
349 Spec::TimerId: Debug,
350 {
351 self.step_deliver_frames_with(|_, meta, frame| Some((meta, frame)))
352 }
353
354 pub fn step_deliver_frames_with<
358 F: FnMut(
359 &mut Spec::Context,
360 Spec::RecvMeta,
361 Buf<Vec<u8>>,
362 ) -> Option<(Spec::RecvMeta, Buf<Vec<u8>>)>,
363 >(
364 &mut self,
365 filter_map_frame: F,
366 ) -> StepResult
367 where
368 Spec::TimerId: Debug,
369 {
370 let mut ret = StepResult::new_idle();
371 for (_, ctx) in self.contexts.iter_mut() {
373 if Spec::process_queues(ctx) {
374 ret.contexts_with_queued_frames += 1;
375 }
376 }
377
378 self.collect_frames();
379 ret.frames_sent = self.dispatch_pending_frames(filter_map_frame);
380
381 ret
382 }
383
384 pub fn run_until_idle(&mut self)
391 where
392 Spec::TimerId: Debug,
393 {
394 self.run_until_idle_with(|_, meta, frame| Some((meta, frame)))
395 }
396
397 pub fn run_until_idle_with<
401 F: FnMut(
402 &mut Spec::Context,
403 Spec::RecvMeta,
404 Buf<Vec<u8>>,
405 ) -> Option<(Spec::RecvMeta, Buf<Vec<u8>>)>,
406 >(
407 &mut self,
408 mut filter_map_frame: F,
409 ) where
410 Spec::TimerId: Debug,
411 {
412 for _ in 0..1_000_000 {
413 if self.step_with(&mut filter_map_frame).is_idle() {
414 return;
415 }
416 }
417 panic!("FakeNetwork seems to have gotten stuck in a loop.");
418 }
419
420 pub fn collect_frames(&mut self) {
428 let all_frames = self.contexts.iter_mut().filter_map(|(n, ctx)| {
429 Spec::fake_frames(ctx).with_fake_frame_ctx_mut(|ctx| {
430 let frames = ctx.take_frames();
431 if frames.is_empty() { None } else { Some((n.clone(), frames)) }
432 })
433 });
434
435 for (src_context, frames) in all_frames {
436 for (send_meta, frame) in frames.into_iter() {
437 for (dst_context, recv_meta, latency) in self.links.map_link(src_context, send_meta)
438 {
439 self.pending_frames.push(PendingFrame::new(
440 self.current_time + latency.unwrap_or(Duration::from_millis(0)),
441 PendingFrameData { frame: frame.clone(), dst_context, meta: recv_meta },
442 ));
443 }
444 }
445 }
446 }
447
448 pub fn dispatch_pending_frames<
459 F: FnMut(
460 &mut Spec::Context,
461 Spec::RecvMeta,
462 Buf<Vec<u8>>,
463 ) -> Option<(Spec::RecvMeta, Buf<Vec<u8>>)>,
464 >(
465 &mut self,
466 mut filter_map_frame: F,
467 ) -> usize {
468 let mut frames_sent = 0;
469 while let Some(InstantAndData(t, _)) = self.pending_frames.peek() {
470 if *t > self.current_time {
473 break;
474 }
475 let PendingFrameData { dst_context, meta, frame } =
477 self.pending_frames.pop().unwrap().1;
478 let dst_context = self.context(dst_context);
479 if let Some((meta, frame)) = filter_map_frame(dst_context, meta, Buf::new(frame, ..)) {
480 Spec::handle_frame(dst_context, meta, frame)
481 }
482 frames_sent += 1;
483 }
484
485 frames_sent
486 }
487
488 pub fn next_step(&self) -> Option<FakeInstant> {
494 let next_timer = self
496 .contexts
497 .iter()
498 .filter_map(|(_, ctx)| {
499 ctx.with_fake_timer_ctx(|ctx| match ctx.timers.peek() {
500 Some(tmr) => Some(tmr.0),
501 None => None,
502 })
503 })
504 .min();
505 let next_packet_due = self.pending_frames.peek().map(|t| t.0);
507
508 match next_timer {
511 Some(t) if next_packet_due.is_some() => Some(t).min(next_packet_due),
512 Some(t) => Some(t),
513 None => next_packet_due,
514 }
515 .map(|t| t.max(self.current_time))
516 }
517}
518
519#[cfg(test)]
520mod tests {
521 use super::*;
522
523 use alloc::vec;
524
525 use crate::testutil::{FakeFrameCtx, FakeTimerCtx};
526 use crate::{SendFrameContext as _, TimerContext as _};
527
528 #[derive(Default)]
531 struct FakeNetworkTestCtx {
532 timer_ctx: FakeTimerCtx<u32>,
533 frame_ctx: FakeFrameCtx<()>,
534 fired_timers: HashMap<u32, usize>,
535 frames_received: usize,
536 }
537
538 impl FakeNetworkTestCtx {
539 #[track_caller]
540 fn drain_and_assert_timers(&mut self, iter: impl IntoIterator<Item = (u32, usize)>) {
541 for (timer, fire_count) in iter {
542 assert_eq!(self.fired_timers.remove(&timer), Some(fire_count), "for timer {timer}");
543 }
544 assert!(self.fired_timers.is_empty(), "remaining timers: {:?}", self.fired_timers);
545 }
546
547 fn request() -> Vec<u8> {
549 vec![1, 2, 3, 4]
550 }
551
552 fn response() -> Vec<u8> {
554 vec![4, 3, 2, 1]
555 }
556 }
557
558 impl FakeNetworkSpec for FakeNetworkTestCtx {
559 type Context = Self;
560 type TimerId = u32;
561 type SendMeta = ();
562 type RecvMeta = ();
563
564 fn handle_frame(ctx: &mut Self, _recv: (), data: Buf<Vec<u8>>) {
565 ctx.frames_received += 1;
566 if data.into_inner() == Self::request() {
569 ctx.frame_ctx.push((), Self::response())
570 }
571 }
572
573 fn handle_timer(ctx: &mut Self, dispatch: u32, _: FakeTimerId) {
574 *ctx.fired_timers.entry(dispatch).or_insert(0) += 1;
575 }
576
577 fn process_queues(_ctx: &mut Self) -> bool {
578 false
579 }
580
581 fn fake_frames(ctx: &mut Self) -> &mut impl WithFakeFrameContext<Self::SendMeta> {
582 ctx
583 }
584 }
585
586 impl WithFakeFrameContext<()> for FakeNetworkTestCtx {
587 fn with_fake_frame_ctx_mut<O, F: FnOnce(&mut FakeFrameCtx<()>) -> O>(&mut self, f: F) -> O {
588 f(&mut self.frame_ctx)
589 }
590 }
591
592 impl WithFakeTimerContext<u32> for FakeNetworkTestCtx {
593 fn with_fake_timer_ctx<O, F: FnOnce(&FakeTimerCtx<u32>) -> O>(&self, f: F) -> O {
594 f(&self.timer_ctx)
595 }
596
597 fn with_fake_timer_ctx_mut<O, F: FnOnce(&mut FakeTimerCtx<u32>) -> O>(
598 &mut self,
599 f: F,
600 ) -> O {
601 f(&mut self.timer_ctx)
602 }
603 }
604
605 fn new_fake_network_with_latency(
606 latency: Option<Duration>,
607 ) -> FakeNetwork<FakeNetworkTestCtx, i32, impl FakeNetworkLinks<(), (), i32>> {
608 FakeNetwork::new(
609 [(1, FakeNetworkTestCtx::default()), (2, FakeNetworkTestCtx::default())],
610 move |id, ()| {
611 vec![(
612 match id {
613 1 => 2,
614 2 => 1,
615 _ => unreachable!(),
616 },
617 (),
618 latency,
619 )]
620 },
621 )
622 }
623
624 #[test]
625 fn timers() {
626 let mut net = new_fake_network_with_latency(None);
627
628 let (mut t1, mut t4, mut t5) =
629 net.with_context(1, |FakeNetworkTestCtx { timer_ctx, .. }| {
630 (timer_ctx.new_timer(1), timer_ctx.new_timer(4), timer_ctx.new_timer(5))
631 });
632
633 net.with_context(1, |FakeNetworkTestCtx { timer_ctx, .. }| {
634 assert_eq!(timer_ctx.schedule_timer(Duration::from_secs(1), &mut t1), None);
635 assert_eq!(timer_ctx.schedule_timer(Duration::from_secs(4), &mut t4), None);
636 assert_eq!(timer_ctx.schedule_timer(Duration::from_secs(5), &mut t5), None);
637 });
638
639 let (mut t2, mut t3, mut t6) =
640 net.with_context(2, |FakeNetworkTestCtx { timer_ctx, .. }| {
641 (timer_ctx.new_timer(2), timer_ctx.new_timer(3), timer_ctx.new_timer(6))
642 });
643
644 net.with_context(2, |FakeNetworkTestCtx { timer_ctx, .. }| {
645 assert_eq!(timer_ctx.schedule_timer(Duration::from_secs(2), &mut t2), None);
646 assert_eq!(timer_ctx.schedule_timer(Duration::from_secs(3), &mut t3), None);
647 assert_eq!(timer_ctx.schedule_timer(Duration::from_secs(5), &mut t6), None);
648 });
649
650 net.context(1).drain_and_assert_timers([]);
652 net.context(2).drain_and_assert_timers([]);
653 assert_eq!(net.step().timers_fired, 1);
654 net.context(1).drain_and_assert_timers([(1, 1)]);
656 net.context(2).drain_and_assert_timers([]);
657 assert_eq!(net.step().timers_fired, 1);
658 net.context(1).drain_and_assert_timers([]);
660 net.context(2).drain_and_assert_timers([(2, 1)]);
661 assert_eq!(net.step().timers_fired, 1);
662 net.context(1).drain_and_assert_timers([]);
664 net.context(2).drain_and_assert_timers([(3, 1)]);
665 assert_eq!(net.step().timers_fired, 1);
666 net.context(1).drain_and_assert_timers([(4, 1)]);
668 net.context(2).drain_and_assert_timers([]);
669 assert_eq!(net.step().timers_fired, 2);
670 net.context(1).drain_and_assert_timers([(5, 1)]);
672 net.context(2).drain_and_assert_timers([(6, 1)]);
673
674 assert!(net.step().is_idle());
675 let t1 = net.with_context(1, |FakeNetworkTestCtx { timer_ctx, .. }| timer_ctx.now());
677 let t2 = net.with_context(2, |FakeNetworkTestCtx { timer_ctx, .. }| timer_ctx.now());
678 assert_eq!(t1, t2);
679 }
680
681 #[test]
682 fn until_idle() {
683 let mut net = new_fake_network_with_latency(None);
684
685 let mut t1 =
686 net.with_context(1, |FakeNetworkTestCtx { timer_ctx, .. }| timer_ctx.new_timer(1));
687 net.with_context(1, |FakeNetworkTestCtx { timer_ctx, .. }| {
688 assert_eq!(timer_ctx.schedule_timer(Duration::from_secs(1), &mut t1), None);
689 });
690
691 let (mut t2, mut t3) = net.with_context(2, |FakeNetworkTestCtx { timer_ctx, .. }| {
692 (timer_ctx.new_timer(2), timer_ctx.new_timer(3))
693 });
694 net.with_context(2, |FakeNetworkTestCtx { timer_ctx, .. }| {
695 assert_eq!(timer_ctx.schedule_timer(Duration::from_secs(2), &mut t2), None);
696 assert_eq!(timer_ctx.schedule_timer(Duration::from_secs(3), &mut t3), None);
697 });
698
699 while !net.step().is_idle() && net.context(1).fired_timers.len() < 1
700 || net.context(2).fired_timers.len() < 1
701 {}
702 assert_eq!(net.step().timers_fired, 1);
705 }
706
707 #[test]
708 fn delayed_packets() {
709 let mut net = new_fake_network_with_latency(Some(Duration::from_millis(5)));
711
712 let mut t11 =
714 net.with_context(1, |FakeNetworkTestCtx { timer_ctx, .. }| timer_ctx.new_timer(1));
715 net.with_context(1, |FakeNetworkTestCtx { frame_ctx, timer_ctx, .. }| {
716 frame_ctx.push((), FakeNetworkTestCtx::request());
717 assert_eq!(timer_ctx.schedule_timer(Duration::from_millis(3), &mut t11), None);
718 });
719 let (mut t21, mut t22) = net.with_context(2, |FakeNetworkTestCtx { timer_ctx, .. }| {
721 (timer_ctx.new_timer(1), timer_ctx.new_timer(2))
722 });
723 net.with_context(2, |FakeNetworkTestCtx { timer_ctx, .. }| {
724 assert_eq!(timer_ctx.schedule_timer(Duration::from_millis(7), &mut t22), None);
725 assert_eq!(timer_ctx.schedule_timer(Duration::from_millis(10), &mut t21), None);
726 });
727
728 let assert_full_state = |net: &mut FakeNetwork<FakeNetworkTestCtx, _, _>,
735 ctx1_timers,
736 ctx2_timers,
737 ctx2_frames,
738 ctx1_frames| {
739 let ctx1 = net.context(1);
740 assert_eq!(ctx1.fired_timers.len(), ctx1_timers);
741 assert_eq!(ctx1.frames_received, ctx1_frames);
742 let ctx2 = net.context(2);
743 assert_eq!(ctx2.fired_timers.len(), ctx2_timers);
744 assert_eq!(ctx2.frames_received, ctx2_frames);
745 };
746
747 assert_eq!(net.step().timers_fired, 1);
748 assert_full_state(&mut net, 1, 0, 0, 0);
749 assert_eq!(net.step().frames_sent, 1);
750 assert_full_state(&mut net, 1, 0, 1, 0);
751 assert_eq!(net.step().timers_fired, 1);
752 assert_full_state(&mut net, 1, 1, 1, 0);
753 let step = net.step();
754 assert_eq!(step.frames_sent, 1);
755 assert_eq!(step.timers_fired, 1);
756 assert_full_state(&mut net, 1, 2, 1, 1);
757
758 assert!(net.step().is_idle());
760 }
761
762 #[test]
763 fn fake_network_transmits_packets() {
764 let mut net = new_fake_network_with_latency(None);
765
766 net.with_context(1, |FakeNetworkTestCtx { frame_ctx, .. }| {
768 frame_ctx.send_frame(&mut (), (), Buf::new(FakeNetworkTestCtx::request(), ..)).unwrap();
769 });
770
771 assert_eq!(net.step().frames_sent, 1);
773 assert_eq!(net.step().frames_sent, 1);
775 assert!(net.step().is_idle());
777 }
778
779 #[test]
780 fn send_to_many() {
781 let mut net = FakeNetworkTestCtx::new_network(
782 [
783 (1, FakeNetworkTestCtx::default()),
784 (2, FakeNetworkTestCtx::default()),
785 (3, FakeNetworkTestCtx::default()),
786 ],
787 |id, ()| match id {
788 1 => vec![(2, (), None), (3, (), None)],
790 2 => vec![(1, (), None)],
792 3 => vec![],
794 _ => unreachable!(),
795 },
796 );
797 net.assert_no_pending_frames();
798
799 net.with_context(1, |FakeNetworkTestCtx { frame_ctx, .. }| {
801 frame_ctx.send_frame(&mut (), (), Buf::new(vec![], ..)).unwrap();
802 });
803 net.collect_frames();
804 assert_eq!(net.iter_pending_frames().count(), 2);
805 assert!(net.iter_pending_frames().any(|InstantAndData(_, x)| x.dst_context == 2));
806 assert!(net.iter_pending_frames().any(|InstantAndData(_, x)| x.dst_context == 3));
807 net.drop_pending_frames();
808
809 net.with_context(2, |FakeNetworkTestCtx { frame_ctx, .. }| {
811 frame_ctx.send_frame(&mut (), (), Buf::new(vec![], ..)).unwrap();
812 });
813 net.collect_frames();
814 assert_eq!(net.iter_pending_frames().count(), 1);
815 assert!(net.iter_pending_frames().any(|InstantAndData(_, x)| x.dst_context == 1));
816 net.drop_pending_frames();
817
818 net.with_context(3, |FakeNetworkTestCtx { frame_ctx, .. }| {
820 frame_ctx.send_frame(&mut (), (), Buf::new(vec![], ..)).unwrap();
821 });
822 net.collect_frames();
823 net.assert_no_pending_frames();
824
825 for i in 1..=3 {
828 assert_eq!(net.context(i).frames_received, 0, "context: {i}");
829 }
830 }
831}