Skip to content

Commit 6e66652

Browse files
Light up multicast_drop counter in dpd/swadm (#89)
Closes: * #86 Includes: * Update packet-test.sh to list expected counters with `swadm` * Remove redundant drop_counter in Filter control
1 parent ab1dc8b commit 6e66652

File tree

5 files changed

+132
-7
lines changed

5 files changed

+132
-7
lines changed

.github/buildomat/jobs/packet-test.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,21 @@ banner "Links"
9494

9595
./target/debug/swadm -h '[::1]' link ls || echo "failed to list links"
9696

97+
banner "swadm Checks"
98+
99+
pushd swadm
100+
101+
DENDRITE_TEST_HOST='[::1]' \
102+
DENDRITE_TEST_VERBOSITY=3 \
103+
cargo test \
104+
--no-fail-fast \
105+
--test \
106+
counters \
107+
-- \
108+
--ignored
109+
110+
popd
111+
97112
banner "Packet Tests"
98113

99114
set +o errexit

dpd-client/tests/integration_tests/mcast.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,6 +1409,14 @@ async fn test_ipv4_multicast_invalid_destination_mac() -> TestResult {
14091409
.await
14101410
.unwrap();
14111411

1412+
let port_label_ingress = switch.port_label(ingress).unwrap();
1413+
1414+
// Check the Multicast_Drop counter baseline for the ingress port
1415+
let drop_mcast_baseline = switch
1416+
.get_counter(&port_label_ingress, Some("multicast_drop"))
1417+
.await
1418+
.unwrap();
1419+
14121420
let result = switch.packet_test(vec![test_pkt], expected_pkts);
14131421

14141422
check_counter_incremented(
@@ -1421,6 +1429,17 @@ async fn test_ipv4_multicast_invalid_destination_mac() -> TestResult {
14211429
.await
14221430
.unwrap();
14231431

1432+
// Verify that the Filter_Drop_Multicast counter also incremented
1433+
check_counter_incremented(
1434+
switch,
1435+
&port_label_ingress,
1436+
drop_mcast_baseline,
1437+
1,
1438+
Some("multicast_drop"),
1439+
)
1440+
.await
1441+
.unwrap();
1442+
14241443
// Cleanup: Remove both external IPv4 group and underlay IPv6 group
14251444
cleanup_test_group(switch, created_group.group_ip).await;
14261445
cleanup_test_group(switch, internal_multicast_ip).await;
@@ -1486,6 +1505,14 @@ async fn test_ipv6_multicast_invalid_destination_mac() -> TestResult {
14861505
.await
14871506
.unwrap();
14881507

1508+
let port_label_ingress = switch.port_label(ingress).unwrap();
1509+
1510+
// Check the Multicast_Drop counter baseline for the ingress port
1511+
let drop_mcast_baseline = switch
1512+
.get_counter(&port_label_ingress, Some("multicast_drop"))
1513+
.await
1514+
.unwrap();
1515+
14891516
let result = switch.packet_test(vec![test_pkt], expected_pkts);
14901517

14911518
check_counter_incremented(
@@ -1498,6 +1525,17 @@ async fn test_ipv6_multicast_invalid_destination_mac() -> TestResult {
14981525
.await
14991526
.unwrap();
15001527

1528+
// Verify that the Multicast_Drop counter also incremented
1529+
check_counter_incremented(
1530+
switch,
1531+
&port_label_ingress,
1532+
drop_mcast_baseline,
1533+
1,
1534+
Some("multicast_drop"),
1535+
)
1536+
.await
1537+
.unwrap();
1538+
15011539
cleanup_test_group(switch, created_group.group_ip).await;
15021540

15031541
result

dpd/p4/sidecar.p4

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ control Filter(
107107
DirectCounter<bit<32>>(CounterType_t.PACKETS_AND_BYTES) ipv4_ctr;
108108
DirectCounter<bit<32>>(CounterType_t.PACKETS_AND_BYTES) ipv6_ctr;
109109
Counter<bit<32>, PortId_t>(512, CounterType_t.PACKETS) drop_mcast_ctr;
110-
Counter<bit<32>, bit<8>>(DROP_REASON_MAX, CounterType_t.PACKETS) drop_reason_ctr;
111110
bit<16> mcast_scope;
112111

113112
action dropv4() {
@@ -184,7 +183,6 @@ control Filter(
184183
if (meta.is_mcast && !meta.is_valid) {
185184
drop_mcast();
186185
drop_mcast_ctr.count(ig_intr_md.ingress_port);
187-
drop_reason_ctr.count(meta.drop_reason);
188186
return;
189187
} else if (meta.is_mcast && meta.is_valid) {
190188
// IPv4 Multicast Address Validation (RFC 1112, RFC 7042)
@@ -223,7 +221,6 @@ control Filter(
223221
if (meta.is_mcast && !meta.is_valid) {
224222
drop_mcast();
225223
drop_mcast_ctr.count(ig_intr_md.ingress_port);
226-
drop_reason_ctr.count(meta.drop_reason);
227224
return;
228225
} else if (meta.is_mcast && meta.is_valid) {
229226
// Validate the IPv6 multicast MAC address format (RFC 2464,
@@ -240,7 +237,6 @@ control Filter(
240237
hdr.ethernet.dst_mac[39:32] != 8w0x33) {
241238
drop_mcast_with_reason(DROP_MULTICAST_INVALID_MAC);
242239
drop_mcast_ctr.count(ig_intr_md.ingress_port);
243-
drop_reason_ctr.count(meta.drop_reason);
244240
return;
245241
}
246242

@@ -255,7 +251,6 @@ control Filter(
255251
hdr.ethernet.dst_mac[7:0] != hdr.ipv6.dst_addr[7:0]) {
256252
drop_mcast_with_reason(DROP_MULTICAST_INVALID_MAC);
257253
drop_mcast_ctr.count(ig_intr_md.ingress_port);
258-
drop_reason_ctr.count(meta.drop_reason);
259254
return;
260255
}
261256
}

dpd/src/counters.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ enum CounterId {
6262
MulticastExt,
6363
MulticastLL,
6464
MulticastUL,
65+
MulticastDrop,
6566
}
6667

6768
impl From<CounterId> for u8 {
@@ -84,7 +85,7 @@ struct CounterDescription {
8485
p4_name: &'static str,
8586
}
8687

87-
const COUNTERS: [CounterDescription; 13] = [
88+
const COUNTERS: [CounterDescription; 14] = [
8889
CounterDescription {
8990
id: CounterId::Service,
9091
client_name: "Service",
@@ -150,6 +151,11 @@ const COUNTERS: [CounterDescription; 13] = [
150151
client_name: "Multicast_Underlay",
151152
p4_name: "pipe.Egress.underlay_mcast_ctr",
152153
},
154+
CounterDescription {
155+
id: CounterId::MulticastDrop,
156+
client_name: "Multicast_Drop",
157+
p4_name: "pipe.Ingress.filter.drop_mcast_ctr",
158+
},
153159
];
154160

155161
/// Get the list of names by which end users can refer to a counter.
@@ -416,7 +422,8 @@ pub async fn get_values(
416422
| CounterId::Multicast
417423
| CounterId::MulticastExt
418424
| CounterId::MulticastLL
419-
| CounterId::MulticastUL => port_label(switch, idx.idx).await,
425+
| CounterId::MulticastUL
426+
| CounterId::MulticastDrop => port_label(switch, idx.idx).await,
420427
CounterId::DropReason | CounterId::EgressDropReason => {
421428
reason_label(idx.idx as u8)?
422429
}

swadm/tests/counters.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at https://mozilla.org/MPL/2.0/
4+
//
5+
// Copyright 2025 Oxide Computer Company
6+
7+
//! Integration test for swadm P4 counter functionality.
8+
9+
use std::process::Command;
10+
11+
// Path to `swadm` executable.
12+
const SWADM: &str = env!("CARGO_BIN_EXE_swadm");
13+
14+
fn swadm() -> Command {
15+
Command::new(SWADM)
16+
}
17+
18+
#[test]
19+
#[ignore]
20+
fn test_p4_counter_list() {
21+
let output = swadm()
22+
.arg("-h")
23+
.arg("[::1]")
24+
.arg("counters")
25+
.arg("list")
26+
.output()
27+
.expect("Failed to execute swadm counters list");
28+
29+
assert!(
30+
output.status.success(),
31+
"swadm counters list failed with stderr: {}",
32+
String::from_utf8_lossy(&output.stderr)
33+
);
34+
35+
let stdout = String::from_utf8_lossy(&output.stdout);
36+
37+
// Verify output is not empty and contains expected counter information
38+
assert!(
39+
!stdout.is_empty(),
40+
"Counter list output should not be empty"
41+
);
42+
43+
// Expected P4 counters from dpd/src/counters.rs COUNTERS array
44+
let expected_counters = [
45+
"Service",
46+
"Ingress",
47+
"Packet",
48+
"Egress",
49+
"Ingress_Drop_Port",
50+
"Ingress_Drop_Reason",
51+
"Egress_Drop_Port",
52+
"Egress_Drop_Reason",
53+
"Unicast",
54+
"Multicast",
55+
"Multicast_External",
56+
"Multicast_Link_Local",
57+
"Multicast_Underlay",
58+
"Multicast_Drop",
59+
];
60+
61+
// Verify all expected counters are present in the output
62+
for counter in &expected_counters {
63+
assert!(
64+
stdout.contains(counter),
65+
"Counter list should contain '{}' counter. Output: {}",
66+
counter,
67+
stdout
68+
);
69+
}
70+
}

0 commit comments

Comments
 (0)