Skip to content
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions common/src/counters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ pub use dpd_types::counters::{
FecRSCounters, PcsCounters, RMonCounters, RMonCountersAll,
};

/// Per-port counter label for the userspace service port, which has no link
/// of its own on the current switch.
pub const SERVICE_PORT_LABEL: &str = "service";

/// sidecar.p4 defines the following set of indirect counters.
#[derive(
Debug,
Expand Down
83 changes: 59 additions & 24 deletions dpd-client/tests/integration_tests/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use std::{fmt, thread};

use anyhow::Context;
use anyhow::anyhow;
use anyhow::bail;
use oxnet::Ipv4Net;
use oxnet::Ipv6Net;
use slog::Drain;
Expand Down Expand Up @@ -45,6 +46,13 @@ pub const ADMIN_LOCAL_MULTICAST_PREFIX: u16 = 0xFF04;
// packets before notifying us that any are ready.
const TEST_PCAP_TIMEOUT_MS: i32 = 1;

// Interval and attempt count for polling a counter until it reaches an
// expected value.
//
// Note: counter updates from the model can lag the packet itself.
const COUNTER_POLL_INTERVAL: Duration = Duration::from_millis(100);
const COUNTER_POLL_ATTEMPTS: usize = 20;

// Physical port number
#[derive(Clone, Copy, PartialOrd, Ord, Hash, PartialEq, Eq)]
pub struct PhysPort(pub u16);
Expand Down Expand Up @@ -791,16 +799,10 @@ impl Switch {
}
}

match errors.len() {
0 => Ok(()),
_ => Err(anyhow!(
errors
.iter()
.map(|e| e.to_string())
.collect::<Vec<String>>()
.join(", ")
)),
if !errors.is_empty() {
bail!("{}", errors.join(", "));
}
Ok(())
}

/// If no client_name is given, this returns the number of packets dropped
Expand All @@ -816,26 +818,58 @@ impl Switch {
counter: &str,
client_name: Option<&str>,
) -> anyhow::Result<u64> {
let client_name = if let Some(client_name) = client_name {
client_name.to_string()
} else {
"ingress_drop_reason".to_string()
};
let client_name = client_name.unwrap_or("ingress_drop_reason");

self.client
.counter_get(&client_name, true)
let entries = self
.client
.counter_get(client_name, true)
.await
.map_err(|e| anyhow::anyhow!("failed to fetch counters: {e:?}"))
.and_then(|entries| {
entries
.iter()
.find(|e| e.keys.get("label").unwrap().as_str() == counter)
.map(|e| e.data.pkts.unwrap())
.ok_or(anyhow::anyhow!("no such counter: {counter}"))
})
.map_err(|e| anyhow!("failed to fetch counters: {e:?}"))?;
let Some(entry) = entries
.iter()
.find(|e| e.keys.get("label").unwrap().as_str() == counter)
else {
bail!("no such counter: {counter} in {client_name}");
};
Ok(entry.data.pkts.unwrap())
}
}

pub async fn check_counter_incremented(
switch: &Switch,
counter_name: &str,
baseline: u64,
expected_increment: u64,
client_name: Option<&str>,
) -> anyhow::Result<u64> {
let expected = baseline + expected_increment;
let table = client_name.unwrap_or("ingress_drop_reason");
let incr_expect = format!(
"counter '{counter_name}' in {table} expected to increase by \
{expected_increment} ({baseline} -> {expected})"
);
let mut new_value = 0;

// Poll for the counter value (with timeout)
for _i in 0..COUNTER_POLL_ATTEMPTS {
thread::sleep(COUNTER_POLL_INTERVAL);
new_value = switch.get_counter(counter_name, client_name).await?;

if new_value == expected {
return Ok(new_value);
}
if new_value > expected {
bail!("{incr_expect}, but overshot to {new_value}");
}
}

// Counter didn't increment as expected
bail!(
"{incr_expect}, but reached {new_value} after \
{COUNTER_POLL_ATTEMPTS} polls"
)
}

Comment thread
zeeshanlakhani marked this conversation as resolved.
Resolved
// Construct a single TCP packet with an optional payload
pub fn gen_tcp_packet_loaded(
src: Endpoint,
Expand Down Expand Up @@ -1516,5 +1550,6 @@ pub mod prelude {
pub use super::Switch;
pub use super::TestPacket;
pub use super::TestResult;
pub use super::check_counter_incremented;
pub use super::get_switch;
}
Loading
Loading