305 lines
10 KiB
Diff
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
|
|
|