diff --git a/examples/ovsbridge_vlan_port.yml b/examples/ovsbridge_vlan_port.yml index b0e610035d..f84090ab98 100644 --- a/examples/ovsbridge_vlan_port.yml +++ b/examples/ovsbridge_vlan_port.yml @@ -3,6 +3,9 @@ interfaces: - name: ovs0 type: ovs-interface state: up + - name: ovs1 + type: ovs-interface + state: up - name: ovs-br0 type: ovs-bridge state: up @@ -12,3 +15,11 @@ interfaces: vlan: mode: access tag: 2 + - name: ovs1 + vlan: + mode: trunk + trunk-tags: + - id: 1 + - id-range: + min: 10 + max: 20 diff --git a/rust/src/lib/nm/nm_dbus/gen_conf/ovs.rs b/rust/src/lib/nm/nm_dbus/gen_conf/ovs.rs index 584ce928ed..489ec91e08 100644 --- a/rust/src/lib/nm/nm_dbus/gen_conf/ovs.rs +++ b/rust/src/lib/nm/nm_dbus/gen_conf/ovs.rs @@ -1,5 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 +use crate::nm::nm_dbus::ToDbusValue; use std::collections::HashMap; use super::super::{ @@ -9,11 +10,41 @@ use super::super::{ }; impl ToKeyfile for NmSettingOvsBridge {} -impl ToKeyfile for NmSettingOvsPort {} impl ToKeyfile for NmSettingOvsIface {} impl ToKeyfile for NmSettingOvsPatch {} impl ToKeyfile for NmSettingOvsDpdk {} +impl ToKeyfile for NmSettingOvsPort { + fn to_keyfile(&self) -> Result, NmError> { + let mut ret = HashMap::new(); + + for (k, v) in self.to_value()?.drain() { + if k != "trunks" { + ret.insert(k.to_string(), v); + } + } + if let Some(vlans) = self.trunks.as_ref() { + let mut vlans_clone = vlans.clone(); + vlans_clone.sort_unstable_by_key(|v| v.start); + let mut vlans_str = Vec::new(); + for vlan in vlans_clone { + let ret = if vlan.start == vlan.end { + vlan.start.to_string() + } else { + format!("{}-{}", vlan.start, vlan.end) + }; + vlans_str.push(ret); + } + ret.insert( + "trunks".to_string(), + zvariant::Value::new(vlans_str.join(",")), + ); + } + + Ok(ret) + } +} + impl ToKeyfile for NmSettingOvsExtIds { fn to_keyfile(&self) -> Result, NmError> { let mut ret = HashMap::new(); diff --git a/tests/integration/nm/gen_conf_test.py b/tests/integration/nm/gen_conf_test.py index ed6a08dc13..68b46076e2 100644 --- a/tests/integration/nm/gen_conf_test.py +++ b/tests/integration/nm/gen_conf_test.py @@ -13,6 +13,7 @@ from libnmstate.schema import RouteRule from libnmstate.schema import LLDP +from ..testlib import assertlib from ..testlib import iprule from ..testlib.env import is_k8s from ..testlib.env import nm_minor_version @@ -67,6 +68,42 @@ def test_gen_conf_ovs_same_name(eth1_up, cleanup_ovs_same_name): retry_verify_ovs_ports("br0", sorted(["eth1", "br0"])) +@pytest.mark.tier1 +@pytest.mark.skipif(is_k8s(), reason="K8S does not support genconf") +def test_gen_conf_ovs_trunk_vlan(): + desired_state = load_yaml( + """ +interfaces: + - name: ovs0 + type: ovs-interface + state: up + - name: ovs1 + type: ovs-interface + state: up + - name: ovs-br0 + type: ovs-bridge + state: up + bridge: + port: + - name: ovs0 + vlan: + mode: access + tag: 10 + - name: ovs1 + vlan: + mode: trunk + trunk-tags: + - id: 1 + - id-range: + min: 10 + max: 20 +""" + ) + + with gen_conf_apply(desired_state): + assertlib.assert_state_match(desired_state) + + @pytest.mark.tier1 def test_gen_conf_routes_rules(): desired_state = load_yaml(