Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
415 changes: 394 additions & 21 deletions dpd-client/tests/integration_tests/mcast.rs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dpd-client/tests/integration_tests/table_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const ADMIN_LOCAL_PREFIX: u16 = 0xFF04;
// investigating. If it only changes by an entry or two, it's fine to just
// adjust the constant below to match the observed result.
//
const IPV4_LPM_SIZE: usize = 8182; // ipv4 forwarding table
const IPV4_LPM_SIZE: usize = 8188; // ipv4 forwarding table
const IPV6_LPM_SIZE: usize = 1023; // ipv6 forwarding table
const SWITCH_IPV4_ADDRS_SIZE: usize = 511; // ipv4 addrs assigned to our ports
const SWITCH_IPV6_ADDRS_SIZE: usize = 511; // ipv6 addrs assigned to our ports
Expand Down
28 changes: 24 additions & 4 deletions dpd/p4/sidecar.p4
Original file line number Diff line number Diff line change
Expand Up @@ -612,8 +612,16 @@ control NatIngress (
}

// Separate table for IPv4 multicast packets that need to be encapsulated.
// Groups without VLAN match untagged only. Groups with VLAN match both
// untagged (for decapsulated Geneve from underlay) and correctly tagged.
// Packets with wrong VLAN miss and are not NAT encapsulated.
// When hdr.vlan.isValid()==false, vlan_id matches as 0.
table ingress_ipv4_mcast {
key = { hdr.ipv4.dst_addr : exact; }
key = {
hdr.ipv4.dst_addr : exact;
hdr.vlan.isValid() : exact;
hdr.vlan.vlan_id : exact;
}
actions = { mcast_forward_ipv4_to; }
const size = IPV4_MULTICAST_TABLE_SIZE;
counters = mcast_ipv4_ingress_ctr;
Expand All @@ -630,8 +638,16 @@ control NatIngress (
}

// Separate table for IPv6 multicast packets that need to be encapsulated.
// Groups without VLAN match untagged only. Groups with VLAN match both
// untagged (for decapsulated Geneve from underlay) and correctly tagged.
// Packets with wrong VLAN miss and are not NAT encapsulated.
// When hdr.vlan.isValid()==false, vlan_id matches as 0.
table ingress_ipv6_mcast {
key = { hdr.ipv6.dst_addr : exact; }
key = {
hdr.ipv6.dst_addr : exact;
hdr.vlan.isValid() : exact;
hdr.vlan.vlan_id : exact;
}
actions = { mcast_forward_ipv6_to; }
const size = IPV6_MULTICAST_TABLE_SIZE;
counters = mcast_ipv6_ingress_ctr;
Expand Down Expand Up @@ -1311,7 +1327,9 @@ control MulticastRouter4(
apply {
// If the packet came in with a VLAN tag, we need to invalidate
// the VLAN header before we do the lookup. The VLAN header
// will be re-attached if set in the forward_vlan action.
// will be re-attached if set in the forward_vlan action (or
// untagged for groups without VLAN). This prevents unintended
// VLAN translation.
if (hdr.vlan.isValid()) {
hdr.ethernet.ether_type = hdr.vlan.ether_type;
hdr.vlan.setInvalid();
Expand Down Expand Up @@ -1449,7 +1467,9 @@ control MulticastRouter6 (
apply {
// If the packet came in with a VLAN tag, we need to invalidate
// the VLAN header before we do the lookup. The VLAN header
// will be re-attached if set in the forward_vlan action.
// will be re-attached if set in the forward_vlan action (or
// untagged for groups without VLAN). This prevents unintended
// VLAN translation.
if (hdr.vlan.isValid()) {
hdr.ethernet.ether_type = hdr.vlan.ether_type;
hdr.vlan.setInvalid();
Expand Down
9 changes: 6 additions & 3 deletions dpd/src/counters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/
//
// Copyright 2025 Oxide Computer Company
// Copyright 2026 Oxide Computer Company

/// This module contains the support for reading the indirect counters defined
/// by the p4 program. While direct counters are attached to an existing table,
Expand Down Expand Up @@ -284,6 +284,7 @@ enum DropReason {
GeneveOptionsTooLong,
GeneveOptionMalformed,
GeneveOptionUnknown,
VlanMismatch,
}

impl TryFrom<u8> for DropReason {
Expand Down Expand Up @@ -317,6 +318,7 @@ impl TryFrom<u8> for DropReason {
23 => Ok(DropReason::GeneveOptionsTooLong),
24 => Ok(DropReason::GeneveOptionMalformed),
25 => Ok(DropReason::GeneveOptionUnknown),
26 => Ok(DropReason::VlanMismatch),
x => Err(format!("Unrecognized drop reason: {x}")),
}
}
Expand All @@ -343,8 +345,8 @@ fn reason_label(ctr: u8) -> Result<Option<String>, String> {
DropReason::Ipv4TtlExceeded => "ipv4_ttl_exceeded".to_string(),
DropReason::Ipv6TtlInvalid => "ipv6_ttl_invalid".to_string(),
DropReason::Ipv6TtlExceeded => "ipv6_ttl_exceeded".to_string(),
DropReason::Ipv4Unrouteable => "ipv6_unrouteable".to_string(),
DropReason::Ipv6Unrouteable => "ipv4_unrouteable".to_string(),
DropReason::Ipv4Unrouteable => "ipv4_unrouteable".to_string(),
DropReason::Ipv6Unrouteable => "ipv6_unrouteable".to_string(),
DropReason::NatIngressMiss => "nat_ingress_miss".to_string(),
DropReason::MulticastNoGroup => "multicast_no_group".to_string(),
DropReason::MulticastInvalidMac => "multicast_invalid_mac".to_string(),
Expand All @@ -362,6 +364,7 @@ fn reason_label(ctr: u8) -> Result<Option<String>, String> {
"geneve_option_malformed".to_string()
}
DropReason::GeneveOptionUnknown => "geneve_option_unknown".to_string(),
DropReason::VlanMismatch => "vlan_mismatch".to_string(),
};
Ok(Some(label))
}
Expand Down
Loading