nmstate/BZ_2111398-ovs-add-support-...

305 lines
10 KiB
Diff

From dce5073432b4d7ce9bb0f3322c9970a714ae44a6 Mon Sep 17 00:00:00 2001
From: Beniamino Galvani <bgalvani@redhat.com>
Date: Wed, 23 Nov 2022 10:26:35 +0100
Subject: [PATCH] ovs: add support for port trunks
This commit adds support for the "trunk-tags" property in ovs ports.
Example:
```yml
- name: ovs0
type: ovs-interface
state: up
- name: ovs-br0
type: ovs-bridge
state: up
bridge:
port:
- name: ovs0
vlan:
mode: trunk
trunk-tags:
- id-range:
min: 20
max: 22
- id-range:
min: 30
max: 32
- id: 40
```
The property is implemented in NM via "ovs-port.trunks" and
corresponds to the "trunks" property of ports in ovs:
```
Bridge ovs-br0
Port ovs0
trunks: [20, 21, 22, 30, 31, 32, 40]
Interface ovs0
type: internal
```
Signed-off-by: Beniamino Galvani <bgalvani@redhat.com>
Signed-off-by: Gris Ge <fge@redhat.com>
---
rust/src/lib/nm/nm_dbus/connection/conn.rs | 38 ++++++++++++++++++++++
rust/src/lib/nm/nm_dbus/connection/mod.rs | 2 +-
rust/src/lib/nm/nm_dbus/connection/ovs.rs | 24 +++++++++++++-
rust/src/lib/nm/nm_dbus/mod.rs | 2 +-
rust/src/lib/nm/query/ovs.rs | 32 +++++++++++++++---
rust/src/lib/nm/settings/ovs.rs | 25 +++++++++++---
6 files changed, 111 insertions(+), 12 deletions(-)
diff --git a/rust/src/lib/nm/nm_dbus/connection/conn.rs b/rust/src/lib/nm/nm_dbus/connection/conn.rs
index 673bc597..69784fed 100644
--- a/rust/src/lib/nm/nm_dbus/connection/conn.rs
+++ b/rust/src/lib/nm/nm_dbus/connection/conn.rs
@@ -442,3 +442,41 @@ pub(crate) fn nm_con_get_from_obj_path(
}
Ok(nm_conn)
}
+
+#[derive(Debug, Clone, PartialEq, Default, Deserialize)]
+#[serde(try_from = "DbusDictionary")]
+#[non_exhaustive]
+pub struct NmRange {
+ pub start: u64,
+ pub end: u64,
+ _other: DbusDictionary,
+}
+
+impl TryFrom<DbusDictionary> for NmRange {
+ type Error = NmError;
+ fn try_from(mut v: DbusDictionary) -> Result<Self, Self::Error> {
+ Ok(Self {
+ start: _from_map!(v, "start", u64::try_from)?.unwrap_or_default(),
+ end: _from_map!(v, "end", u64::try_from)?.unwrap_or_default(),
+ _other: v,
+ })
+ }
+}
+
+impl NmRange {
+ pub fn to_value(&self) -> Result<zvariant::Value, NmError> {
+ let mut ret = zvariant::Dict::new(
+ zvariant::Signature::from_str_unchecked("s"),
+ zvariant::Signature::from_str_unchecked("v"),
+ );
+ ret.append(
+ zvariant::Value::new("start"),
+ zvariant::Value::new(zvariant::Value::U64(self.start)),
+ )?;
+ ret.append(
+ zvariant::Value::new("end"),
+ zvariant::Value::new(zvariant::Value::U64(self.end)),
+ )?;
+ Ok(zvariant::Value::Dict(ret))
+ }
+}
diff --git a/rust/src/lib/nm/nm_dbus/connection/mod.rs b/rust/src/lib/nm/nm_dbus/connection/mod.rs
index 04f2ee49..57504f77 100644
--- a/rust/src/lib/nm/nm_dbus/connection/mod.rs
+++ b/rust/src/lib/nm/nm_dbus/connection/mod.rs
@@ -42,7 +42,7 @@ pub use self::bridge::{
NmSettingBridge, NmSettingBridgePort, NmSettingBridgeVlanRange,
};
pub use self::conn::{
- NmConnection, NmSettingConnection, NmSettingsConnectionFlag,
+ NmConnection, NmRange, NmSettingConnection, NmSettingsConnectionFlag,
};
pub use self::ethtool::NmSettingEthtool;
pub use self::ieee8021x::NmSetting8021X;
diff --git a/rust/src/lib/nm/nm_dbus/connection/ovs.rs b/rust/src/lib/nm/nm_dbus/connection/ovs.rs
index 2221c003..b728d88f 100644
--- a/rust/src/lib/nm/nm_dbus/connection/ovs.rs
+++ b/rust/src/lib/nm/nm_dbus/connection/ovs.rs
@@ -5,7 +5,7 @@ use std::convert::TryFrom;
use serde::Deserialize;
-use super::super::{connection::DbusDictionary, NmError, ToDbusValue};
+use super::super::{connection::DbusDictionary, NmError, NmRange, ToDbusValue};
#[derive(Debug, Clone, PartialEq, Default, Deserialize)]
#[serde(try_from = "DbusDictionary")]
@@ -71,6 +71,7 @@ pub struct NmSettingOvsPort {
pub down_delay: Option<u32>,
pub tag: Option<u32>,
pub vlan_mode: Option<String>,
+ pub trunks: Option<Vec<NmRange>>,
pub lacp: Option<String>,
_other: HashMap<String, zvariant::OwnedValue>,
}
@@ -85,11 +86,23 @@ impl TryFrom<DbusDictionary> for NmSettingOvsPort {
tag: _from_map!(v, "tag", u32::try_from)?,
vlan_mode: _from_map!(v, "vlan-mode", String::try_from)?,
lacp: _from_map!(v, "lacp", String::try_from)?,
+ trunks: _from_map!(v, "trunks", own_value_to_trunks)?,
_other: v,
})
}
}
+fn own_value_to_trunks(
+ value: zvariant::OwnedValue,
+) -> Result<Vec<NmRange>, NmError> {
+ let mut ret = Vec::new();
+ let raw_ranges = Vec::<DbusDictionary>::try_from(value)?;
+ for raw_range in raw_ranges {
+ ret.push(NmRange::try_from(raw_range)?);
+ }
+ Ok(ret)
+}
+
impl ToDbusValue for NmSettingOvsPort {
fn to_value(&self) -> Result<HashMap<&str, zvariant::Value>, NmError> {
let mut ret = HashMap::new();
@@ -111,6 +124,15 @@ impl ToDbusValue for NmSettingOvsPort {
if let Some(v) = self.lacp.as_ref() {
ret.insert("lacp", zvariant::Value::new(v));
}
+ if let Some(v) = self.trunks.as_ref() {
+ let mut trunk_values = zvariant::Array::new(
+ zvariant::Signature::from_str_unchecked("a{sv}"),
+ );
+ for range in v {
+ trunk_values.append(range.to_value()?)?;
+ }
+ ret.insert("trunks", zvariant::Value::Array(trunk_values));
+ }
ret.extend(self._other.iter().map(|(key, value)| {
(key.as_str(), zvariant::Value::from(value.clone()))
}));
diff --git a/rust/src/lib/nm/nm_dbus/mod.rs b/rust/src/lib/nm/nm_dbus/mod.rs
index 5e408be5..053d92a0 100644
--- a/rust/src/lib/nm/nm_dbus/mod.rs
+++ b/rust/src/lib/nm/nm_dbus/mod.rs
@@ -26,7 +26,7 @@ pub use self::active_connection::{
NmActiveConnection, NM_ACTIVATION_STATE_FLAG_EXTERNAL,
};
pub use self::connection::{
- NmConnection, NmIpRoute, NmIpRouteRule, NmIpRouteRuleAction,
+ NmConnection, NmIpRoute, NmIpRouteRule, NmIpRouteRuleAction, NmRange,
NmSetting8021X, NmSettingBond, NmSettingBridge, NmSettingBridgePort,
NmSettingBridgeVlanRange, NmSettingConnection, NmSettingEthtool,
NmSettingInfiniBand, NmSettingIp, NmSettingIpMethod, NmSettingLoopback,
diff --git a/rust/src/lib/nm/query/ovs.rs b/rust/src/lib/nm/query/ovs.rs
index 30bfc160..33b82150 100644
--- a/rust/src/lib/nm/query/ovs.rs
+++ b/rust/src/lib/nm/query/ovs.rs
@@ -3,15 +3,16 @@
use std::convert::TryFrom;
use super::super::{
- nm_dbus::NmConnection,
+ nm_dbus::{NmConnection, NmRange},
settings::{get_exist_profile, NM_SETTING_OVS_PORT_SETTING_NAME},
};
use crate::{
- BridgePortVlanConfig, BridgePortVlanMode, Interface, InterfaceType,
- Interfaces, NmstateError, OvsBridgeBondConfig, OvsBridgeBondMode,
- OvsBridgeBondPortConfig, OvsBridgeConfig, OvsBridgeOptions,
- OvsBridgePortConfig, OvsDpdkConfig, OvsPatchConfig,
+ BridgePortTunkTag, BridgePortVlanConfig, BridgePortVlanMode,
+ BridgePortVlanRange, Interface, InterfaceType, Interfaces, NmstateError,
+ OvsBridgeBondConfig, OvsBridgeBondMode, OvsBridgeBondPortConfig,
+ OvsBridgeConfig, OvsBridgeOptions, OvsBridgePortConfig, OvsDpdkConfig,
+ OvsPatchConfig,
};
pub(crate) fn nm_ovs_bridge_conf_get(
@@ -202,6 +203,16 @@ fn get_vlan_info(nm_conn: &NmConnection) -> Option<BridgePortVlanConfig> {
return None;
}
}),
+ trunk_tags: match port_conf.trunks.as_deref() {
+ Some(trunks) => {
+ let mut ret = Vec::new();
+ for t in trunks {
+ ret.push(nm_range_to_trunk_tag(t));
+ }
+ Some(ret)
+ }
+ _ => None,
+ },
..Default::default()
});
}
@@ -209,6 +220,17 @@ fn get_vlan_info(nm_conn: &NmConnection) -> Option<BridgePortVlanConfig> {
None
}
+fn nm_range_to_trunk_tag(range: &NmRange) -> BridgePortTunkTag {
+ if range.start == range.end {
+ BridgePortTunkTag::Id(range.start as u16)
+ } else {
+ BridgePortTunkTag::IdRange(BridgePortVlanRange {
+ min: range.start as u16,
+ max: range.end as u16,
+ })
+ }
+}
+
pub(crate) fn get_ovs_patch_config(
nm_conn: &NmConnection,
) -> Option<OvsPatchConfig> {
diff --git a/rust/src/lib/nm/settings/ovs.rs b/rust/src/lib/nm/settings/ovs.rs
index 3d3b3c5a..dd71d8a7 100644
--- a/rust/src/lib/nm/settings/ovs.rs
+++ b/rust/src/lib/nm/settings/ovs.rs
@@ -4,15 +4,16 @@ use std::collections::HashMap;
use std::iter::FromIterator;
use super::super::nm_dbus::{
- NmConnection, NmSettingOvsDpdk, NmSettingOvsExtIds, NmSettingOvsIface,
- NmSettingOvsPatch,
+ NmConnection, NmRange, NmSettingOvsDpdk, NmSettingOvsExtIds,
+ NmSettingOvsIface, NmSettingOvsPatch,
};
use super::connection::gen_nm_conn_setting;
use crate::{
- BaseInterface, Interface, InterfaceType, NmstateError, OvsBridgeBondMode,
- OvsBridgeInterface, OvsBridgePortConfig, OvsInterface, UnknownInterface,
+ BaseInterface, BridgePortTunkTag, Interface, InterfaceType, NmstateError,
+ OvsBridgeBondMode, OvsBridgeInterface, OvsBridgePortConfig, OvsInterface,
+ UnknownInterface,
};
pub(crate) fn create_ovs_port_nm_conn(
@@ -66,11 +67,27 @@ pub(crate) fn create_ovs_port_nm_conn(
if let Some(vlan_mode) = vlan_conf.mode {
nm_ovs_port_set.vlan_mode = Some(vlan_mode.to_string());
}
+ if let Some(trunk_tags) = &vlan_conf.trunk_tags {
+ let mut ret = Vec::new();
+ for trunk_tag in trunk_tags.as_slice() {
+ ret.push(trunk_tag_to_nm_range(trunk_tag));
+ }
+ nm_ovs_port_set.trunks = Some(ret);
+ }
}
+
nm_conn.ovs_port = Some(nm_ovs_port_set);
Ok(nm_conn)
}
+fn trunk_tag_to_nm_range(trunk_tag: &BridgePortTunkTag) -> NmRange {
+ let mut ret = NmRange::default();
+ let (vid_min, vid_max) = trunk_tag.get_vlan_tag_range();
+ ret.start = vid_min.into();
+ ret.end = vid_max.into();
+ ret
+}
+
pub(crate) fn get_ovs_port_name(
ovs_br_iface: &OvsBridgeInterface,
ovs_iface_name: &str,
--
2.39.0