Skip to content

Commit

Permalink
Add LLDP support
Browse files Browse the repository at this point in the history
  • Loading branch information
Nieuwejaar committed Jul 19, 2024
1 parent 92c39e5 commit 954e72f
Show file tree
Hide file tree
Showing 40 changed files with 1,226 additions and 211 deletions.
1 change: 1 addition & 0 deletions clients/sled-agent-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ progenitor::generate_api!(
BfdPeerConfig = { derives = [Eq, Hash] },
BgpConfig = { derives = [Eq, Hash] },
BgpPeerConfig = { derives = [Eq, Hash] },
LldpPortConfig = { derives = [Eq, Hash, PartialOrd, Ord] },
OmicronPhysicalDiskConfig = { derives = [Eq, Hash, PartialOrd, Ord] },
PortConfigV2 = { derives = [Eq, Hash] },
RouteConfig = { derives = [Eq, Hash] },
Expand Down
34 changes: 15 additions & 19 deletions common/src/api/external/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2157,7 +2157,7 @@ pub struct SwitchPortSettingsView {
pub links: Vec<SwitchPortLinkConfig>,

/// Link-layer discovery protocol (LLDP) settings.
pub link_lldp: Vec<LldpServiceConfig>,
pub link_lldp: Vec<LldpLinkConfig>,

/// Layer 3 interface settings.
pub interfaces: Vec<SwitchInterfaceConfig>,
Expand Down Expand Up @@ -2299,7 +2299,7 @@ pub struct SwitchPortLinkConfig {

/// The link-layer discovery protocol service configuration id for this
/// link.
pub lldp_service_config_id: Uuid,
pub lldp_link_config_id: Uuid,

/// The name of this link.
pub link_name: String,
Expand All @@ -2319,34 +2319,30 @@ pub struct SwitchPortLinkConfig {

/// A link layer discovery protocol (LLDP) service configuration.
#[derive(Clone, Debug, Deserialize, JsonSchema, Serialize, PartialEq)]
pub struct LldpServiceConfig {
pub struct LldpLinkConfig {
/// The id of this LLDP service instance.
pub id: Uuid,

/// The link-layer discovery protocol configuration for this service.
pub lldp_config_id: Option<Uuid>,

/// Whether or not the LLDP service is enabled.
pub enabled: bool,
}

/// A link layer discovery protocol (LLDP) base configuration.
#[derive(Clone, Debug, Deserialize, JsonSchema, Serialize, PartialEq)]
pub struct LldpConfig {
#[serde(flatten)]
pub identity: IdentityMetadata,
/// The LLDP link name TLV.
pub link_name: Option<String>,

/// The LLDP link description TLV.
pub link_description: Option<String>,

/// The LLDP chassis identifier TLV.
pub chassis_id: String,
pub chassis_id: Option<String>,

/// THE LLDP system name TLV.
pub system_name: String,
/// The LLDP system name TLV.
pub system_name: Option<String>,

/// THE LLDP system description TLV.
pub system_description: String,
/// The LLDP system description TLV.
pub system_description: Option<String>,

/// THE LLDP management IP TLV.
pub management_ip: oxnet::IpNet,
/// The LLDP management IP TLV.
pub management_ip: Option<oxnet::IpNet>,
}

/// Describes the kind of an switch interface.
Expand Down
107 changes: 106 additions & 1 deletion common/src/api/internal/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,107 @@ impl FromStr for UplinkAddressConfig {
}
}

#[derive(
Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq, JsonSchema,
)]
#[serde(rename_all = "snake_case")]
/// To what extent should this port participate in LLDP
pub enum LldpAdminStatus {
#[default]
Enabled,
Disabled,
RxOnly,
TxOnly,
}

impl fmt::Display for LldpAdminStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
LldpAdminStatus::Enabled => write!(f, "enabled"),
LldpAdminStatus::Disabled => write!(f, "disabled"),
LldpAdminStatus::RxOnly => write!(f, "rx_only"),
LldpAdminStatus::TxOnly => write!(f, "tx_only"),
}
}
}

#[derive(Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct ParseLldpAdminStatusError(String);

impl std::fmt::Display for ParseLldpAdminStatusError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "LLDP admin status error: {}", self.0)
}
}

impl FromStr for LldpAdminStatus {
type Err = ParseLldpAdminStatusError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"enabled" => Ok(Self::Enabled),
"disabled" => Ok(Self::Disabled),
"rxonly" | "rx_only" => Ok(Self::RxOnly),
"txonly" | "tx_only" => Ok(Self::TxOnly),
_ => Err(ParseLldpAdminStatusError(format!(
"not a valid admin status: {s}"
))),
}
}
}

