Skip to main content

nv_redfish/
ethernet_interface.rs

1// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16//! Ethernet interfaces
17//!
18
19use crate::mac_address::MacAddress;
20use crate::schema::redfish::ethernet_interface::EthernetInterface as EthernetInterfaceSchema;
21use crate::schema::redfish::ethernet_interface_collection::EthernetInterfaceCollection as EthernetInterfaceCollectionSchema;
22use crate::Error;
23use crate::NvBmc;
24use crate::Resource;
25use crate::ResourceSchema;
26use nv_redfish_core::Bmc;
27use nv_redfish_core::NavProperty;
28use std::marker::PhantomData;
29use std::sync::Arc;
30use tagged_types::TaggedType;
31
32#[doc(inline)]
33pub use crate::schema::redfish::ethernet_interface::LinkStatus;
34
35/// Ethernet interfaces collection.
36///
37/// Provides functions to access collection members.
38pub struct EthernetInterfaceCollection<B: Bmc> {
39    bmc: NvBmc<B>,
40    collection: Arc<EthernetInterfaceCollectionSchema>,
41}
42
43impl<B: Bmc> EthernetInterfaceCollection<B> {
44    /// Create a new manager collection handle.
45    pub(crate) async fn new(
46        bmc: &NvBmc<B>,
47        nav: &NavProperty<EthernetInterfaceCollectionSchema>,
48    ) -> Result<Self, Error<B>> {
49        let collection = bmc.expand_property(nav).await?;
50        Ok(Self {
51            bmc: bmc.clone(),
52            collection,
53        })
54    }
55
56    /// List all managers available in this BMC.
57    ///
58    /// # Errors
59    ///
60    /// Returns an error if fetching manager data fails.
61    pub async fn members(&self) -> Result<Vec<EthernetInterface<B>>, Error<B>> {
62        let mut members = Vec::new();
63        for m in &self.collection.members {
64            members.push(EthernetInterface::new(&self.bmc, m).await?);
65        }
66        Ok(members)
67    }
68}
69
70/// Uefi device path for the interface.
71///
72/// Nv-redfish keeps open underlying type for `UefiDevicePath` because it
73/// can really be represented by any implementation of UEFI's device path.
74pub type UefiDevicePath<T> = TaggedType<T, UefiDevicePathTag>;
75#[doc(hidden)]
76#[derive(tagged_types::Tag)]
77#[implement(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
78#[transparent(Debug, Display, FromStr, Serialize, Deserialize)]
79#[capability(inner_access)]
80pub enum UefiDevicePathTag {}
81
82/// Ethernet Interface.
83///
84/// Provides functions to access ethernet interface.
85pub struct EthernetInterface<B: Bmc> {
86    data: Arc<EthernetInterfaceSchema>,
87    _marker: PhantomData<B>,
88}
89
90impl<B: Bmc> EthernetInterface<B> {
91    /// Create a new log service handle.
92    pub(crate) async fn new(
93        bmc: &NvBmc<B>,
94        nav: &NavProperty<EthernetInterfaceSchema>,
95    ) -> Result<Self, Error<B>> {
96        nav.get(bmc.as_ref())
97            .await
98            .map_err(crate::Error::Bmc)
99            .map(|data| Self {
100                data,
101                _marker: PhantomData,
102            })
103    }
104
105    /// Get the raw schema data for this ethernet interface.
106    #[must_use]
107    pub fn raw(&self) -> Arc<EthernetInterfaceSchema> {
108        self.data.clone()
109    }
110
111    /// State of the interface. `None` means that BMC hasn't reported
112    /// interface state or reported null.
113    #[must_use]
114    pub fn interface_enabled(&self) -> Option<bool> {
115        self.data
116            .interface_enabled
117            .as_ref()
118            .and_then(Option::as_ref)
119            .copied()
120    }
121
122    /// Link status of the interface.
123    #[must_use]
124    pub fn link_status(&self) -> Option<LinkStatus> {
125        self.data
126            .link_status
127            .as_ref()
128            .and_then(Option::as_ref)
129            .copied()
130    }
131
132    /// MAC address of the interface.
133    #[must_use]
134    pub fn mac_address(&self) -> Option<MacAddress<'_>> {
135        self.data
136            .mac_address
137            .as_ref()
138            .and_then(Option::as_ref)
139            .map(String::as_str)
140            .map(MacAddress::new)
141    }
142
143    /// Permanent MAC address of the interface.
144    #[must_use]
145    pub fn permanent_mac_address(&self) -> Option<MacAddress<'_>> {
146        self.data
147            .permanent_mac_address
148            .as_ref()
149            .and_then(Option::as_ref)
150            .map(String::as_str)
151            .map(MacAddress::new)
152    }
153
154    /// UEFI device path for the interface.
155    #[must_use]
156    pub fn uefi_device_path(&self) -> Option<UefiDevicePath<&str>> {
157        self.data
158            .uefi_device_path
159            .as_ref()
160            .and_then(Option::as_ref)
161            .map(String::as_str)
162            .map(UefiDevicePath::new)
163    }
164}
165
166impl<B: Bmc> Resource for EthernetInterface<B> {
167    fn resource_ref(&self) -> &ResourceSchema {
168        &self.data.as_ref().base
169    }
170}