diff --git a/CHANGELOG.md b/CHANGELOG.md index 07f3563..f13c047 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed * The default output power interlock threshold has been increased from 0 dBm to 20 dBm. +* The MTU used for MQTT messages is now configurable in flash. ### Added diff --git a/src/hardware/external_mac.rs b/src/hardware/external_mac.rs index 97df944..0fd3861 100644 --- a/src/hardware/external_mac.rs +++ b/src/hardware/external_mac.rs @@ -2,6 +2,7 @@ use super::Mac; use enc424j600::EthPhy; use smoltcp_nal::smoltcp; +use super::net_interface::MAX_MTU; impl smoltcp::phy::Device for Mac { type RxToken<'a> @@ -15,7 +16,7 @@ impl smoltcp::phy::Device for Mac { fn capabilities(&self) -> smoltcp::phy::DeviceCapabilities { let mut caps = smoltcp::phy::DeviceCapabilities::default(); - caps.max_transmission_unit = 1500; + caps.max_transmission_unit = MAX_MTU; caps.medium = smoltcp::phy::Medium::Ethernet; caps } @@ -24,7 +25,7 @@ impl smoltcp::phy::Device for Mac { &mut self, _timestamp: smoltcp::time::Instant, ) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { - let mut buffer = [0u8; 1500]; + let mut buffer = [0u8; MAX_MTU]; let len = match self { Mac::W5500(w5500) => w5500.read_frame(&mut buffer[..]).unwrap(), Mac::Enc424j600(mac) => match mac.recv_packet(false) { @@ -79,7 +80,7 @@ impl smoltcp::phy::TxToken for TxToken<'_> { where F: FnOnce(&mut [u8]) -> R, { - let mut buffer = [0u8; 1500]; + let mut buffer = [0u8; MAX_MTU]; let result = f(&mut buffer[..len]); match self.mac { Mac::W5500(mac) => { diff --git a/src/hardware/net_interface.rs b/src/hardware/net_interface.rs index b1fa3d8..3863fd4 100644 --- a/src/hardware/net_interface.rs +++ b/src/hardware/net_interface.rs @@ -6,6 +6,8 @@ use super::Mac; /// The number of TCP sockets supported in the network stack. const NUM_TCP_SOCKETS: usize = 4; +/// The maximum MTU configurable for the network interface. +pub const MAX_MTU: usize = 1500; /// Containers for smoltcp-related network configurations struct NetStorage { diff --git a/src/hardware/setup.rs b/src/hardware/setup.rs index 2701c53..bf56de7 100644 --- a/src/hardware/setup.rs +++ b/src/hardware/setup.rs @@ -16,7 +16,7 @@ use super::{ }; use stm32f4xx_hal::hal::delay::DelayNs; -use crate::settings::eeprom::main_board::BoosterMainBoardData; +use crate::settings::eeprom::main_board::{BoosterMainBoardData, Mtu}; use stm32f4xx_hal as hal; @@ -323,6 +323,7 @@ pub fn setup( ip: Leaf(eeprom_settings.ip), broker: Leaf(eeprom_settings.broker), gateway: Leaf(eeprom_settings.gateway), + mtu: Leaf(Mtu(eeprom_settings.mtu)), id: Leaf(eeprom_settings.id), booster: runtime_settings, }; diff --git a/src/settings/eeprom/main_board.rs b/src/settings/eeprom/main_board.rs index acd2173..64166ab 100644 --- a/src/settings/eeprom/main_board.rs +++ b/src/settings/eeprom/main_board.rs @@ -23,6 +23,7 @@ use heapless::String; use smoltcp_nal::smoltcp; use crate::hardware::chassis_fans::DEFAULT_FAN_SPEED; +use crate::hardware::net_interface::MAX_MTU; use super::{sinara::SinaraConfiguration, SemVersion}; use serde::{Deserialize, Serialize}; @@ -42,6 +43,26 @@ fn identifier_is_valid(id: &str) -> bool { id.len() <= 23 && id.chars().all(|x| x.is_alphanumeric() || x == '-') } +#[derive(DeserializeFromStr, Copy, Clone, Debug)] +pub struct Mtu(pub u16); + +impl core::str::FromStr for Mtu { + type Err = &'static str; + fn from_str(s: &str) -> Result { + let mtu = s.parse::().map_err(|_| "Invalid MTU format (expected decimal integer)")?; + if mtu as usize > MAX_MTU { + return Err("Specified MTU exceeds maximum allowed value"); + } + Ok(Self(mtu)) + } +} + +impl Serialize for Mtu { + fn serialize(&self, serializer: S) -> Result { + serializer.serialize_u16(self.0) + } +} + #[derive(DeserializeFromStr, Copy, Clone, Debug)] pub struct IpAddr(pub smoltcp_nal::smoltcp::wire::Ipv4Address); @@ -171,6 +192,7 @@ pub struct SerializedMainBoardData { pub netmask: IpAddr, pub id: MqttIdentifier, pub fan_speed: f32, + pub mtu: u16, } impl SerializedMainBoardData { @@ -189,6 +211,7 @@ impl SerializedMainBoardData { gateway: self.gateway, id: self.id.0, fan_speed: self.fan_speed, + mtu: self.mtu, } } } @@ -203,6 +226,7 @@ pub struct BoosterMainBoardData { pub gateway: IpAddr, pub id: String<23>, pub fan_speed: f32, + pub mtu: u16, } impl BoosterMainBoardData { @@ -238,6 +262,7 @@ impl BoosterMainBoardData { gateway: "0.0.0.0".parse().unwrap(), id: name, fan_speed: DEFAULT_FAN_SPEED, + mtu: MAX_MTU as u16, } } @@ -278,3 +303,24 @@ impl BoosterMainBoardData { Ok((config.with_mac(eui48), modified)) } } + + +#[cfg(test)] +mod tests { + // use super::MTU; + // use core::str::FromStr; + // + // // TODO: restructure repo tree to allow logic tests to run not on embedded + // // hardware, but on the host machine + // #[test] + // fn test_mtu_parsing() { + // let mtu: MTU = MTU::from_str("1500").unwrap(); + // assert_eq!(mtu.0, 1500); + + // let mtu_err = MTU::from_str("1501"); + // assert!(mtu_err.is_err()); + + // let mtu_err = MTU::from_str("invalid"); + // assert!(mtu_err.is_err()); + // } +} diff --git a/src/settings/mod.rs b/src/settings/mod.rs index 60f27ef..78b2163 100644 --- a/src/settings/mod.rs +++ b/src/settings/mod.rs @@ -9,6 +9,7 @@ pub mod flash; pub mod runtime_settings; use eeprom::main_board::{Cidr, IpAddr}; +use eeprom::main_board::Mtu; use runtime_settings::RuntimeSettings; #[derive(Clone, Debug, Tree)] @@ -22,6 +23,7 @@ pub struct Settings { pub broker: Leaf>, pub gateway: Leaf, pub id: Leaf>, + pub mtu: Leaf, } impl serial_settings::Settings for Settings { @@ -33,5 +35,6 @@ impl serial_settings::Settings for Settings { self.ip = Leaf("0.0.0.0/0".parse().unwrap()); self.broker = Leaf("mqtt".parse().unwrap()); self.gateway = Leaf("0.0.0.0".parse().unwrap()); + self.mtu = Leaf("1500".parse().unwrap()); } }