diff --git a/rust/agama-dbus-server/src/network/model.rs b/rust/agama-dbus-server/src/network/model.rs index 3b8dbd9731..0d59fa171c 100644 --- a/rust/agama-dbus-server/src/network/model.rs +++ b/rust/agama-dbus-server/src/network/model.rs @@ -378,6 +378,7 @@ pub struct Connection { pub status: Status, pub interface: Option, pub controller: Option, + pub port_config: PortConfig, pub match_config: MatchConfig, pub config: ConnectionConfig, } @@ -397,6 +398,7 @@ impl Connection { DeviceType::Dummy => ConnectionConfig::Dummy, DeviceType::Bond => ConnectionConfig::Bond(Default::default()), DeviceType::Vlan => ConnectionConfig::Vlan(Default::default()), + DeviceType::Bridge => ConnectionConfig::Bridge(Default::default()), }; Self { id, @@ -436,6 +438,7 @@ impl Connection { || matches!(self.config, ConnectionConfig::Dummy) || matches!(self.config, ConnectionConfig::Bond(_)) || matches!(self.config, ConnectionConfig::Vlan(_)) + || matches!(self.config, ConnectionConfig::Bridge(_)) } } @@ -449,6 +452,7 @@ impl Default for Connection { status: Default::default(), interface: Default::default(), controller: Default::default(), + port_config: Default::default(), match_config: Default::default(), config: Default::default(), } @@ -464,6 +468,14 @@ pub enum ConnectionConfig { Dummy, Bond(BondConfig), Vlan(VlanConfig), + Bridge(BridgeConfig), +} + +#[derive(Default, Debug, PartialEq, Clone)] +pub enum PortConfig { + #[default] + None, + Bridge(BridgePortConfig), } impl From for ConnectionConfig { @@ -874,3 +886,19 @@ impl TryFrom for BondConfig { } } } + +#[derive(Debug, Default, PartialEq, Clone)] +pub struct BridgeConfig { + pub stp: bool, + pub priority: Option, + pub forward_delay: Option, + pub hello_time: Option, + pub max_age: Option, + pub ageing_time: Option, +} + +#[derive(Debug, Default, PartialEq, Clone)] +pub struct BridgePortConfig { + pub priority: Option, + pub path_cost: Option, +} diff --git a/rust/agama-dbus-server/src/network/nm/dbus.rs b/rust/agama-dbus-server/src/network/nm/dbus.rs index f424139aaa..b28d654dd3 100644 --- a/rust/agama-dbus-server/src/network/nm/dbus.rs +++ b/rust/agama-dbus-server/src/network/nm/dbus.rs @@ -20,6 +20,8 @@ const WIRELESS_SECURITY_KEY: &str = "802-11-wireless-security"; const LOOPBACK_KEY: &str = "loopback"; const DUMMY_KEY: &str = "dummy"; const VLAN_KEY: &str = "vlan"; +const BRIDGE_KEY: &str = "bridge"; +const BRIDGE_PORT_KEY: &str = "bridge-port"; /// Converts a connection struct into a HashMap that can be sent over D-Bus. /// @@ -39,14 +41,22 @@ pub fn connection_to_dbus<'a>( } if let Some(controller) = controller { - connection_dbus.insert("slave-type", "bond".into()); // TODO: only 'bond' is supported + let slave_type = match controller.config { + ConnectionConfig::Bond(_) => BOND_KEY, + ConnectionConfig::Bridge(_) => BRIDGE_KEY, + _ => { + log::error!("Controller {} has unhandled config type", controller.id); + "" + } + }; + connection_dbus.insert("slave-type", slave_type.into()); let master = controller .interface .as_deref() .unwrap_or(controller.id.as_str()); connection_dbus.insert("master", master.into()); } else { - connection_dbus.insert("slave-type", "".into()); // TODO: only 'bond' is supported + connection_dbus.insert("slave-type", "".into()); connection_dbus.insert("master", "".into()); } @@ -73,7 +83,7 @@ pub fn connection_to_dbus<'a>( if !connection_dbus.contains_key("interface-name") { connection_dbus.insert("interface-name", conn.id.as_str().into()); } - result.insert("bond", bond_config_to_dbus(bond)); + result.insert(BOND_KEY, bond_config_to_dbus(bond)); } ConnectionConfig::Dummy => { connection_dbus.insert("type", DUMMY_KEY.into()); @@ -82,9 +92,20 @@ pub fn connection_to_dbus<'a>( connection_dbus.insert("type", VLAN_KEY.into()); result.extend(vlan_config_to_dbus(vlan)); } + ConnectionConfig::Bridge(bridge) => { + connection_dbus.insert("type", BRIDGE_KEY.into()); + result.insert(BRIDGE_KEY, bridge_config_to_dbus(bridge)); + } _ => {} } + match &conn.port_config { + PortConfig::Bridge(bridge_port) => { + result.insert(BRIDGE_PORT_KEY, bridge_port_config_to_dbus(bridge_port)); + } + PortConfig::None => {} + } + result.insert("connection", connection_dbus); result } @@ -95,6 +116,10 @@ pub fn connection_to_dbus<'a>( pub fn connection_from_dbus(conn: OwnedNestedHash) -> Option { let mut connection = base_connection_from_dbus(&conn)?; + if let Some(bridge_port_config) = bridge_port_config_from_dbus(&conn) { + connection.port_config = PortConfig::Bridge(bridge_port_config); + } + if let Some(wireless_config) = wireless_config_from_dbus(&conn) { connection.config = ConnectionConfig::Wireless(wireless_config); return Some(connection); @@ -110,6 +135,11 @@ pub fn connection_from_dbus(conn: OwnedNestedHash) -> Option { return Some(connection); } + if let Some(bridge_config) = bridge_config_from_dbus(&conn) { + connection.config = ConnectionConfig::Bridge(bridge_config); + return Some(connection); + } + if conn.get(DUMMY_KEY).is_some() { connection.config = ConnectionConfig::Dummy; return Some(connection); @@ -313,6 +343,97 @@ fn bond_config_to_dbus(config: &BondConfig) -> HashMap<&str, zvariant::Value> { HashMap::from([("options", Value::new(options))]) } +fn bridge_config_to_dbus(bridge: &BridgeConfig) -> HashMap<&str, zvariant::Value> { + let mut hash = HashMap::new(); + + hash.insert("stp", bridge.stp.into()); + if let Some(prio) = bridge.priority { + hash.insert("priority", prio.into()); + } + if let Some(fwd_delay) = bridge.forward_delay { + hash.insert("forward-delay", fwd_delay.into()); + } + if let Some(hello_time) = bridge.hello_time { + hash.insert("hello-time", hello_time.into()); + } + if let Some(max_age) = bridge.max_age { + hash.insert("max-age", max_age.into()); + } + if let Some(ageing_time) = bridge.ageing_time { + hash.insert("ageing-time", ageing_time.into()); + } + + hash +} + +fn bridge_config_from_dbus(conn: &OwnedNestedHash) -> Option { + let Some(bridge) = conn.get(BRIDGE_KEY) else { + return None; + }; + + let Some(stp) = bridge.get("stp") else { + return None; + }; + + let mut bc = BridgeConfig { + stp: *stp.downcast_ref::()?, + ..Default::default() + }; + + if let Some(prio) = bridge.get("priority") { + bc.priority = Some(*prio.downcast_ref::()?); + } + + if let Some(fwd_delay) = bridge.get("forward-delay") { + bc.forward_delay = Some(*fwd_delay.downcast_ref::()?); + } + + if let Some(hello_time) = bridge.get("hello-time") { + bc.hello_time = Some(*hello_time.downcast_ref::()?); + } + + if let Some(max_age) = bridge.get("max-age") { + bc.max_age = Some(*max_age.downcast_ref::()?); + } + + if let Some(ageing_time) = bridge.get("ageing-time") { + bc.ageing_time = Some(*ageing_time.downcast_ref::()?); + } + + Some(bc) +} + +fn bridge_port_config_to_dbus(bridge_port: &BridgePortConfig) -> HashMap<&str, zvariant::Value> { + let mut hash = HashMap::new(); + + if let Some(prio) = bridge_port.priority { + hash.insert("priority", prio.into()); + } + if let Some(pc) = bridge_port.path_cost { + hash.insert("path-cost", pc.into()); + } + + hash +} + +fn bridge_port_config_from_dbus(conn: &OwnedNestedHash) -> Option { + let Some(bridge_port) = conn.get(BRIDGE_PORT_KEY) else { + return None; + }; + + let mut bpc = BridgePortConfig::default(); + + if let Some(prio) = bridge_port.get("priority") { + bpc.priority = Some(*prio.downcast_ref::()?); + } + + if let Some(path_cost) = bridge_port.get("path_cost") { + bpc.path_cost = Some(*path_cost.downcast_ref::()?); + } + + Some(bpc) +} + /// Converts a MatchConfig struct into a HashMap that can be sent over D-Bus. /// /// * `match_config`: MatchConfig to convert. diff --git a/rust/agama-lib/src/network/types.rs b/rust/agama-lib/src/network/types.rs index 6d26fc953d..cb8f9695c8 100644 --- a/rust/agama-lib/src/network/types.rs +++ b/rust/agama-lib/src/network/types.rs @@ -39,6 +39,7 @@ pub enum DeviceType { Dummy = 3, Bond = 4, Vlan = 5, + Bridge = 6, } /// Bond mode @@ -141,6 +142,7 @@ impl TryFrom for DeviceType { 3 => Ok(DeviceType::Dummy), 4 => Ok(DeviceType::Bond), 5 => Ok(DeviceType::Vlan), + 6 => Ok(DeviceType::Bridge), _ => Err(InvalidDeviceType(value)), } } diff --git a/rust/package/agama-cli.changes b/rust/package/agama-cli.changes index c259cd26a3..ccf0d6d60f 100644 --- a/rust/package/agama-cli.changes +++ b/rust/package/agama-cli.changes @@ -1,3 +1,13 @@ +------------------------------------------------------------------- +Thu Jan 23 18:00:00 UTC 2024 - Clemens Famulla-Conrad + +- Add Bridge model (gh#openSUSE/agama#1008) + +------------------------------------------------------------------- +Thu Jan 23 17:38:23 UTC 2024 - Clemens Famulla-Conrad + +- Add VLAN model (gh#openSUSE/agama#918) + ------------------------------------------------------------------- Thu Jan 11 15:34:15 UTC 2024 - Imobach Gonzalez Sosa