From 3fce3bc36e6e8bfc321327061c8d4af28f299036 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Wed, 22 Apr 2020 13:28:26 +0200 Subject: [PATCH] src/config/network/parser.rs: parse MTU settings --- src/api2/config/network.rs | 22 ++++++++++++++++++++++ src/api2/types.rs | 8 ++++++++ src/config/network.rs | 15 ++++++++++++++- src/config/network/lexer.rs | 2 ++ src/config/network/parser.rs | 27 ++++++++++++++++++++++++--- 5 files changed, 70 insertions(+), 4 deletions(-) diff --git a/src/api2/config/network.rs b/src/api2/config/network.rs index 26a66038..cfb82980 100644 --- a/src/api2/config/network.rs +++ b/src/api2/config/network.rs @@ -91,6 +91,10 @@ pub enum DeletableProperty { method_v4, /// Delete the whole IPv6 configuration entry. method_v6, + /// Delete mtu for IPv4. + mtu_v4, + /// Delete mtu IPv6. + mtu_v6, } #[api( @@ -116,6 +120,18 @@ pub enum DeletableProperty { schema: IP_SCHEMA, optional: true, }, + mtu_v4: { + description: "Maximum Transmission Unit for IPv4.", + optional: true, + minimum: 46, + maximum: 65535, + }, + mtu_v6: { + description: "Maximum Transmission Unit for IPv6.", + optional: true, + minimum: 46, + maximum: 65535, + }, delete: { description: "List of properties to delete.", type: Array, @@ -141,6 +157,8 @@ pub fn update_interface( method_v6: Option, address: Option, gateway: Option, + mtu_v4: Option, + mtu_v6: Option, delete: Option>, digest: Option, ) -> Result<(), Error> { @@ -165,12 +183,16 @@ pub fn update_interface( DeletableProperty::gateway_v6 => { interface.gateway_v6 = None; }, DeletableProperty::method_v4 => { interface.method_v4 = None; }, DeletableProperty::method_v6 => { interface.method_v6 = None; }, + DeletableProperty::mtu_v4 => { interface.mtu_v4 = None; }, + DeletableProperty::mtu_v6 => { interface.mtu_v6 = None; }, } } } if method_v4.is_some() { interface.method_v4 = method_v4; } if method_v6.is_some() { interface.method_v6 = method_v6; } + if mtu_v4.is_some() { interface.mtu_v4 = mtu_v4; } + if mtu_v6.is_some() { interface.mtu_v6 = mtu_v6; } if let Some(address) = address { let (_, _, is_v6) = network::parse_cidr(&address)?; diff --git a/src/api2/types.rs b/src/api2/types.rs index 580ed911..9385008d 100644 --- a/src/api2/types.rs +++ b/src/api2/types.rs @@ -585,6 +585,14 @@ pub struct Interface { #[serde(skip_serializing_if="Option::is_none")] /// IPv6 gateway pub gateway_v6: Option, + + #[serde(skip_serializing_if="Option::is_none")] + /// Maximum Transmission Unit for IPv4 + pub mtu_v4: Option, + #[serde(skip_serializing_if="Option::is_none")] + /// Maximum Transmission Unit for IPv6 + pub mtu_v6: Option, + #[serde(skip_serializing_if="Vec::is_empty")] pub options_v4: Vec, #[serde(skip_serializing_if="Vec::is_empty")] diff --git a/src/config/network.rs b/src/config/network.rs index 82be5de2..fb0c6d83 100644 --- a/src/config/network.rs +++ b/src/config/network.rs @@ -30,6 +30,8 @@ impl Interface { gateway_v4: None, cidr_v6: None, gateway_v6: None, + mtu_v4: None, + mtu_v6: None, options_v4: Vec::new(), options_v6: Vec::new(), } @@ -107,6 +109,10 @@ impl Interface { } } + if let Some(mtu) = &self.mtu_v4 { + writeln!(w, " mtu {}", mtu)?; + } + for option in &self.options_v4 { writeln!(w, " {}", option)?; } @@ -124,6 +130,10 @@ impl Interface { } } + if let Some(mtu) = &self.mtu_v6 { + writeln!(w, " mtu {}", mtu)?; + } + for option in &self.options_v6 { writeln!(w, " {}", option)?; } @@ -148,7 +158,10 @@ impl Interface { writeln!(w, "auto {}", self.name)?; } - if self.method_v4 == self.method_v6 { + if self.method_v4 == self.method_v6 + && self.mtu_v4 == self.mtu_v6 + && self.options_v4.is_empty() == self.options_v6.is_empty() + { if let Some(method) = self.method_v4 { writeln!(w, "iface {} {}", self.name, method_to_str(method))?; self.write_iface_attributes_v4(w, method)?; diff --git a/src/config/network/lexer.rs b/src/config/network/lexer.rs index c897d464..93d3b36f 100644 --- a/src/config/network/lexer.rs +++ b/src/config/network/lexer.rs @@ -21,6 +21,7 @@ pub enum Token { Netmask, Static, Attribute, + MTU, EOF, } @@ -38,6 +39,7 @@ lazy_static! { map.insert("manual", Token::Manual); map.insert("netmask", Token::Netmask); map.insert("static", Token::Static); + map.insert("mtu", Token::MTU); map }; } diff --git a/src/config/network/parser.rs b/src/config/network/parser.rs index 4f24ed2a..3ecae114 100644 --- a/src/config/network/parser.rs +++ b/src/config/network/parser.rs @@ -121,6 +121,22 @@ impl NetworkParser { Ok(()) } + fn parse_iface_mtu(&mut self) -> Result { + self.eat(Token::MTU)?; + + let mtu = self.next_text()?; + let mtu = match u64::from_str_radix(&mtu, 10) { + Ok(mtu) => mtu, + Err(err) => { + bail!("unable to parse mtu value '{}' - {}", mtu, err); + } + }; + + self.eat(Token::Newline)?; + + Ok(mtu) + } + fn parse_to_eol(&mut self) -> Result { let mut line = String::new(); loop { @@ -140,7 +156,7 @@ impl NetworkParser { Ok(()) } - fn parse_iface_attributes(&mut self, interface: &mut Interface) -> Result<(), Error> { + fn parse_iface_attributes(&mut self, interface: &mut Interface, family_v4: bool, family_v6: bool) -> Result<(), Error> { loop { match self.peek()? { @@ -152,6 +168,11 @@ impl NetworkParser { match self.peek()? { Token::Address => self.parse_iface_address(interface)?, Token::Gateway => self.parse_iface_gateway(interface)?, + Token::MTU => { + let mtu = self.parse_iface_mtu()?; + if family_v4 { interface.mtu_v4 = Some(mtu); } + if family_v6 { interface.mtu_v6 = Some(mtu); } + } Token::Netmask => bail!("netmask is deprecated and no longer supported"), _ => { self.parse_iface_addon_attribute(interface)?; @@ -200,7 +221,7 @@ impl NetworkParser { interface.set_method_v6(config_method)?; } - if has_attributes { self.parse_iface_attributes(&mut interface)?; } + if has_attributes { self.parse_iface_attributes(&mut interface, address_family_v4, address_family_v6)?; } } else { let mut interface = Interface::new(iface.clone()); if address_family_v4 { @@ -210,7 +231,7 @@ impl NetworkParser { interface.set_method_v6(config_method)?; } - if has_attributes { self.parse_iface_attributes(&mut interface)?; } + if has_attributes { self.parse_iface_attributes(&mut interface, address_family_v4, address_family_v6)?; } config.interfaces.insert(interface.name.clone(), interface);