Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

linux bridge: Add support of vlan protocol #1938

Merged
merged 1 commit into from Jun 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion rust/src/lib/ifaces/linux_bridge.rs
Expand Up @@ -6,7 +6,8 @@ use std::str::FromStr;
use serde::{de, de::Visitor, Deserialize, Deserializer, Serialize};

use crate::{
BaseInterface, BridgePortVlanConfig, ErrorKind, InterfaceType, NmstateError,
BaseInterface, BridgePortVlanConfig, ErrorKind, InterfaceType,
NmstateError, VlanProtocol,
};

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
Expand Down Expand Up @@ -432,6 +433,8 @@ pub struct LinuxBridgeOptions {
pub multicast_startup_query_interval: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub stp: Option<LinuxBridgeStpOptions>,
#[serde(skip_serializing_if = "Option::is_none")]
pub vlan_protocol: Option<VlanProtocol>,
}

impl LinuxBridgeOptions {
Expand Down
2 changes: 1 addition & 1 deletion rust/src/lib/ifaces/mod.rs
Expand Up @@ -50,6 +50,6 @@ pub use ovs::{
OvsDpdkConfig, OvsInterface, OvsPatchConfig,
};
pub use sriov::{SrIovConfig, SrIovVfConfig};
pub use vlan::{VlanConfig, VlanInterface};
pub use vlan::{VlanConfig, VlanInterface, VlanProtocol};
pub use vrf::{VrfConfig, VrfInterface};
pub use vxlan::{VxlanConfig, VxlanInterface};
27 changes: 27 additions & 0 deletions rust/src/lib/ifaces/vlan.rs
Expand Up @@ -59,3 +59,30 @@ impl VlanConfig {
}
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum VlanProtocol {
#[serde(rename = "802.1q")]
Ieee8021Q,
#[serde(rename = "802.1ad")]
Ieee8021Ad,
}

impl Default for VlanProtocol {
fn default() -> Self {
Self::Ieee8021Q
}
}

impl std::fmt::Display for VlanProtocol {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
Self::Ieee8021Q => "802.1q",
Self::Ieee8021Ad => "802.1ad",
}
)
}
}
3 changes: 2 additions & 1 deletion rust/src/lib/lib.rs
Expand Up @@ -41,7 +41,8 @@ pub use crate::ifaces::{
OvsBridgeBondPortConfig, OvsBridgeConfig, OvsBridgeInterface,
OvsBridgeOptions, OvsBridgePortConfig, OvsDpdkConfig, OvsInterface,
OvsPatchConfig, SrIovConfig, SrIovVfConfig, VethConfig, VlanConfig,
VlanInterface, VrfConfig, VrfInterface, VxlanConfig, VxlanInterface,
VlanInterface, VlanProtocol, VrfConfig, VrfInterface, VxlanConfig,
VxlanInterface,
};
pub use crate::ip::{
Dhcpv4ClientId, Dhcpv6Duid, InterfaceIpAddr, InterfaceIpv4, InterfaceIpv6,
Expand Down
14 changes: 14 additions & 0 deletions rust/src/lib/nispor/linux_bridge.rs
Expand Up @@ -6,6 +6,7 @@ use crate::{
nispor::linux_bridge_port_vlan::parse_port_vlan_conf, BaseInterface,
LinuxBridgeConfig, LinuxBridgeInterface, LinuxBridgeMulticastRouterType,
LinuxBridgeOptions, LinuxBridgePortConfig, LinuxBridgeStpOptions,
VlanProtocol,
};

pub(crate) fn np_bridge_to_nmstate(
Expand Down Expand Up @@ -118,6 +119,19 @@ fn np_bridge_options_to_nmstate(
np_bridge.multicast_startup_query_count;
options.multicast_startup_query_interval =
np_bridge.multicast_startup_query_interval;
options.vlan_protocol =
np_bridge.vlan_protocol.as_ref().and_then(|v| match v {
nispor::BridgeVlanProtocol::Ieee8021Q => {
Some(VlanProtocol::Ieee8021Q)
}
nispor::BridgeVlanProtocol::Ieee8021AD => {
Some(VlanProtocol::Ieee8021Ad)
}
_ => {
warn!("Unsupported linux bridge vlan protocol {:?}", v);
None
}
});
}
options
}
Expand Down
9 changes: 8 additions & 1 deletion rust/src/lib/nm/bridge.rs
@@ -1,10 +1,11 @@
use crate::nm::nm_dbus::{
NmConnection, NmSettingBridge, NmSettingBridgeVlanRange,
NmConnection, NmSettingBridge, NmSettingBridgeVlanRange, NmVlanProtocol,
};

use crate::{
BridgePortTunkTag, BridgePortVlanConfig, BridgePortVlanMode,
LinuxBridgeInterface, LinuxBridgeOptions, LinuxBridgeStpOptions,
VlanProtocol,
};

pub(crate) fn gen_nm_br_setting(
Expand Down Expand Up @@ -82,6 +83,12 @@ fn apply_br_options(
if let Some(v) = br_opts.multicast_startup_query_interval.as_ref() {
nm_br_set.multicast_startup_query_interval = Some(*v);
}
if let Some(v) = br_opts.vlan_protocol.as_ref() {
nm_br_set.vlan_protocol = match v {
VlanProtocol::Ieee8021Q => Some(NmVlanProtocol::Dot1Q),
VlanProtocol::Ieee8021Ad => Some(NmVlanProtocol::Dot1Ad),
}
}

if let Some(stp_opts) = br_opts.stp.as_ref() {
apply_stp_setting(nm_br_set, stp_opts);
Expand Down
2 changes: 1 addition & 1 deletion rust/src/lib/nm/nm_dbus/connection/bridge.rs
Expand Up @@ -293,7 +293,7 @@ impl NmSettingBridge {
ret.insert("vlan-filtering", zvariant::Value::new(v));
}
if let Some(v) = &self.vlan_protocol {
ret.insert("vlan-protocol", zvariant::Value::new(v.to_str()));
ret.insert("vlan-protocol", zvariant::Value::new(v.to_string()));
}
if let Some(v) = &self.vlan_stats_enabled {
ret.insert("vlan-stats-enabled", zvariant::Value::new(v));
Expand Down
18 changes: 11 additions & 7 deletions rust/src/lib/nm/nm_dbus/connection/vlan.rs
Expand Up @@ -55,7 +55,7 @@ impl NmSettingVlan {
}

const NM_VLAN_PROTOCOL_802_1Q: &str = "802.1Q";
const NM_VLAN_PROTOCOL_802_1AD: &str = "802.1AD";
const NM_VLAN_PROTOCOL_802_1AD: &str = "802.1ad";

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
Expand Down Expand Up @@ -93,11 +93,15 @@ impl TryFrom<String> for NmVlanProtocol {
}
}

impl NmVlanProtocol {
pub fn to_str(self) -> &'static str {
match self {
Self::Dot1Q => NM_VLAN_PROTOCOL_802_1Q,
Self::Dot1Ad => NM_VLAN_PROTOCOL_802_1AD,
}
impl std::fmt::Display for NmVlanProtocol {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
Self::Dot1Q => NM_VLAN_PROTOCOL_802_1Q,
Self::Dot1Ad => NM_VLAN_PROTOCOL_802_1AD,
}
)
}
}
3 changes: 3 additions & 0 deletions rust/src/python/libnmstate/schema.py
Expand Up @@ -214,6 +214,7 @@ class Options:
MULTICAST_QUERY_RESPONSE_INTERVAL = "multicast-query-response-interval"
MULTICAST_STARTUP_QUERY_COUNT = "multicast-startup-query-count"
MULTICAST_STARTUP_QUERY_INTERVAL = "multicast-startup-query-interval"
VLAN_PROTOCOL = "vlan-protocol"

# Read only properties begin
HELLO_TIMER = "hello-timer"
Expand Down Expand Up @@ -274,6 +275,8 @@ class VLAN:

ID = "id"
BASE_IFACE = "base-iface"
PROTOCOL_802_1AD = "802.1ad"
PROTOCOL_802_1Q = "802.1q"


class VXLAN:
Expand Down
21 changes: 21 additions & 0 deletions tests/integration/linux_bridge_test.py
Expand Up @@ -36,6 +36,7 @@
from libnmstate.schema import InterfaceIPv6
from libnmstate.schema import InterfaceState
from libnmstate.schema import LinuxBridge
from libnmstate.schema import VLAN

from .testlib import assertlib
from .testlib.assertlib import assert_mac_address
Expand Down Expand Up @@ -985,3 +986,23 @@ def test_linux_bridge_show_port_ip_as_disabled(bridge0_with_port0):
assert state[Interface.KEY][0][Interface.IPV6] == {
InterfaceIPv6.ENABLED: False
}


@pytest.mark.tier1
@pytest.mark.parametrize(
"vlan_protocol",
[
VLAN.PROTOCOL_802_1AD,
VLAN.PROTOCOL_802_1Q,
],
)
def test_linux_bridge_set_vlan_protocol(bridge0_with_port0, vlan_protocol):
iface_state = {
Interface.NAME: TEST_BRIDGE0,
LinuxBridge.CONFIG_SUBTREE: {
LinuxBridge.OPTIONS_SUBTREE: {
LinuxBridge.Options.VLAN_PROTOCOL: vlan_protocol,
}
},
}
libnmstate.apply({Interface.KEY: [iface_state]})