Skip to main content

wayle_network/core/device/wired/
mod.rs

1pub(crate) mod monitoring;
2/// Wired device types.
3pub mod types;
4
5use std::sync::Arc;
6
7use types::SpeedMbps;
8pub(crate) use types::{DeviceWiredParams, LiveDeviceWiredParams, WiredProperties};
9use wayle_core::{Property, unwrap_dbus};
10use wayle_traits::{ModelMonitoring, Reactive};
11use zbus::{Connection, zvariant::OwnedObjectPath};
12
13use super::{Device, LiveDeviceParams};
14use crate::{
15    error::Error,
16    proxy::devices::{DeviceProxy, wired::DeviceWiredProxy},
17    types::device::NMDeviceType,
18};
19
20/// Wired (Ethernet) network device.
21///
22/// Provides access to wired-specific properties like link speed and permanent
23/// hardware address while inheriting all base device properties through Deref.
24#[derive(Debug, Clone)]
25pub struct DeviceWired {
26    /// The underlying NetworkManager device providing core network functionality.
27    pub core: Device,
28
29    /// Permanent hardware address of the device.
30    pub perm_hw_address: Property<String>,
31
32    /// Design speed of the device, in megabits/second (Mb/s).
33    pub speed: Property<SpeedMbps>,
34
35    /// Array of S/390 subchannels for S/390 or z/Architecture devices.
36    pub s390_subchannels: Property<Vec<String>>,
37}
38
39impl Reactive for DeviceWired {
40    type Context<'a> = DeviceWiredParams<'a>;
41    type LiveContext<'a> = LiveDeviceWiredParams<'a>;
42    type Error = Error;
43
44    async fn get(params: Self::Context<'_>) -> Result<Self, Self::Error> {
45        Self::from_path(params.connection, params.device_path).await
46    }
47
48    async fn get_live(params: Self::LiveContext<'_>) -> Result<Arc<Self>, Self::Error> {
49        Self::verify_is_ethernet_device(params.connection, &params.device_path).await?;
50
51        let base_device = Device::get_live(LiveDeviceParams {
52            connection: params.connection,
53            object_path: params.device_path.clone(),
54            cancellation_token: params.cancellation_token,
55        })
56        .await?;
57        let base = Device::clone(&base_device);
58        let wired_props =
59            Self::fetch_wired_properties(params.connection, &params.device_path).await?;
60        let device = Arc::new(Self::from_props(base, wired_props));
61
62        device.clone().start_monitoring().await?;
63
64        Ok(device)
65    }
66}
67
68impl DeviceWired {
69    async fn verify_is_ethernet_device(
70        connection: &Connection,
71        device_path: &OwnedObjectPath,
72    ) -> Result<(), Error> {
73        let device_proxy = DeviceProxy::new(connection, device_path)
74            .await
75            .map_err(Error::DbusError)?;
76
77        let device_type = device_proxy.device_type().await.map_err(Error::DbusError)?;
78
79        if device_type != NMDeviceType::Ethernet as u32 {
80            return Err(Error::WrongObjectType {
81                object_path: device_path.clone(),
82                expected: String::from("Ethernet device"),
83                actual: format!("device type {device_type}"),
84            });
85        }
86
87        Ok(())
88    }
89
90    async fn fetch_wired_properties(
91        connection: &Connection,
92        device_path: &OwnedObjectPath,
93    ) -> Result<WiredProperties, Error> {
94        let wired_proxy = DeviceWiredProxy::new(connection, device_path)
95            .await
96            .map_err(Error::DbusError)?;
97
98        let (perm_hw_address, speed, s390_subchannels) = tokio::join!(
99            wired_proxy.perm_hw_address(),
100            wired_proxy.speed(),
101            wired_proxy.s390_subchannels(),
102        );
103
104        Ok(WiredProperties {
105            perm_hw_address: unwrap_dbus!(perm_hw_address, device_path),
106            speed: unwrap_dbus!(speed, device_path),
107            s390_subchannels: unwrap_dbus!(s390_subchannels, device_path),
108        })
109    }
110
111    fn from_props(core: Device, props: WiredProperties) -> Self {
112        Self {
113            core,
114            perm_hw_address: Property::new(props.perm_hw_address),
115            speed: Property::new(props.speed),
116            s390_subchannels: Property::new(props.s390_subchannels),
117        }
118    }
119
120    async fn from_path(connection: &Connection, path: OwnedObjectPath) -> Result<Self, Error> {
121        Self::verify_is_ethernet_device(connection, &path).await?;
122
123        let base = Device::from_path(connection, path.clone(), None).await?;
124        let wired_props = Self::fetch_wired_properties(connection, &path).await?;
125
126        Ok(Self::from_props(base, wired_props))
127    }
128}