use alloc::{string::String, vec::Vec};
use smoltcp::{
storage::PacketBuffer,
time::Instant,
wire::{IpAddress, Ipv4Cidr},
};
use crate::config::InterfaceId;
mod driver;
mod ethernet;
mod loopback;
#[cfg(feature = "vsock")]
mod vsock;
pub use driver::*;
pub use ethernet::*;
pub use loopback::*;
#[cfg(feature = "vsock")]
pub use vsock::*;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ArpEntry {
pub ip_addr: [u8; 4],
pub hw_type: u16,
pub flags: u16,
pub hw_addr: [u8; 6],
pub device: String,
}
pub trait Device: Send {
fn name(&self) -> &str;
fn recv(
&mut self,
interface_id: InterfaceId,
buffer: &mut PacketBuffer<InterfaceId>,
timestamp: Instant,
snoop: &mut dyn FnMut(&[u8]),
) -> usize;
fn send(&mut self, next_hop: IpAddress, packet: &[u8], timestamp: Instant) -> usize;
fn drain_deferred_tx(&mut self) -> Vec<usize> {
Vec::new()
}
fn drain_deferred_rx(&mut self) -> Vec<usize> {
Vec::new()
}
fn drain_deferred_tx_errors(&mut self) -> u64 {
0
}
fn drain_deferred_tx_drops(&mut self) -> u64 {
0
}
fn drain_deferred_rx_errors(&mut self) -> u64 {
0
}
fn drain_deferred_rx_drops(&mut self) -> u64 {
0
}
fn set_ipv4_addr(&mut self, _addr: Option<Ipv4Cidr>) {}
fn arp_entries(&self, _timestamp: Instant) -> Vec<ArpEntry> {
Vec::new()
}
}
#[cfg(test)]
mod tests {
use smoltcp::wire::Ipv4Address;
use super::*;
struct DefaultDevice;
impl Device for DefaultDevice {
fn name(&self) -> &str {
"default-device"
}
fn recv(
&mut self,
_interface_id: InterfaceId,
_buffer: &mut PacketBuffer<InterfaceId>,
_timestamp: Instant,
_snoop: &mut dyn FnMut(&[u8]),
) -> usize {
0
}
fn send(&mut self, _next_hop: IpAddress, _packet: &[u8], _timestamp: Instant) -> usize {
0
}
}
#[test]
fn device_defaults_report_no_deferred_work_or_readiness() {
let mut device = DefaultDevice;
assert_eq!(device.name(), "default-device");
assert!(device.drain_deferred_tx().is_empty());
assert!(device.drain_deferred_rx().is_empty());
assert_eq!(device.drain_deferred_tx_errors(), 0);
assert_eq!(device.drain_deferred_tx_drops(), 0);
assert_eq!(device.drain_deferred_rx_errors(), 0);
assert_eq!(device.drain_deferred_rx_drops(), 0);
assert!(device.arp_entries(Instant::from_millis(1)).is_empty());
device.set_ipv4_addr(Some(Ipv4Cidr::new(Ipv4Address::LOCALHOST, 8)));
}
#[test]
fn arp_entry_keeps_neighbor_metadata() {
let entry = ArpEntry {
ip_addr: [192, 168, 1, 1],
hw_type: 1,
flags: 2,
hw_addr: [1, 2, 3, 4, 5, 6],
device: String::from("eth0"),
};
assert_eq!(entry.ip_addr, [192, 168, 1, 1]);
assert_eq!(entry.device, "eth0");
}
}