浏览代码

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.
Thales Fragoso 4 年之前
父节点
当前提交
3bd6bc03a1
共有 2 个文件被更改,包括 11 次插入7 次删除
  1. 4 5
      src/iface/ethernet.rs
  2. 7 2
      src/iface/neighbor.rs

+ 4 - 5
src/iface/ethernet.rs

@@ -1618,8 +1618,6 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
 
 
                     arp_repr.emit(&mut ArpPacket::new_unchecked(frame.payload_mut()))
                     arp_repr.emit(&mut ArpPacket::new_unchecked(frame.payload_mut()))
                 })?;
                 })?;
-
-                Err(Error::Unaddressable)
             }
             }
 
 
             #[cfg(feature = "proto-ipv6")]
             #[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(),
                     solicit.emit(&ip_repr.src_addr(), &ip_repr.dst_addr(),
                                  &mut Icmpv6Packet::new_unchecked(payload), &checksum_caps);
                                  &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,
     fn dispatch_ip<Tx, F>(&mut self, tx_token: Tx, timestamp: Instant,

+ 7 - 2
src/iface/neighbor.rs

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