Skip to content

Commit

Permalink
Add bridge model (#1008)
Browse files Browse the repository at this point in the history
## Problem

Bridge interface wasn't implemented 

## Solution

* Implement bridge interface type with the subset of configuration
parameters needed for wicked migration (see
jcronenberg#66).

## Testing

- *Tested manually*
  • Loading branch information
imobachgs authored Jan 24, 2024
2 parents 6a99bea + 20417ad commit 764f398
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 3 deletions.
28 changes: 28 additions & 0 deletions rust/agama-dbus-server/src/network/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ pub struct Connection {
pub status: Status,
pub interface: Option<String>,
pub controller: Option<Uuid>,
pub port_config: PortConfig,
pub match_config: MatchConfig,
pub config: ConnectionConfig,
}
Expand All @@ -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,
Expand Down Expand Up @@ -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(_))
}
}

Expand All @@ -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(),
}
Expand All @@ -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<BondConfig> for ConnectionConfig {
Expand Down Expand Up @@ -874,3 +886,19 @@ impl TryFrom<ConnectionConfig> for BondConfig {
}
}
}

#[derive(Debug, Default, PartialEq, Clone)]
pub struct BridgeConfig {
pub stp: bool,
pub priority: Option<u32>,
pub forward_delay: Option<u32>,
pub hello_time: Option<u32>,
pub max_age: Option<u32>,
pub ageing_time: Option<u32>,
}

#[derive(Debug, Default, PartialEq, Clone)]
pub struct BridgePortConfig {
pub priority: Option<u32>,
pub path_cost: Option<u32>,
}
127 changes: 124 additions & 3 deletions rust/agama-dbus-server/src/network/nm/dbus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand All @@ -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());
}

Expand All @@ -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());
Expand All @@ -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
}
Expand All @@ -95,6 +116,10 @@ pub fn connection_to_dbus<'a>(
pub fn connection_from_dbus(conn: OwnedNestedHash) -> Option<Connection> {
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);
Expand All @@ -110,6 +135,11 @@ pub fn connection_from_dbus(conn: OwnedNestedHash) -> Option<Connection> {
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);
Expand Down Expand Up @@ -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<BridgeConfig> {
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::<bool>()?,
..Default::default()
};

if let Some(prio) = bridge.get("priority") {
bc.priority = Some(*prio.downcast_ref::<u32>()?);
}

if let Some(fwd_delay) = bridge.get("forward-delay") {
bc.forward_delay = Some(*fwd_delay.downcast_ref::<u32>()?);
}

if let Some(hello_time) = bridge.get("hello-time") {
bc.hello_time = Some(*hello_time.downcast_ref::<u32>()?);
}

if let Some(max_age) = bridge.get("max-age") {
bc.max_age = Some(*max_age.downcast_ref::<u32>()?);
}

if let Some(ageing_time) = bridge.get("ageing-time") {
bc.ageing_time = Some(*ageing_time.downcast_ref::<u32>()?);
}

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<BridgePortConfig> {
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::<u32>()?);
}

if let Some(path_cost) = bridge_port.get("path_cost") {
bpc.path_cost = Some(*path_cost.downcast_ref::<u32>()?);
}

Some(bpc)
}

/// Converts a MatchConfig struct into a HashMap that can be sent over D-Bus.
///
/// * `match_config`: MatchConfig to convert.
Expand Down
2 changes: 2 additions & 0 deletions rust/agama-lib/src/network/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pub enum DeviceType {
Dummy = 3,
Bond = 4,
Vlan = 5,
Bridge = 6,
}

/// Bond mode
Expand Down Expand Up @@ -141,6 +142,7 @@ impl TryFrom<u8> for DeviceType {
3 => Ok(DeviceType::Dummy),
4 => Ok(DeviceType::Bond),
5 => Ok(DeviceType::Vlan),
6 => Ok(DeviceType::Bridge),
_ => Err(InvalidDeviceType(value)),
}
}
Expand Down
10 changes: 10 additions & 0 deletions rust/package/agama-cli.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
-------------------------------------------------------------------
Thu Jan 23 18:00:00 UTC 2024 - Clemens Famulla-Conrad <cfamullaconrad@suse.de>

- Add Bridge model (gh#openSUSE/agama#1008)

-------------------------------------------------------------------
Thu Jan 23 17:38:23 UTC 2024 - Clemens Famulla-Conrad <cfamullaconrad@suse.de>

- Add VLAN model (gh#openSUSE/agama#918)

-------------------------------------------------------------------
Thu Jan 11 15:34:15 UTC 2024 - Imobach Gonzalez Sosa <igonzalezsosa@suse.com>

Expand Down

0 comments on commit 764f398

Please sign in to comment.