diff --git a/common/src/api/external/mod.rs b/common/src/api/external/mod.rs index 6981f10fa6..fffea4321b 100644 --- a/common/src/api/external/mod.rs +++ b/common/src/api/external/mod.rs @@ -2497,7 +2497,7 @@ pub struct SwitchPortSettingsView { pub routes: Vec, /// BGP peer settings. - pub bgp_peers: Vec, + pub bgp_peers: Vec, /// Layer 3 IP address settings. pub addresses: Vec, @@ -2551,6 +2551,74 @@ pub struct SwitchPortConfig { pub geometry: SwitchPortGeometry, } +/// The speed of a link. +#[derive(Copy, Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq)] +#[serde(rename_all = "snake_case")] +pub enum LinkSpeed { + /// Zero gigabits per second. + Speed0G, + /// 1 gigabit per second. + Speed1G, + /// 10 gigabits per second. + Speed10G, + /// 25 gigabits per second. + Speed25G, + /// 40 gigabits per second. + Speed40G, + /// 50 gigabits per second. + Speed50G, + /// 100 gigabits per second. + Speed100G, + /// 200 gigabits per second. + Speed200G, + /// 400 gigabits per second. + Speed400G, +} + +/// The forward error correction mode of a link. +#[derive(Copy, Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq)] +#[serde(rename_all = "snake_case")] +pub enum LinkFec { + /// Firecode foward error correction. + Firecode, + /// No forward error correction. + None, + /// Reed-Solomon forward error correction. + Rs, +} + +impl From for LinkFec { + fn from(x: crate::api::internal::shared::PortFec) -> LinkFec { + match x { + crate::api::internal::shared::PortFec::Firecode => Self::Firecode, + crate::api::internal::shared::PortFec::None => Self::None, + crate::api::internal::shared::PortFec::Rs => Self::Rs, + } + } +} + +impl From for LinkSpeed { + fn from(x: crate::api::internal::shared::PortSpeed) -> Self { + match x { + crate::api::internal::shared::PortSpeed::Speed0G => Self::Speed0G, + crate::api::internal::shared::PortSpeed::Speed1G => Self::Speed1G, + crate::api::internal::shared::PortSpeed::Speed10G => Self::Speed10G, + crate::api::internal::shared::PortSpeed::Speed25G => Self::Speed25G, + crate::api::internal::shared::PortSpeed::Speed40G => Self::Speed40G, + crate::api::internal::shared::PortSpeed::Speed50G => Self::Speed50G, + crate::api::internal::shared::PortSpeed::Speed100G => { + Self::Speed100G + } + crate::api::internal::shared::PortSpeed::Speed200G => { + Self::Speed200G + } + crate::api::internal::shared::PortSpeed::Speed400G => { + Self::Speed400G + } + } + } +} + /// A link configuration for a port settings object. #[derive(Clone, Debug, Deserialize, JsonSchema, Serialize, PartialEq)] pub struct SwitchPortLinkConfig { @@ -2566,6 +2634,15 @@ pub struct SwitchPortLinkConfig { /// The maximum transmission unit for this link. pub mtu: u16, + + /// The forward error correction mode of the link. + pub fec: LinkFec, + + /// The configured speed of the link. + pub speed: LinkSpeed, + + /// Whether or not the link has autonegotiation enabled. + pub autoneg: bool, } /// A link layer discovery protocol (LLDP) service configuration. @@ -2674,6 +2751,7 @@ pub struct SwitchPortRouteConfig { pub vlan_id: Option, } +/* /// A BGP peer configuration for a port settings object. #[derive(Clone, Debug, Deserialize, JsonSchema, Serialize, PartialEq)] pub struct SwitchPortBgpPeerConfig { @@ -2692,6 +2770,74 @@ pub struct SwitchPortBgpPeerConfig { /// The address of the peer. pub addr: IpAddr, } +*/ + +/// A BGP peer configuration for an interface. Includes the set of announcements +/// that will be advertised to the peer identified by `addr`. The `bgp_config` +/// parameter is a reference to global BGP parameters. The `interface_name` +/// indicates what interface the peer should be contacted on. +#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq)] +pub struct BgpPeer { + /// The global BGP configuration used for establishing a session with this + /// peer. + pub bgp_config: NameOrId, + + /// The name of interface to peer on. This is relative to the port + /// configuration this BGP peer configuration is a part of. For example this + /// value could be phy0 to refer to a primary physical interface. Or it + /// could be vlan47 to refer to a VLAN interface. + pub interface_name: String, + + /// The address of the host to peer with. + pub addr: IpAddr, + + /// How long to hold peer connections between keepalives (seconds). + pub hold_time: u32, + + /// How long to hold a peer in idle before attempting a new session + /// (seconds). + pub idle_hold_time: u32, + + /// How long to delay sending an open request after establishing a TCP + /// session (seconds). + pub delay_open: u32, + + /// How long to to wait between TCP connection retries (seconds). + pub connect_retry: u32, + + /// How often to send keepalive requests (seconds). + pub keepalive: u32, + + /// Require that a peer has a specified ASN. + pub remote_asn: Option, + + /// Require messages from a peer have a minimum IP time to live field. + pub min_ttl: Option, + + /// Use the given key for TCP-MD5 authentication with the peer. + pub md5_auth_key: Option, + + /// Apply the provided multi-exit discriminator (MED) updates sent to the peer. + pub multi_exit_discriminator: Option, + + /// Include the provided communities in updates sent to the peer. + pub communities: Vec, + + /// Apply a local preference to routes received from this peer. + pub local_pref: Option, + + /// Enforce that the first AS in paths received from this peer is the peer's AS. + pub enforce_first_as: bool, + + /// Define import policy for a peer. + pub allowed_import: ImportExportPolicy, + + /// Define export policy for a peer. + pub allowed_export: ImportExportPolicy, + + /// Associate a VLAN ID with a peer. + pub vlan_id: Option, +} /// A base BGP configuration. #[derive( diff --git a/nexus/db-model/src/switch_port.rs b/nexus/db-model/src/switch_port.rs index 8acf580e73..b10f6ba679 100644 --- a/nexus/db-model/src/switch_port.rs +++ b/nexus/db-model/src/switch_port.rs @@ -17,10 +17,10 @@ use crate::{SqlU16, SqlU8}; use db_macros::Resource; use diesel::AsChangeset; use ipnetwork::IpNetwork; -use nexus_types::external_api::params::{self, BgpPeer}; +use nexus_types::external_api::params; use nexus_types::identity::Resource; use omicron_common::api::external; -use omicron_common::api::external::ImportExportPolicy; +use omicron_common::api::external::{BgpPeer, ImportExportPolicy}; use omicron_common::api::internal::shared::{PortFec, PortSpeed}; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -110,12 +110,22 @@ impl From for PortFec { } } -impl From for SwitchLinkFec { - fn from(value: params::LinkFec) -> Self { +impl From for SwitchLinkFec { + fn from(value: external::LinkFec) -> Self { match value { - params::LinkFec::Firecode => SwitchLinkFec::Firecode, - params::LinkFec::None => SwitchLinkFec::None, - params::LinkFec::Rs => SwitchLinkFec::Rs, + external::LinkFec::Firecode => SwitchLinkFec::Firecode, + external::LinkFec::None => SwitchLinkFec::None, + external::LinkFec::Rs => SwitchLinkFec::Rs, + } + } +} + +impl From for external::LinkFec { + fn from(value: SwitchLinkFec) -> Self { + match value { + SwitchLinkFec::Firecode => external::LinkFec::Firecode, + SwitchLinkFec::None => external::LinkFec::None, + SwitchLinkFec::Rs => external::LinkFec::Rs, } } } @@ -136,18 +146,34 @@ impl From for PortSpeed { } } -impl From for SwitchLinkSpeed { - fn from(value: params::LinkSpeed) -> Self { +impl From for SwitchLinkSpeed { + fn from(value: external::LinkSpeed) -> Self { + match value { + external::LinkSpeed::Speed0G => SwitchLinkSpeed::Speed0G, + external::LinkSpeed::Speed1G => SwitchLinkSpeed::Speed1G, + external::LinkSpeed::Speed10G => SwitchLinkSpeed::Speed10G, + external::LinkSpeed::Speed25G => SwitchLinkSpeed::Speed25G, + external::LinkSpeed::Speed40G => SwitchLinkSpeed::Speed40G, + external::LinkSpeed::Speed50G => SwitchLinkSpeed::Speed50G, + external::LinkSpeed::Speed100G => SwitchLinkSpeed::Speed100G, + external::LinkSpeed::Speed200G => SwitchLinkSpeed::Speed200G, + external::LinkSpeed::Speed400G => SwitchLinkSpeed::Speed400G, + } + } +} + +impl From for external::LinkSpeed { + fn from(value: SwitchLinkSpeed) -> Self { match value { - params::LinkSpeed::Speed0G => SwitchLinkSpeed::Speed0G, - params::LinkSpeed::Speed1G => SwitchLinkSpeed::Speed1G, - params::LinkSpeed::Speed10G => SwitchLinkSpeed::Speed10G, - params::LinkSpeed::Speed25G => SwitchLinkSpeed::Speed25G, - params::LinkSpeed::Speed40G => SwitchLinkSpeed::Speed40G, - params::LinkSpeed::Speed50G => SwitchLinkSpeed::Speed50G, - params::LinkSpeed::Speed100G => SwitchLinkSpeed::Speed100G, - params::LinkSpeed::Speed200G => SwitchLinkSpeed::Speed200G, - params::LinkSpeed::Speed400G => SwitchLinkSpeed::Speed400G, + SwitchLinkSpeed::Speed0G => external::LinkSpeed::Speed0G, + SwitchLinkSpeed::Speed1G => external::LinkSpeed::Speed1G, + SwitchLinkSpeed::Speed10G => external::LinkSpeed::Speed10G, + SwitchLinkSpeed::Speed25G => external::LinkSpeed::Speed25G, + SwitchLinkSpeed::Speed40G => external::LinkSpeed::Speed40G, + SwitchLinkSpeed::Speed50G => external::LinkSpeed::Speed50G, + SwitchLinkSpeed::Speed100G => external::LinkSpeed::Speed100G, + SwitchLinkSpeed::Speed200G => external::LinkSpeed::Speed200G, + SwitchLinkSpeed::Speed400G => external::LinkSpeed::Speed400G, } } } @@ -391,6 +417,9 @@ impl Into for SwitchPortLinkConfig { lldp_service_config_id: self.lldp_service_config_id, link_name: self.link_name.clone(), mtu: self.mtu.into(), + fec: self.fec.into(), + speed: self.speed.into(), + autoneg: self.autoneg, } } } @@ -676,17 +705,6 @@ impl SwitchPortBgpPeerConfig { } } -impl Into for SwitchPortBgpPeerConfig { - fn into(self) -> external::SwitchPortBgpPeerConfig { - external::SwitchPortBgpPeerConfig { - port_settings_id: self.port_settings_id, - bgp_config_id: self.bgp_config_id, - interface_name: self.interface_name.clone(), - addr: self.addr.ip(), - } - } -} - #[derive( Queryable, Insertable, diff --git a/nexus/db-queries/src/db/datastore/switch_port.rs b/nexus/db-queries/src/db/datastore/switch_port.rs index 7db3c0d4a3..3f3717a9c4 100644 --- a/nexus/db-queries/src/db/datastore/switch_port.rs +++ b/nexus/db-queries/src/db/datastore/switch_port.rs @@ -2,6 +2,9 @@ // 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/. +use std::collections::BTreeMap; +use std::net::IpAddr; + use super::DataStore; use crate::context::OpContext; use crate::db; @@ -25,16 +28,72 @@ use diesel::{ CombineDsl, ExpressionMethods, JoinOnDsl, NullableExpressionMethods, QueryDsl, SelectableHelper, }; +use ipnetwork::IpNetwork; +use nexus_db_model::{ + SqlU16, SqlU32, SqlU8, SwitchPortBgpPeerConfigAllowExport, + SwitchPortBgpPeerConfigAllowImport, SwitchPortBgpPeerConfigCommunity, +}; use nexus_types::external_api::params; use omicron_common::api::external::http_pagination::PaginatedBy; use omicron_common::api::external::{ - self, CreateResult, DataPageParams, DeleteResult, Error, ListResultVec, - LookupResult, NameOrId, ResourceType, UpdateResult, + self, CreateResult, DataPageParams, DeleteResult, Error, + ImportExportPolicy, ListResultVec, LookupResult, NameOrId, ResourceType, + UpdateResult, }; use ref_cast::RefCast; use serde::{Deserialize, Serialize}; use uuid::Uuid; +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct BgpPeerConfig { + pub port_settings_id: Uuid, + pub bgp_config_id: Uuid, + pub interface_name: String, + pub addr: IpNetwork, + pub hold_time: SqlU32, + pub idle_hold_time: SqlU32, + pub delay_open: SqlU32, + pub connect_retry: SqlU32, + pub keepalive: SqlU32, + pub remote_asn: Option, + pub min_ttl: Option, + pub md5_auth_key: Option, + pub multi_exit_discriminator: Option, + pub local_pref: Option, + pub enforce_first_as: bool, + pub allowed_import: ImportExportPolicy, + pub allowed_export: ImportExportPolicy, + pub communities: Vec, + pub vlan_id: Option, +} + +impl Into for BgpPeerConfig { + fn into(self) -> external::BgpPeer { + external::BgpPeer { + bgp_config: self.bgp_config_id.into(), + interface_name: self.interface_name.clone(), + addr: self.addr.ip(), + hold_time: self.hold_time.into(), + idle_hold_time: self.idle_hold_time.into(), + delay_open: self.delay_open.into(), + connect_retry: self.connect_retry.into(), + keepalive: self.keepalive.into(), + remote_asn: self.remote_asn.map(Into::into), + min_ttl: self.min_ttl.map(Into::into), + md5_auth_key: self.md5_auth_key.clone(), + multi_exit_discriminator: self + .multi_exit_discriminator + .map(Into::into), + communities: self.communities, + local_pref: self.local_pref.map(Into::into), + enforce_first_as: self.enforce_first_as, + allowed_import: self.allowed_import, + allowed_export: self.allowed_export, + vlan_id: self.vlan_id.map(Into::into), + } + } +} + #[derive(Clone, Debug, Deserialize, Serialize)] pub struct SwitchPortSettingsCombinedResult { pub settings: SwitchPortSettings, @@ -45,7 +104,7 @@ pub struct SwitchPortSettingsCombinedResult { pub interfaces: Vec, pub vlan_interfaces: Vec, pub routes: Vec, - pub bgp_peers: Vec, + pub bgp_peers: Vec, pub addresses: Vec, } @@ -147,6 +206,9 @@ impl DataStore { switch_port_settings::dsl as port_settings_dsl, switch_port_settings_address_config::dsl as address_config_dsl, switch_port_settings_bgp_peer_config::dsl as bgp_peer_dsl, + switch_port_settings_bgp_peer_config_allow_export::dsl as allow_export_dsl, + switch_port_settings_bgp_peer_config_allow_import::dsl as allow_import_dsl, + switch_port_settings_bgp_peer_config_communities::dsl as bgp_communities_dsl, switch_port_settings_interface_config::dsl as interface_config_dsl, switch_port_settings_link_config::dsl as link_config_dsl, switch_port_settings_port_config::dsl as port_config_dsl, @@ -179,7 +241,7 @@ impl DataStore { //let port_settings = SwitchPortSettings::new(¶ms.identity); let db_port_settings: SwitchPortSettings = diesel::insert_into(port_settings_dsl::switch_port_settings) - .values(port_settings) + .values(port_settings.clone()) .returning(SwitchPortSettings::as_returning()) .get_result_async(&conn) .await?; @@ -243,6 +305,7 @@ impl DataStore { .returning(LldpServiceConfig::as_returning()) .get_results_async(&conn) .await?; + result.links = diesel::insert_into( link_config_dsl::switch_port_settings_link_config) @@ -303,9 +366,12 @@ impl DataStore { .get_results_async(&conn) .await?; + let mut peer_by_addr: BTreeMap = BTreeMap::new(); + let mut bgp_peer_config = Vec::new(); for (interface_name, peer_config) in ¶ms.bgp_peers { for p in &peer_config.peers { + peer_by_addr.insert(p.addr, &p); use db::schema::bgp_config; let bgp_config_id = match &p.bgp_config { NameOrId::Id(id) => *id, @@ -327,6 +393,63 @@ impl DataStore { } }; + if let ImportExportPolicy::Allow(list) = &p.allowed_import { + let id = port_settings.identity.id; + let to_insert: Vec = list.clone().into_iter().map(|x| { + SwitchPortBgpPeerConfigAllowImport { + port_settings_id: id, + interface_name: interface_name.clone(), + addr: p.addr.into(), + prefix: x.into(), + } + }).collect(); + + diesel::insert_into(allow_import_dsl::switch_port_settings_bgp_peer_config_allow_import) + .values(to_insert) + .execute_async(&conn) + .await?; + } + + if let ImportExportPolicy::Allow(list) = &p.allowed_export { + let id = port_settings.identity.id; + let to_insert: Vec = list + .clone() + .into_iter() + .map(|x| { + SwitchPortBgpPeerConfigAllowExport { + port_settings_id: id, + interface_name: interface_name.clone(), + addr: p.addr.into(), + prefix: x.into(), + } + }).collect(); + + diesel::insert_into(allow_export_dsl::switch_port_settings_bgp_peer_config_allow_export) + .values(to_insert) + .execute_async(&conn) + .await?; + } + + if !p.communities.is_empty() { + let id = port_settings.identity.id; + let to_insert: Vec = p.communities + .clone() + .into_iter() + .map(|x| { + SwitchPortBgpPeerConfigCommunity{ + port_settings_id: id, + interface_name: interface_name.clone(), + addr: p.addr.into(), + community: x.into(), + } + }).collect(); + + diesel::insert_into(bgp_communities_dsl::switch_port_settings_bgp_peer_config_communities) + .values(to_insert) + .execute_async(&conn) + .await?; + } + bgp_peer_config.push(SwitchPortBgpPeerConfig::new( psid, bgp_config_id, @@ -336,7 +459,7 @@ impl DataStore { } } - result.bgp_peers = + let db_bgp_peers: Vec = diesel::insert_into( bgp_peer_dsl::switch_port_settings_bgp_peer_config) .values(bgp_peer_config) @@ -344,6 +467,40 @@ impl DataStore { .get_results_async(&conn) .await?; + for p in db_bgp_peers.into_iter() { + let view = BgpPeerConfig { + port_settings_id: p.port_settings_id, + bgp_config_id: p.bgp_config_id, + interface_name: p.interface_name, + addr: p.addr, + hold_time: p.hold_time, + idle_hold_time: p.idle_hold_time, + delay_open: p.delay_open, + connect_retry: p.connect_retry, + keepalive: p.keepalive, + remote_asn: p.remote_asn, + min_ttl: p.min_ttl, + md5_auth_key: p.md5_auth_key, + multi_exit_discriminator: p.multi_exit_discriminator, + local_pref: p.local_pref, + enforce_first_as: p.enforce_first_as, + vlan_id: p.vlan_id, + allowed_import: peer_by_addr.get(&p.addr.ip()) + .map(|x| x.allowed_import.clone()) + .unwrap_or(ImportExportPolicy::NoFiltering) + .clone(), + allowed_export: peer_by_addr.get(&p.addr.ip()) + .map(|x| x.allowed_export.clone()) + .unwrap_or(ImportExportPolicy::NoFiltering) + .clone(), + communities: peer_by_addr.get(&p.addr.ip()) + .map(|x| x.communities.clone()) + .unwrap_or(Vec::new()) + .clone(), + }; + result.bgp_peers.push(view); + } + let mut address_config = Vec::new(); use db::schema::address_lot; for (interface_name, a) in ¶ms.addresses { @@ -678,6 +835,11 @@ impl DataStore { use db::schema::switch_port_settings::{ self, dsl as port_settings_dsl, }; + use db::schema::{ + switch_port_settings_bgp_peer_config_allow_import::dsl as allow_import_dsl, + switch_port_settings_bgp_peer_config_allow_export::dsl as allow_export_dsl, + switch_port_settings_bgp_peer_config_communities::dsl as bgp_communities_dsl, + }; let id = match name_or_id { NameOrId::Id(id) => *id, @@ -793,13 +955,86 @@ impl DataStore { self as bgp_peer, dsl as bgp_peer_dsl, }; - result.bgp_peers = + let peers: Vec = bgp_peer_dsl::switch_port_settings_bgp_peer_config .filter(bgp_peer::port_settings_id.eq(id)) .select(SwitchPortBgpPeerConfig::as_select()) .load_async::(&conn) .await?; + for p in peers.iter() { + let allowed_import: ImportExportPolicy = if p.allow_import_list_active { + let db_list: Vec = + allow_import_dsl::switch_port_settings_bgp_peer_config_allow_import + .filter(allow_import_dsl::port_settings_id.eq(id)) + .filter(allow_import_dsl::interface_name.eq(p.interface_name.clone())) + .filter(allow_import_dsl::addr.eq(p.addr)) + .select(SwitchPortBgpPeerConfigAllowImport::as_select()) + .load_async::(&conn) + .await?; + + ImportExportPolicy::Allow(db_list + .into_iter() + .map(|x| x.prefix.into()) + .collect() + ) + } else { + ImportExportPolicy::NoFiltering + }; + + let allowed_export: ImportExportPolicy = if p.allow_export_list_active { + let db_list: Vec = + allow_export_dsl::switch_port_settings_bgp_peer_config_allow_export + .filter(allow_export_dsl::port_settings_id.eq(id)) + .filter(allow_export_dsl::interface_name.eq(p.interface_name.clone())) + .filter(allow_export_dsl::addr.eq(p.addr)) + .select(SwitchPortBgpPeerConfigAllowExport::as_select()) + .load_async::(&conn) + .await?; + + ImportExportPolicy::Allow(db_list + .into_iter() + .map(|x| x.prefix.into()) + .collect() + ) + } else { + ImportExportPolicy::NoFiltering + }; + + let communities: Vec = + bgp_communities_dsl::switch_port_settings_bgp_peer_config_communities + .filter(bgp_communities_dsl::port_settings_id.eq(id)) + .filter(bgp_communities_dsl::interface_name.eq(p.interface_name.clone())) + .filter(bgp_communities_dsl::addr.eq(p.addr)) + .select(SwitchPortBgpPeerConfigCommunity::as_select()) + .load_async::(&conn) + .await?; + + let view = BgpPeerConfig { + port_settings_id: p.port_settings_id, + bgp_config_id: p.bgp_config_id, + interface_name: p.interface_name.clone(), + addr: p.addr, + hold_time: p.hold_time, + idle_hold_time: p.idle_hold_time, + delay_open: p.delay_open, + connect_retry: p.connect_retry, + keepalive: p.keepalive, + remote_asn: p.remote_asn, + min_ttl: p.min_ttl, + md5_auth_key: p.md5_auth_key.clone(), + multi_exit_discriminator: p.multi_exit_discriminator, + local_pref: p.local_pref, + enforce_first_as: p.enforce_first_as, + vlan_id: p.vlan_id, + communities: communities.into_iter().map(|c| c.community.0).collect(), + allowed_import, + allowed_export, + }; + + result.bgp_peers.push(view); + } + // get the address configs use db::schema::switch_port_settings_address_config::{ self as address_config, dsl as address_config_dsl, @@ -1189,11 +1424,12 @@ mod test { use crate::db::datastore::UpdatePrecondition; use nexus_test_utils::db::test_setup_database; use nexus_types::external_api::params::{ - BgpAnnounceSetCreate, BgpConfigCreate, BgpPeer, BgpPeerConfig, + BgpAnnounceSetCreate, BgpConfigCreate, BgpPeerConfig, SwitchPortConfigCreate, SwitchPortGeometry, SwitchPortSettingsCreate, }; use omicron_common::api::external::{ - IdentityMetadataCreateParams, ImportExportPolicy, Name, NameOrId, + BgpPeer, IdentityMetadataCreateParams, ImportExportPolicy, Name, + NameOrId, }; use omicron_test_utils::dev; use std::collections::HashMap; @@ -1257,9 +1493,6 @@ mod test { "phy0".into(), BgpPeerConfig { peers: vec![BgpPeer { - bgp_announce_set: NameOrId::Name( - "test-announce-set".parse().unwrap(), - ), bgp_config: NameOrId::Name( "test-bgp-config".parse().unwrap(), ), diff --git a/nexus/src/app/rack.rs b/nexus/src/app/rack.rs index 4c5fb332ac..25c0824ce6 100644 --- a/nexus/src/app/rack.rs +++ b/nexus/src/app/rack.rs @@ -31,7 +31,6 @@ use nexus_types::external_api::params::AddressLotBlockCreate; use nexus_types::external_api::params::BgpAnnounceSetCreate; use nexus_types::external_api::params::BgpAnnouncementCreate; use nexus_types::external_api::params::BgpConfigCreate; -use nexus_types::external_api::params::BgpPeer; use nexus_types::external_api::params::LinkConfigCreate; use nexus_types::external_api::params::LldpServiceConfigCreate; use nexus_types::external_api::params::RouteConfig; @@ -50,6 +49,7 @@ use nexus_types::external_api::views; use nexus_types::internal_api::params::DnsRecord; use omicron_common::address::{get_64_subnet, Ipv6Subnet, RACK_PREFIX}; use omicron_common::api::external::AddressLotKind; +use omicron_common::api::external::BgpPeer; use omicron_common::api::external::DataPageParams; use omicron_common::api::external::Error; use omicron_common::api::external::IdentityMetadataCreateParams; @@ -549,9 +549,6 @@ impl super::Nexus { .bgp_peers .iter() .map(|r| BgpPeer { - bgp_announce_set: NameOrId::Name( - format!("as{}-announce", r.asn).parse().unwrap(), - ), bgp_config: NameOrId::Name( format!("as{}", r.asn).parse().unwrap(), ), diff --git a/nexus/tests/integration_tests/switch_port.rs b/nexus/tests/integration_tests/switch_port.rs index 9660bef3dd..41542d8554 100644 --- a/nexus/tests/integration_tests/switch_port.rs +++ b/nexus/tests/integration_tests/switch_port.rs @@ -10,16 +10,16 @@ use nexus_test_utils::http_testing::{AuthnMode, NexusRequest, RequestBuilder}; use nexus_test_utils_macros::nexus_test; use nexus_types::external_api::params::{ Address, AddressConfig, AddressLotBlockCreate, AddressLotCreate, - BgpAnnounceSetCreate, BgpAnnouncementCreate, BgpConfigCreate, BgpPeer, - BgpPeerConfig, LinkConfigCreate, LinkFec, LinkSpeed, - LldpServiceConfigCreate, Route, RouteConfig, SwitchInterfaceConfigCreate, - SwitchInterfaceKind, SwitchPortApplySettings, SwitchPortSettingsCreate, + BgpAnnounceSetCreate, BgpAnnouncementCreate, BgpConfigCreate, + BgpPeerConfig, LinkConfigCreate, LldpServiceConfigCreate, Route, + RouteConfig, SwitchInterfaceConfigCreate, SwitchInterfaceKind, + SwitchPortApplySettings, SwitchPortSettingsCreate, }; use nexus_types::external_api::views::Rack; use omicron_common::api::external::ImportExportPolicy; use omicron_common::api::external::{ - self, AddressLotKind, IdentityMetadataCreateParams, NameOrId, SwitchPort, - SwitchPortSettingsView, + self, AddressLotKind, BgpPeer, IdentityMetadataCreateParams, LinkFec, + LinkSpeed, NameOrId, SwitchPort, SwitchPortSettingsView, }; type ControlPlaneTestContext = @@ -258,7 +258,6 @@ async fn test_port_settings_basic_crud(ctx: &ControlPlaneTestContext) { BgpPeerConfig { peers: vec![BgpPeer { bgp_config: NameOrId::Name("as47".parse().unwrap()), - bgp_announce_set: NameOrId::Name("instances".parse().unwrap()), interface_name: "phy0".to_string(), addr: "1.2.3.4".parse().unwrap(), hold_time: 6, diff --git a/nexus/types/src/external_api/params.rs b/nexus/types/src/external_api/params.rs index 912cbeab4f..1b252c77cb 100644 --- a/nexus/types/src/external_api/params.rs +++ b/nexus/types/src/external_api/params.rs @@ -9,9 +9,9 @@ use crate::external_api::shared; use base64::Engine; use chrono::{DateTime, Utc}; use omicron_common::api::external::{ - AddressLotKind, AllowedSourceIps, BfdMode, ByteCount, Hostname, + AddressLotKind, AllowedSourceIps, BfdMode, BgpPeer, ByteCount, Hostname, IdentityMetadataCreateParams, IdentityMetadataUpdateParams, - ImportExportPolicy, InstanceCpuCount, IpNet, Ipv4Net, Ipv6Net, Name, + InstanceCpuCount, IpNet, Ipv4Net, Ipv6Net, LinkFec, LinkSpeed, Name, NameOrId, PaginationOrder, RouteDestination, RouteTarget, SemverVersion, }; use schemars::JsonSchema; @@ -1519,88 +1519,6 @@ pub enum SwitchPortGeometry { Sfp28x4, } -/// The forward error correction mode of a link. -#[derive(Copy, Clone, Debug, Deserialize, Serialize, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum LinkFec { - /// Firecode foward error correction. - Firecode, - /// No forward error correction. - None, - /// Reed-Solomon forward error correction. - Rs, -} - -impl From for LinkFec { - fn from(x: omicron_common::api::internal::shared::PortFec) -> LinkFec { - match x { - omicron_common::api::internal::shared::PortFec::Firecode => { - Self::Firecode - } - omicron_common::api::internal::shared::PortFec::None => Self::None, - omicron_common::api::internal::shared::PortFec::Rs => Self::Rs, - } - } -} - -/// The speed of a link. -#[derive(Copy, Clone, Debug, Deserialize, Serialize, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum LinkSpeed { - /// Zero gigabits per second. - Speed0G, - /// 1 gigabit per second. - Speed1G, - /// 10 gigabits per second. - Speed10G, - /// 25 gigabits per second. - Speed25G, - /// 40 gigabits per second. - Speed40G, - /// 50 gigabits per second. - Speed50G, - /// 100 gigabits per second. - Speed100G, - /// 200 gigabits per second. - Speed200G, - /// 400 gigabits per second. - Speed400G, -} - -impl From for LinkSpeed { - fn from(x: omicron_common::api::internal::shared::PortSpeed) -> Self { - match x { - omicron_common::api::internal::shared::PortSpeed::Speed0G => { - Self::Speed0G - } - omicron_common::api::internal::shared::PortSpeed::Speed1G => { - Self::Speed1G - } - omicron_common::api::internal::shared::PortSpeed::Speed10G => { - Self::Speed10G - } - omicron_common::api::internal::shared::PortSpeed::Speed25G => { - Self::Speed25G - } - omicron_common::api::internal::shared::PortSpeed::Speed40G => { - Self::Speed40G - } - omicron_common::api::internal::shared::PortSpeed::Speed50G => { - Self::Speed50G - } - omicron_common::api::internal::shared::PortSpeed::Speed100G => { - Self::Speed100G - } - omicron_common::api::internal::shared::PortSpeed::Speed200G => { - Self::Speed200G - } - omicron_common::api::internal::shared::PortSpeed::Speed400G => { - Self::Speed400G - } - } - } -} - /// Switch link configuration. #[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)] pub struct LinkConfigCreate { @@ -1710,76 +1628,6 @@ pub struct BgpPeerConfig { pub peers: Vec, } -/// A BGP peer configuration for an interface. Includes the set of announcements -/// that will be advertised to the peer identified by `addr`. The `bgp_config` -/// parameter is a reference to global BGP parameters. The `interface_name` -/// indicates what interface the peer should be contacted on. -#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)] -pub struct BgpPeer { - /// The set of announcements advertised by the peer. - pub bgp_announce_set: NameOrId, - - /// The global BGP configuration used for establishing a session with this - /// peer. - pub bgp_config: NameOrId, - - /// The name of interface to peer on. This is relative to the port - /// configuration this BGP peer configuration is a part of. For example this - /// value could be phy0 to refer to a primary physical interface. Or it - /// could be vlan47 to refer to a VLAN interface. - pub interface_name: String, - - /// The address of the host to peer with. - pub addr: IpAddr, - - /// How long to hold peer connections between keppalives (seconds). - pub hold_time: u32, - - /// How long to hold a peer in idle before attempting a new session - /// (seconds). - pub idle_hold_time: u32, - - /// How long to delay sending an open request after establishing a TCP - /// session (seconds). - pub delay_open: u32, - - /// How long to to wait between TCP connection retries (seconds). - pub connect_retry: u32, - - /// How often to send keepalive requests (seconds). - pub keepalive: u32, - - /// Require that a peer has a specified ASN. - pub remote_asn: Option, - - /// Require messages from a peer have a minimum IP time to live field. - pub min_ttl: Option, - - /// Use the given key for TCP-MD5 authentication with the peer. - pub md5_auth_key: Option, - - /// Apply the provided multi-exit discriminator (MED) updates sent to the peer. - pub multi_exit_discriminator: Option, - - /// Include the provided communities in updates sent to the peer. - pub communities: Vec, - - /// Apply a local preference to routes received from this peer. - pub local_pref: Option, - - /// Enforce that the first AS in paths received from this peer is the peer's AS. - pub enforce_first_as: bool, - - /// Define import policy for a peer. - pub allowed_import: ImportExportPolicy, - - /// Define export policy for a peer. - pub allowed_export: ImportExportPolicy, - - /// Associate a VLAN ID with a peer. - pub vlan_id: Option, -} - /// Parameters for creating a named set of BGP announcements. #[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)] pub struct BgpAnnounceSetCreate { diff --git a/openapi/nexus.json b/openapi/nexus.json index 74efd47a66..27157e5759 100644 --- a/openapi/nexus.json +++ b/openapi/nexus.json @@ -9807,14 +9807,6 @@ } ] }, - "bgp_announce_set": { - "description": "The set of announcements advertised by the peer.", - "allOf": [ - { - "$ref": "#/components/schemas/NameOrId" - } - ] - }, "bgp_config": { "description": "The global BGP configuration used for establishing a session with this peer.", "allOf": [ @@ -9849,7 +9841,7 @@ "type": "boolean" }, "hold_time": { - "description": "How long to hold peer connections between keppalives (seconds).", + "description": "How long to hold peer connections between keepalives (seconds).", "type": "integer", "format": "uint32", "minimum": 0 @@ -9915,7 +9907,6 @@ "addr", "allowed_export", "allowed_import", - "bgp_announce_set", "bgp_config", "communities", "connect_retry", @@ -17291,37 +17282,6 @@ "port_settings" ] }, - "SwitchPortBgpPeerConfig": { - "description": "A BGP peer configuration for a port settings object.", - "type": "object", - "properties": { - "addr": { - "description": "The address of the peer.", - "type": "string", - "format": "ip" - }, - "bgp_config_id": { - "description": "The id of the global BGP configuration referenced by this peer configuration.", - "type": "string", - "format": "uuid" - }, - "interface_name": { - "description": "The interface name used to establish a peer session.", - "type": "string" - }, - "port_settings_id": { - "description": "The port settings object this BGP configuration belongs to.", - "type": "string", - "format": "uuid" - } - }, - "required": [ - "addr", - "bgp_config_id", - "interface_name", - "port_settings_id" - ] - }, "SwitchPortConfig": { "description": "A physical port configuration for a port settings object.", "type": "object", @@ -17418,6 +17378,18 @@ "description": "A link configuration for a port settings object.", "type": "object", "properties": { + "autoneg": { + "description": "Whether or not the link has autonegotiation enabled.", + "type": "boolean" + }, + "fec": { + "description": "The forward error correction mode of the link.", + "allOf": [ + { + "$ref": "#/components/schemas/LinkFec" + } + ] + }, "link_name": { "description": "The name of this link.", "type": "string" @@ -17437,13 +17409,24 @@ "description": "The port settings this link configuration belongs to.", "type": "string", "format": "uuid" + }, + "speed": { + "description": "The configured speed of the link.", + "allOf": [ + { + "$ref": "#/components/schemas/LinkSpeed" + } + ] } }, "required": [ + "autoneg", + "fec", "link_name", "lldp_service_config_id", "mtu", - "port_settings_id" + "port_settings_id", + "speed" ] }, "SwitchPortResultsPage": { @@ -17674,7 +17657,7 @@ "description": "BGP peer settings.", "type": "array", "items": { - "$ref": "#/components/schemas/SwitchPortBgpPeerConfig" + "$ref": "#/components/schemas/BgpPeer" } }, "groups": {