atmos/kernel/net/
arp_cache.rs1#[derive(Copy, Clone, PartialEq, Eq, Debug)]
12pub struct ArpEntry {
13 pub valid: bool,
14 pub ip: [u8; 4],
15 pub mac: [u8; 6],
16 pub age: u32,
18}
19
20impl ArpEntry {
21 pub const fn empty() -> Self {
22 Self {
23 valid: false,
24 ip: [0; 4],
25 mac: [0; 6],
26 age: 0,
27 }
28 }
29}
30
31#[derive(Copy, Clone, PartialEq, Eq, Debug)]
33pub enum UpsertOutcome {
34 Updated,
36 Inserted,
38 Evicted,
40 Ignored,
42}
43
44pub fn lookup(table: &[ArpEntry], ip: [u8; 4]) -> Option<[u8; 6]> {
45 for e in table.iter() {
46 if e.valid && e.ip == ip {
47 return Some(e.mac);
48 }
49 }
50 None
51}
52
53pub fn upsert(table: &mut [ArpEntry], ip: [u8; 4], mac: [u8; 6], age: u32) -> UpsertOutcome {
58 if ip == [0, 0, 0, 0] || ip == [255, 255, 255, 255] {
61 return UpsertOutcome::Ignored;
62 }
63 if table.is_empty() {
64 return UpsertOutcome::Ignored;
65 }
66
67 for e in table.iter_mut() {
69 if e.valid && e.ip == ip {
70 e.mac = mac;
71 e.age = age;
72 return UpsertOutcome::Updated;
73 }
74 }
75
76 for e in table.iter_mut() {
78 if !e.valid {
79 *e = ArpEntry {
80 valid: true,
81 ip,
82 mac,
83 age,
84 };
85 return UpsertOutcome::Inserted;
86 }
87 }
88
89 let mut oldest_idx = 0usize;
91 let mut oldest_age = table[0].age;
92 for (i, e) in table.iter().enumerate().skip(1) {
93 if e.age < oldest_age {
94 oldest_age = e.age;
95 oldest_idx = i;
96 }
97 }
98 table[oldest_idx] = ArpEntry {
99 valid: true,
100 ip,
101 mac,
102 age,
103 };
104 UpsertOutcome::Evicted
105}
106
107#[derive(Copy, Clone, PartialEq, Eq, Debug)]
113pub struct NegativeCache {
114 pub ip: [u8; 4],
115 pub until_ms: u64,
116}
117
118impl NegativeCache {
119 pub const fn empty() -> Self {
120 Self {
121 ip: [0; 4],
122 until_ms: 0,
123 }
124 }
125
126 pub fn should_skip(&self, ip: [u8; 4], now_ms: u64) -> bool {
128 self.ip == ip && now_ms < self.until_ms
129 }
130
131 pub fn record_failure(&mut self, ip: [u8; 4], now_ms: u64, ttl_ms: u64) {
132 self.ip = ip;
133 self.until_ms = now_ms.saturating_add(ttl_ms);
134 }
135
136 pub fn clear_if_matches(&mut self, ip: [u8; 4]) {
139 if self.ip == ip {
140 self.ip = [0; 4];
141 self.until_ms = 0;
142 }
143 }
144}