Only limit the neighbor cache rate after sending a request packet

Prior to this change, the neighbor cache would get limited even when the
device failed to process our arp packet, which could put the socket in
the waiting state in the next poll.

This change only limits the cache rate if the device successfully
consumed our packet.
v0.7.x
Thales Fragoso 2020-08-11 21:37:08 -03:00 committed by whitequark
parent 11e97f3a06
commit 1e5de8d42c
2 changed files with 11 additions and 7 deletions

View File

@ -1618,8 +1618,6 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
arp_repr.emit(&mut ArpPacket::new_unchecked(frame.payload_mut()))
})?;
Err(Error::Unaddressable)
}
#[cfg(feature = "proto-ipv6")]
@ -1646,12 +1644,13 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
solicit.emit(&ip_repr.src_addr(), &ip_repr.dst_addr(),
&mut Icmpv6Packet::new_unchecked(payload), &checksum_caps);
})?;
Err(Error::Unaddressable)
}
_ => Err(Error::Unaddressable)
_ => ()
}
// The request got dispatched, limit the rate on the cache.
self.neighbor_cache.limit_rate(timestamp);
Err(Error::Unaddressable)
}
fn dispatch_ip<Tx, F>(&mut self, tx_token: Tx, timestamp: Instant,

View File

@ -172,18 +172,21 @@ impl<'a> Cache<'a> {
None
}
pub(crate) fn lookup(&mut self, protocol_addr: &IpAddress, timestamp: Instant) -> Answer {
pub(crate) fn lookup(&self, protocol_addr: &IpAddress, timestamp: Instant) -> Answer {
match self.lookup_pure(protocol_addr, timestamp) {
Some(hardware_addr) =>
Answer::Found(hardware_addr),
None if timestamp < self.silent_until =>
Answer::RateLimited,
None => {
self.silent_until = timestamp + Self::SILENT_TIME;
Answer::NotFound
}
}
}
pub(crate) fn limit_rate(&mut self, timestamp: Instant) {
self.silent_until = timestamp + Self::SILENT_TIME;
}
}
#[cfg(test)]
@ -273,6 +276,8 @@ mod test {
let mut cache = Cache::new(&mut cache_storage[..]);
assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)), Answer::NotFound);
cache.limit_rate(Instant::from_millis(0));
assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(100)), Answer::RateLimited);
assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(2000)), Answer::NotFound);
}