parent
5185a105c3
commit
1ce91fc206
|
@ -613,6 +613,7 @@ where
|
|||
/// This function panics if any of the addresses are not unicast.
|
||||
pub fn update_ip_addrs<F: FnOnce(&mut ManagedSlice<'a, IpCidr>)>(&mut self, f: F) {
|
||||
f(&mut self.inner.ip_addrs);
|
||||
InterfaceInner::flush_cache(&mut self.inner);
|
||||
InterfaceInner::check_ip_addrs(&self.inner.ip_addrs)
|
||||
}
|
||||
|
||||
|
@ -2225,6 +2226,12 @@ impl<'a> InterfaceInner<'a> {
|
|||
Err(Error::Unaddressable)
|
||||
}
|
||||
|
||||
fn flush_cache(&mut self) {
|
||||
if let Some(cache) = self.neighbor_cache.as_mut() {
|
||||
cache.flush()
|
||||
}
|
||||
}
|
||||
|
||||
fn dispatch_ip<Tx: TxToken>(
|
||||
&mut self,
|
||||
cx: &Context,
|
||||
|
@ -3313,6 +3320,76 @@ mod test {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(feature = "medium-ethernet", feature = "proto-ipv4"))]
|
||||
fn test_arp_flush_after_update_ip() {
|
||||
let (mut iface, mut socket_set) = create_loopback_ethernet();
|
||||
|
||||
let mut eth_bytes = vec![0u8; 42];
|
||||
|
||||
let local_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x01]);
|
||||
let remote_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x02]);
|
||||
let local_hw_addr = EthernetAddress([0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
||||
let remote_hw_addr = EthernetAddress([0x52, 0x54, 0x00, 0x00, 0x00, 0x00]);
|
||||
|
||||
let repr = ArpRepr::EthernetIpv4 {
|
||||
operation: ArpOperation::Request,
|
||||
source_hardware_addr: remote_hw_addr,
|
||||
source_protocol_addr: remote_ip_addr,
|
||||
target_hardware_addr: EthernetAddress::default(),
|
||||
target_protocol_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
|
||||
};
|
||||
|
||||
let mut frame = EthernetFrame::new_unchecked(&mut eth_bytes);
|
||||
frame.set_dst_addr(EthernetAddress::BROADCAST);
|
||||
frame.set_src_addr(remote_hw_addr);
|
||||
frame.set_ethertype(EthernetProtocol::Arp);
|
||||
{
|
||||
let mut packet = ArpPacket::new_unchecked(frame.payload_mut());
|
||||
repr.emit(&mut packet);
|
||||
}
|
||||
|
||||
let cx = iface.context(Instant::from_secs(0));
|
||||
|
||||
// Ensure an ARP Request for us triggers an ARP Reply
|
||||
assert_eq!(
|
||||
iface
|
||||
.inner
|
||||
.process_ethernet(&cx, &mut socket_set, frame.into_inner()),
|
||||
Ok(Some(EthernetPacket::Arp(ArpRepr::EthernetIpv4 {
|
||||
operation: ArpOperation::Reply,
|
||||
source_hardware_addr: local_hw_addr,
|
||||
source_protocol_addr: local_ip_addr,
|
||||
target_hardware_addr: remote_hw_addr,
|
||||
target_protocol_addr: remote_ip_addr
|
||||
})))
|
||||
);
|
||||
|
||||
// Ensure the address of the requestor was entered in the cache
|
||||
assert_eq!(
|
||||
iface.inner.lookup_hardware_addr(
|
||||
&cx,
|
||||
MockTxToken,
|
||||
&IpAddress::Ipv4(local_ip_addr),
|
||||
&IpAddress::Ipv4(remote_ip_addr)
|
||||
),
|
||||
Ok((HardwareAddress::Ethernet(remote_hw_addr), MockTxToken))
|
||||
);
|
||||
|
||||
// Update IP addrs to trigger ARP cache flush
|
||||
let local_ip_addr_new = Ipv4Address([0x7f, 0x00, 0x00, 0x01]);
|
||||
iface.update_ip_addrs(|addrs| {
|
||||
addrs.iter_mut().next().map(|addr| {
|
||||
*addr = IpCidr::Ipv4(Ipv4Cidr::new(local_ip_addr_new, 24));
|
||||
});
|
||||
});
|
||||
|
||||
// ARP cache flush after address change
|
||||
assert!(!iface
|
||||
.inner
|
||||
.has_neighbor(&cx, &IpAddress::Ipv4(remote_ip_addr)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(feature = "socket-icmp", feature = "proto-ipv4"))]
|
||||
fn test_icmpv4_socket() {
|
||||
|
|
|
@ -218,6 +218,10 @@ impl<'a> Cache<'a> {
|
|||
pub(crate) fn limit_rate(&mut self, timestamp: Instant) {
|
||||
self.silent_until = timestamp + Self::SILENT_TIME;
|
||||
}
|
||||
|
||||
pub(crate) fn flush(&mut self) {
|
||||
self.storage.clear()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -370,4 +374,27 @@ mod test {
|
|||
Answer::NotFound
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_flush() {
|
||||
let mut cache_storage = [Default::default(); 3];
|
||||
let mut cache = Cache::new(&mut cache_storage[..]);
|
||||
|
||||
cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0));
|
||||
assert_eq!(
|
||||
cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
|
||||
Answer::Found(HADDR_A)
|
||||
);
|
||||
assert!(!cache
|
||||
.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0))
|
||||
.found());
|
||||
|
||||
cache.flush();
|
||||
assert!(!cache
|
||||
.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0))
|
||||
.found());
|
||||
assert!(!cache
|
||||
.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0))
|
||||
.found());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue