Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
75d1edd
[countersyncd]: Harden and optimize HFT IPFIX processing
Pterosaur Sep 2, 2026
2690ebf
Merge remote-tracking branch 'upstream/master' into fix/countersyncd-…
Pterosaur Sep 2, 2026
3107c2e
[countersyncd]: Address HFT IPFIX review feedback
Pterosaur Sep 3, 2026
b28d2ac
[countersyncd]: Address remaining IPFIX review feedback
Pterosaur Sep 4, 2026
998c8b7
[countersyncd]: Make IPFIX baseline patch reproducible
Pterosaur Sep 4, 2026
afda9b2
[countersyncd]: Close remaining IPFIX lifecycle gaps
Pterosaur Sep 4, 2026
2aae93e
[countersyncd]: Decode template-defined counter widths
Pterosaur Sep 4, 2026
2aa5c7a
[countersyncd]: Unify variable-width counter decoding
Pterosaur Sep 4, 2026
bff4dc8
[countersyncd]: Fix HFT restart and batch boundaries
Pterosaur Sep 5, 2026
7fe62d9
[countersyncd]: Remove counter count admission limit
Pterosaur Sep 5, 2026
49a864a
[countersyncd]: Fence rejected keys and harden restart arbitration
Pterosaur Sep 5, 2026
e7b9a85
[countersyncd]: Remove redundant IPFIX lifecycle paths
Pterosaur Sep 5, 2026
f102104
[countersyncd]: Reconcile capacity failures and deferred delivery
Pterosaur Sep 5, 2026
48c1992
[countersyncd]: Preserve deferred peers and unrelated batching
Pterosaur Sep 5, 2026
2adb313
[countersyncd]: Recheck deferred readiness after preflush
Pterosaur Sep 5, 2026
8288650
[countersyncd]: Reclaim retired deferred sets behind barriers
Pterosaur Sep 5, 2026
67d0747
[countersyncd]: Reclaim deferred data and preserve shutdown causes
Pterosaur Sep 5, 2026
3da4c1f
[countersyncd]: Simplify best-effort template lifecycle
Pterosaur Sep 5, 2026
72c143b
[countersyncd]: Switch session snapshots and isolate malformed Redis …
Pterosaur Sep 5, 2026
43552db
[countersyncd]: Reset reconciled owners after lost Redis notifications
Pterosaur Sep 5, 2026
a1e328e
[countersyncd]: Preserve incumbent ownership during reconciliation
Pterosaur Sep 5, 2026
d614a46
[countersyncd]: Preserve table-relative session identities
Pterosaur Sep 5, 2026
5794633
[countersyncd]: Express message and reconciliation invariants in types
Pterosaur Sep 5, 2026
229e2b2
[countersyncd]: Remove PR-specific review artifacts
Pterosaur Sep 5, 2026
2d09793
[countersyncd]: Drop out-of-scope OTel failure arbitration
Pterosaur Sep 5, 2026
07dc30d
[countersyncd]: Keep actor failure policy outside decoder refactor
Pterosaur Sep 5, 2026
fb9984f
[countersyncd]: Decode hardware HFT timestamp and placeholder fields
Pterosaur Sep 6, 2026
f44df29
[countersyncd]: Restore OTel input queue default to 1024
Pterosaur Sep 6, 2026
cc41bc5
[countersyncd]: Prefer observed packet time before system fallback
Pterosaur Sep 6, 2026
4560323
[countersyncd]: Rate limit malformed IPFIX input warnings
Pterosaur Sep 6, 2026
51e3a58
[countersyncd]: Remove WRONGTYPE reconciliation machinery
Pterosaur Sep 6, 2026
3822498
[countersyncd]: Size template admission for future queue scale
Pterosaur Sep 6, 2026
2e9ede3
[countersyncd]: Admit future-scale IPFIX aggregates
Pterosaur Sep 6, 2026
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
180 changes: 28 additions & 152 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 1 addition & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,8 @@ netlink-packet-generic = "0.3"
netlink-packet-utils = "0.5"
netlink-sys = "0.8"

# IPFIX parser for traffic flow analysis
ipfixrw = "0.1.0"
# IPFIX/HFT wire decoding
ahash = "0.8.11"
binrw = "0.15.0"
byteorder = "1.5.0"

# Configuration and serialization
Expand All @@ -59,7 +57,6 @@ clap = { version = "4", features = ["derive", "cargo", "wrap_help", "unicode", "
color-eyre = "0.6"

# Utilities
rand = "0.8.5"
once_cell = "1.18.0"
lazy_static = "1.4"
regex = "1"
Expand Down
5 changes: 1 addition & 4 deletions crates/countersyncd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,8 @@ netlink-packet-utils = { workspace = true }
netlink-sys = { workspace = true }
libc = "0.2"

# IPFIX parser for traffic flow analysis
ipfixrw = { workspace = true }
# IPFIX/HFT wire decoding
ahash = { workspace = true }
binrw = { workspace = true }
byteorder = { workspace = true }

# Logging and error handling
Expand All @@ -39,7 +37,6 @@ env_logger = { workspace = true }
chrono = { workspace = true }

# Utilities
rand = { workspace = true }
once_cell = { workspace = true }

# Command line utilities
Expand Down
68 changes: 42 additions & 26 deletions crates/countersyncd/benches/counter_db_actor_perf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,36 @@ use tokio::runtime::Builder;
use tokio::sync::mpsc;

use countersyncd::actor::counter_db::{CounterDBActor, CounterDBConfig};
use countersyncd::message::saistats::{SAIStat, SAIStats, SAIStatsMessage};
use countersyncd::message::saistats::{SAIStat, SAIStatsBatch, SAIStatsBatchMessage};
use countersyncd::sai::saitypes::SaiObjectType;
use swss_common::{CxxString, DbConnector};

mod ipfix_bench_data;
use ipfix_bench_data::{PreparedDataset, datasets};
use ipfix_bench_data::{datasets, PreparedDataset};

const COUNTERS_DB_ID: i32 = 2;
const SOCK_PATH: &str = "/var/run/redis/redis.sock";

fn build_stats_message(count: usize, seq: u64) -> SAIStatsMessage {
fn build_stats_batch(count: usize, start_seq: usize, records: usize) -> SAIStatsBatchMessage {
let type_id = SaiObjectType::Port.to_u32();

let stats = (0..count)
.map(|idx| SAIStat {
object_name: format!("Ethernet{}", idx % 16),
type_id,
stat_id: (idx % 4) as u32, // Small, valid port stat IDs
counter: seq.wrapping_add(idx as u64),
})
.collect();

std::sync::Arc::new(SAIStats::new(seq, stats))
let mut batch = SAIStatsBatch::with_capacity(records, count * records);
for seq in start_seq..start_seq + records {
batch.push_record(
seq as u64,
(0..count).map(|idx| SAIStat {
object_name: format!("Ethernet{}", idx % 16).into(),
type_id,
stat_id: (idx % 4) as u32, // Small, valid port stat IDs
counter: (seq as u64).wrapping_add(idx as u64),
}),
);
}
std::sync::Arc::new(batch)
}

fn seed_port_name_map(port_count: usize) {
let db = DbConnector::new_unix(COUNTERS_DB_ID, SOCK_PATH, 0)
.expect("connect counter db for seed");
let db =
DbConnector::new_unix(COUNTERS_DB_ID, SOCK_PATH, 0).expect("connect counter db for seed");

let table = "COUNTERS_PORT_NAME_MAP";
for idx in 0..port_count {
Expand All @@ -58,10 +60,7 @@ fn flush_counters_db() {
.expect("spawn redis-cli for flush");

if !output.status.success() {
panic!(
"redis-cli FLUSHDB failed with status {}",
output.status
);
panic!("redis-cli FLUSHDB failed with status {}", output.status);
}
}

Expand All @@ -79,14 +78,31 @@ async fn run_stream(prepared: PreparedDataset) -> (Duration, usize) {
let start = std::time::Instant::now();

for tmpl in prepared.templates.iter() {
for msg_idx in 0..tmpl.records {
let msg = build_stats_message(tmpl.spec.counters, msg_idx as u64);
let _ = tx.send(msg).await;
const RECORDS_PER_BATCH: usize = 64;
let full_batches = tmpl.records / RECORDS_PER_BATCH;
for batch_idx in 0..full_batches {
tx.send(build_stats_batch(
tmpl.spec.counters,
batch_idx * RECORDS_PER_BATCH,
RECORDS_PER_BATCH,
))
.await
.expect("send stats batch");
}
let remaining = tmpl.records % RECORDS_PER_BATCH;
if remaining > 0 {
tx.send(build_stats_batch(
tmpl.spec.counters,
full_batches * RECORDS_PER_BATCH,
remaining,
))
.await
.expect("send final stats batch");
}
}

drop(tx);
let _ = handle.await;
handle.await.expect("CounterDB actor should join");

(start.elapsed(), total_counters)
}
Expand All @@ -106,7 +122,7 @@ fn bench_counter_db_actor(c: &mut Criterion) {

for spec in datasets() {
group.throughput(Throughput::Elements(
spec.total_counters_per_iteration() as u64,
spec.total_counters_per_iteration() as u64
));

let bench_id = BenchmarkId::from_parameter(spec.name);
Expand Down Expand Up @@ -145,4 +161,4 @@ fn bench_counter_db_actor(c: &mut Criterion) {
}

criterion_group!(benches, bench_counter_db_actor);
criterion_main!(benches);
criterion_main!(benches);
Loading
Loading