Skip to content

Commit 26fad69

Browse files
authored
add bfd to bootstore and early networking (#5313)
1 parent 00deace commit 26fad69

File tree

25 files changed

+407
-34
lines changed

25 files changed

+407
-34
lines changed

clients/sled-agent-client/src/lib.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ use std::convert::TryFrom;
1111
use std::hash::Hash;
1212
use std::net::IpAddr;
1313
use std::net::SocketAddr;
14-
use types::{BgpConfig, BgpPeerConfig, PortConfigV1, RouteConfig};
14+
use types::{
15+
BfdPeerConfig, BgpConfig, BgpPeerConfig, PortConfigV1, RouteConfig,
16+
};
1517
use uuid::Uuid;
1618

1719
progenitor::generate_api!(
@@ -651,3 +653,16 @@ impl Hash for PortConfigV1 {
651653
self.uplink_port_speed.hash(state);
652654
}
653655
}
656+
657+
impl Eq for BfdPeerConfig {}
658+
659+
impl Hash for BfdPeerConfig {
660+
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
661+
self.local.hash(state);
662+
self.remote.hash(state);
663+
self.detection_threshold.hash(state);
664+
self.required_rx.hash(state);
665+
self.mode.hash(state);
666+
self.switch.hash(state);
667+
}
668+
}

common/src/api/external/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2821,6 +2821,25 @@ pub struct BgpImportedRouteIpv4 {
28212821
pub switch: SwitchLocation,
28222822
}
28232823

2824+
/// BFD connection mode.
2825+
#[derive(
2826+
Clone,
2827+
Copy,
2828+
Debug,
2829+
Deserialize,
2830+
Serialize,
2831+
JsonSchema,
2832+
PartialEq,
2833+
Eq,
2834+
Ord,
2835+
PartialOrd,
2836+
)]
2837+
#[serde(rename_all = "snake_case")]
2838+
pub enum BfdMode {
2839+
SingleHop,
2840+
MultiHop,
2841+
}
2842+
28242843
/// A description of an uploaded TUF repository.
28252844
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, JsonSchema)]
28262845
pub struct TufRepoDescription {

common/src/api/internal/shared.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
//! Types shared between Nexus and Sled Agent.
66
7-
use crate::api::external::{self, Name};
7+
use crate::api::external::{self, BfdMode, Name};
88
use ipnetwork::{IpNetwork, Ipv4Network, Ipv6Network};
99
use schemars::JsonSchema;
1010
use serde::{Deserialize, Serialize};
@@ -87,6 +87,9 @@ pub struct RackNetworkConfigV1 {
8787
pub ports: Vec<PortConfigV1>,
8888
/// BGP configurations for connecting the rack to external networks
8989
pub bgp: Vec<BgpConfig>,
90+
/// BFD configuration for connecting the rack to external networks
91+
#[serde(default)]
92+
pub bfd: Vec<BfdPeerConfig>,
9093
}
9194

9295
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, JsonSchema)]
@@ -118,6 +121,16 @@ pub struct BgpPeerConfig {
118121
pub keepalive: Option<u64>,
119122
}
120123

