diff --git a/awkernel_lib/src/net/if_net.rs b/awkernel_lib/src/net/if_net.rs index b80abfaf9..c16f54840 100644 --- a/awkernel_lib/src/net/if_net.rs +++ b/awkernel_lib/src/net/if_net.rs @@ -27,7 +27,7 @@ use smoltcp::{ wire::HardwareAddress, }; -use crate::sync::{mcs::MCSNode, mutex::Mutex}; +use crate::sync::{mcs::MCSNode, mutex::Mutex, rwlock::RwLock}; use super::{ ether::{extract_headers, NetworkHdr, TransportHdr, ETHER_ADDR_LEN}, @@ -163,6 +163,7 @@ impl Device for NetDriverRef<'_> { pub(super) struct IfNet { vlan: Option, pub(super) inner: Mutex, + pub(super) socket_set: RwLock>, rx_irq_to_driver: BTreeMap, tx_only_ringq: Vec>>>, pub(super) net_device: Arc, @@ -173,7 +174,6 @@ pub(super) struct IfNet { pub(super) struct IfNetInner { pub(super) interface: Interface, - pub(super) socket_set: SocketSet<'static>, pub(super) default_gateway_ipv4: Option, multicast_addr_ipv4: BTreeSet, @@ -182,8 +182,8 @@ pub(super) struct IfNetInner { impl IfNetInner { #[inline(always)] - pub fn split(&mut self) -> (&mut Interface, &mut SocketSet<'static>) { - (&mut self.interface, &mut self.socket_set) + pub fn get_interface(&mut self) -> &mut Interface { + &mut self.interface } #[inline(always)] @@ -277,11 +277,11 @@ impl IfNet { vlan, inner: Mutex::new(IfNetInner { interface, - socket_set, default_gateway_ipv4: None, multicast_addr_ipv4: BTreeSet::new(), multicast_addr_mac: BTreeMap::new(), }), + socket_set: RwLock::new(socket_set), rx_irq_to_driver, net_device, tx_only_ringq, @@ -488,8 +488,8 @@ impl IfNet { let mut node = MCSNode::new(); let mut inner = self.inner.lock(&mut node); - let (interface, socket_set) = inner.split(); - interface.poll(timestamp, &mut device_ref, socket_set) + let interface = inner.get_interface(); + interface.poll(timestamp, &mut device_ref, &self.socket_set) }; // send packets from the queue. @@ -547,9 +547,8 @@ impl IfNet { let mut node = MCSNode::new(); let mut inner = self.inner.lock(&mut node); - let (interface, socket_set) = inner.split(); - - interface.poll(timestamp, &mut device_ref, socket_set) + let interface = inner.get_interface(); + interface.poll(timestamp, &mut device_ref, &self.socket_set) }; // send packets from the queue. diff --git a/awkernel_lib/src/net/tcp_listener.rs b/awkernel_lib/src/net/tcp_listener.rs index d9ea360e4..699a13efd 100644 --- a/awkernel_lib/src/net/tcp_listener.rs +++ b/awkernel_lib/src/net/tcp_listener.rs @@ -76,12 +76,7 @@ impl TcpListener { // Create a TCP socket. let socket = create_listen_socket(&addr, port.port(), rx_buffer_size, tx_buffer_size); - let handle = { - let mut node = MCSNode::new(); - let mut if_net_inner = if_net.inner.lock(&mut node); - - if_net_inner.socket_set.add(socket) - }; + let handle = if_net.socket_set.write().add(socket); handles.push(handle); } @@ -128,12 +123,23 @@ impl TcpListener { let if_net = if_net.clone(); drop(net_manager); - let mut node = MCSNode::new(); - let mut interface = if_net.inner.lock(&mut node); - for handle in self.handles.iter_mut() { - let socket: &mut smoltcp::socket::tcp::Socket = interface.socket_set.get_mut(*handle); - if socket.may_send() { + let (may_send, is_not_open) = { + let socket_set = if_net.socket_set.read(); + let mut node: MCSNode = MCSNode::new(); + let socket = socket_set + .get::(*handle) + .lock(&mut node); + if socket.may_send() { + (true, false) + } else if !socket.is_open() { + (false, true) + } else { + (false, false) + } + }; + + if may_send { // If the connection is established, create a new socket and add it to the interface. let new_socket = create_listen_socket( &self.addr, @@ -141,14 +147,15 @@ impl TcpListener { self.rx_buffer_size, self.tx_buffer_size, ); - let mut new_handle = interface.socket_set.add(new_socket); + let mut socket_set = if_net.socket_set.write(); + let mut new_handle = socket_set.add(new_socket); // Swap the new handle with the old handle. core::mem::swap(handle, &mut new_handle); // The old handle is now a connected socket. self.connected_sockets.push_back(new_handle); - } else if !socket.is_open() { + } else if is_not_open { // If the socket is closed, create a new socket and add it to the interface. let new_socket = create_listen_socket( &self.addr, @@ -156,15 +163,14 @@ impl TcpListener { self.rx_buffer_size, self.tx_buffer_size, ); - interface.socket_set.remove(*handle); - *handle = interface.socket_set.add(new_socket); + let mut socket_set = if_net.socket_set.write(); + socket_set.remove(*handle); + *handle = socket_set.add(new_socket); } } // If there is a connected socket, return it. if let Some(handle) = self.connected_sockets.pop_front() { - drop(interface); - let port = { let mut net_manager = NET_MANAGER.write(); if self.addr.is_ipv4() { @@ -183,14 +189,16 @@ impl TcpListener { })); } + let socket_set = if_net.socket_set.read(); // Register the waker for the listening sockets. for handle in self.handles.iter() { - let socket: &mut smoltcp::socket::tcp::Socket = interface.socket_set.get_mut(*handle); + let mut node: MCSNode = MCSNode::new(); + let mut socket = socket_set + .get::(*handle) + .lock(&mut node); socket.register_send_waker(waker); } - drop(interface); - Ok(None) } } @@ -203,23 +211,28 @@ impl Drop for TcpListener { let if_net = if_net.clone(); drop(net_manager); - let mut node = MCSNode::new(); - let mut inner = if_net.inner.lock(&mut node); + { + let socket_set = if_net.socket_set.read(); - // Close listening sockets. - for handle in self.handles.iter() { - let socket: &mut smoltcp::socket::tcp::Socket = inner.socket_set.get_mut(*handle); - socket.abort(); - } + // Close listening sockets. + for handle in self.handles.iter() { + let mut node: MCSNode = MCSNode::new(); + let mut socket = socket_set + .get::(*handle) + .lock(&mut node); + socket.abort(); + } - // Close connected sockets. - for handle in self.connected_sockets.iter() { - let socket: &mut smoltcp::socket::tcp::Socket = inner.socket_set.get_mut(*handle); - socket.abort(); + // Close connected sockets. + for handle in self.connected_sockets.iter() { + let mut node: MCSNode = MCSNode::new(); + let mut socket = socket_set + .get::(*handle) + .lock(&mut node); + socket.abort(); + } } - drop(inner); - let que_id = crate::cpu::raw_cpu_id() & (if_net.net_device.num_queues() - 1); if_net.poll_tx_only(que_id); } diff --git a/awkernel_lib/src/net/tcp_stream.rs b/awkernel_lib/src/net/tcp_stream.rs index 47a97e158..18a456a66 100644 --- a/awkernel_lib/src/net/tcp_stream.rs +++ b/awkernel_lib/src/net/tcp_stream.rs @@ -41,19 +41,29 @@ impl Drop for TcpStream { drop(net_manager); { - let mut node = MCSNode::new(); - let mut inner = if_net.inner.lock(&mut node); + let socket_set = if_net.socket_set.read(); + let closed = { + let mut node: MCSNode = MCSNode::new(); + let socket = socket_set + .get::(self.handle) + .lock(&mut node); - let socket: &mut smoltcp::socket::tcp::Socket = inner.socket_set.get_mut(self.handle); + matches!(socket.state(), smoltcp::socket::tcp::State::Closed) + }; // If the socket is already closed, remove it from the socket set. - if matches!(socket.state(), smoltcp::socket::tcp::State::Closed) { - inner.socket_set.remove(self.handle); - + if closed { + drop(socket_set); + let mut socket_set = if_net.socket_set.write(); + socket_set.remove(self.handle); return; } // Otherwise, close the socket. + let mut node: MCSNode = MCSNode::new(); + let mut socket = socket_set + .get::(self.handle) + .lock(&mut node); socket.close(); } @@ -98,16 +108,25 @@ pub fn close_connections() { let mut remain_v = VecDeque::new(); { - let mut node = MCSNode::new(); - let mut inner = if_net.inner.lock(&mut node); - while let Some((handle, port)) = v.pop_front() { - let socket: &mut smoltcp::socket::tcp::Socket = - inner.socket_set.get_mut(handle); - if socket.state() == smoltcp::socket::tcp::State::Closed { + let socket_set = if_net.socket_set.read(); + let closed = { + let mut node: MCSNode = MCSNode::new(); + let socket = socket_set + .get::(handle) + .lock(&mut node); + socket.state() == smoltcp::socket::tcp::State::Closed + }; + if closed { + drop(socket_set); + let mut socket_set = if_net.socket_set.write(); // If the socket is already closed, remove it from the socket set. - inner.socket_set.remove(handle); + socket_set.remove(handle); } else { + let mut node: MCSNode = MCSNode::new(); + let mut socket = socket_set + .get::(handle) + .lock(&mut node); socket.close(); remain_v.push_back((handle, port)); } @@ -180,20 +199,27 @@ impl TcpStream { let mut node = MCSNode::new(); let mut inner = if_net.inner.lock(&mut node); - let (interface, socket_set) = inner.split(); + let interface = inner.get_interface(); + let mut socket_set = if_net.socket_set.write(); handle = socket_set.add(socket); - let socket: &mut smoltcp::socket::tcp::Socket = socket_set.get_mut(handle); - - if socket - .connect( - interface.context(), - (remote_addr.addr, remote_port), - local_port.port(), - ) - .is_err() - { + let connect_is_err = { + let mut node: MCSNode = MCSNode::new(); + let mut socket = socket_set + .get::(handle) + .lock(&mut node); + + socket + .connect( + interface.context(), + (remote_addr.addr, remote_port), + local_port.port(), + ) + .is_err() + }; + + if connect_is_err { socket_set.remove(handle); return Err(NetManagerError::InvalidState); } @@ -227,10 +253,12 @@ impl TcpStream { let if_net = if_net.clone(); drop(net_manager); - let mut node = MCSNode::new(); - let mut inner = if_net.inner.lock(&mut node); + let socket_set = if_net.socket_set.read(); - let socket: &mut smoltcp::socket::tcp::Socket = inner.socket_set.get_mut(self.handle); + let mut node: MCSNode = MCSNode::new(); + let mut socket = socket_set + .get::(self.handle) + .lock(&mut node); if socket.state() == smoltcp::socket::tcp::State::SynSent { socket.register_recv_waker(waker); @@ -271,10 +299,12 @@ impl TcpStream { let if_net = if_net.clone(); drop(net_manager); - let mut node = MCSNode::new(); - let mut inner = if_net.inner.lock(&mut node); + let socket_set = if_net.socket_set.read(); - let socket: &mut smoltcp::socket::tcp::Socket = inner.socket_set.get_mut(self.handle); + let mut node: MCSNode = MCSNode::new(); + let mut socket = socket_set + .get::(self.handle) + .lock(&mut node); if socket.state() == smoltcp::socket::tcp::State::SynSent { socket.register_recv_waker(waker); @@ -308,10 +338,12 @@ impl TcpStream { let if_net = if_net.clone(); drop(net_manager); - let mut node = MCSNode::new(); - let inner = if_net.inner.lock(&mut node); + let socket_set = if_net.socket_set.read(); - let socket: &smoltcp::socket::tcp::Socket = inner.socket_set.get(self.handle); + let mut node: MCSNode = MCSNode::new(); + let socket = socket_set + .get::(self.handle) + .lock(&mut node); if let Some(endpoint) = socket.remote_endpoint() { Ok(( diff --git a/awkernel_lib/src/net/udp_socket.rs b/awkernel_lib/src/net/udp_socket.rs index 3d9eb2f2c..9bc51ec4f 100644 --- a/awkernel_lib/src/net/udp_socket.rs +++ b/awkernel_lib/src/net/udp_socket.rs @@ -1,7 +1,5 @@ -use crate::{ - net::{ip_addr::IpAddr, NET_MANAGER}, - sync::mcs::MCSNode, -}; +use crate::net::{ip_addr::IpAddr, NET_MANAGER}; +use awkernel_sync::mcs::MCSNode; use super::NetManagerError; @@ -126,12 +124,7 @@ impl UdpSocket { } // Add the socket to the interface. - let handle = { - let mut node = MCSNode::new(); - let mut if_net_inner = if_net.inner.lock(&mut node); - - if_net_inner.socket_set.add(socket) - }; + let handle = if_net.socket_set.write().add(socket); Ok(UdpSocket { handle, @@ -165,21 +158,23 @@ impl UdpSocket { let if_net = if_net.clone(); drop(net_manager); - let mut node = MCSNode::new(); - let mut inner = if_net.inner.lock(&mut node); + let socket_set = if_net.socket_set.read(); + let socket_mutex = socket_set.get::(self.handle); - let socket = inner - .socket_set - .get_mut::(self.handle); + let mut node = MCSNode::new(); + let mut socket = socket_mutex.lock(&mut node); - if socket.can_send() { + let can_send = socket.can_send(); + if can_send { socket .send_slice(buf, (addr.addr, port)) .or(Err(NetManagerError::SendError))?; - drop(inner); - let que_id = crate::cpu::raw_cpu_id() & (if_net.net_device.num_queues() - 1); + + // To avoid deadlock + drop(socket); + drop(socket_set); if_net.poll_tx_only(que_id); Ok(true) @@ -209,13 +204,11 @@ impl UdpSocket { let if_net = if_net.clone(); drop(net_manager); - let mut node = MCSNode::new(); - let mut inner = if_net.inner.lock(&mut node); - - let socket = inner - .socket_set - .get_mut::(self.handle); + let socket_set = if_net.socket_set.read(); + let socket_mutex = socket_set.get::(self.handle); + let mut node = MCSNode::new(); + let mut socket = socket_mutex.lock(&mut node); if socket.can_recv() { let (data, meta_data) = socket.recv().or(Err(NetManagerError::RecvError))?; @@ -248,9 +241,7 @@ impl Drop for UdpSocket { } if let Some(if_net) = net_manager.interfaces.get(&self.interface_id) { - let mut node = MCSNode::new(); - let mut if_net_inner = if_net.inner.lock(&mut node); - if_net_inner.socket_set.remove(self.handle); + if_net.socket_set.write().remove(self.handle); } } } diff --git a/smoltcp/Cargo.toml b/smoltcp/Cargo.toml index 025ac7d8b..02c9a4e2b 100644 --- a/smoltcp/Cargo.toml +++ b/smoltcp/Cargo.toml @@ -155,6 +155,9 @@ required-features = [ "socket-dns", ] +[dependencies.awkernel_sync] +git = "https://github.com/tier4/awkernel_sync.git" + [dependencies.bitflags] version = "1.0" default-features = false diff --git a/smoltcp/src/iface/interface/ethernet.rs b/smoltcp/src/iface/interface/ethernet.rs index e2555a1da..3c492c2c0 100644 --- a/smoltcp/src/iface/interface/ethernet.rs +++ b/smoltcp/src/iface/interface/ethernet.rs @@ -6,6 +6,8 @@ use super::InterfaceInner; use super::SocketSet; use core::result::Result; +use awkernel_sync::rwlock::RwLock; + use crate::phy::TxToken; use crate::wire::*; @@ -13,7 +15,7 @@ impl InterfaceInner { #[cfg(feature = "medium-ethernet")] pub(super) fn process_ethernet<'frame>( &mut self, - sockets: &mut SocketSet, + sockets: &RwLock, meta: crate::phy::PacketMeta, frame: &'frame [u8], fragments: &'frame mut FragmentsBuffer, diff --git a/smoltcp/src/iface/interface/ipv4.rs b/smoltcp/src/iface/interface/ipv4.rs index 0500ffd25..2df73975b 100644 --- a/smoltcp/src/iface/interface/ipv4.rs +++ b/smoltcp/src/iface/interface/ipv4.rs @@ -13,7 +13,7 @@ impl InterfaceInner { #[allow(unused_variables)] pub(super) fn process_ipv4<'a>( &mut self, - sockets: &mut SocketSet, + sockets: &RwLock, meta: PacketMeta, ipv4_packet: &Ipv4Packet<&'a [u8]>, frag: &'a mut FragmentsBuffer, @@ -235,7 +235,7 @@ impl InterfaceInner { pub(super) fn process_icmpv4<'frame>( &mut self, - _sockets: &mut SocketSet, + sockets: &RwLock, ip_repr: IpRepr, ip_payload: &'frame [u8], ) -> Option> { @@ -246,12 +246,15 @@ impl InterfaceInner { let mut handled_by_icmp_socket = false; #[cfg(all(feature = "socket-icmp", feature = "proto-ipv4"))] - for icmp_socket in _sockets - .items_mut() - .filter_map(|i| icmp::Socket::downcast_mut(&mut i.socket)) + for icmp_socket in sockets + .read() + .items() + .filter_map(|i| icmp::Socket::downcast(&i.socket)) { - if icmp_socket.accepts(self, &ip_repr, &icmp_repr.into()) { - icmp_socket.process(self, &ip_repr, &icmp_repr.into()); + let mut node = MCSNode::new(); + let mut socket = icmp_socket.lock(&mut node); + if socket.accepts(self, &ip_repr, &icmp_repr.into()) { + socket.process(self, &ip_repr, &icmp_repr.into()); handled_by_icmp_socket = true; } } diff --git a/smoltcp/src/iface/interface/ipv6.rs b/smoltcp/src/iface/interface/ipv6.rs index 22e65b967..61bd9a645 100644 --- a/smoltcp/src/iface/interface/ipv6.rs +++ b/smoltcp/src/iface/interface/ipv6.rs @@ -28,7 +28,7 @@ impl Default for HopByHopResponse<'_> { impl InterfaceInner { pub(super) fn process_ipv6<'frame>( &mut self, - sockets: &mut SocketSet, + sockets: &RwLock, meta: PacketMeta, ipv6_packet: &Ipv6Packet<&'frame [u8]>, ) -> Option> { @@ -132,7 +132,7 @@ impl InterfaceInner { /// function. fn process_nxt_hdr<'frame>( &mut self, - sockets: &mut SocketSet, + sockets: &RwLock, meta: PacketMeta, ipv6_repr: Ipv6Repr, nxt_hdr: IpProtocol, @@ -187,7 +187,7 @@ impl InterfaceInner { pub(super) fn process_icmpv6<'frame>( &mut self, - _sockets: &mut SocketSet, + sockets: &RwLock, ip_repr: IpRepr, ip_payload: &'frame [u8], ) -> Option> { @@ -203,12 +203,15 @@ impl InterfaceInner { let mut handled_by_icmp_socket = false; #[cfg(feature = "socket-icmp")] - for icmp_socket in _sockets - .items_mut() - .filter_map(|i| icmp::Socket::downcast_mut(&mut i.socket)) + for icmp_socket in sockets + .read() + .items() + .filter_map(|i| icmp::Socket::downcast(&i.socket)) { - if icmp_socket.accepts(self, &ip_repr, &icmp_repr.into()) { - icmp_socket.process(self, &ip_repr, &icmp_repr.into()); + let mut node = MCSNode::new(); + let mut socket = icmp_socket.lock(&mut node); + if socket.accepts(self, &ip_repr, &icmp_repr.into()) { + socket.process(self, &ip_repr, &icmp_repr.into()); handled_by_icmp_socket = true; } } diff --git a/smoltcp/src/iface/interface/mod.rs b/smoltcp/src/iface/interface/mod.rs index 20fb3c2a1..e5b6e0ecf 100644 --- a/smoltcp/src/iface/interface/mod.rs +++ b/smoltcp/src/iface/interface/mod.rs @@ -20,6 +20,8 @@ mod sixlowpan; #[cfg(feature = "proto-igmp")] mod igmp; +use awkernel_sync::{mcs::MCSNode, rwlock::RwLock}; + #[cfg(feature = "proto-igmp")] pub use igmp::MulticastError; @@ -415,7 +417,7 @@ impl Interface { &mut self, timestamp: Instant, device: &mut D, - sockets: &mut SocketSet<'_>, + sockets: &RwLock>, ) -> bool where D: Device + ?Sized, @@ -516,7 +518,7 @@ impl Interface { } } - fn socket_ingress(&mut self, device: &mut D, sockets: &mut SocketSet<'_>) -> bool + fn socket_ingress(&mut self, device: &mut D, sockets: &RwLock>) -> bool where D: Device + ?Sized, { @@ -587,7 +589,7 @@ impl Interface { processed_any } - fn socket_egress(&mut self, device: &mut D, sockets: &mut SocketSet<'_>) -> bool + fn socket_egress(&mut self, device: &mut D, sockets: &RwLock>) -> bool where D: Device + ?Sized, { @@ -600,7 +602,7 @@ impl Interface { } let mut emitted_any = false; - for item in sockets.items_mut() { + for item in sockets.read().items() { if !item .meta .egress_permitted(self.inner.now, |ip_addr| self.inner.has_neighbor(&ip_addr)) @@ -625,7 +627,7 @@ impl Interface { Ok(()) }; - let result = match &mut item.socket { + let result = match &item.socket { #[cfg(feature = "socket-raw")] Socket::Raw(socket) => socket.dispatch(&mut self.inner, |inner, (ip, raw)| { respond( @@ -636,7 +638,9 @@ impl Interface { }), #[cfg(feature = "socket-icmp")] Socket::Icmp(socket) => { - socket.dispatch(&mut self.inner, |inner, response| match response { + let mut node = MCSNode::new(); + let mut guard = socket.lock(&mut node); + guard.dispatch(&mut self.inner, |inner, response| match response { #[cfg(feature = "proto-ipv4")] (IpRepr::Ipv4(ipv4_repr), IcmpRepr::Ipv4(icmpv4_repr)) => respond( inner, @@ -655,18 +659,24 @@ impl Interface { } #[cfg(feature = "socket-udp")] Socket::Udp(socket) => { - socket.dispatch(&mut self.inner, |inner, meta, (ip, udp, payload)| { + let mut node = MCSNode::new(); + let mut guard = socket.lock(&mut node); + guard.dispatch(&mut self.inner, |inner, meta, (ip, udp, payload)| { respond(inner, meta, Packet::new(ip, IpPayload::Udp(udp, payload))) }) } #[cfg(feature = "socket-tcp")] - Socket::Tcp(socket) => socket.dispatch(&mut self.inner, |inner, (ip, tcp)| { - respond( - inner, - PacketMeta::default(), - Packet::new(ip, IpPayload::Tcp(tcp)), - ) - }), + Socket::Tcp(socket) => { + let mut node = MCSNode::new(); + let mut guard = socket.lock(&mut node); + guard.dispatch(&mut self.inner, |inner, (ip, tcp)| { + respond( + inner, + PacketMeta::default(), + Packet::new(ip, IpPayload::Tcp(tcp)), + ) + }) + } #[cfg(feature = "socket-dhcpv4")] Socket::Dhcpv4(socket) => { socket.dispatch(&mut self.inner, |inner, (ip, udp, dhcp)| { @@ -1112,7 +1122,7 @@ impl InterfaceInner { #[allow(clippy::too_many_arguments)] fn process_udp<'frame>( &mut self, - sockets: &mut SocketSet, + sockets: &RwLock, meta: PacketMeta, ip_repr: IpRepr, udp_repr: UdpRepr, @@ -1122,11 +1132,14 @@ impl InterfaceInner { ) -> Option> { #[cfg(feature = "socket-udp")] for udp_socket in sockets - .items_mut() - .filter_map(|i| udp::Socket::downcast_mut(&mut i.socket)) + .read() + .items() + .filter_map(|i| udp::Socket::downcast(&i.socket)) { - if udp_socket.accepts(self, &ip_repr, &udp_repr) { - udp_socket.process(self, meta, &ip_repr, &udp_repr, udp_payload); + let mut node = MCSNode::new(); + let mut socket = udp_socket.lock(&mut node); + if socket.accepts(self, &ip_repr, &udp_repr) { + socket.process(self, meta, &ip_repr, &udp_repr, udp_payload); return None; } } @@ -1176,7 +1189,7 @@ impl InterfaceInner { #[cfg(feature = "socket-tcp")] pub(crate) fn process_tcp<'frame>( &mut self, - sockets: &mut SocketSet, + sockets: &RwLock, ip_repr: IpRepr, ip_payload: &'frame [u8], ) -> Option> { @@ -1190,11 +1203,14 @@ impl InterfaceInner { )); for tcp_socket in sockets - .items_mut() - .filter_map(|i| tcp::Socket::downcast_mut(&mut i.socket)) + .read() + .items() + .filter_map(|i| tcp::Socket::downcast(&i.socket)) { - if tcp_socket.accepts(self, &ip_repr, &tcp_repr) { - return tcp_socket + let mut node = MCSNode::new(); + let mut socket = tcp_socket.lock(&mut node); + if socket.accepts(self, &ip_repr, &tcp_repr) { + return socket .process(self, &ip_repr, &tcp_repr) .map(|(ip, tcp)| Packet::new(ip, IpPayload::Tcp(tcp))); } diff --git a/smoltcp/src/iface/socket_meta.rs b/smoltcp/src/iface/socket_meta.rs index 82c99087b..547e457b0 100644 --- a/smoltcp/src/iface/socket_meta.rs +++ b/smoltcp/src/iface/socket_meta.rs @@ -4,14 +4,15 @@ use crate::{ time::{Duration, Instant}, wire::IpAddress, }; +use awkernel_sync::{mcs::MCSNode, mutex::Mutex}; /// Neighbor dependency. /// /// This enum tracks whether the socket should be polled based on the neighbor /// it is going to send packets to. -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -enum NeighborState { +pub enum NeighborState { /// Socket can be polled immediately. #[default] Active, @@ -28,14 +29,13 @@ enum NeighborState { /// This includes things that only external (to the socket, that is) code /// is interested in, but which are more conveniently stored inside the socket /// itself. -#[derive(Debug, Default)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) struct Meta { /// Handle of this socket within its enclosing `SocketSet`. /// Mainly useful for debug output. - pub(crate) handle: SocketHandle, + pub(crate) handle: Mutex, /// See [NeighborState](struct.NeighborState.html). - neighbor_state: NeighborState, + pub neighbor_state: Mutex, } impl Meta { @@ -49,35 +49,48 @@ impl Meta { where F: Fn(IpAddress) -> bool, { - match self.neighbor_state { + let mut node = MCSNode::new(); + let neighbor_state = self.neighbor_state.lock(&mut node); + match *neighbor_state { NeighborState::Active => socket_poll_at, NeighborState::Waiting { neighbor, .. } if has_neighbor(neighbor) => socket_poll_at, NeighborState::Waiting { silent_until, .. } => PollAt::Time(silent_until), } } - pub(crate) fn egress_permitted(&mut self, timestamp: Instant, has_neighbor: F) -> bool + pub(crate) fn egress_permitted(&self, timestamp: Instant, has_neighbor: F) -> bool where F: Fn(IpAddress) -> bool, { - match self.neighbor_state { + let mut node = MCSNode::new(); + let neighbor_state = self.neighbor_state.lock(&mut node); + let neighbor_state_copied = *neighbor_state; + drop(neighbor_state); + + match neighbor_state_copied { NeighborState::Active => true, NeighborState::Waiting { neighbor, silent_until, } => { if has_neighbor(neighbor) { - net_trace!( - "{}: neighbor {} discovered, unsilencing", - self.handle, - neighbor - ); - self.neighbor_state = NeighborState::Active; + { + let mut node = MCSNode::new(); + let handle = self.handle.lock(&mut node); + net_trace!("{}: neighbor {} discovered, unsilencing", *handle, neighbor); + } + { + let mut node = MCSNode::new(); + let mut neighbor_state = self.neighbor_state.lock(&mut node); + *neighbor_state = NeighborState::Active; + } true } else if timestamp >= silent_until { + let mut node = MCSNode::new(); + let handle = self.handle.lock(&mut node); net_trace!( "{}: neighbor {} silence timer expired, rediscovering", - self.handle, + *handle, neighbor ); true @@ -88,16 +101,24 @@ impl Meta { } } - pub(crate) fn neighbor_missing(&mut self, timestamp: Instant, neighbor: IpAddress) { - net_trace!( - "{}: neighbor {} missing, silencing until t+{}", - self.handle, - neighbor, - Self::DISCOVERY_SILENT_TIME - ); - self.neighbor_state = NeighborState::Waiting { - neighbor, - silent_until: timestamp + Self::DISCOVERY_SILENT_TIME, - }; + pub(crate) fn neighbor_missing(&self, timestamp: Instant, neighbor: IpAddress) { + { + let mut node = MCSNode::new(); + let handle = self.handle.lock(&mut node); + net_trace!( + "{}: neighbor {} missing, silencing until t+{}", + *handle, + neighbor, + Self::DISCOVERY_SILENT_TIME + ); + } + { + let mut node = MCSNode::new(); + let mut neighbor_state = self.neighbor_state.lock(&mut node); + *neighbor_state = NeighborState::Waiting { + neighbor, + silent_until: timestamp + Self::DISCOVERY_SILENT_TIME, + }; + } } } diff --git a/smoltcp/src/iface/socket_set.rs b/smoltcp/src/iface/socket_set.rs index b70332deb..d2a4d1818 100644 --- a/smoltcp/src/iface/socket_set.rs +++ b/smoltcp/src/iface/socket_set.rs @@ -1,14 +1,14 @@ +use awkernel_sync::mutex::Mutex; use core::fmt; use managed::ManagedSlice; -use super::socket_meta::Meta; +use super::socket_meta::{Meta, NeighborState}; use crate::socket::{AnySocket, Socket}; /// Opaque struct with space for storing one socket. /// /// This is public so you can use it to allocate space for storing /// sockets when creating an Interface. -#[derive(Debug, Default)] pub struct SocketStorage<'a> { inner: Option>, } @@ -18,7 +18,6 @@ impl SocketStorage<'_> { } /// An item of a socket set. -#[derive(Debug)] pub(crate) struct Item<'a> { pub(crate) meta: Meta, pub(crate) socket: Socket<'a>, @@ -40,7 +39,6 @@ impl fmt::Display for SocketHandle { /// The lifetime `'a` is used when storing a `Socket<'a>`. If you're using /// owned buffers for your sockets (passed in as `Vec`s) you can use /// `SocketSet<'static>`. -#[derive(Debug)] pub struct SocketSet<'a> { sockets: ManagedSlice<'a, SocketStorage<'a>>, } @@ -63,8 +61,11 @@ impl<'a> SocketSet<'a> { fn put<'a>(index: usize, slot: &mut SocketStorage<'a>, socket: Socket<'a>) -> SocketHandle { net_trace!("[{}]: adding", index); let handle = SocketHandle(index); - let mut meta = Meta::default(); - meta.handle = handle; + let mut meta = Meta { + handle: Mutex::new(SocketHandle::default()), + neighbor_state: Mutex::new(NeighborState::default()), + }; + meta.handle = Mutex::new(handle); *slot = SocketStorage { inner: Some(Item { meta, socket }), }; @@ -95,7 +96,7 @@ impl<'a> SocketSet<'a> { /// # Panics /// This function may panic if the handle does not belong to this socket set /// or the socket has the wrong type. - pub fn get>(&self, handle: SocketHandle) -> &T { + pub fn get>(&self, handle: SocketHandle) -> &Mutex { match self.sockets[handle.0].inner.as_ref() { Some(item) => { T::downcast(&item.socket).expect("handle refers to a socket of a wrong type") @@ -109,7 +110,7 @@ impl<'a> SocketSet<'a> { /// # Panics /// This function may panic if the handle does not belong to this socket set /// or the socket has the wrong type. - pub fn get_mut>(&mut self, handle: SocketHandle) -> &mut T { + pub fn get_mut>(&mut self, handle: SocketHandle) -> &mut Mutex { match self.sockets[handle.0].inner.as_mut() { Some(item) => T::downcast_mut(&mut item.socket) .expect("handle refers to a socket of a wrong type"), @@ -130,13 +131,13 @@ impl<'a> SocketSet<'a> { } /// Get an iterator to the inner sockets. - pub fn iter(&self) -> impl Iterator)> { - self.items().map(|i| (i.meta.handle, &i.socket)) + pub fn iter(&self) -> impl Iterator, &Socket<'a>)> { + self.items().map(|i| (&i.meta.handle, &i.socket)) } /// Get a mutable iterator to the inner sockets. - pub fn iter_mut(&mut self) -> impl Iterator)> { - self.items_mut().map(|i| (i.meta.handle, &mut i.socket)) + pub fn iter_mut(&mut self) -> impl Iterator, &mut Socket<'a>)> { + self.items_mut().map(|i| (&i.meta.handle, &mut i.socket)) } /// Iterate every socket in this set. diff --git a/smoltcp/src/socket/icmp.rs b/smoltcp/src/socket/icmp.rs index c18b754d5..e6bfd0135 100644 --- a/smoltcp/src/socket/icmp.rs +++ b/smoltcp/src/socket/icmp.rs @@ -628,613 +628,613 @@ impl<'a> Socket<'a> { } } -#[cfg(test)] -mod tests_common { - pub use super::*; - pub use crate::wire::IpAddress; - - pub fn buffer(packets: usize) -> PacketBuffer<'static> { - PacketBuffer::new(vec![PacketMetadata::EMPTY; packets], vec![0; 66 * packets]) - } - - pub fn socket( - rx_buffer: PacketBuffer<'static>, - tx_buffer: PacketBuffer<'static>, - ) -> Socket<'static> { - Socket::new(rx_buffer, tx_buffer) - } - - pub const LOCAL_PORT: u16 = 53; - - pub static UDP_REPR: UdpRepr = UdpRepr { - src_port: 53, - dst_port: 9090, - }; - - pub static UDP_PAYLOAD: &[u8] = &[0xff; 10]; -} - -#[cfg(all(test, feature = "proto-ipv4"))] -mod test_ipv4 { - use crate::phy::Medium; - use crate::tests::setup; - use rstest::*; - - use super::tests_common::*; - use crate::wire::{Icmpv4DstUnreachable, IpEndpoint, Ipv4Address}; - - const REMOTE_IPV4: Ipv4Address = Ipv4Address([192, 168, 1, 2]); - const LOCAL_IPV4: Ipv4Address = Ipv4Address([192, 168, 1, 1]); - const LOCAL_END_V4: IpEndpoint = IpEndpoint { - addr: IpAddress::Ipv4(LOCAL_IPV4), - port: LOCAL_PORT, - }; - - static ECHOV4_REPR: Icmpv4Repr = Icmpv4Repr::EchoRequest { - ident: 0x1234, - seq_no: 0x5678, - data: &[0xff; 16], - }; - - static LOCAL_IPV4_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr { - src_addr: LOCAL_IPV4, - dst_addr: REMOTE_IPV4, - next_header: IpProtocol::Icmp, - payload_len: 24, - hop_limit: 0x40, - }); - - static REMOTE_IPV4_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr { - src_addr: REMOTE_IPV4, - dst_addr: LOCAL_IPV4, - next_header: IpProtocol::Icmp, - payload_len: 24, - hop_limit: 0x40, - }); - - #[test] - fn test_send_unaddressable() { - let mut socket = socket(buffer(0), buffer(1)); - assert_eq!( - socket.send_slice(b"abcdef", IpAddress::Ipv4(Ipv4Address::default())), - Err(SendError::Unaddressable) - ); - assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV4.into()), Ok(())); - } - - #[rstest] - #[case::ethernet(Medium::Ethernet)] - #[cfg(feature = "medium-ethernet")] - fn test_send_dispatch(#[case] medium: Medium) { - let (mut iface, _, _) = setup(medium); - let cx = iface.context(); - - let mut socket = socket(buffer(0), buffer(1)); - let checksum = ChecksumCapabilities::default(); - - assert_eq!(socket.dispatch(cx, |_, _| unreachable!()), Ok::<_, ()>(())); - - // This buffer is too long - assert_eq!( - socket.send_slice(&[0xff; 67], REMOTE_IPV4.into()), - Err(SendError::BufferFull) - ); - assert!(socket.can_send()); - - let mut bytes = [0xff; 24]; - let mut packet = Icmpv4Packet::new_unchecked(&mut bytes); - ECHOV4_REPR.emit(&mut packet, &checksum); - - assert_eq!( - socket.send_slice(&*packet.into_inner(), REMOTE_IPV4.into()), - Ok(()) - ); - assert_eq!( - socket.send_slice(b"123456", REMOTE_IPV4.into()), - Err(SendError::BufferFull) - ); - assert!(!socket.can_send()); - - assert_eq!( - socket.dispatch(cx, |_, (ip_repr, icmp_repr)| { - assert_eq!(ip_repr, LOCAL_IPV4_REPR); - assert_eq!(icmp_repr, ECHOV4_REPR.into()); - Err(()) - }), - Err(()) - ); - // buffer is not taken off of the tx queue due to the error - assert!(!socket.can_send()); - - assert_eq!( - socket.dispatch(cx, |_, (ip_repr, icmp_repr)| { - assert_eq!(ip_repr, LOCAL_IPV4_REPR); - assert_eq!(icmp_repr, ECHOV4_REPR.into()); - Ok::<_, ()>(()) - }), - Ok(()) - ); - // buffer is taken off of the queue this time - assert!(socket.can_send()); - } - - #[rstest] - #[case::ethernet(Medium::Ethernet)] - #[cfg(feature = "medium-ethernet")] - fn test_set_hop_limit_v4(#[case] medium: Medium) { - let (mut iface, _, _) = setup(medium); - let cx = iface.context(); - - let mut s = socket(buffer(0), buffer(1)); - let checksum = ChecksumCapabilities::default(); - - let mut bytes = [0xff; 24]; - let mut packet = Icmpv4Packet::new_unchecked(&mut bytes); - ECHOV4_REPR.emit(&mut packet, &checksum); - - s.set_hop_limit(Some(0x2a)); - - assert_eq!( - s.send_slice(&*packet.into_inner(), REMOTE_IPV4.into()), - Ok(()) - ); - assert_eq!( - s.dispatch(cx, |_, (ip_repr, _)| { - assert_eq!( - ip_repr, - IpRepr::Ipv4(Ipv4Repr { - src_addr: LOCAL_IPV4, - dst_addr: REMOTE_IPV4, - next_header: IpProtocol::Icmp, - payload_len: ECHOV4_REPR.buffer_len(), - hop_limit: 0x2a, - }) - ); - Ok::<_, ()>(()) - }), - Ok(()) - ); - } - - #[rstest] - #[case::ethernet(Medium::Ethernet)] - #[cfg(feature = "medium-ethernet")] - fn test_recv_process(#[case] medium: Medium) { - let (mut iface, _, _) = setup(medium); - let cx = iface.context(); - - let mut socket = socket(buffer(1), buffer(1)); - assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(())); - - assert!(!socket.can_recv()); - assert_eq!(socket.recv(), Err(RecvError::Exhausted)); - - let checksum = ChecksumCapabilities::default(); - - let mut bytes = [0xff; 24]; - let mut packet = Icmpv4Packet::new_unchecked(&mut bytes[..]); - ECHOV4_REPR.emit(&mut packet, &checksum); - let data = &*packet.into_inner(); - - assert!(socket.accepts(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into())); - socket.process(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()); - assert!(socket.can_recv()); - - assert!(socket.accepts(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into())); - socket.process(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()); - - assert_eq!(socket.recv(), Ok((data, REMOTE_IPV4.into()))); - assert!(!socket.can_recv()); - } - - #[rstest] - #[case::ethernet(Medium::Ethernet)] - #[cfg(feature = "medium-ethernet")] - fn test_accept_bad_id(#[case] medium: Medium) { - let (mut iface, _, _) = setup(medium); - let cx = iface.context(); - - let mut socket = socket(buffer(1), buffer(1)); - assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(())); - - let checksum = ChecksumCapabilities::default(); - let mut bytes = [0xff; 20]; - let mut packet = Icmpv4Packet::new_unchecked(&mut bytes); - let icmp_repr = Icmpv4Repr::EchoRequest { - ident: 0x4321, - seq_no: 0x5678, - data: &[0xff; 16], - }; - icmp_repr.emit(&mut packet, &checksum); - - // Ensure that a packet with an identifier that isn't the bound - // ID is not accepted - assert!(!socket.accepts(cx, &REMOTE_IPV4_REPR, &icmp_repr.into())); - } - - #[rstest] - #[case::ethernet(Medium::Ethernet)] - #[cfg(feature = "medium-ethernet")] - fn test_accepts_udp(#[case] medium: Medium) { - let (mut iface, _, _) = setup(medium); - let cx = iface.context(); - - let mut socket = socket(buffer(1), buffer(1)); - assert_eq!(socket.bind(Endpoint::Udp(LOCAL_END_V4.into())), Ok(())); - - let checksum = ChecksumCapabilities::default(); - - let mut bytes = [0xff; 18]; - let mut packet = UdpPacket::new_unchecked(&mut bytes); - UDP_REPR.emit( - &mut packet, - &REMOTE_IPV4.into(), - &LOCAL_IPV4.into(), - UDP_PAYLOAD.len(), - |buf| buf.copy_from_slice(UDP_PAYLOAD), - &checksum, - ); - - let data = &*packet.into_inner(); - - let icmp_repr = Icmpv4Repr::DstUnreachable { - reason: Icmpv4DstUnreachable::PortUnreachable, - header: Ipv4Repr { - src_addr: LOCAL_IPV4, - dst_addr: REMOTE_IPV4, - next_header: IpProtocol::Icmp, - payload_len: 12, - hop_limit: 0x40, - }, - data, - }; - let ip_repr = IpRepr::Ipv4(Ipv4Repr { - src_addr: REMOTE_IPV4, - dst_addr: LOCAL_IPV4, - next_header: IpProtocol::Icmp, - payload_len: icmp_repr.buffer_len(), - hop_limit: 0x40, - }); - - assert!(!socket.can_recv()); - - // Ensure we can accept ICMP error response to the bound - // UDP port - assert!(socket.accepts(cx, &ip_repr, &icmp_repr.into())); - socket.process(cx, &ip_repr, &icmp_repr.into()); - assert!(socket.can_recv()); - - let mut bytes = [0x00; 46]; - let mut packet = Icmpv4Packet::new_unchecked(&mut bytes[..]); - icmp_repr.emit(&mut packet, &checksum); - assert_eq!( - socket.recv(), - Ok((&*packet.into_inner(), REMOTE_IPV4.into())) - ); - assert!(!socket.can_recv()); - } -} - -#[cfg(all(test, feature = "proto-ipv6"))] -mod test_ipv6 { - use crate::phy::Medium; - use crate::tests::setup; - use rstest::*; - - use super::tests_common::*; - - use crate::wire::{Icmpv6DstUnreachable, IpEndpoint, Ipv6Address}; - - const REMOTE_IPV6: Ipv6Address = - Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]); - const LOCAL_IPV6: Ipv6Address = - Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); - const LOCAL_END_V6: IpEndpoint = IpEndpoint { - addr: IpAddress::Ipv6(LOCAL_IPV6), - port: LOCAL_PORT, - }; - static ECHOV6_REPR: Icmpv6Repr = Icmpv6Repr::EchoRequest { - ident: 0x1234, - seq_no: 0x5678, - data: &[0xff; 16], - }; - - static LOCAL_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr { - src_addr: LOCAL_IPV6, - dst_addr: REMOTE_IPV6, - next_header: IpProtocol::Icmpv6, - payload_len: 24, - hop_limit: 0x40, - }); - - static REMOTE_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr { - src_addr: REMOTE_IPV6, - dst_addr: LOCAL_IPV6, - next_header: IpProtocol::Icmpv6, - payload_len: 24, - hop_limit: 0x40, - }); - - #[test] - fn test_send_unaddressable() { - let mut socket = socket(buffer(0), buffer(1)); - assert_eq!( - socket.send_slice(b"abcdef", IpAddress::Ipv6(Ipv6Address::default())), - Err(SendError::Unaddressable) - ); - assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV6.into()), Ok(())); - } - - #[rstest] - #[case::ethernet(Medium::Ethernet)] - #[cfg(feature = "medium-ethernet")] - fn test_send_dispatch(#[case] medium: Medium) { - let (mut iface, _, _) = setup(medium); - let cx = iface.context(); - - let mut socket = socket(buffer(0), buffer(1)); - let checksum = ChecksumCapabilities::default(); - - assert_eq!(socket.dispatch(cx, |_, _| unreachable!()), Ok::<_, ()>(())); - - // This buffer is too long - assert_eq!( - socket.send_slice(&[0xff; 67], REMOTE_IPV6.into()), - Err(SendError::BufferFull) - ); - assert!(socket.can_send()); - - let mut bytes = vec![0xff; 24]; - let mut packet = Icmpv6Packet::new_unchecked(&mut bytes); - ECHOV6_REPR.emit( - &LOCAL_IPV6.into(), - &REMOTE_IPV6.into(), - &mut packet, - &checksum, - ); - - assert_eq!( - socket.send_slice(&*packet.into_inner(), REMOTE_IPV6.into()), - Ok(()) - ); - assert_eq!( - socket.send_slice(b"123456", REMOTE_IPV6.into()), - Err(SendError::BufferFull) - ); - assert!(!socket.can_send()); - - assert_eq!( - socket.dispatch(cx, |_, (ip_repr, icmp_repr)| { - assert_eq!(ip_repr, LOCAL_IPV6_REPR); - assert_eq!(icmp_repr, ECHOV6_REPR.into()); - Err(()) - }), - Err(()) - ); - // buffer is not taken off of the tx queue due to the error - assert!(!socket.can_send()); - - assert_eq!( - socket.dispatch(cx, |_, (ip_repr, icmp_repr)| { - assert_eq!(ip_repr, LOCAL_IPV6_REPR); - assert_eq!(icmp_repr, ECHOV6_REPR.into()); - Ok::<_, ()>(()) - }), - Ok(()) - ); - // buffer is taken off of the queue this time - assert!(socket.can_send()); - } - - #[rstest] - #[case::ethernet(Medium::Ethernet)] - #[cfg(feature = "medium-ethernet")] - fn test_set_hop_limit(#[case] medium: Medium) { - let (mut iface, _, _) = setup(medium); - let cx = iface.context(); - - let mut s = socket(buffer(0), buffer(1)); - let checksum = ChecksumCapabilities::default(); - - let mut bytes = vec![0xff; 24]; - let mut packet = Icmpv6Packet::new_unchecked(&mut bytes); - ECHOV6_REPR.emit( - &LOCAL_IPV6.into(), - &REMOTE_IPV6.into(), - &mut packet, - &checksum, - ); - - s.set_hop_limit(Some(0x2a)); - - assert_eq!( - s.send_slice(&*packet.into_inner(), REMOTE_IPV6.into()), - Ok(()) - ); - assert_eq!( - s.dispatch(cx, |_, (ip_repr, _)| { - assert_eq!( - ip_repr, - IpRepr::Ipv6(Ipv6Repr { - src_addr: LOCAL_IPV6, - dst_addr: REMOTE_IPV6, - next_header: IpProtocol::Icmpv6, - payload_len: ECHOV6_REPR.buffer_len(), - hop_limit: 0x2a, - }) - ); - Ok::<_, ()>(()) - }), - Ok(()) - ); - } - - #[rstest] - #[case::ethernet(Medium::Ethernet)] - #[cfg(feature = "medium-ethernet")] - fn test_recv_process(#[case] medium: Medium) { - let (mut iface, _, _) = setup(medium); - let cx = iface.context(); - - let mut socket = socket(buffer(1), buffer(1)); - assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(())); - - assert!(!socket.can_recv()); - assert_eq!(socket.recv(), Err(RecvError::Exhausted)); - - let checksum = ChecksumCapabilities::default(); - - let mut bytes = [0xff; 24]; - let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]); - ECHOV6_REPR.emit( - &LOCAL_IPV6.into(), - &REMOTE_IPV6.into(), - &mut packet, - &checksum, - ); - let data = &*packet.into_inner(); - - assert!(socket.accepts(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into())); - socket.process(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()); - assert!(socket.can_recv()); - - assert!(socket.accepts(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into())); - socket.process(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()); - - assert_eq!(socket.recv(), Ok((data, REMOTE_IPV6.into()))); - assert!(!socket.can_recv()); - } - - #[rstest] - #[case::ethernet(Medium::Ethernet)] - #[cfg(feature = "medium-ethernet")] - fn test_truncated_recv_slice(#[case] medium: Medium) { - let (mut iface, _, _) = setup(medium); - let cx = iface.context(); - - let mut socket = socket(buffer(1), buffer(1)); - assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(())); - - let checksum = ChecksumCapabilities::default(); - - let mut bytes = [0xff; 24]; - let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]); - ECHOV6_REPR.emit( - &LOCAL_IPV6.into(), - &REMOTE_IPV6.into(), - &mut packet, - &checksum, - ); - - assert!(socket.accepts(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into())); - socket.process(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()); - assert!(socket.can_recv()); - - assert!(socket.accepts(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into())); - socket.process(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()); - - let mut buffer = [0u8; 1]; - assert_eq!( - socket.recv_slice(&mut buffer[..]), - Err(RecvError::Truncated) - ); - assert!(!socket.can_recv()); - } - - #[rstest] - #[case::ethernet(Medium::Ethernet)] - #[cfg(feature = "medium-ethernet")] - fn test_accept_bad_id(#[case] medium: Medium) { - let (mut iface, _, _) = setup(medium); - let cx = iface.context(); - - let mut socket = socket(buffer(1), buffer(1)); - assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(())); - - let checksum = ChecksumCapabilities::default(); - let mut bytes = [0xff; 20]; - let mut packet = Icmpv6Packet::new_unchecked(&mut bytes); - let icmp_repr = Icmpv6Repr::EchoRequest { - ident: 0x4321, - seq_no: 0x5678, - data: &[0xff; 16], - }; - icmp_repr.emit( - &LOCAL_IPV6.into(), - &REMOTE_IPV6.into(), - &mut packet, - &checksum, - ); - - // Ensure that a packet with an identifier that isn't the bound - // ID is not accepted - assert!(!socket.accepts(cx, &REMOTE_IPV6_REPR, &icmp_repr.into())); - } - - #[rstest] - #[case::ethernet(Medium::Ethernet)] - #[cfg(feature = "medium-ethernet")] - fn test_accepts_udp(#[case] medium: Medium) { - let (mut iface, _, _) = setup(medium); - let cx = iface.context(); - - let mut socket = socket(buffer(1), buffer(1)); - assert_eq!(socket.bind(Endpoint::Udp(LOCAL_END_V6.into())), Ok(())); - - let checksum = ChecksumCapabilities::default(); - - let mut bytes = [0xff; 18]; - let mut packet = UdpPacket::new_unchecked(&mut bytes); - UDP_REPR.emit( - &mut packet, - &REMOTE_IPV6.into(), - &LOCAL_IPV6.into(), - UDP_PAYLOAD.len(), - |buf| buf.copy_from_slice(UDP_PAYLOAD), - &checksum, - ); - - let data = &*packet.into_inner(); - - let icmp_repr = Icmpv6Repr::DstUnreachable { - reason: Icmpv6DstUnreachable::PortUnreachable, - header: Ipv6Repr { - src_addr: LOCAL_IPV6, - dst_addr: REMOTE_IPV6, - next_header: IpProtocol::Icmpv6, - payload_len: 12, - hop_limit: 0x40, - }, - data, - }; - let ip_repr = IpRepr::Ipv6(Ipv6Repr { - src_addr: REMOTE_IPV6, - dst_addr: LOCAL_IPV6, - next_header: IpProtocol::Icmpv6, - payload_len: icmp_repr.buffer_len(), - hop_limit: 0x40, - }); - - assert!(!socket.can_recv()); - - // Ensure we can accept ICMP error response to the bound - // UDP port - assert!(socket.accepts(cx, &ip_repr, &icmp_repr.into())); - socket.process(cx, &ip_repr, &icmp_repr.into()); - assert!(socket.can_recv()); - - let mut bytes = [0x00; 66]; - let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]); - icmp_repr.emit( - &LOCAL_IPV6.into(), - &REMOTE_IPV6.into(), - &mut packet, - &checksum, - ); - assert_eq!( - socket.recv(), - Ok((&*packet.into_inner(), REMOTE_IPV6.into())) - ); - assert!(!socket.can_recv()); - } -} +//#[cfg(test)] +//mod tests_common { +//pub use super::*; +//pub use crate::wire::IpAddress; + +//pub fn buffer(packets: usize) -> PacketBuffer<'static> { +//PacketBuffer::new(vec![PacketMetadata::EMPTY; packets], vec![0; 66 * packets]) +//} + +//pub fn socket( +//rx_buffer: PacketBuffer<'static>, +//tx_buffer: PacketBuffer<'static>, +//) -> Socket<'static> { +//Socket::new(rx_buffer, tx_buffer) +//} + +//pub const LOCAL_PORT: u16 = 53; + +//pub static UDP_REPR: UdpRepr = UdpRepr { +//src_port: 53, +//dst_port: 9090, +//}; + +//pub static UDP_PAYLOAD: &[u8] = &[0xff; 10]; +//} + +//#[cfg(all(test, feature = "proto-ipv4"))] +//mod test_ipv4 { +//use crate::phy::Medium; +//use crate::tests::setup; +//use rstest::*; + +//use super::tests_common::*; +//use crate::wire::{Icmpv4DstUnreachable, IpEndpoint, Ipv4Address}; + +//const REMOTE_IPV4: Ipv4Address = Ipv4Address([192, 168, 1, 2]); +//const LOCAL_IPV4: Ipv4Address = Ipv4Address([192, 168, 1, 1]); +//const LOCAL_END_V4: IpEndpoint = IpEndpoint { +//addr: IpAddress::Ipv4(LOCAL_IPV4), +//port: LOCAL_PORT, +//}; + +//static ECHOV4_REPR: Icmpv4Repr = Icmpv4Repr::EchoRequest { +//ident: 0x1234, +//seq_no: 0x5678, +//data: &[0xff; 16], +//}; + +//static LOCAL_IPV4_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr { +//src_addr: LOCAL_IPV4, +//dst_addr: REMOTE_IPV4, +//next_header: IpProtocol::Icmp, +//payload_len: 24, +//hop_limit: 0x40, +//}); + +//static REMOTE_IPV4_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr { +//src_addr: REMOTE_IPV4, +//dst_addr: LOCAL_IPV4, +//next_header: IpProtocol::Icmp, +//payload_len: 24, +//hop_limit: 0x40, +//}); + +//#[test] +//fn test_send_unaddressable() { +//let mut socket = socket(buffer(0), buffer(1)); +//assert_eq!( +//socket.send_slice(b"abcdef", IpAddress::Ipv4(Ipv4Address::default())), +//Err(SendError::Unaddressable) +//); +//assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV4.into()), Ok(())); +//} + +//#[rstest] +//#[case::ethernet(Medium::Ethernet)] +//#[cfg(feature = "medium-ethernet")] +//fn test_send_dispatch(#[case] medium: Medium) { +//let (mut iface, _, _) = setup(medium); +//let cx = iface.context(); + +//let mut socket = socket(buffer(0), buffer(1)); +//let checksum = ChecksumCapabilities::default(); + +//assert_eq!(socket.dispatch(cx, |_, _| unreachable!()), Ok::<_, ()>(())); + +//// This buffer is too long +//assert_eq!( +//socket.send_slice(&[0xff; 67], REMOTE_IPV4.into()), +//Err(SendError::BufferFull) +//); +//assert!(socket.can_send()); + +//let mut bytes = [0xff; 24]; +//let mut packet = Icmpv4Packet::new_unchecked(&mut bytes); +//ECHOV4_REPR.emit(&mut packet, &checksum); + +//assert_eq!( +//socket.send_slice(&*packet.into_inner(), REMOTE_IPV4.into()), +//Ok(()) +//); +//assert_eq!( +//socket.send_slice(b"123456", REMOTE_IPV4.into()), +//Err(SendError::BufferFull) +//); +//assert!(!socket.can_send()); + +//assert_eq!( +//socket.dispatch(cx, |_, (ip_repr, icmp_repr)| { +//assert_eq!(ip_repr, LOCAL_IPV4_REPR); +//assert_eq!(icmp_repr, ECHOV4_REPR.into()); +//Err(()) +//}), +//Err(()) +//); +//// buffer is not taken off of the tx queue due to the error +//assert!(!socket.can_send()); + +//assert_eq!( +//socket.dispatch(cx, |_, (ip_repr, icmp_repr)| { +//assert_eq!(ip_repr, LOCAL_IPV4_REPR); +//assert_eq!(icmp_repr, ECHOV4_REPR.into()); +//Ok::<_, ()>(()) +//}), +//Ok(()) +//); +//// buffer is taken off of the queue this time +//assert!(socket.can_send()); +//} + +//#[rstest] +//#[case::ethernet(Medium::Ethernet)] +//#[cfg(feature = "medium-ethernet")] +//fn test_set_hop_limit_v4(#[case] medium: Medium) { +//let (mut iface, _, _) = setup(medium); +//let cx = iface.context(); + +//let mut s = socket(buffer(0), buffer(1)); +//let checksum = ChecksumCapabilities::default(); + +//let mut bytes = [0xff; 24]; +//let mut packet = Icmpv4Packet::new_unchecked(&mut bytes); +//ECHOV4_REPR.emit(&mut packet, &checksum); + +//s.set_hop_limit(Some(0x2a)); + +//assert_eq!( +//s.send_slice(&*packet.into_inner(), REMOTE_IPV4.into()), +//Ok(()) +//); +//assert_eq!( +//s.dispatch(cx, |_, (ip_repr, _)| { +//assert_eq!( +//ip_repr, +//IpRepr::Ipv4(Ipv4Repr { +//src_addr: LOCAL_IPV4, +//dst_addr: REMOTE_IPV4, +//next_header: IpProtocol::Icmp, +//payload_len: ECHOV4_REPR.buffer_len(), +//hop_limit: 0x2a, +//}) +//); +//Ok::<_, ()>(()) +//}), +//Ok(()) +//); +//} + +//#[rstest] +//#[case::ethernet(Medium::Ethernet)] +//#[cfg(feature = "medium-ethernet")] +//fn test_recv_process(#[case] medium: Medium) { +//let (mut iface, _, _) = setup(medium); +//let cx = iface.context(); + +//let mut socket = socket(buffer(1), buffer(1)); +//assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(())); + +//assert!(!socket.can_recv()); +//assert_eq!(socket.recv(), Err(RecvError::Exhausted)); + +//let checksum = ChecksumCapabilities::default(); + +//let mut bytes = [0xff; 24]; +//let mut packet = Icmpv4Packet::new_unchecked(&mut bytes[..]); +//ECHOV4_REPR.emit(&mut packet, &checksum); +//let data = &*packet.into_inner(); + +//assert!(socket.accepts(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into())); +//socket.process(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()); +//assert!(socket.can_recv()); + +//assert!(socket.accepts(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into())); +//socket.process(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()); + +//assert_eq!(socket.recv(), Ok((data, REMOTE_IPV4.into()))); +//assert!(!socket.can_recv()); +//} + +//#[rstest] +//#[case::ethernet(Medium::Ethernet)] +//#[cfg(feature = "medium-ethernet")] +//fn test_accept_bad_id(#[case] medium: Medium) { +//let (mut iface, _, _) = setup(medium); +//let cx = iface.context(); + +//let mut socket = socket(buffer(1), buffer(1)); +//assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(())); + +//let checksum = ChecksumCapabilities::default(); +//let mut bytes = [0xff; 20]; +//let mut packet = Icmpv4Packet::new_unchecked(&mut bytes); +//let icmp_repr = Icmpv4Repr::EchoRequest { +//ident: 0x4321, +//seq_no: 0x5678, +//data: &[0xff; 16], +//}; +//icmp_repr.emit(&mut packet, &checksum); + +//// Ensure that a packet with an identifier that isn't the bound +//// ID is not accepted +//assert!(!socket.accepts(cx, &REMOTE_IPV4_REPR, &icmp_repr.into())); +//} + +//#[rstest] +//#[case::ethernet(Medium::Ethernet)] +//#[cfg(feature = "medium-ethernet")] +//fn test_accepts_udp(#[case] medium: Medium) { +//let (mut iface, _, _) = setup(medium); +//let cx = iface.context(); + +//let mut socket = socket(buffer(1), buffer(1)); +//assert_eq!(socket.bind(Endpoint::Udp(LOCAL_END_V4.into())), Ok(())); + +//let checksum = ChecksumCapabilities::default(); + +//let mut bytes = [0xff; 18]; +//let mut packet = UdpPacket::new_unchecked(&mut bytes); +//UDP_REPR.emit( +//&mut packet, +//&REMOTE_IPV4.into(), +//&LOCAL_IPV4.into(), +//UDP_PAYLOAD.len(), +//|buf| buf.copy_from_slice(UDP_PAYLOAD), +//&checksum, +//); + +//let data = &*packet.into_inner(); + +//let icmp_repr = Icmpv4Repr::DstUnreachable { +//reason: Icmpv4DstUnreachable::PortUnreachable, +//header: Ipv4Repr { +//src_addr: LOCAL_IPV4, +//dst_addr: REMOTE_IPV4, +//next_header: IpProtocol::Icmp, +//payload_len: 12, +//hop_limit: 0x40, +//}, +//data, +//}; +//let ip_repr = IpRepr::Ipv4(Ipv4Repr { +//src_addr: REMOTE_IPV4, +//dst_addr: LOCAL_IPV4, +//next_header: IpProtocol::Icmp, +//payload_len: icmp_repr.buffer_len(), +//hop_limit: 0x40, +//}); + +//assert!(!socket.can_recv()); + +//// Ensure we can accept ICMP error response to the bound +//// UDP port +//assert!(socket.accepts(cx, &ip_repr, &icmp_repr.into())); +//socket.process(cx, &ip_repr, &icmp_repr.into()); +//assert!(socket.can_recv()); + +//let mut bytes = [0x00; 46]; +//let mut packet = Icmpv4Packet::new_unchecked(&mut bytes[..]); +//icmp_repr.emit(&mut packet, &checksum); +//assert_eq!( +//socket.recv(), +//Ok((&*packet.into_inner(), REMOTE_IPV4.into())) +//); +//assert!(!socket.can_recv()); +//} +//} + +//#[cfg(all(test, feature = "proto-ipv6"))] +//mod test_ipv6 { +//use crate::phy::Medium; +//use crate::tests::setup; +//use rstest::*; + +//use super::tests_common::*; + +//use crate::wire::{Icmpv6DstUnreachable, IpEndpoint, Ipv6Address}; + +//const REMOTE_IPV6: Ipv6Address = +//Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]); +//const LOCAL_IPV6: Ipv6Address = +//Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); +//const LOCAL_END_V6: IpEndpoint = IpEndpoint { +//addr: IpAddress::Ipv6(LOCAL_IPV6), +//port: LOCAL_PORT, +//}; +//static ECHOV6_REPR: Icmpv6Repr = Icmpv6Repr::EchoRequest { +//ident: 0x1234, +//seq_no: 0x5678, +//data: &[0xff; 16], +//}; + +//static LOCAL_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr { +//src_addr: LOCAL_IPV6, +//dst_addr: REMOTE_IPV6, +//next_header: IpProtocol::Icmpv6, +//payload_len: 24, +//hop_limit: 0x40, +//}); + +//static REMOTE_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr { +//src_addr: REMOTE_IPV6, +//dst_addr: LOCAL_IPV6, +//next_header: IpProtocol::Icmpv6, +//payload_len: 24, +//hop_limit: 0x40, +//}); + +//#[test] +//fn test_send_unaddressable() { +//let mut socket = socket(buffer(0), buffer(1)); +//assert_eq!( +//socket.send_slice(b"abcdef", IpAddress::Ipv6(Ipv6Address::default())), +//Err(SendError::Unaddressable) +//); +//assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV6.into()), Ok(())); +//} + +//#[rstest] +//#[case::ethernet(Medium::Ethernet)] +//#[cfg(feature = "medium-ethernet")] +//fn test_send_dispatch(#[case] medium: Medium) { +//let (mut iface, _, _) = setup(medium); +//let cx = iface.context(); + +//let mut socket = socket(buffer(0), buffer(1)); +//let checksum = ChecksumCapabilities::default(); + +//assert_eq!(socket.dispatch(cx, |_, _| unreachable!()), Ok::<_, ()>(())); + +//// This buffer is too long +//assert_eq!( +//socket.send_slice(&[0xff; 67], REMOTE_IPV6.into()), +//Err(SendError::BufferFull) +//); +//assert!(socket.can_send()); + +//let mut bytes = vec![0xff; 24]; +//let mut packet = Icmpv6Packet::new_unchecked(&mut bytes); +//ECHOV6_REPR.emit( +//&LOCAL_IPV6.into(), +//&REMOTE_IPV6.into(), +//&mut packet, +//&checksum, +//); + +//assert_eq!( +//socket.send_slice(&*packet.into_inner(), REMOTE_IPV6.into()), +//Ok(()) +//); +//assert_eq!( +//socket.send_slice(b"123456", REMOTE_IPV6.into()), +//Err(SendError::BufferFull) +//); +//assert!(!socket.can_send()); + +//assert_eq!( +//socket.dispatch(cx, |_, (ip_repr, icmp_repr)| { +//assert_eq!(ip_repr, LOCAL_IPV6_REPR); +//assert_eq!(icmp_repr, ECHOV6_REPR.into()); +//Err(()) +//}), +//Err(()) +//); +//// buffer is not taken off of the tx queue due to the error +//assert!(!socket.can_send()); + +//assert_eq!( +//socket.dispatch(cx, |_, (ip_repr, icmp_repr)| { +//assert_eq!(ip_repr, LOCAL_IPV6_REPR); +//assert_eq!(icmp_repr, ECHOV6_REPR.into()); +//Ok::<_, ()>(()) +//}), +//Ok(()) +//); +//// buffer is taken off of the queue this time +//assert!(socket.can_send()); +//} + +//#[rstest] +//#[case::ethernet(Medium::Ethernet)] +//#[cfg(feature = "medium-ethernet")] +//fn test_set_hop_limit(#[case] medium: Medium) { +//let (mut iface, _, _) = setup(medium); +//let cx = iface.context(); + +//let mut s = socket(buffer(0), buffer(1)); +//let checksum = ChecksumCapabilities::default(); + +//let mut bytes = vec![0xff; 24]; +//let mut packet = Icmpv6Packet::new_unchecked(&mut bytes); +//ECHOV6_REPR.emit( +//&LOCAL_IPV6.into(), +//&REMOTE_IPV6.into(), +//&mut packet, +//&checksum, +//); + +//s.set_hop_limit(Some(0x2a)); + +//assert_eq!( +//s.send_slice(&*packet.into_inner(), REMOTE_IPV6.into()), +//Ok(()) +//); +//assert_eq!( +//s.dispatch(cx, |_, (ip_repr, _)| { +//assert_eq!( +//ip_repr, +//IpRepr::Ipv6(Ipv6Repr { +//src_addr: LOCAL_IPV6, +//dst_addr: REMOTE_IPV6, +//next_header: IpProtocol::Icmpv6, +//payload_len: ECHOV6_REPR.buffer_len(), +//hop_limit: 0x2a, +//}) +//); +//Ok::<_, ()>(()) +//}), +//Ok(()) +//); +//} + +//#[rstest] +//#[case::ethernet(Medium::Ethernet)] +//#[cfg(feature = "medium-ethernet")] +//fn test_recv_process(#[case] medium: Medium) { +//let (mut iface, _, _) = setup(medium); +//let cx = iface.context(); + +//let mut socket = socket(buffer(1), buffer(1)); +//assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(())); + +//assert!(!socket.can_recv()); +//assert_eq!(socket.recv(), Err(RecvError::Exhausted)); + +//let checksum = ChecksumCapabilities::default(); + +//let mut bytes = [0xff; 24]; +//let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]); +//ECHOV6_REPR.emit( +//&LOCAL_IPV6.into(), +//&REMOTE_IPV6.into(), +//&mut packet, +//&checksum, +//); +//let data = &*packet.into_inner(); + +//assert!(socket.accepts(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into())); +//socket.process(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()); +//assert!(socket.can_recv()); + +//assert!(socket.accepts(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into())); +//socket.process(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()); + +//assert_eq!(socket.recv(), Ok((data, REMOTE_IPV6.into()))); +//assert!(!socket.can_recv()); +//} + +//#[rstest] +//#[case::ethernet(Medium::Ethernet)] +//#[cfg(feature = "medium-ethernet")] +//fn test_truncated_recv_slice(#[case] medium: Medium) { +//let (mut iface, _, _) = setup(medium); +//let cx = iface.context(); + +//let mut socket = socket(buffer(1), buffer(1)); +//assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(())); + +//let checksum = ChecksumCapabilities::default(); + +//let mut bytes = [0xff; 24]; +//let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]); +//ECHOV6_REPR.emit( +//&LOCAL_IPV6.into(), +//&REMOTE_IPV6.into(), +//&mut packet, +//&checksum, +//); + +//assert!(socket.accepts(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into())); +//socket.process(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()); +//assert!(socket.can_recv()); + +//assert!(socket.accepts(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into())); +//socket.process(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()); + +//let mut buffer = [0u8; 1]; +//assert_eq!( +//socket.recv_slice(&mut buffer[..]), +//Err(RecvError::Truncated) +//); +//assert!(!socket.can_recv()); +//} + +//#[rstest] +//#[case::ethernet(Medium::Ethernet)] +//#[cfg(feature = "medium-ethernet")] +//fn test_accept_bad_id(#[case] medium: Medium) { +//let (mut iface, _, _) = setup(medium); +//let cx = iface.context(); + +//let mut socket = socket(buffer(1), buffer(1)); +//assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(())); + +//let checksum = ChecksumCapabilities::default(); +//let mut bytes = [0xff; 20]; +//let mut packet = Icmpv6Packet::new_unchecked(&mut bytes); +//let icmp_repr = Icmpv6Repr::EchoRequest { +//ident: 0x4321, +//seq_no: 0x5678, +//data: &[0xff; 16], +//}; +//icmp_repr.emit( +//&LOCAL_IPV6.into(), +//&REMOTE_IPV6.into(), +//&mut packet, +//&checksum, +//); + +//// Ensure that a packet with an identifier that isn't the bound +//// ID is not accepted +//assert!(!socket.accepts(cx, &REMOTE_IPV6_REPR, &icmp_repr.into())); +//} + +//#[rstest] +//#[case::ethernet(Medium::Ethernet)] +//#[cfg(feature = "medium-ethernet")] +//fn test_accepts_udp(#[case] medium: Medium) { +//let (mut iface, _, _) = setup(medium); +//let cx = iface.context(); + +//let mut socket = socket(buffer(1), buffer(1)); +//assert_eq!(socket.bind(Endpoint::Udp(LOCAL_END_V6.into())), Ok(())); + +//let checksum = ChecksumCapabilities::default(); + +//let mut bytes = [0xff; 18]; +//let mut packet = UdpPacket::new_unchecked(&mut bytes); +//UDP_REPR.emit( +//&mut packet, +//&REMOTE_IPV6.into(), +//&LOCAL_IPV6.into(), +//UDP_PAYLOAD.len(), +//|buf| buf.copy_from_slice(UDP_PAYLOAD), +//&checksum, +//); + +//let data = &*packet.into_inner(); + +//let icmp_repr = Icmpv6Repr::DstUnreachable { +//reason: Icmpv6DstUnreachable::PortUnreachable, +//header: Ipv6Repr { +//src_addr: LOCAL_IPV6, +//dst_addr: REMOTE_IPV6, +//next_header: IpProtocol::Icmpv6, +//payload_len: 12, +//hop_limit: 0x40, +//}, +//data, +//}; +//let ip_repr = IpRepr::Ipv6(Ipv6Repr { +//src_addr: REMOTE_IPV6, +//dst_addr: LOCAL_IPV6, +//next_header: IpProtocol::Icmpv6, +//payload_len: icmp_repr.buffer_len(), +//hop_limit: 0x40, +//}); + +//assert!(!socket.can_recv()); + +//// Ensure we can accept ICMP error response to the bound +//// UDP port +//assert!(socket.accepts(cx, &ip_repr, &icmp_repr.into())); +//socket.process(cx, &ip_repr, &icmp_repr.into()); +//assert!(socket.can_recv()); + +//let mut bytes = [0x00; 66]; +//let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]); +//icmp_repr.emit( +//&LOCAL_IPV6.into(), +//&REMOTE_IPV6.into(), +//&mut packet, +//&checksum, +//); +//assert_eq!( +//socket.recv(), +//Ok((&*packet.into_inner(), REMOTE_IPV6.into())) +//); +//assert!(!socket.can_recv()); +//} +//} diff --git a/smoltcp/src/socket/mod.rs b/smoltcp/src/socket/mod.rs index 048a6a327..028ab3ff3 100644 --- a/smoltcp/src/socket/mod.rs +++ b/smoltcp/src/socket/mod.rs @@ -13,6 +13,7 @@ size for a buffer, allocate it, and let the networking stack use it. use crate::iface::Context; use crate::time::Instant; +use awkernel_sync::{mcs::MCSNode, mutex::Mutex}; #[cfg(feature = "socket-dhcpv4")] pub mod dhcpv4; @@ -55,48 +56,71 @@ pub(crate) enum PollAt { /// /// [AnySocket]: trait.AnySocket.html /// [SocketSet::get]: struct.SocketSet.html#method.get -#[derive(Debug)] pub enum Socket<'a> { #[cfg(feature = "socket-raw")] - Raw(raw::Socket<'a>), + Raw(Mutex>), #[cfg(feature = "socket-icmp")] - Icmp(icmp::Socket<'a>), + Icmp(Mutex>), #[cfg(feature = "socket-udp")] - Udp(udp::Socket<'a>), + Udp(Mutex>), #[cfg(feature = "socket-tcp")] - Tcp(tcp::Socket<'a>), + Tcp(Mutex>), #[cfg(feature = "socket-dhcpv4")] - Dhcpv4(dhcpv4::Socket<'a>), + Dhcpv4(Mutex>), #[cfg(feature = "socket-dns")] - Dns(dns::Socket<'a>), + Dns(Mutex>), } impl Socket<'_> { pub(crate) fn poll_at(&self, cx: &mut Context) -> PollAt { match self { #[cfg(feature = "socket-raw")] - Socket::Raw(s) => s.poll_at(cx), + Socket::Raw(s) => { + let mut node = MCSNode::new(); + let guard = s.lock(&mut node); + guard.poll_at(cx) + } #[cfg(feature = "socket-icmp")] - Socket::Icmp(s) => s.poll_at(cx), + Socket::Icmp(s) => { + let mut node = MCSNode::new(); + let guard = s.lock(&mut node); + guard.poll_at(cx) + } #[cfg(feature = "socket-udp")] - Socket::Udp(s) => s.poll_at(cx), + Socket::Udp(s) => { + let mut node = MCSNode::new(); + let guard = s.lock(&mut node); + guard.poll_at(cx) + } #[cfg(feature = "socket-tcp")] - Socket::Tcp(s) => s.poll_at(cx), + Socket::Tcp(s) => { + let mut node = MCSNode::new(); + let guard = s.lock(&mut node); + guard.poll_at(cx) + } #[cfg(feature = "socket-dhcpv4")] - Socket::Dhcpv4(s) => s.poll_at(cx), + Socket::Dhcpv4(s) => { + let mut node = MCSNode::new(); + let guard = s.lock(&mut node); + guard.poll_at(cx) + } #[cfg(feature = "socket-dns")] - Socket::Dns(s) => s.poll_at(cx), + Socket::Dns(s) => { + let mut node = MCSNode::new(); + let guard = s.lock(&mut node); + guard.poll_at(cx) + } } } } /// A conversion trait for network sockets. -pub trait AnySocket<'a> { +pub trait AnySocket<'a>: Send { fn upcast(self) -> Socket<'a>; - fn downcast<'c>(socket: &'c Socket<'a>) -> Option<&'c Self> + fn downcast<'c>(socket: &'c Socket<'a>) -> Option<&'c Mutex> where Self: Sized; - fn downcast_mut<'c>(socket: &'c mut Socket<'a>) -> Option<&'c mut Self> + fn downcast_mut<'c>(socket: &'c mut Socket<'a>) -> Option<&'c mut Mutex> where Self: Sized; } @@ -105,10 +129,10 @@ macro_rules! from_socket { ($socket:ty, $variant:ident) => { impl<'a> AnySocket<'a> for $socket { fn upcast(self) -> Socket<'a> { - Socket::$variant(self) + Socket::$variant(Mutex::new(self)) } - fn downcast<'c>(socket: &'c Socket<'a>) -> Option<&'c Self> { + fn downcast<'c>(socket: &'c Socket<'a>) -> Option<&'c Mutex> { #[allow(unreachable_patterns)] match socket { Socket::$variant(socket) => Some(socket), @@ -116,7 +140,7 @@ macro_rules! from_socket { } } - fn downcast_mut<'c>(socket: &'c mut Socket<'a>) -> Option<&'c mut Self> { + fn downcast_mut<'c>(socket: &'c mut Socket<'a>) -> Option<&'c mut Mutex> { #[allow(unreachable_patterns)] match socket { Socket::$variant(socket) => Some(socket), diff --git a/smoltcp/src/socket/udp.rs b/smoltcp/src/socket/udp.rs index 82eebf26d..6e799c363 100644 --- a/smoltcp/src/socket/udp.rs +++ b/smoltcp/src/socket/udp.rs @@ -573,458 +573,457 @@ impl<'a> Socket<'a> { } } -#[cfg(test)] -mod test { - use super::*; - use crate::wire::{IpRepr, UdpRepr}; - - use crate::phy::Medium; - use crate::tests::setup; - use rstest::*; - - fn buffer(packets: usize) -> PacketBuffer<'static> { - PacketBuffer::new( - (0..packets) - .map(|_| PacketMetadata::EMPTY) - .collect::>(), - vec![0; 16 * packets], - ) - } - - fn socket( - rx_buffer: PacketBuffer<'static>, - tx_buffer: PacketBuffer<'static>, - ) -> Socket<'static> { - Socket::new(rx_buffer, tx_buffer) - } - - const LOCAL_PORT: u16 = 53; - const REMOTE_PORT: u16 = 49500; - - cfg_if::cfg_if! { - if #[cfg(feature = "proto-ipv4")] { - use crate::wire::Ipv4Address as IpvXAddress; - use crate::wire::Ipv4Repr as IpvXRepr; - use IpRepr::Ipv4 as IpReprIpvX; - - const LOCAL_ADDR: IpvXAddress = IpvXAddress([192, 168, 1, 1]); - const REMOTE_ADDR: IpvXAddress = IpvXAddress([192, 168, 1, 2]); - const OTHER_ADDR: IpvXAddress = IpvXAddress([192, 168, 1, 3]); - } else { - use crate::wire::Ipv6Address as IpvXAddress; - use crate::wire::Ipv6Repr as IpvXRepr; - use IpRepr::Ipv6 as IpReprIpvX; - - const LOCAL_ADDR: IpvXAddress = IpvXAddress([ - 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - ]); - const REMOTE_ADDR: IpvXAddress = IpvXAddress([ - 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, - ]); - const OTHER_ADDR: IpvXAddress = IpvXAddress([ - 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, - ]); - } - } - - pub const LOCAL_END: IpEndpoint = IpEndpoint { - addr: LOCAL_ADDR.into_address(), - port: LOCAL_PORT, - }; - pub const REMOTE_END: IpEndpoint = IpEndpoint { - addr: REMOTE_ADDR.into_address(), - port: REMOTE_PORT, - }; - - pub const LOCAL_IP_REPR: IpRepr = IpReprIpvX(IpvXRepr { - src_addr: LOCAL_ADDR, - dst_addr: REMOTE_ADDR, - next_header: IpProtocol::Udp, - payload_len: 8 + 6, - hop_limit: 64, - }); - - pub const REMOTE_IP_REPR: IpRepr = IpReprIpvX(IpvXRepr { - src_addr: REMOTE_ADDR, - dst_addr: LOCAL_ADDR, - next_header: IpProtocol::Udp, - payload_len: 8 + 6, - hop_limit: 64, - }); - - pub const BAD_IP_REPR: IpRepr = IpReprIpvX(IpvXRepr { - src_addr: REMOTE_ADDR, - dst_addr: OTHER_ADDR, - next_header: IpProtocol::Udp, - payload_len: 8 + 6, - hop_limit: 64, - }); - - const LOCAL_UDP_REPR: UdpRepr = UdpRepr { - src_port: LOCAL_PORT, - dst_port: REMOTE_PORT, - }; - - const REMOTE_UDP_REPR: UdpRepr = UdpRepr { - src_port: REMOTE_PORT, - dst_port: LOCAL_PORT, - }; - - const PAYLOAD: &[u8] = b"abcdef"; - - #[test] - fn test_bind_unaddressable() { - let mut socket = socket(buffer(0), buffer(0)); - assert_eq!(socket.bind(0), Err(BindError::Unaddressable)); - } - - #[test] - fn test_bind_twice() { - let mut socket = socket(buffer(0), buffer(0)); - assert_eq!(socket.bind(1), Ok(())); - assert_eq!(socket.bind(2), Err(BindError::InvalidState)); - } - - #[test] - #[should_panic(expected = "the time-to-live value of a packet must not be zero")] - fn test_set_hop_limit_zero() { - let mut s = socket(buffer(0), buffer(1)); - s.set_hop_limit(Some(0)); - } - - #[test] - fn test_send_unaddressable() { - let mut socket = socket(buffer(0), buffer(1)); - - assert_eq!( - socket.send_slice(b"abcdef", REMOTE_END), - Err(SendError::Unaddressable) - ); - assert_eq!(socket.bind(LOCAL_PORT), Ok(())); - assert_eq!( - socket.send_slice( - b"abcdef", - IpEndpoint { - addr: IpvXAddress::UNSPECIFIED.into(), - ..REMOTE_END - } - ), - Err(SendError::Unaddressable) - ); - assert_eq!( - socket.send_slice( - b"abcdef", - IpEndpoint { - port: 0, - ..REMOTE_END - } - ), - Err(SendError::Unaddressable) - ); - assert_eq!(socket.send_slice(b"abcdef", REMOTE_END), Ok(())); - } - - #[rstest] - #[case::ip(Medium::Ip)] - #[cfg(feature = "medium-ip")] - #[case::ethernet(Medium::Ethernet)] - #[cfg(feature = "medium-ethernet")] - #[case::ieee802154(Medium::Ieee802154)] - #[cfg(feature = "medium-ieee802154")] - fn test_send_dispatch(#[case] medium: Medium) { - let (mut iface, _, _) = setup(medium); - let cx = iface.context(); - let mut socket = socket(buffer(0), buffer(1)); - - assert_eq!(socket.bind(LOCAL_END), Ok(())); - - assert!(socket.can_send()); - assert_eq!( - socket.dispatch(cx, |_, _, _| unreachable!()), - Ok::<_, ()>(()) - ); - - assert_eq!(socket.send_slice(b"abcdef", REMOTE_END), Ok(())); - assert_eq!( - socket.send_slice(b"123456", REMOTE_END), - Err(SendError::BufferFull) - ); - assert!(!socket.can_send()); - - assert_eq!( - socket.dispatch(cx, |_, _, (ip_repr, udp_repr, payload)| { - assert_eq!(ip_repr, LOCAL_IP_REPR); - assert_eq!(udp_repr, LOCAL_UDP_REPR); - assert_eq!(payload, PAYLOAD); - Err(()) - }), - Err(()) - ); - assert!(!socket.can_send()); - - assert_eq!( - socket.dispatch(cx, |_, _, (ip_repr, udp_repr, payload)| { - assert_eq!(ip_repr, LOCAL_IP_REPR); - assert_eq!(udp_repr, LOCAL_UDP_REPR); - assert_eq!(payload, PAYLOAD); - Ok::<_, ()>(()) - }), - Ok(()) - ); - assert!(socket.can_send()); - } - - #[rstest] - #[case::ip(Medium::Ip)] - #[cfg(feature = "medium-ip")] - #[case::ethernet(Medium::Ethernet)] - #[cfg(feature = "medium-ethernet")] - #[case::ieee802154(Medium::Ieee802154)] - #[cfg(feature = "medium-ieee802154")] - fn test_recv_process(#[case] medium: Medium) { - let (mut iface, _, _) = setup(medium); - let cx = iface.context(); - - let mut socket = socket(buffer(1), buffer(0)); - - assert_eq!(socket.bind(LOCAL_PORT), Ok(())); - - assert!(!socket.can_recv()); - assert_eq!(socket.recv(), Err(RecvError::Exhausted)); - - assert!(socket.accepts(cx, &REMOTE_IP_REPR, &REMOTE_UDP_REPR)); - socket.process( - cx, - PacketMeta::default(), - &REMOTE_IP_REPR, - &REMOTE_UDP_REPR, - PAYLOAD, - ); - assert!(socket.can_recv()); - - assert!(socket.accepts(cx, &REMOTE_IP_REPR, &REMOTE_UDP_REPR)); - socket.process( - cx, - PacketMeta::default(), - &REMOTE_IP_REPR, - &REMOTE_UDP_REPR, - PAYLOAD, - ); - - assert_eq!(socket.recv(), Ok((&b"abcdef"[..], REMOTE_END.into()))); - assert!(!socket.can_recv()); - } - - #[rstest] - #[case::ip(Medium::Ip)] - #[cfg(feature = "medium-ip")] - #[case::ethernet(Medium::Ethernet)] - #[cfg(feature = "medium-ethernet")] - #[case::ieee802154(Medium::Ieee802154)] - #[cfg(feature = "medium-ieee802154")] - fn test_peek_process(#[case] medium: Medium) { - let (mut iface, _, _) = setup(medium); - let cx = iface.context(); - - let mut socket = socket(buffer(1), buffer(0)); - - assert_eq!(socket.bind(LOCAL_PORT), Ok(())); - - assert_eq!(socket.peek(), Err(RecvError::Exhausted)); - - socket.process( - cx, - PacketMeta::default(), - &REMOTE_IP_REPR, - &REMOTE_UDP_REPR, - PAYLOAD, - ); - assert_eq!(socket.peek(), Ok((&b"abcdef"[..], &REMOTE_END.into(),))); - assert_eq!(socket.recv(), Ok((&b"abcdef"[..], REMOTE_END.into(),))); - assert_eq!(socket.peek(), Err(RecvError::Exhausted)); - } - - #[rstest] - #[case::ip(Medium::Ip)] - #[cfg(feature = "medium-ip")] - #[case::ethernet(Medium::Ethernet)] - #[cfg(feature = "medium-ethernet")] - #[case::ieee802154(Medium::Ieee802154)] - #[cfg(feature = "medium-ieee802154")] - fn test_recv_truncated_slice(#[case] medium: Medium) { - let (mut iface, _, _) = setup(medium); - let cx = iface.context(); - - let mut socket = socket(buffer(1), buffer(0)); - - assert_eq!(socket.bind(LOCAL_PORT), Ok(())); - - assert!(socket.accepts(cx, &REMOTE_IP_REPR, &REMOTE_UDP_REPR)); - socket.process( - cx, - PacketMeta::default(), - &REMOTE_IP_REPR, - &REMOTE_UDP_REPR, - PAYLOAD, - ); - - let mut slice = [0; 4]; - assert_eq!(socket.recv_slice(&mut slice[..]), Err(RecvError::Truncated)); - } - - #[rstest] - #[case::ip(Medium::Ip)] - #[cfg(feature = "medium-ip")] - #[case::ethernet(Medium::Ethernet)] - #[cfg(feature = "medium-ethernet")] - #[case::ieee802154(Medium::Ieee802154)] - #[cfg(feature = "medium-ieee802154")] - fn test_peek_truncated_slice(#[case] medium: Medium) { - let (mut iface, _, _) = setup(medium); - let cx = iface.context(); - - let mut socket = socket(buffer(1), buffer(0)); - - assert_eq!(socket.bind(LOCAL_PORT), Ok(())); - - socket.process( - cx, - PacketMeta::default(), - &REMOTE_IP_REPR, - &REMOTE_UDP_REPR, - PAYLOAD, - ); - - let mut slice = [0; 4]; - assert_eq!(socket.peek_slice(&mut slice[..]), Err(RecvError::Truncated)); - assert_eq!(socket.recv_slice(&mut slice[..]), Err(RecvError::Truncated)); - assert_eq!(socket.peek_slice(&mut slice[..]), Err(RecvError::Exhausted)); - } - - #[rstest] - #[case::ip(Medium::Ip)] - #[cfg(feature = "medium-ip")] - #[case::ethernet(Medium::Ethernet)] - #[cfg(feature = "medium-ethernet")] - #[case::ieee802154(Medium::Ieee802154)] - #[cfg(feature = "medium-ieee802154")] - fn test_set_hop_limit(#[case] medium: Medium) { - let (mut iface, _, _) = setup(medium); - let cx = iface.context(); - - let mut s = socket(buffer(0), buffer(1)); - - assert_eq!(s.bind(LOCAL_END), Ok(())); - - s.set_hop_limit(Some(0x2a)); - assert_eq!(s.send_slice(b"abcdef", REMOTE_END), Ok(())); - assert_eq!( - s.dispatch(cx, |_, _, (ip_repr, _, _)| { - assert_eq!( - ip_repr, - IpReprIpvX(IpvXRepr { - src_addr: LOCAL_ADDR, - dst_addr: REMOTE_ADDR, - next_header: IpProtocol::Udp, - payload_len: 8 + 6, - hop_limit: 0x2a, - }) - ); - Ok::<_, ()>(()) - }), - Ok(()) - ); - } - - #[rstest] - #[case::ip(Medium::Ip)] - #[cfg(feature = "medium-ip")] - #[case::ethernet(Medium::Ethernet)] - #[cfg(feature = "medium-ethernet")] - #[case::ieee802154(Medium::Ieee802154)] - #[cfg(feature = "medium-ieee802154")] - fn test_doesnt_accept_wrong_port(#[case] medium: Medium) { - let (mut iface, _, _) = setup(medium); - let cx = iface.context(); - - let mut socket = socket(buffer(1), buffer(0)); - - assert_eq!(socket.bind(LOCAL_PORT), Ok(())); - - let mut udp_repr = REMOTE_UDP_REPR; - assert!(socket.accepts(cx, &REMOTE_IP_REPR, &udp_repr)); - udp_repr.dst_port += 1; - assert!(!socket.accepts(cx, &REMOTE_IP_REPR, &udp_repr)); - } - - #[rstest] - #[case::ip(Medium::Ip)] - #[cfg(feature = "medium-ip")] - #[case::ethernet(Medium::Ethernet)] - #[cfg(feature = "medium-ethernet")] - #[case::ieee802154(Medium::Ieee802154)] - #[cfg(feature = "medium-ieee802154")] - fn test_doesnt_accept_wrong_ip(#[case] medium: Medium) { - let (mut iface, _, _) = setup(medium); - let cx = iface.context(); - - let mut port_bound_socket = socket(buffer(1), buffer(0)); - assert_eq!(port_bound_socket.bind(LOCAL_PORT), Ok(())); - assert!(port_bound_socket.accepts(cx, &BAD_IP_REPR, &REMOTE_UDP_REPR)); - - let mut ip_bound_socket = socket(buffer(1), buffer(0)); - assert_eq!(ip_bound_socket.bind(LOCAL_END), Ok(())); - assert!(!ip_bound_socket.accepts(cx, &BAD_IP_REPR, &REMOTE_UDP_REPR)); - } - - #[test] - fn test_send_large_packet() { - // buffer(4) creates a payload buffer of size 16*4 - let mut socket = socket(buffer(0), buffer(4)); - assert_eq!(socket.bind(LOCAL_END), Ok(())); - - let too_large = b"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefx"; - assert_eq!( - socket.send_slice(too_large, REMOTE_END), - Err(SendError::BufferFull) - ); - assert_eq!(socket.send_slice(&too_large[..16 * 4], REMOTE_END), Ok(())); - } - - #[rstest] - #[case::ip(Medium::Ip)] - #[cfg(feature = "medium-ip")] - #[case::ethernet(Medium::Ethernet)] - #[cfg(feature = "medium-ethernet")] - #[case::ieee802154(Medium::Ieee802154)] - #[cfg(feature = "medium-ieee802154")] - fn test_process_empty_payload(#[case] medium: Medium) { - let meta = Box::leak(Box::new([PacketMetadata::EMPTY])); - let recv_buffer = PacketBuffer::new(&mut meta[..], vec![]); - let mut socket = socket(recv_buffer, buffer(0)); - - let (mut iface, _, _) = setup(medium); - let cx = iface.context(); - - assert_eq!(socket.bind(LOCAL_PORT), Ok(())); - - let repr = UdpRepr { - src_port: REMOTE_PORT, - dst_port: LOCAL_PORT, - }; - socket.process(cx, PacketMeta::default(), &REMOTE_IP_REPR, &repr, &[]); - assert_eq!(socket.recv(), Ok((&[][..], REMOTE_END.into()))); - } - - #[test] - fn test_closing() { - let meta = Box::leak(Box::new([PacketMetadata::EMPTY])); - let recv_buffer = PacketBuffer::new(&mut meta[..], vec![]); - let mut socket = socket(recv_buffer, buffer(0)); - assert_eq!(socket.bind(LOCAL_PORT), Ok(())); - - assert!(socket.is_open()); - socket.close(); - assert!(!socket.is_open()); - } -} +//#[cfg(test)] //mod test { +//use super::*; +//use crate::wire::{IpRepr, UdpRepr}; + +//use crate::phy::Medium; +//use crate::tests::setup; +//use rstest::*; + +//fn buffer(packets: usize) -> PacketBuffer<'static> { +//PacketBuffer::new( +//(0..packets) +//.map(|_| PacketMetadata::EMPTY) +//.collect::>(), +//vec![0; 16 * packets], +//) +//} + +//fn socket( +//rx_buffer: PacketBuffer<'static>, +//tx_buffer: PacketBuffer<'static>, +//) -> Socket<'static> { +//Socket::new(rx_buffer, tx_buffer) +//} + +//const LOCAL_PORT: u16 = 53; +//const REMOTE_PORT: u16 = 49500; + +//cfg_if::cfg_if! { +//if #[cfg(feature = "proto-ipv4")] { +//use crate::wire::Ipv4Address as IpvXAddress; +//use crate::wire::Ipv4Repr as IpvXRepr; +//use IpRepr::Ipv4 as IpReprIpvX; + +//const LOCAL_ADDR: IpvXAddress = IpvXAddress([192, 168, 1, 1]); +//const REMOTE_ADDR: IpvXAddress = IpvXAddress([192, 168, 1, 2]); +//const OTHER_ADDR: IpvXAddress = IpvXAddress([192, 168, 1, 3]); +//} else { +//use crate::wire::Ipv6Address as IpvXAddress; +//use crate::wire::Ipv6Repr as IpvXRepr; +//use IpRepr::Ipv6 as IpReprIpvX; + +//const LOCAL_ADDR: IpvXAddress = IpvXAddress([ +//0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, +//]); +//const REMOTE_ADDR: IpvXAddress = IpvXAddress([ +//0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, +//]); +//const OTHER_ADDR: IpvXAddress = IpvXAddress([ +//0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, +//]); +//} +//} + +//pub const LOCAL_END: IpEndpoint = IpEndpoint { +//addr: LOCAL_ADDR.into_address(), +//port: LOCAL_PORT, +//}; +//pub const REMOTE_END: IpEndpoint = IpEndpoint { +//addr: REMOTE_ADDR.into_address(), +//port: REMOTE_PORT, +//}; + +//pub const LOCAL_IP_REPR: IpRepr = IpReprIpvX(IpvXRepr { +//src_addr: LOCAL_ADDR, +//dst_addr: REMOTE_ADDR, +//next_header: IpProtocol::Udp, +//payload_len: 8 + 6, +//hop_limit: 64, +//}); + +//pub const REMOTE_IP_REPR: IpRepr = IpReprIpvX(IpvXRepr { +//src_addr: REMOTE_ADDR, +//dst_addr: LOCAL_ADDR, +//next_header: IpProtocol::Udp, +//payload_len: 8 + 6, +//hop_limit: 64, +//}); + +//pub const BAD_IP_REPR: IpRepr = IpReprIpvX(IpvXRepr { +//src_addr: REMOTE_ADDR, +//dst_addr: OTHER_ADDR, +//next_header: IpProtocol::Udp, +//payload_len: 8 + 6, +//hop_limit: 64, +//}); + +//const LOCAL_UDP_REPR: UdpRepr = UdpRepr { +//src_port: LOCAL_PORT, +//dst_port: REMOTE_PORT, +//}; + +//const REMOTE_UDP_REPR: UdpRepr = UdpRepr { +//src_port: REMOTE_PORT, +//dst_port: LOCAL_PORT, +//}; + +//const PAYLOAD: &[u8] = b"abcdef"; + +//#[test] +//fn test_bind_unaddressable() { +//let mut socket = socket(buffer(0), buffer(0)); +//assert_eq!(socket.bind(0), Err(BindError::Unaddressable)); +//} + +//#[test] +//fn test_bind_twice() { +//let mut socket = socket(buffer(0), buffer(0)); +//assert_eq!(socket.bind(1), Ok(())); +//assert_eq!(socket.bind(2), Err(BindError::InvalidState)); +//} + +//#[test] +//#[should_panic(expected = "the time-to-live value of a packet must not be zero")] +//fn test_set_hop_limit_zero() { +//let mut s = socket(buffer(0), buffer(1)); +//s.set_hop_limit(Some(0)); +//} + +//#[test] +//fn test_send_unaddressable() { +//let mut socket = socket(buffer(0), buffer(1)); + +//assert_eq!( +//socket.send_slice(b"abcdef", REMOTE_END), +//Err(SendError::Unaddressable) +//); +//assert_eq!(socket.bind(LOCAL_PORT), Ok(())); +//assert_eq!( +//socket.send_slice( +//b"abcdef", +//IpEndpoint { +//addr: IpvXAddress::UNSPECIFIED.into(), +//..REMOTE_END +//} +//), +//Err(SendError::Unaddressable) +//); +//assert_eq!( +//socket.send_slice( +//b"abcdef", +//IpEndpoint { +//port: 0, +//..REMOTE_END +//} +//), +//Err(SendError::Unaddressable) +//); +//assert_eq!(socket.send_slice(b"abcdef", REMOTE_END), Ok(())); +//} + +//#[rstest] +//#[case::ip(Medium::Ip)] +//#[cfg(feature = "medium-ip")] +//#[case::ethernet(Medium::Ethernet)] +//#[cfg(feature = "medium-ethernet")] +//#[case::ieee802154(Medium::Ieee802154)] +//#[cfg(feature = "medium-ieee802154")] +//fn test_send_dispatch(#[case] medium: Medium) { +//let (mut iface, _, _) = setup(medium); +//let cx = iface.context(); +//let mut socket = socket(buffer(0), buffer(1)); + +//assert_eq!(socket.bind(LOCAL_END), Ok(())); + +//assert!(socket.can_send()); +//assert_eq!( +//socket.dispatch(cx, |_, _, _| unreachable!()), +//Ok::<_, ()>(()) +//); + +//assert_eq!(socket.send_slice(b"abcdef", REMOTE_END), Ok(())); +//assert_eq!( +//socket.send_slice(b"123456", REMOTE_END), +//Err(SendError::BufferFull) +//); +//assert!(!socket.can_send()); + +//assert_eq!( +//socket.dispatch(cx, |_, _, (ip_repr, udp_repr, payload)| { +//assert_eq!(ip_repr, LOCAL_IP_REPR); +//assert_eq!(udp_repr, LOCAL_UDP_REPR); +//assert_eq!(payload, PAYLOAD); +//Err(()) +//}), +//Err(()) +//); +//assert!(!socket.can_send()); + +//assert_eq!( +//socket.dispatch(cx, |_, _, (ip_repr, udp_repr, payload)| { +//assert_eq!(ip_repr, LOCAL_IP_REPR); +//assert_eq!(udp_repr, LOCAL_UDP_REPR); +//assert_eq!(payload, PAYLOAD); +//Ok::<_, ()>(()) +//}), +//Ok(()) +//); +//assert!(socket.can_send()); +//} + +//#[rstest] +//#[case::ip(Medium::Ip)] +//#[cfg(feature = "medium-ip")] +//#[case::ethernet(Medium::Ethernet)] +//#[cfg(feature = "medium-ethernet")] +//#[case::ieee802154(Medium::Ieee802154)] +//#[cfg(feature = "medium-ieee802154")] +//fn test_recv_process(#[case] medium: Medium) { +//let (mut iface, _, _) = setup(medium); +//let cx = iface.context(); + +//let mut socket = socket(buffer(1), buffer(0)); + +//assert_eq!(socket.bind(LOCAL_PORT), Ok(())); + +//assert!(!socket.can_recv()); +//assert_eq!(socket.recv(), Err(RecvError::Exhausted)); + +//assert!(socket.accepts(cx, &REMOTE_IP_REPR, &REMOTE_UDP_REPR)); +//socket.process( +//cx, +//PacketMeta::default(), +//&REMOTE_IP_REPR, +//&REMOTE_UDP_REPR, +//PAYLOAD, +//); +//assert!(socket.can_recv()); + +//assert!(socket.accepts(cx, &REMOTE_IP_REPR, &REMOTE_UDP_REPR)); +//socket.process( +//cx, +//PacketMeta::default(), +//&REMOTE_IP_REPR, +//&REMOTE_UDP_REPR, +//PAYLOAD, +//); + +//assert_eq!(socket.recv(), Ok((&b"abcdef"[..], REMOTE_END.into()))); +//assert!(!socket.can_recv()); +//} + +//#[rstest] +//#[case::ip(Medium::Ip)] +//#[cfg(feature = "medium-ip")] +//#[case::ethernet(Medium::Ethernet)] +//#[cfg(feature = "medium-ethernet")] +//#[case::ieee802154(Medium::Ieee802154)] +//#[cfg(feature = "medium-ieee802154")] +//fn test_peek_process(#[case] medium: Medium) { +//let (mut iface, _, _) = setup(medium); +//let cx = iface.context(); + +//let mut socket = socket(buffer(1), buffer(0)); + +//assert_eq!(socket.bind(LOCAL_PORT), Ok(())); + +//assert_eq!(socket.peek(), Err(RecvError::Exhausted)); + +//socket.process( +//cx, +//PacketMeta::default(), +//&REMOTE_IP_REPR, +//&REMOTE_UDP_REPR, +//PAYLOAD, +//); +//assert_eq!(socket.peek(), Ok((&b"abcdef"[..], &REMOTE_END.into(),))); +//assert_eq!(socket.recv(), Ok((&b"abcdef"[..], REMOTE_END.into(),))); +//assert_eq!(socket.peek(), Err(RecvError::Exhausted)); +//} + +//#[rstest] +//#[case::ip(Medium::Ip)] +//#[cfg(feature = "medium-ip")] +//#[case::ethernet(Medium::Ethernet)] +//#[cfg(feature = "medium-ethernet")] +//#[case::ieee802154(Medium::Ieee802154)] +//#[cfg(feature = "medium-ieee802154")] +//fn test_recv_truncated_slice(#[case] medium: Medium) { +//let (mut iface, _, _) = setup(medium); +//let cx = iface.context(); + +//let mut socket = socket(buffer(1), buffer(0)); + +//assert_eq!(socket.bind(LOCAL_PORT), Ok(())); + +//assert!(socket.accepts(cx, &REMOTE_IP_REPR, &REMOTE_UDP_REPR)); +//socket.process( +//cx, +//PacketMeta::default(), +//&REMOTE_IP_REPR, +//&REMOTE_UDP_REPR, +//PAYLOAD, +//); + +//let mut slice = [0; 4]; +//assert_eq!(socket.recv_slice(&mut slice[..]), Err(RecvError::Truncated)); +//} + +//#[rstest] +//#[case::ip(Medium::Ip)] +//#[cfg(feature = "medium-ip")] +//#[case::ethernet(Medium::Ethernet)] +//#[cfg(feature = "medium-ethernet")] +//#[case::ieee802154(Medium::Ieee802154)] +//#[cfg(feature = "medium-ieee802154")] +//fn test_peek_truncated_slice(#[case] medium: Medium) { +//let (mut iface, _, _) = setup(medium); +//let cx = iface.context(); + +//let mut socket = socket(buffer(1), buffer(0)); + +//assert_eq!(socket.bind(LOCAL_PORT), Ok(())); + +//socket.process( +//cx, +//PacketMeta::default(), +//&REMOTE_IP_REPR, +//&REMOTE_UDP_REPR, +//PAYLOAD, +//); + +//let mut slice = [0; 4]; +//assert_eq!(socket.peek_slice(&mut slice[..]), Err(RecvError::Truncated)); +//assert_eq!(socket.recv_slice(&mut slice[..]), Err(RecvError::Truncated)); +//assert_eq!(socket.peek_slice(&mut slice[..]), Err(RecvError::Exhausted)); +//} + +//#[rstest] +//#[case::ip(Medium::Ip)] +//#[cfg(feature = "medium-ip")] +//#[case::ethernet(Medium::Ethernet)] +//#[cfg(feature = "medium-ethernet")] +//#[case::ieee802154(Medium::Ieee802154)] +//#[cfg(feature = "medium-ieee802154")] +//fn test_set_hop_limit(#[case] medium: Medium) { +//let (mut iface, _, _) = setup(medium); +//let cx = iface.context(); + +//let mut s = socket(buffer(0), buffer(1)); + +//assert_eq!(s.bind(LOCAL_END), Ok(())); + +//s.set_hop_limit(Some(0x2a)); +//assert_eq!(s.send_slice(b"abcdef", REMOTE_END), Ok(())); +//assert_eq!( +//s.dispatch(cx, |_, _, (ip_repr, _, _)| { +//assert_eq!( +//ip_repr, +//IpReprIpvX(IpvXRepr { +//src_addr: LOCAL_ADDR, +//dst_addr: REMOTE_ADDR, +//next_header: IpProtocol::Udp, +//payload_len: 8 + 6, +//hop_limit: 0x2a, +//}) +//); +//Ok::<_, ()>(()) +//}), +//Ok(()) +//); +//} + +//#[rstest] +//#[case::ip(Medium::Ip)] +//#[cfg(feature = "medium-ip")] +//#[case::ethernet(Medium::Ethernet)] +//#[cfg(feature = "medium-ethernet")] +//#[case::ieee802154(Medium::Ieee802154)] +//#[cfg(feature = "medium-ieee802154")] +//fn test_doesnt_accept_wrong_port(#[case] medium: Medium) { +//let (mut iface, _, _) = setup(medium); +//let cx = iface.context(); + +//let mut socket = socket(buffer(1), buffer(0)); + +//assert_eq!(socket.bind(LOCAL_PORT), Ok(())); + +//let mut udp_repr = REMOTE_UDP_REPR; +//assert!(socket.accepts(cx, &REMOTE_IP_REPR, &udp_repr)); +//udp_repr.dst_port += 1; +//assert!(!socket.accepts(cx, &REMOTE_IP_REPR, &udp_repr)); +//} + +//#[rstest] +//#[case::ip(Medium::Ip)] +//#[cfg(feature = "medium-ip")] +//#[case::ethernet(Medium::Ethernet)] +//#[cfg(feature = "medium-ethernet")] +//#[case::ieee802154(Medium::Ieee802154)] +//#[cfg(feature = "medium-ieee802154")] +//fn test_doesnt_accept_wrong_ip(#[case] medium: Medium) { +//let (mut iface, _, _) = setup(medium); +//let cx = iface.context(); + +//let mut port_bound_socket = socket(buffer(1), buffer(0)); +//assert_eq!(port_bound_socket.bind(LOCAL_PORT), Ok(())); +//assert!(port_bound_socket.accepts(cx, &BAD_IP_REPR, &REMOTE_UDP_REPR)); + +//let mut ip_bound_socket = socket(buffer(1), buffer(0)); +//assert_eq!(ip_bound_socket.bind(LOCAL_END), Ok(())); +//assert!(!ip_bound_socket.accepts(cx, &BAD_IP_REPR, &REMOTE_UDP_REPR)); +//} + +//#[test] +//fn test_send_large_packet() { +//// buffer(4) creates a payload buffer of size 16*4 +//let mut socket = socket(buffer(0), buffer(4)); +//assert_eq!(socket.bind(LOCAL_END), Ok(())); + +//let too_large = b"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefx"; +//assert_eq!( +//socket.send_slice(too_large, REMOTE_END), +//Err(SendError::BufferFull) +//); +//assert_eq!(socket.send_slice(&too_large[..16 * 4], REMOTE_END), Ok(())); +//} + +//#[rstest] +//#[case::ip(Medium::Ip)] +//#[cfg(feature = "medium-ip")] +//#[case::ethernet(Medium::Ethernet)] +//#[cfg(feature = "medium-ethernet")] +//#[case::ieee802154(Medium::Ieee802154)] +//#[cfg(feature = "medium-ieee802154")] +//fn test_process_empty_payload(#[case] medium: Medium) { +//let meta = Box::leak(Box::new([PacketMetadata::EMPTY])); +//let recv_buffer = PacketBuffer::new(&mut meta[..], vec![]); +//let mut socket = socket(recv_buffer, buffer(0)); + +//let (mut iface, _, _) = setup(medium); +//let cx = iface.context(); + +//assert_eq!(socket.bind(LOCAL_PORT), Ok(())); + +//let repr = UdpRepr { +//src_port: REMOTE_PORT, +//dst_port: LOCAL_PORT, +//}; +//socket.process(cx, PacketMeta::default(), &REMOTE_IP_REPR, &repr, &[]); +//assert_eq!(socket.recv(), Ok((&[][..], REMOTE_END.into()))); +//} + +//#[test] +//fn test_closing() { +//let meta = Box::leak(Box::new([PacketMetadata::EMPTY])); +//let recv_buffer = PacketBuffer::new(&mut meta[..], vec![]); +//let mut socket = socket(recv_buffer, buffer(0)); +//assert_eq!(socket.bind(LOCAL_PORT), Ok(())); + +//assert!(socket.is_open()); +//socket.close(); +//assert!(!socket.is_open()); +//} +//}