Skip to content
Merged
580 changes: 535 additions & 45 deletions dpd-client/tests/integration_tests/mcast.rs

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion dpd-client/tests/integration_tests/table_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//
// Copyright 2026 Oxide Computer Company

#[cfg(feature = "multicast")]
use std::net::IpAddr;
use std::net::Ipv4Addr;
use std::net::Ipv6Addr;
Expand Down Expand Up @@ -41,8 +42,11 @@ use crate::integration_tests::common::prelude::*;
// investigating. If it only changes by an entry or two, it's fine to just
// adjust the constant below to match the observed result.
//
// TODO: Multicast drops IPv4 LPM capacity to 7164 (from 8187) due to
// ingress TCAM pressure. Investigate moving MulticastRouter4/6 into the
// egress pipeline to reclaim capacity.
#[cfg(feature = "multicast")]
const IPV4_LPM_SIZE: usize = 8175; // ipv4 forwarding table
const IPV4_LPM_SIZE: usize = 7164; // ipv4 forwarding table
#[cfg(not(feature = "multicast"))]
const IPV4_LPM_SIZE: usize = 8187; // ipv4 forwarding table

Expand Down
34 changes: 26 additions & 8 deletions dpd/p4/sidecar.p4
Original file line number Diff line number Diff line change
Expand Up @@ -608,8 +608,17 @@ control NatIngress (
}

// Separate table for IPv4 multicast packets that need to be encapsulated.
//
// Each group has a single entry keyed on (dst_addr, vlan_valid, vlan_id).
// Groups with a VLAN match on (addr, true, vlan_id). Groups without VLAN
// match on (addr, false, 0). Packets with the wrong VLAN miss and are
// not NAT encapsulated.
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 @@ -625,9 +634,14 @@ control NatIngress (
mcast_ipv6_ingress_ctr.count();
}

// Separate table for IPv6 multicast packets that need to be encapsulated.
// IPv6 counterpart of ingress_ipv4_mcast for IPv6 packets that need to be
// encapsulated. See ingress_ipv4_mcast for details on VLAN matching.
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 @@ -1330,15 +1344,17 @@ 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();
}

if (!tbl.apply().hit) {
icmp_error(ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE);
meta.drop_reason = DROP_IPV6_UNROUTEABLE;
icmp_error(ICMP_DEST_UNREACH, ICMP_DST_UNREACH_NET);
meta.drop_reason = DROP_IPV4_UNROUTEABLE;
// Dont set meta.dropped because we want an error packet
// to go out.
} else if (hdr.ipv4.ttl == 1 && !meta.service_routed) {
Expand Down Expand Up @@ -1470,7 +1486,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 Expand Up @@ -1564,7 +1582,7 @@ control EgressFilter(
egress_filter.apply();
}
}

control MacRewrite(
inout sidecar_headers_t hdr,
in PortId_t port
Expand Down
Loading