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
73 changes: 64 additions & 9 deletions dpd-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use std::collections::BTreeMap;
use std::net::{Ipv4Addr, Ipv6Addr};

use dpd_types_versions::{latest, v1, v4, v7};
use dpd_types_versions::{latest, v1, v4, v7, v8};
use dropshot::{
EmptyScanParams, HttpError, HttpResponseCreated, HttpResponseDeleted,
HttpResponseOk, HttpResponseUpdatedNoContent, PaginationParams, Path,
Expand All @@ -29,6 +29,7 @@ api_versions!([
// | example for the next person.
// v
// (next_int, IDENT),
(14, MCAST_EXTERNAL_SCOPE_DOCS),
(13, ALLOW_DDM_TRAFFIC),
(12, PRBS_ERROR_TRACKING),
(11, WALLCLOCK_HISTORY),
Expand Down Expand Up @@ -1971,14 +1972,17 @@ pub trait DpdApi {
/**
* Create an external-only multicast group configuration.
*
* External-only groups are used for IPv4 and non-admin-local IPv6 multicast
* traffic that doesn't require replication infrastructure. These groups use
* simple forwarding tables and require a NAT target.
* External-only groups are used for IPv4 and IPv6 multicast traffic that
* does not require replication infrastructure. Any admitted IPv6 scope may
* be used, admin-local included, except within the reserved underlay
* subnet ff04::/64, which belongs to the internal multicast API.
*
* These groups carry no direct members and require a NAT target.
*/
#[endpoint {
method = POST,
path = "/multicast/external-groups",
versions = VERSION_MCAST_STRICT_UNDERLAY..,
versions = VERSION_MCAST_EXTERNAL_SCOPE_DOCS..,
}]
async fn multicast_group_create_external(
rqctx: RequestContext<Self::Context>,
Expand All @@ -1988,6 +1992,29 @@ pub trait DpdApi {
HttpError,
>;

/**
* Create an external-only multicast group configuration.
*
* External-only groups are used for IPv4 and non-admin-local IPv6 multicast
* traffic that doesn't require replication infrastructure. These groups use
* simple forwarding tables and require a NAT target.
*/
#[endpoint {
method = POST,
path = "/multicast/external-groups",
versions = VERSION_MCAST_STRICT_UNDERLAY..VERSION_MCAST_EXTERNAL_SCOPE_DOCS,
operation_id = "multicast_group_create_external",
}]
async fn multicast_group_create_external_v8(
rqctx: RequestContext<Self::Context>,
group: TypedBody<v7::mcast::MulticastGroupCreateExternalEntry>,
) -> Result<
HttpResponseCreated<v8::mcast::MulticastGroupExternalResponse>,
HttpError,
> {
Self::multicast_group_create_external(rqctx, group).await
}

/// Create an external-only multicast group configuration.
#[endpoint {
method = POST,
Expand All @@ -2002,7 +2029,7 @@ pub trait DpdApi {
HttpResponseCreated<v7::mcast::MulticastGroupExternalResponse>,
HttpError,
> {
Self::multicast_group_create_external(rqctx, group)
Self::multicast_group_create_external_v8(rqctx, group)
.await
.map(|resp| resp.map(Into::into))
}
Expand Down Expand Up @@ -2278,15 +2305,17 @@ pub trait DpdApi {
/**
* Update an external-only multicast group configuration for a given group IP address.
*
* External-only groups are used for IPv4 and non-admin-local IPv6 multicast
* traffic that doesn't require replication infrastructure.
* External-only groups are used for IPv4 and IPv6 multicast traffic that
* does not require replication infrastructure. Any admitted IPv6 scope may
* be used, admin-local included, except within the reserved underlay
* subnet ff04::/64, which belongs to the internal multicast API.
*
* The `tag` query parameter must match the group's existing tag.
*/
#[endpoint {
method = PUT,
path = "/multicast/external-groups/{group_ip}",
versions = VERSION_MCAST_STRICT_UNDERLAY..,
versions = VERSION_MCAST_EXTERNAL_SCOPE_DOCS..,
}]
async fn multicast_group_update_external(
rqctx: RequestContext<Self::Context>,
Expand All @@ -2298,6 +2327,32 @@ pub trait DpdApi {
HttpError,
>;

/**
* Update an external-only multicast group configuration for a given group IP address.
*
* External-only groups are used for IPv4 and non-admin-local IPv6 multicast
* traffic that doesn't require replication infrastructure.
*
* The `tag` query parameter must match the group's existing tag.
*/
#[endpoint {
method = PUT,
path = "/multicast/external-groups/{group_ip}",
versions = VERSION_MCAST_STRICT_UNDERLAY..VERSION_MCAST_EXTERNAL_SCOPE_DOCS,
operation_id = "multicast_group_update_external",
}]
async fn multicast_group_update_external_v8(
rqctx: RequestContext<Self::Context>,
path: Path<v1::mcast::MulticastGroupIpParam>,
query: Query<v8::mcast::MulticastGroupTagQuery>,
group: TypedBody<v8::mcast::MulticastGroupUpdateExternalEntry>,
) -> Result<
HttpResponseOk<v8::mcast::MulticastGroupExternalResponse>,
HttpError,
> {
Self::multicast_group_update_external(rqctx, path, query, group).await
}

/**
* Update an external-only multicast group configuration.
*
Expand Down
15 changes: 9 additions & 6 deletions dpd/src/mcast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,18 @@
//! The multicast implementation uses a bifurcated design that separates
//! external (customer) and (internal) underlay traffic:
//!
//! 1. External-only groups (IPv4 and non-admin-local IPv6):
//! 1. External-only groups (IPv4 and IPv6 outside the reserved underlay
//! subnet ff04::/64):
//! - Created from API control plane IPs for customer traffic
//! - Handle customer traffic to/from outside the rack
//! - Use the external multicast API (/multicast/external-groups)
//! - Must have NAT targets pointing to internal groups for proper forwarding
//!
//! 2. Internal groups (admin-local IPv6 multicast):
//! - Admin-local = scope 4 (ff04::/16) as defined in
//! [RFC 7346] and [RFC 4291]
//! - Geneve encapsulated multicast traffic (NAT targets of external-only groups)
//! 2. Internal groups (underlay IPv6 multicast):
//! - Reserved underlay subnet ff04::/64, within admin-local scope-4
//! (ff04::/16) as defined in [RFC 7346] and [RFC 4291]
//! - Geneve encapsulated multicast traffic (NAT targets of
//! external-only groups)
//! - Use the internal multicast API (/multicast/underlay-groups)
//! - Can replicate to:
//! a) External group members (customer traffic)
Expand Down Expand Up @@ -559,7 +561,8 @@ pub(crate) fn del_group(
let mut mcast = s.mcast.lock().unwrap();

// Check if this is an internal group referenced by an external group.
// Internal groups are identified by admin-scoped IPv6 addresses (ff04::/16).
// Internal groups are identified by addresses in the reserved underlay
// subnet (i.e., ff04::/64).
if let IpAddr::V6(ipv6) = group_ip
&& let Ok(admin_scoped) = UnderlayMulticastIpv6::new(ipv6)
&& let Some(external_ip) = mcast.nat_target_refs.get(&admin_scoped)
Expand Down
1 change: 1 addition & 0 deletions openapi/dpd/dpd-13.0.0-5db8bd.json.gitstub
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2df9101e95757037f2cc4e31e8bf00fd9e79efc7:openapi/dpd/dpd-13.0.0-5db8bd.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"url": "https://oxide.computer",
"email": "api@oxide.computer"
},
"version": "13.0.0"
"version": "14.0.0"
},
"paths": {
"/all-settings": {
Expand Down Expand Up @@ -1249,7 +1249,7 @@
"/multicast/external-groups": {
"post": {
"summary": "Create an external-only multicast group configuration.",
"description": "External-only groups are used for IPv4 and non-admin-local IPv6 multicast traffic that doesn't require replication infrastructure. These groups use simple forwarding tables and require a NAT target.",
"description": "External-only groups are used for IPv4 and IPv6 multicast traffic that does not require replication infrastructure. Any admitted IPv6 scope may be used, admin-local included, except within the reserved underlay subnet ff04::/64, which belongs to the internal multicast API.\n\nThese groups carry no direct members and require a NAT target.",
"operationId": "multicast_group_create_external",
"requestBody": {
"content": {
Expand Down Expand Up @@ -1284,7 +1284,7 @@
"/multicast/external-groups/{group_ip}": {
"put": {
"summary": "Update an external-only multicast group configuration for a given group IP address.",
"description": "External-only groups are used for IPv4 and non-admin-local IPv6 multicast traffic that doesn't require replication infrastructure.\n\nThe `tag` query parameter must match the group's existing tag.",
"description": "External-only groups are used for IPv4 and IPv6 multicast traffic that does not require replication infrastructure. Any admitted IPv6 scope may be used, admin-local included, except within the reserved underlay subnet ff04::/64, which belongs to the internal multicast API.\n\nThe `tag` query parameter must match the group's existing tag.",
"operationId": "multicast_group_update_external",
"parameters": [
{
Expand Down
2 changes: 1 addition & 1 deletion openapi/dpd/dpd-latest.json