1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#![allow(dead_code)]
#![allow(unused_imports)]
use std::{
collections::BTreeMap,
sync::{Arc, Mutex},
time::Duration,
};
use twizzler_async::{timeout_after, FlagBlock};
use twizzler_net::addr::Ipv4Addr;
use crate::link::ethernet::EthernetAddr;
const ARP_TIMEOUT: Duration = Duration::from_millis(8000);
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]
pub struct ArpInfo {
eth_addr: EthernetAddr,
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]
pub struct ArpKey {
addr: Ipv4Addr,
}
struct ArpTableInner {
entries: Mutex<BTreeMap<ArpKey, ArpInfo>>,
flag: FlagBlock,
}
struct ArpTable {
inner: Arc<ArpTableInner>,
}
lazy_static::lazy_static! {
static ref ARP_TABLE: ArpTable = ArpTable::new();
}
impl ArpTable {
fn new() -> Self {
Self {
inner: Arc::new(ArpTableInner {
entries: Mutex::new(BTreeMap::new()),
flag: FlagBlock::new(),
}),
}
}
async fn lookup(&self, dst: ArpKey) -> ArpInfo {
loop {
let entries = self.inner.entries.lock().unwrap();
if let Some(res) = entries.get(&dst) {
return *res;
}
println!("didn't find arp entry");
let fut = self.inner.flag.wait();
println!("future created");
drop(entries);
println!("firing request");
self.fire_arp_request(dst);
println!("awaiting completion");
fut.await;
}
}
fn fire_arp_request(&self, _dst: ArpKey) {
println!("fire arp request");
}
fn add_entry(&self, key: ArpKey, info: ArpInfo) {
self.inner.entries.lock().unwrap().insert(key, info);
self.inner.flag.signal_all();
}
}
pub async fn lookup_arp_info(key: ArpKey) -> Result<Option<ArpInfo>, ()> {
Ok(twizzler_async::timeout_after(ARP_TABLE.lookup(key), ARP_TIMEOUT).await)
}