5
0
mirror of git://git.proxmox.com/git/proxmox-backup.git synced 2024-12-22 13:34:16 +03:00

config: parse vlan interface from config

Support three types of vlan configurations defined in interfaces,
conforming to the PVE configurations:

iface nic.<vlan-id> inet

iface vlan<vlan-id> inet
	vlan-raw-device <nic>

iface <arbitraty-name> inet
	vlan-id <vlan-id>
	vlan-raw-device <nic>

* Add lexer Token enum variants for vlan-id and vlan-raw-device and parse
  them in parse_iface_attributes.
* Add tests to verify this works in the above scenarios

Signed-off-by: Stefan Lendl <s.lendl@proxmox.com>
Tested-by: Lukas Wagner <l.wagner@proxmox.com>
Reviewed-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Folke Gleumes <f.gleumes@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Stefan Lendl 2024-04-04 12:00:32 +02:00 committed by Thomas Lamprecht
parent 5f14a0a2ab
commit b276acf7ba
2 changed files with 102 additions and 1 deletions

View File

@ -24,6 +24,8 @@ pub enum Token {
MTU,
BridgePorts,
BridgeVlanAware,
VlanId,
VlanRawDevice,
BondSlaves,
BondMode,
BondPrimary,
@ -50,6 +52,10 @@ lazy_static! {
map.insert("bridge_ports", Token::BridgePorts);
map.insert("bridge-vlan-aware", Token::BridgeVlanAware);
map.insert("bridge_vlan_aware", Token::BridgeVlanAware);
map.insert("vlan-id", Token::VlanId);
map.insert("vlan_id", Token::VlanId);
map.insert("vlan-raw-device", Token::VlanRawDevice);
map.insert("vlan_raw_device", Token::VlanRawDevice);
map.insert("bond-slaves", Token::BondSlaves);
map.insert("bond_slaves", Token::BondSlaves);
map.insert("bond-mode", Token::BondMode);

View File

@ -361,6 +361,20 @@ impl<R: BufRead> NetworkParser<R> {
interface.bond_xmit_hash_policy = Some(policy);
self.eat(Token::Newline)?;
}
Token::VlanId => {
self.eat(Token::VlanId)?;
let vlan_id = self.next_text()?.parse()?;
interface.vlan_id = Some(vlan_id);
set_interface_type(interface, NetworkInterfaceType::Vlan)?;
self.eat(Token::Newline)?;
}
Token::VlanRawDevice => {
self.eat(Token::VlanRawDevice)?;
let vlan_raw_device = self.next_text()?;
interface.vlan_raw_device = Some(vlan_raw_device);
set_interface_type(interface, NetworkInterfaceType::Vlan)?;
self.eat(Token::Newline)?;
}
_ => {
// parse addon attributes
let option = self.parse_to_eol()?;
@ -522,7 +536,7 @@ impl<R: BufRead> NetworkParser<R> {
lazy_static! {
static ref INTERFACE_ALIAS_REGEX: Regex = Regex::new(r"^\S+:\d+$").unwrap();
static ref VLAN_INTERFACE_REGEX: Regex = Regex::new(r"^\S+\.\d+$").unwrap();
static ref VLAN_INTERFACE_REGEX: Regex = Regex::new(r"^\S+\.\d+|vlan\d+$").unwrap();
}
if let Some(existing_interfaces) = existing_interfaces {
@ -748,4 +762,85 @@ mod test {
Ok(())
}
#[test]
fn test_network_config_parser_vlan_id_in_name() {
let input = "iface vmbr0.100 inet static manual";
let mut parser = NetworkParser::new(input.as_bytes());
let config = parser.parse_interfaces(None).unwrap();
let iface = config.interfaces.get("vmbr0.100").unwrap();
assert_eq!(iface.interface_type, NetworkInterfaceType::Vlan);
assert_eq!(iface.vlan_raw_device, None);
assert_eq!(iface.vlan_id, None);
}
#[test]
fn test_network_config_parser_vlan_with_raw_device() {
let input = r#"
iface vlan100 inet manual
vlan-raw-device vmbr0"#;
let mut parser = NetworkParser::new(input.as_bytes());
let config = parser.parse_interfaces(None).unwrap();
let iface = config.interfaces.get("vlan100").unwrap();
assert_eq!(iface.interface_type, NetworkInterfaceType::Vlan);
assert_eq!(iface.vlan_raw_device, Some(String::from("vmbr0")));
assert_eq!(iface.vlan_id, None);
}
#[test]
fn test_network_config_parser_vlan_with_raw_device_static() {
let input = r#"
iface vlan100 inet static
vlan-raw-device vmbr0
address 10.0.0.100/16"#;
let mut parser = NetworkParser::new(input.as_bytes());
let config = parser.parse_interfaces(None).unwrap();
let iface = config.interfaces.get("vlan100").unwrap();
assert_eq!(iface.interface_type, NetworkInterfaceType::Vlan);
assert_eq!(iface.vlan_raw_device, Some(String::from("vmbr0")));
assert_eq!(iface.vlan_id, None);
assert_eq!(iface.method, Some(NetworkConfigMethod::Static));
assert_eq!(iface.cidr, Some(String::from("10.0.0.100/16")));
}
#[test]
fn test_network_config_parser_vlan_individual_name() {
let input = r#"
iface individual_name inet manual
vlan-id 100
vlan-raw-device vmbr0"#;
let mut parser = NetworkParser::new(input.as_bytes());
let config = parser.parse_interfaces(None).unwrap();
let iface = config.interfaces.get("individual_name").unwrap();
assert_eq!(iface.interface_type, NetworkInterfaceType::Vlan);
assert_eq!(iface.vlan_raw_device, Some(String::from("vmbr0")));
assert_eq!(iface.vlan_id, Some(100));
}
#[test]
fn test_network_config_parser_vlan_individual_name_static() {
let input = r#"
iface individual_name inet static
vlan-id 100
vlan-raw-device vmbr0
address 10.0.0.100/16
"#;
let mut parser = NetworkParser::new(input.as_bytes());
let config = parser.parse_interfaces(None).unwrap();
let iface = config.interfaces.get("individual_name").unwrap();
assert_eq!(iface.interface_type, NetworkInterfaceType::Vlan);
assert_eq!(iface.vlan_raw_device, Some(String::from("vmbr0")));
assert_eq!(iface.vlan_id, Some(100));
assert_eq!(iface.method, Some(NetworkConfigMethod::Static));
assert_eq!(iface.cidr, Some(String::from("10.0.0.100/16")));
}
}