2022-03-02 07:09:06 -08:00
|
|
|
use std::time::Duration;
|
|
|
|
|
|
|
|
enum PacketThresholdUpdate {
|
|
|
|
Increase,
|
|
|
|
Decrease,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PacketThresholdUpdate {
|
|
|
|
const PERCENTAGE: usize = 90;
|
|
|
|
|
|
|
|
fn calculate(&self, current: usize) -> usize {
|
|
|
|
match *self {
|
|
|
|
PacketThresholdUpdate::Increase => {
|
|
|
|
current.saturating_mul(100).saturating_div(Self::PERCENTAGE)
|
|
|
|
}
|
|
|
|
PacketThresholdUpdate::Decrease => {
|
|
|
|
current.saturating_mul(Self::PERCENTAGE).saturating_div(100)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct DynamicPacketToProcessThreshold {
|
|
|
|
max_packets: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for DynamicPacketToProcessThreshold {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
max_packets: Self::DEFAULT_MAX_PACKETS,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DynamicPacketToProcessThreshold {
|
|
|
|
const DEFAULT_MAX_PACKETS: usize = 1024;
|
|
|
|
const TIME_THRESHOLD: Duration = Duration::from_secs(1);
|
|
|
|
|
|
|
|
pub fn update(&mut self, total_packets: usize, compute_time: Duration) {
|
|
|
|
if total_packets >= self.max_packets {
|
|
|
|
let threshold_update = if compute_time > Self::TIME_THRESHOLD {
|
|
|
|
PacketThresholdUpdate::Decrease
|
|
|
|
} else {
|
|
|
|
PacketThresholdUpdate::Increase
|
|
|
|
};
|
|
|
|
self.max_packets = threshold_update.calculate(self.max_packets);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn should_drop(&self, total: usize) -> bool {
|
|
|
|
total >= self.max_packets
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
2022-03-02 09:54:58 -08:00
|
|
|
use {super::DynamicPacketToProcessThreshold, std::time::Duration};
|
2022-03-02 07:09:06 -08:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_dynamic_packet_threshold() {
|
|
|
|
let mut threshold = DynamicPacketToProcessThreshold::default();
|
|
|
|
assert_eq!(
|
|
|
|
threshold.max_packets,
|
|
|
|
DynamicPacketToProcessThreshold::DEFAULT_MAX_PACKETS
|
|
|
|
);
|
|
|
|
|
|
|
|
assert!(!threshold.should_drop(10));
|
|
|
|
assert!(threshold.should_drop(2000));
|
|
|
|
|
|
|
|
let old = threshold.max_packets;
|
|
|
|
|
|
|
|
// Increase
|
|
|
|
let total = 2000;
|
|
|
|
let compute_time = Duration::from_millis(500);
|
|
|
|
threshold.update(total, compute_time);
|
|
|
|
assert!(threshold.max_packets > old);
|
|
|
|
|
|
|
|
// Decrease
|
|
|
|
let compute_time = Duration::from_millis(2000);
|
|
|
|
threshold.update(total, compute_time);
|
|
|
|
assert_eq!(threshold.max_packets, old - 1); // due to rounding error, there is a difference of 1
|
|
|
|
}
|
|
|
|
}
|