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
45 changes: 28 additions & 17 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ members = [
resolver = "2"

[workspace.dependencies]
p4rs = { git = "https://github.com/oxidecomputer/p4", branch = "main" }
p4-macro = { git = "https://github.com/oxidecomputer/p4", branch = "main" }
p4-test = { package = "tests", git = "https://github.com/oxidecomputer/p4", branch = "main" }
p4rs = { git = "https://github.com/oxidecomputer/p4", branch = "zl/multicast" }
p4-macro = { git = "https://github.com/oxidecomputer/p4", branch = "zl/multicast" }
p4-test = { package = "tests", git = "https://github.com/oxidecomputer/p4", branch = "zl/multicast" }
usdt = { git = "https://github.com/oxidecomputer/usdt" }

base64 = { version = "0.22" }
Expand Down
4 changes: 2 additions & 2 deletions p4/headers.p4
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2025 Oxide Computer Company
// Copyright 2026 Oxide Computer Company

header sidecar_h {
bit<8> sc_code;
Expand Down Expand Up @@ -96,7 +96,7 @@ header geneve_opt_h {
}

header oxg_opt_multicast_h {
bit<2> replication;
bit<2> mcast_tag;
bit<30> reserved;
}

Expand Down
37 changes: 36 additions & 1 deletion p4/parser.p4
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2024 Oxide Computer Company
// Copyright 2026 Oxide Computer Company

parser parse(
packet_in pkt,
Expand Down Expand Up @@ -46,6 +46,29 @@ parser parse(

state ipv6 {
pkt.extract(hdr.ipv6);
if (hdr.ipv6.dst[127:120] == 8w0xff) { transition ipv6_mcast; }
transition ipv6_proto;
}

state ipv6_mcast {
// Interface-local (ff01) must not be forwarded.
if (hdr.ipv6.dst[127:112] == 16w0xff01) { transition reject; }

// Link-local (ff02) is forwarded to scrimlet.
// Allow hop_limit == 1 (link-local scope) but still reject expired
// packets.
if (hdr.ipv6.dst[127:112] == 16w0xff02) {
if (hdr.ipv6.hop_limit == 8w0) { transition reject; }
transition ipv6_proto;
}

// Non-link-local multicast requires hop_limit > 1.
if (hdr.ipv6.hop_limit == 8w0) { transition reject; }
if (hdr.ipv6.hop_limit == 8w1) { transition reject; }
transition ipv6_proto;
}

state ipv6_proto {
if (hdr.ipv6.next_hdr == 8w0xdd) { transition ddm; }
if (hdr.ipv6.next_hdr == 8w58) { transition icmp; }
if (hdr.ipv6.next_hdr == 8w17) { transition udp; }
Expand Down Expand Up @@ -82,6 +105,18 @@ parser parse(

state ipv4 {
pkt.extract(hdr.ipv4);
if (hdr.ipv4.dst[31:28] == 4w0xe) { transition ipv4_mcast; }
transition ipv4_proto;
}

state ipv4_mcast {
// Multicast with TTL <= 1 must not be forwarded (RFC 1112).
if (hdr.ipv4.ttl == 8w0) { transition reject; }
if (hdr.ipv4.ttl == 8w1) { transition reject; }
transition ipv4_proto;
}

state ipv4_proto {
if (hdr.ipv4.protocol == 8w17) { transition udp; }
if (hdr.ipv4.protocol == 8w6) { transition tcp; }
if (hdr.ipv4.protocol == 8w1) { transition icmp; }
Expand Down
Loading