/// Per-port LLDP configuration settings. Only the "status" setting is
/// mandatory. All other fields have natural defaults or may be inherited from
/// the switch.
#[derive(
Clone, Debug, Deserialize, Serialize, PartialEq, Eq, JsonSchema, Default,
)]
pub struct LldpPortConfig {
/// To what extent should this port participate in LLDP
pub status: LldpAdminStatus,
/// Chassis ID to advertise. If this is set, it will be advertised as a
/// LocallyAssigned ID type. If this is not set, it will be
/// inherited from the switch-level settings.
pub chassis_id: Option<String>,
/// Port ID to advertise. If this is set, it will be advertised as a
/// LocallyAssigned ID type. If this is not set, it will be set to
/// the port name. e.g., qsfp0/0.
pub port_id: Option<String>,
/// Port description to advertise. If this is not set, no
/// description will be advertised.
pub port_description: Option<String>,
/// System name to advertise. If this is not set, it will be
/// inherited from the switch-level settings.
pub system_name: Option<String>,
/// System description to advertise. If this is not set, it will be
/// inherited from the switch-level settings.
pub system_description: Option<String>,
/// Management IP addresses to advertise. If this is not set, it will be
/// inherited from the switch-level settings.
pub management_addrs: Option<Vec<IpAddr>>,
}

impl From<external::LldpLinkConfig> for LldpPortConfig {
fn from(x: external::LldpLinkConfig) -> Self {
Self {
status: if x.enabled {
LldpAdminStatus::Enabled
} else {
LldpAdminStatus::Disabled
},
chassis_id: x.chassis_id.clone(),
port_id: x.link_name.clone(),
port_description: x.link_description.clone(),
system_name: x.system_name.clone(),
system_description: x.system_description.clone(),
management_addrs: match x.management_ip {
Some(a) => Some(vec![a.addr()]),
None => None,
},
}
}
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, JsonSchema)]
pub struct PortConfigV2 {
/// The set of routes associated with this port.
Expand All @@ -393,6 +494,8 @@ pub struct PortConfigV2 {
/// Whether or not to set autonegotiation
#[serde(default)]
pub autoneg: bool,
/// LLDP configuration for this port
pub lldp: Option<LldpPortConfig>,
}

/// A set of switch uplinks.
Expand All @@ -409,11 +512,13 @@ pub struct HostPortConfig {
/// IP Address and prefix (e.g., `192.168.0.1/16`) to apply to switchport
/// (must be in infra_ip pool). May also include an optional VLAN ID.
pub addrs: Vec<UplinkAddressConfig>,

pub lldp: Option<LldpPortConfig>,
}

impl From<PortConfigV2> for HostPortConfig {
fn from(x: PortConfigV2) -> Self {
Self { port: x.port, addrs: x.addresses }
Self { port: x.port, addrs: x.addresses, lldp: x.lldp.clone() }
}
}

Expand Down
23 changes: 8 additions & 15 deletions nexus/db-model/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,35 +139,28 @@ table! {
table! {
switch_port_settings_link_config (port_settings_id, link_name) {
port_settings_id -> Uuid,
lldp_service_config_id -> Uuid,
link_name -> Text,
mtu -> Int4,
fec -> crate::SwitchLinkFecEnum,
speed -> crate::SwitchLinkSpeedEnum,
autoneg -> Bool,
lldp_link_config_id -> Uuid,
}
}

table! {
lldp_service_config (id) {
lldp_link_config (id) {
id -> Uuid,
enabled -> Bool,
lldp_config_id -> Nullable<Uuid>,
}
}

table! {
lldp_config (id) {
id -> Uuid,
name -> Text,
description -> Text,
link_name -> Nullable<Text>,
link_description -> Nullable<Text>,
time_created -> Timestamptz,
time_modified -> Timestamptz,
time_deleted -> Nullable<Timestamptz>,
chassis_id -> Text,
system_name -> Text,
system_description -> Text,
management_ip -> Inet,
chassis_id -> Nullable<Text>,
system_name -> Nullable<Text>,
system_description -> Nullable<Text>,
management_ip -> Nullable<Inet>,
}
}

Expand Down
3 changes: 2 additions & 1 deletion nexus/db-model/src/schema_versions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use std::collections::BTreeMap;
///
/// This must be updated when you change the database schema. Refer to
/// schema/crdb/README.adoc in the root of this repository for details.
pub const SCHEMA_VERSION: SemverVersion = SemverVersion::new(83, 0, 0);
pub const SCHEMA_VERSION: SemverVersion = SemverVersion::new(84, 0, 0);

/// List of all past database schema versions, in *reverse* order
///
Expand All @@ -29,6 +29,7 @@ static KNOWN_VERSIONS: Lazy<Vec<KnownVersion>> = Lazy::new(|| {
// | leaving the first copy as an example for the next person.
// v
// KnownVersion::new(next_int, "unique-dirname-with-the-sql-files"),
KnownVersion::new(84, "collapse_lldp_settings"),
KnownVersion::new(83, "dataset-address-optional"),
KnownVersion::new(82, "region-port"),
KnownVersion::new(81, "add-nullable-filesystem-pool"),
Expand Down
Loading

0 comments on commit 954e72f

Please sign in to comment.