Support for loopback interface.
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
use smoltcp::iface::{ArpCache, SliceArpCache};
|
||||
use smoltcp::wire::{EthernetAddress, IpAddress};
|
||||
use std::collections::BTreeSet;
|
||||
use std::iter::FromIterator;
|
||||
|
||||
//TODO: move to EthernetAddress::LOCAL (?)
|
||||
pub const LOOPBACK_HWADDR: EthernetAddress = EthernetAddress([0; 6]);
|
||||
|
||||
pub struct LoArpCache {
|
||||
arp_cache: SliceArpCache<'static>,
|
||||
local_ips: BTreeSet<IpAddress>,
|
||||
}
|
||||
|
||||
impl LoArpCache {
|
||||
pub fn new<I>(local_ips: I) -> LoArpCache
|
||||
where
|
||||
I: IntoIterator<Item = IpAddress>,
|
||||
{
|
||||
LoArpCache {
|
||||
arp_cache: SliceArpCache::new(vec![Default::default(); 16]),
|
||||
local_ips: BTreeSet::from_iter(local_ips),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ArpCache for LoArpCache {
|
||||
fn fill(&mut self, protocol_addr: &IpAddress, hardware_addr: &EthernetAddress) {
|
||||
self.arp_cache.fill(protocol_addr, hardware_addr)
|
||||
}
|
||||
|
||||
fn lookup(&mut self, protocol_addr: &IpAddress) -> Option<EthernetAddress> {
|
||||
//TODO: use IpAddress::is_loopback
|
||||
if let &IpAddress::Ipv4(ipv4_addr) = protocol_addr {
|
||||
if ipv4_addr.is_loopback() {
|
||||
return Some(LOOPBACK_HWADDR);
|
||||
}
|
||||
}
|
||||
|
||||
if self.local_ips.contains(protocol_addr) {
|
||||
return Some(LOOPBACK_HWADDR);
|
||||
}
|
||||
|
||||
self.arp_cache.lookup(protocol_addr)
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::ops::{Deref, DerefMut, Drop};
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use std::mem::swap;
|
||||
use std::mem::{replace, swap};
|
||||
|
||||
type BufferStack = Rc<RefCell<Vec<Vec<u8>>>>;
|
||||
|
||||
@@ -14,6 +14,13 @@ impl Buffer {
|
||||
pub fn resize(&mut self, new_len: usize) {
|
||||
self.buffer.resize(new_len, 0u8);
|
||||
}
|
||||
|
||||
pub fn move_out(&mut self) -> Buffer {
|
||||
Buffer {
|
||||
buffer: replace(&mut self.buffer, vec![]),
|
||||
stack: self.stack.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for Buffer {
|
||||
@@ -44,11 +51,13 @@ impl DerefMut for Buffer {
|
||||
|
||||
impl Drop for Buffer {
|
||||
fn drop(&mut self) {
|
||||
let mut tmp = vec![];
|
||||
swap(&mut tmp, &mut self.buffer);
|
||||
{
|
||||
let mut stack = self.stack.borrow_mut();
|
||||
stack.push(tmp);
|
||||
if self.buffer.capacity() > 0 {
|
||||
let mut tmp = vec![];
|
||||
swap(&mut tmp, &mut self.buffer);
|
||||
{
|
||||
let mut stack = self.stack.borrow_mut();
|
||||
stack.push(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+32
-4
@@ -5,11 +5,14 @@ use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::rc::Rc;
|
||||
|
||||
use buffer_pool::Buffer;
|
||||
use buffer_pool::{Buffer, BufferPool};
|
||||
use arp_cache::LOOPBACK_HWADDR;
|
||||
|
||||
pub struct NetworkDevice {
|
||||
network_file: Rc<RefCell<File>>,
|
||||
input_queue: Rc<RefCell<VecDeque<Buffer>>>,
|
||||
local_hwaddr: smoltcp::wire::EthernetAddress,
|
||||
buffer_pool: Rc<RefCell<BufferPool>>,
|
||||
}
|
||||
|
||||
impl NetworkDevice {
|
||||
@@ -18,17 +21,23 @@ impl NetworkDevice {
|
||||
pub fn new(
|
||||
network_file: Rc<RefCell<File>>,
|
||||
input_queue: Rc<RefCell<VecDeque<Buffer>>>,
|
||||
local_hwaddr: smoltcp::wire::EthernetAddress,
|
||||
buffer_pool: Rc<RefCell<BufferPool>>,
|
||||
) -> NetworkDevice {
|
||||
NetworkDevice {
|
||||
network_file,
|
||||
input_queue,
|
||||
local_hwaddr,
|
||||
buffer_pool,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TxBuffer {
|
||||
buffer: Vec<u8>,
|
||||
buffer: Buffer,
|
||||
network_file: Rc<RefCell<File>>,
|
||||
input_queue: Rc<RefCell<VecDeque<Buffer>>>,
|
||||
local_hwaddr: smoltcp::wire::EthernetAddress,
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for TxBuffer {
|
||||
@@ -45,7 +54,22 @@ impl AsMut<[u8]> for TxBuffer {
|
||||
|
||||
impl Drop for TxBuffer {
|
||||
fn drop(&mut self) {
|
||||
let _ = self.network_file.borrow_mut().write(&self.buffer);
|
||||
let mut loopback = false;
|
||||
|
||||
if let Ok(mut frame) = smoltcp::wire::EthernetFrame::new_checked(&mut self.buffer) {
|
||||
if frame.dst_addr() == LOOPBACK_HWADDR {
|
||||
frame.set_dst_addr(self.local_hwaddr);
|
||||
loopback = true;
|
||||
}
|
||||
}
|
||||
|
||||
if loopback {
|
||||
self.input_queue
|
||||
.borrow_mut()
|
||||
.push_back(self.buffer.move_out());
|
||||
} else {
|
||||
let _ = self.network_file.borrow_mut().write(&self.buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,9 +92,13 @@ impl smoltcp::phy::Device for NetworkDevice {
|
||||
}
|
||||
|
||||
fn transmit(&mut self, _timestamp: u64, length: usize) -> smoltcp::Result<Self::TxBuffer> {
|
||||
let mut buffer = self.buffer_pool.borrow_mut().get_buffer();
|
||||
buffer.resize(length);
|
||||
Ok(TxBuffer {
|
||||
network_file: Rc::clone(&self.network_file),
|
||||
buffer: vec![0; length],
|
||||
buffer,
|
||||
input_queue: Rc::clone(&self.input_queue),
|
||||
local_hwaddr: self.local_hwaddr,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ mod error;
|
||||
mod logger;
|
||||
mod port_set;
|
||||
mod scheme;
|
||||
mod arp_cache;
|
||||
|
||||
fn run() -> Result<()> {
|
||||
use syscall::flag::*;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use netutils::getcfg;
|
||||
use smoltcp::iface::{ArpCache, EthernetInterface, SliceArpCache};
|
||||
use smoltcp::iface::{ArpCache, EthernetInterface};
|
||||
use smoltcp::socket::SocketSet as SmoltcpSocketSet;
|
||||
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, IpEndpoint, Ipv4Address};
|
||||
use std::cell::RefCell;
|
||||
@@ -16,6 +16,7 @@ use syscall;
|
||||
use buffer_pool::{Buffer, BufferPool};
|
||||
use device::NetworkDevice;
|
||||
use error::{Error, Result};
|
||||
use arp_cache::LoArpCache;
|
||||
use self::ip::IpScheme;
|
||||
use self::tcp::TcpScheme;
|
||||
use self::udp::UdpScheme;
|
||||
@@ -41,11 +42,11 @@ pub struct Smolnetd {
|
||||
tcp_scheme: TcpScheme,
|
||||
|
||||
input_queue: Rc<RefCell<VecDeque<Buffer>>>,
|
||||
input_buffer_pool: BufferPool,
|
||||
buffer_pool: Rc<RefCell<BufferPool>>,
|
||||
}
|
||||
|
||||
impl Smolnetd {
|
||||
const INGRESS_PACKET_SIZE: usize = 2048;
|
||||
const MAX_PACKET_SIZE: usize = 2048;
|
||||
const SOCKET_BUFFER_SIZE: usize = 128; //packets
|
||||
const MIN_CHECK_TIMEOUT_MS: i64 = 10;
|
||||
const MAX_CHECK_TIMEOUT_MS: i64 = 500;
|
||||
@@ -57,17 +58,28 @@ impl Smolnetd {
|
||||
tcp_file: File,
|
||||
time_file: File,
|
||||
) -> Smolnetd {
|
||||
let arp_cache = SliceArpCache::new(vec![Default::default(); 8]);
|
||||
let hardware_addr = EthernetAddress::from_str(getcfg("mac").unwrap().trim())
|
||||
.expect("Can't parse the 'mac' cfg");
|
||||
let local_ip =
|
||||
IpAddress::from_str(getcfg("ip").unwrap().trim()).expect("Can't parse the 'ip' cfg.");
|
||||
let protocol_addrs = [IpCidr::new(local_ip, 24)];
|
||||
let protocol_addrs = [
|
||||
IpCidr::new(local_ip, 24),
|
||||
IpCidr::new(IpAddress::v4(127, 0, 0, 1), 8),
|
||||
];
|
||||
let default_gw = Ipv4Address::from_str(getcfg("ip_router").unwrap().trim())
|
||||
.expect("Can't parse the 'ip_router' cfg.");
|
||||
|
||||
|
||||
let buffer_pool = Rc::new(RefCell::new(BufferPool::new(Self::MAX_PACKET_SIZE)));
|
||||
let input_queue = Rc::new(RefCell::new(VecDeque::new()));
|
||||
let network_file = Rc::new(RefCell::new(network_file));
|
||||
let network_device = NetworkDevice::new(Rc::clone(&network_file), Rc::clone(&input_queue));
|
||||
let network_device = NetworkDevice::new(
|
||||
Rc::clone(&network_file),
|
||||
Rc::clone(&input_queue),
|
||||
hardware_addr,
|
||||
buffer_pool.clone(),
|
||||
);
|
||||
let arp_cache = LoArpCache::new(protocol_addrs.iter().map(IpCidr::address));
|
||||
let iface = EthernetInterface::new(
|
||||
Box::new(network_device),
|
||||
Box::new(arp_cache) as Box<ArpCache>,
|
||||
@@ -86,7 +98,7 @@ impl Smolnetd {
|
||||
tcp_scheme: TcpScheme::new(Rc::clone(&socket_set), tcp_file),
|
||||
input_queue,
|
||||
network_file,
|
||||
input_buffer_pool: BufferPool::new(Self::INGRESS_PACKET_SIZE),
|
||||
buffer_pool,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,7 +185,7 @@ impl Smolnetd {
|
||||
fn read_frames(&mut self) -> Result<usize> {
|
||||
let mut total_frames = 0;
|
||||
loop {
|
||||
let mut buffer = self.input_buffer_pool.get_buffer();
|
||||
let mut buffer = self.buffer_pool.borrow_mut().get_buffer();
|
||||
let count = self.network_file
|
||||
.borrow_mut()
|
||||
.read(&mut buffer)
|
||||
|
||||
Reference in New Issue
Block a user