124+
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, JsonSchema)]
125+
pub struct BfdPeerConfig {
126+
pub local: Option<IpAddr>,
127+
pub remote: IpAddr,
128+
pub detection_threshold: u8,
129+
pub required_rx: u64,
130+
pub mode: BfdMode,
131+
pub switch: SwitchLocation,
132+
}
133+
121134
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, JsonSchema)]
122135
pub struct RouteConfig {
123136
/// The destination of the route.

nexus/db-model/src/bfd.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,13 @@ pub struct BfdSession {
4545
pub time_deleted: Option<DateTime<Utc>>,
4646
}
4747

48-
impl From<nexus_types::external_api::params::BfdMode> for BfdMode {
49-
fn from(value: nexus_types::external_api::params::BfdMode) -> Self {
48+
impl From<omicron_common::api::external::BfdMode> for BfdMode {
49+
fn from(value: omicron_common::api::external::BfdMode) -> Self {
5050
match value {
51-
nexus_types::external_api::params::BfdMode::SingleHop => {
51+
omicron_common::api::external::BfdMode::SingleHop => {
5252
BfdMode::SingleHop
5353
}
54-
nexus_types::external_api::params::BfdMode::MultiHop => {
54+
omicron_common::api::external::BfdMode::MultiHop => {
5555
BfdMode::MultiHop
5656
}
5757
}

nexus/src/app/background/sync_switch_configuration.rs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ use nexus_types::{external_api::params, identity::Resource};
3939
use omicron_common::OMICRON_DPD_TAG;
4040
use omicron_common::{
4141
address::{get_sled_address, Ipv6Subnet},
42-
api::external::{DataPageParams, SwitchLocation},
42+
api::{
43+
external::{DataPageParams, SwitchLocation},
44+
internal::shared::ParseSwitchLocationError,
45+
},
4346
};
4447
use serde_json::json;
4548
use sled_agent_client::types::{
@@ -210,6 +213,56 @@ impl SwitchPortSettingsManager {
210213

211214
Ok(set)
212215
}
216+
217+
async fn bfd_peer_configs_from_db<'a>(
218+
&'a mut self,
219+
opctx: &OpContext,
220+
) -> Result<
221+
Vec<sled_agent_client::types::BfdPeerConfig>,
222+
omicron_common::api::external::Error,
223+
> {
224+
let db_data = self
225+
.datastore
226+
.bfd_session_list(opctx, &DataPageParams::max_page())
227+
.await?;
228+
229+
let mut result = Vec::new();
230+
for spec in db_data.into_iter() {
231+
let config = sled_agent_client::types::BfdPeerConfig {
232+
local: spec.local.map(|x| x.ip()),
233+
remote: spec.remote.ip(),
234+
detection_threshold: spec.detection_threshold.0.try_into().map_err(|_| {
235+
omicron_common::api::external::Error::InternalError {
236+
internal_message: format!(
237+
"db_bfd_peer_configs: detection threshold overflow: {}",
238+
spec.detection_threshold.0,
239+
),
240+
}
241+
})?,
242+
required_rx: spec.required_rx.0.into(),
243+
mode: match spec.mode {
244+
nexus_db_model::BfdMode::SingleHop => {
245+
sled_agent_client::types::BfdMode::SingleHop
246+
}
247+
nexus_db_model::BfdMode::MultiHop => {
248+
sled_agent_client::types::BfdMode::MultiHop
249+
}
250+
},
251+
switch: spec.switch.parse().map_err(|e: ParseSwitchLocationError| {
252+
omicron_common::api::external::Error::InternalError {
253+
internal_message: format!(
254+
"db_bfd_peer_configs: failed to parse switch name: {}: {:?}",
255+
spec.switch,
256+
e,
257+
),
258+
}
259+
})?,
260+
};
261+
result.push(config);
262+
}
263+
264+
Ok(result)
265+
}
213266
}
214267

215268
#[derive(Debug)]
@@ -799,6 +852,14 @@ impl BackgroundTask for SwitchPortSettingsManager {
799852
;
800853

801854

855+
let bfd = match self.bfd_peer_configs_from_db(opctx).await {
856+
Ok(bfd) => bfd,
857+
Err(e) => {
858+
error!(log, "error fetching bfd config from db"; "error" => %e);
859+
continue;
860+
}
861+
};
862+
802863
let mut desired_config = EarlyNetworkConfig {
803864
generation: 0,
804865
schema_version: 1,
@@ -810,6 +871,7 @@ impl BackgroundTask for SwitchPortSettingsManager {
810871
infra_ip_last,
811872
ports,
812873
bgp,
874+
bfd,
813875
}),
814876
},
815877
};
@@ -838,6 +900,7 @@ impl BackgroundTask for SwitchPortSettingsManager {
838900
let rnc_differs = match (config.body.rack_network_config.clone(), desired_config.body.rack_network_config.clone()) {
839901
(Some(current_rnc), Some(desired_rnc)) => {
840902
!hashset_eq(current_rnc.bgp.clone(), desired_rnc.bgp.clone()) ||
903+
!hashset_eq(current_rnc.bfd.clone(), desired_rnc.bfd.clone()) ||
841904
!hashset_eq(current_rnc.ports.clone(), desired_rnc.ports.clone()) ||
842905
current_rnc.rack_subnet != desired_rnc.rack_subnet ||
843906
current_rnc.infra_ip_first != desired_rnc.infra_ip_first ||

nexus/src/app/bfd.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ impl super::Nexus {
4242
self.background_tasks
4343
.driver
4444
.activate(&self.background_tasks.bfd_manager);
45+
// for timely propagation to bootstore
46+
self.background_tasks
47+
.driver
48+
.activate(&self.background_tasks.task_switch_port_settings_manager);
4549
Ok(())
4650
}
4751

@@ -56,6 +60,10 @@ impl super::Nexus {
5660
self.background_tasks
5761
.driver
5862
.activate(&self.background_tasks.bfd_manager);
63+
// for timely propagation to bootstore
64+
self.background_tasks
65+
.driver
66+
.activate(&self.background_tasks.task_switch_port_settings_manager);
5967
Ok(())
6068
}
6169

@@ -93,10 +101,10 @@ impl super::Nexus {
93101
required_rx: info.config.required_rx,
94102
mode: match info.config.mode {
95103
mg_admin_client::types::SessionMode::SingleHop => {
96-
params::BfdMode::SingleHop
104+
omicron_common::api::external::BfdMode::SingleHop
97105
}
98106
mg_admin_client::types::SessionMode::MultiHop => {
99-
params::BfdMode::MultiHop
107+
omicron_common::api::external::BfdMode::MultiHop
100108
}
101109
},
102110
})

nexus/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ impl nexus_test_interface::NexusServer for Server {
302302
infra_ip_last: Ipv4Addr::UNSPECIFIED,
303303
ports: Vec::new(),
304304
bgp: Vec::new(),
305+
bfd: Vec::new(),
305306
},
306307
},
307308
)

nexus/tests/integration_tests/endpoints.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ pub static DEMO_BFD_ENABLE: Lazy<params::BfdSessionEnable> =
595595
detection_threshold: 3,
596596
required_rx: 1000000,
597597
switch: "switch0".parse().unwrap(),
598-
mode: params::BfdMode::MultiHop,
598+
mode: omicron_common::api::external::BfdMode::MultiHop,
599599
});
600600

601601
pub static DEMO_BFD_DISABLE: Lazy<params::BfdSessionDisable> =

nexus/types/src/external_api/params.rs

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::external_api::shared;
99
use base64::Engine;
1010
use chrono::{DateTime, Utc};
1111
use omicron_common::api::external::{
12-
AddressLotKind, ByteCount, Hostname, IdentityMetadataCreateParams,
12+
AddressLotKind, BfdMode, ByteCount, Hostname, IdentityMetadataCreateParams,
1313
IdentityMetadataUpdateParams, InstanceCpuCount, IpNet, Ipv4Net, Ipv6Net,
1414
Name, NameOrId, PaginationOrder, RouteDestination, RouteTarget,
1515
SemverVersion,
@@ -1814,24 +1814,6 @@ pub struct BgpStatusSelector {
18141814
pub name_or_id: NameOrId,
18151815
}
18161816

1817-
#[derive(
1818-
Clone,
1819-
Copy,
1820-
Debug,
1821-
Deserialize,
1822-
Serialize,
1823-
JsonSchema,
1824-
PartialEq,
1825-
Eq,
1826-
Ord,
1827-
PartialOrd,
1828-
)]
1829-
#[serde(rename_all = "snake_case")]
1830-
pub enum BfdMode {
1831-
SingleHop,
1832-
MultiHop,
1833-
}
1834-
18351817
/// Information about a bidirectional forwarding detection (BFD) session.
18361818
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq)]
18371819
pub struct BfdSessionEnable {

nexus/types/src/external_api/shared.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ use strum::EnumIter;
1717
use uuid::Uuid;
1818

1919
pub use omicron_common::address::{IpRange, Ipv4Range, Ipv6Range};
20-
21-
use super::params::BfdMode;
20+
pub use omicron_common::api::external::BfdMode;
2221

2322
/// Maximum number of role assignments allowed on any one resource
2423
// Today's implementation assumes a relatively small number of role assignments

openapi/bootstrap-agent.json

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,51 @@
229229
}
230230
]
231231
},
232+
"BfdMode": {
233+
"description": "BFD connection mode.",
234+
"type": "string",
235+
"enum": [
236+
"single_hop",
237+
"multi_hop"
238+
]
239+
},
240+
"BfdPeerConfig": {
241+
"type": "object",
242+
"properties": {
243+
"detection_threshold": {
244+
"type": "integer",
245+
"format": "uint8",
246+
"minimum": 0
247+
},
248+
"local": {
249+
"nullable": true,
250+
"type": "string",
251+
"format": "ip"
252+
},
253+
"mode": {
254+
"$ref": "#/components/schemas/BfdMode"
255+
},
256+
"remote": {
257+
"type": "string",
258+
"format": "ip"
259+
},
260+
"required_rx": {
261+
"type": "integer",
262+
"format": "uint64",
263+
"minimum": 0
264+
},
265+
"switch": {
266+
"$ref": "#/components/schemas/SwitchLocation"
267+
}
268+
},
269+
"required": [
270+
"detection_threshold",
271+
"mode",
272+
"remote",
273+
"required_rx",
274+
"switch"
275+
]
276+
},
232277
"BgpConfig": {
233278
"type": "object",
234279
"properties": {
@@ -691,6 +736,14 @@
691736
"description": "Initial network configuration",
692737
"type": "object",
693738
"properties": {
739+
"bfd": {
740+
"description": "BFD configuration for connecting the rack to external networks",
741+
"default": [],
742+
"type": "array",
743+
"items": {
744+
"$ref": "#/components/schemas/BfdPeerConfig"
745+
}
746+
},
694747
"bgp": {
695748
"description": "BGP configurations for connecting the rack to external networks",
696749
"type": "array",

0 commit comments

Comments
 (0)