From 0b5fda2cd9e156744d1935f872288eedaa341a3b Mon Sep 17 00:00:00 2001 From: linuswck Date: Wed, 4 Sep 2024 15:24:03 +0800 Subject: [PATCH] net: close oldest sock if available socks run out - By default, smoltcp by default reset any new connections if there is no available socket --- src/main.rs | 37 +++++++++++++++++++++++++++-- src/net/cmd_handler.rs | 1 + src/net/net.rs | 53 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 86 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index 0b95626..5505f79 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ #![cfg_attr(not(test), no_main)] #![cfg_attr(not(test), no_std)] -use core::marker::PhantomData; +use core::{marker::PhantomData, u32}; use cortex_m_rt::entry; use log::{debug, info}; @@ -82,6 +82,8 @@ fn main() -> ! { let eth_data_buffer = unsafe { addr_of_mut!(ETH_DATA_BUFFER).as_mut().unwrap() }; + let mut sock_ts: [u32; net::net::NUM_OF_SOCKETS] = [0; net::net::NUM_OF_SOCKETS]; + loop { wd.feed(); @@ -183,6 +185,10 @@ fn main() -> ! { thermostat.start_tec_readings_conversion(); } + let mut num_of_connected_sock: u8 = 0; + let mut oldest_connected_sock_ts: u32 = u32::MAX; + let mut oldest_connected_sock_id: usize = 0; + net::net::for_each(|mut socket, id| { if net::net::eth_is_socket_active(socket) && net::net::eth_is_socket_connected(socket) { if net::net::eth_can_sock_recv(socket) && net::net::eth_can_sock_send(socket) { @@ -204,8 +210,35 @@ fn main() -> ! { ); } } + + num_of_connected_sock += 1; + + if sock_ts[id] == 0 { + sock_ts[id] = sys_timer::now(); + } + if oldest_connected_sock_ts > sock_ts[id] { + oldest_connected_sock_ts = sock_ts[id]; + oldest_connected_sock_id = id; + } + } else { + sock_ts[id] = 0; } - }) + }); + + if num_of_connected_sock == net::net::NUM_OF_SOCKETS as u8 { + let mut sock_handle = net::net::eth_get_sock_handle(oldest_connected_sock_id); + net::cmd_handler::send_response( + eth_data_buffer, + net::cmd_handler::ResponseEnum::ConnectionClose, + None, + &mut sock_handle, + ); + net::net::eth_poll_iface(); + debug!("Waiting for ConnectionClose msg to be sent"); + while !net::net::eth_is_data_sent() { } + net::net::eth_close_socket_by_id(oldest_connected_sock_id); + debug!("Closing socket id: {:?}", oldest_connected_sock_id); + } } State::SaveLdThermostatSettings => { // State Transition diff --git a/src/net/cmd_handler.rs b/src/net/cmd_handler.rs index 3626198..ed6bdfb 100644 --- a/src/net/cmd_handler.rs +++ b/src/net/cmd_handler.rs @@ -31,6 +31,7 @@ pub enum ResponseEnum { InvalidDatatype, InvalidCmd, HardReset, + ConnectionClose, } pub type MsgType = Option<&'static str>; diff --git a/src/net/net.rs b/src/net/net.rs index 22233f3..0c23451 100644 --- a/src/net/net.rs +++ b/src/net/net.rs @@ -47,6 +47,7 @@ pub struct ServerHandle { dma: EthernetDMA<'static, 'static>, phy: EthernetPhy>, Pin<'C', 1, Alternate<11>>>>, link_was_up: bool, + data_sent: bool, } pub type EthernetPins = EthPins, PA7, PB11, PB12, PB13, PC4, PC5>; pub struct EthernetMgmtPins { @@ -55,7 +56,7 @@ pub struct EthernetMgmtPins { } pub type EthInterface = Interface; -pub const NUM_OF_SOCKETS: usize = 4; +pub const NUM_OF_SOCKETS: usize = 4 + 1; const TCP_BUFFER_SIZE: usize = 4096; static mut RX_RING: Option<[RxRingEntry; 8]> = None; static mut TX_RING: Option<[TxRingEntry; 8]> = None; @@ -138,7 +139,7 @@ impl ServerHandle { let tcp_handles = { // Do not use NUM_OF_SOCKETS to define array size to // remind developers to create/remove tcp_handles accordingly after changing NUM_OF_SOCKETS - let mut tcp_handles: [MaybeUninit; 4] = unsafe { MaybeUninit::uninit().assume_init() }; + let mut tcp_handles: [MaybeUninit; 5] = unsafe { MaybeUninit::uninit().assume_init() }; macro_rules! create_tcp_handle { ($rx_storage:ident, $tx_storage:ident, $handle:expr) => { @@ -155,8 +156,9 @@ impl ServerHandle { create_tcp_handle!(RX_STORAGE1, TX_STORAGE1, tcp_handles[1]); create_tcp_handle!(RX_STORAGE2, TX_STORAGE2, tcp_handles[2]); create_tcp_handle!(RX_STORAGE3, TX_STORAGE3, tcp_handles[3]); + create_tcp_handle!(RX_STORAGE4, TX_STORAGE4, tcp_handles[4]); - unsafe { mem::transmute::<_, [SocketHandle; 4]>(tcp_handles) } + unsafe { mem::transmute::<_, [SocketHandle; 5]>(tcp_handles) } }; for i in 0..NUM_OF_SOCKETS { @@ -189,6 +191,7 @@ impl ServerHandle { dma: dma, phy: phy, link_was_up: false, + data_sent: true, }; unsafe { @@ -249,6 +252,7 @@ impl ServerHandle { cortex_m::interrupt::free(|_| { match socket.send_slice(&buffer[..num_bytes]) { Ok(_) => { + self.data_sent = false; info!("Enqueued {} bytes.", num_bytes); } Err(err) => { @@ -501,6 +505,46 @@ pub fn eth_close_socket(socket_handles: SocketHandle) { } } +pub fn eth_get_sock_handle(id: usize) -> SocketHandle { + unsafe { + if let Some(ref mut server_handle) = SERVER_HANDLE { + server_handle.socket_handles[id] + } else { + panic!("eth_get_sock_handle is called before init"); + } + } +} + +pub fn eth_close_socket_by_id(id: usize) { + unsafe { + if let Some(ref mut server_handle) = SERVER_HANDLE { + server_handle.close_socket(server_handle.socket_handles[id]) + } else { + panic!("eth_close_socket_by_id is called before init"); + } + } +} + +pub fn eth_is_data_sent() -> bool { + unsafe { + if let Some(ref mut server_handle) = SERVER_HANDLE { + server_handle.data_sent + } else { + panic!("eth_is_data_sent is called before init"); + } + } +} + +fn eth_set_data_sent(val: bool) { + unsafe { + if let Some(ref mut server_handle) = SERVER_HANDLE { + server_handle.data_sent = val; + } else { + panic!("eth_is_data_sent is called before init"); + } + } +} + pub fn for_each(mut callback: F) { unsafe { if let Some(ref mut server_handle) = SERVER_HANDLE { @@ -521,6 +565,9 @@ fn ETH() { if interrupt_reason.rx { eth_poll_iface(); } + if interrupt_reason.tx { + eth_set_data_sent(true); + } debug!("Ethernet Interrupt{:?}", interrupt_reason); }