140 lines
3.2 KiB
Rust
140 lines
3.2 KiB
Rust
|
#![feature(map_try_insert)]
|
||
|
#![no_std]
|
||
|
|
||
|
extern crate alloc;
|
||
|
|
||
|
use core::{
|
||
|
fmt,
|
||
|
future::Future,
|
||
|
mem::size_of,
|
||
|
net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4},
|
||
|
pin::Pin,
|
||
|
str::FromStr,
|
||
|
sync::atomic::{AtomicU32, Ordering},
|
||
|
task::{Context, Poll},
|
||
|
};
|
||
|
|
||
|
use alloc::{collections::BTreeMap, format, string::String, vec::Vec};
|
||
|
use ethernet::{EtherType, EthernetFrame, L2Packet};
|
||
|
use interface::{NetworkDevice, NetworkInterface};
|
||
|
use kernel_fs::devfs;
|
||
|
use kernel_util::{
|
||
|
mem::PageBox,
|
||
|
runtime::{self, QueueWaker},
|
||
|
sync::{mutex::Mutex, spin_rwlock::IrqSafeRwLock, IrqSafeSpinlock},
|
||
|
util::ring::RingBuffer,
|
||
|
};
|
||
|
use l3::{ip::Protocol, L3Packet, Route};
|
||
|
use queue::Queue;
|
||
|
use socket::UdpSocket;
|
||
|
use types::{MacAddress, NetValue, SubnetAddress, Value};
|
||
|
use vfs::{impls::FnValueNode, PacketSocket};
|
||
|
use yggdrasil_abi::error::Error;
|
||
|
|
||
|
use crate::types::SubnetV4Address;
|
||
|
|
||
|
pub mod ethernet;
|
||
|
pub mod l3;
|
||
|
pub mod l4;
|
||
|
|
||
|
pub mod socket;
|
||
|
|
||
|
pub mod interface;
|
||
|
pub mod queue;
|
||
|
pub mod types;
|
||
|
|
||
|
pub use interface::register_interface;
|
||
|
|
||
|
pub struct Packet {
|
||
|
// TODO info about "received" interface
|
||
|
buffer: PageBox<[u8]>,
|
||
|
offset: usize,
|
||
|
iface: u32,
|
||
|
}
|
||
|
|
||
|
impl Packet {
|
||
|
#[inline]
|
||
|
pub fn new(buffer: PageBox<[u8]>, offset: usize, iface: u32) -> Self {
|
||
|
Self {
|
||
|
buffer,
|
||
|
offset,
|
||
|
iface,
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static PACKET_QUEUE: Queue<Packet> = Queue::new();
|
||
|
static ACCEPT_QUEUE: Queue<L3Packet> = Queue::new();
|
||
|
|
||
|
#[inline]
|
||
|
pub fn receive_packet(packet: Packet) -> Result<(), Error> {
|
||
|
PACKET_QUEUE.receive_packet(packet)
|
||
|
}
|
||
|
|
||
|
pub fn start_network_tasks() -> Result<(), Error> {
|
||
|
devfs::add_network_config(
|
||
|
"routes",
|
||
|
FnValueNode::new(
|
||
|
|| {
|
||
|
let mut output = String::new();
|
||
|
l3::list_routes(|route| {
|
||
|
output.push_str(&format!("{}\n", route));
|
||
|
});
|
||
|
|
||
|
Ok(output)
|
||
|
},
|
||
|
|_value| Err(Error::NotImplemented),
|
||
|
),
|
||
|
);
|
||
|
|
||
|
runtime::spawn(l2_packet_handler_worker())?;
|
||
|
for _ in 0..1 {
|
||
|
runtime::spawn(l3_accept_worker())?;
|
||
|
}
|
||
|
|
||
|
Ok(())
|
||
|
}
|
||
|
|
||
|
async fn l2_packet_handler_worker() {
|
||
|
loop {
|
||
|
let packet = PACKET_QUEUE.wait().await;
|
||
|
|
||
|
let eth_frame: &EthernetFrame = bytemuck::from_bytes(
|
||
|
&packet.buffer[packet.offset..packet.offset + size_of::<EthernetFrame>()],
|
||
|
);
|
||
|
|
||
|
let l2_packet = L2Packet {
|
||
|
interface_id: packet.iface,
|
||
|
|
||
|
source_address: eth_frame.source_mac,
|
||
|
destination_address: eth_frame.destination_mac,
|
||
|
|
||
|
l2_offset: packet.offset,
|
||
|
l3_offset: packet.offset + size_of::<EthernetFrame>(),
|
||
|
|
||
|
data: packet.buffer,
|
||
|
};
|
||
|
|
||
|
ethernet::handle(l2_packet);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async fn l3_accept_worker() {
|
||
|
loop {
|
||
|
let l3_packet = ACCEPT_QUEUE.wait().await;
|
||
|
|
||
|
log::debug!(
|
||
|
"INPUT {:?} {}:{:?} -> {}:{:?}: ACCEPT",
|
||
|
l3_packet.protocol,
|
||
|
l3_packet.source_address,
|
||
|
l3_packet.source_port,
|
||
|
l3_packet.destination_address,
|
||
|
l3_packet.destination_port
|
||
|
);
|
||
|
|
||
|
if let Err(error) = l3::handle_accepted(l3_packet) {
|
||
|
log::error!("L3 handle error: {:?}", error);
|
||
|
}
|
||
|
}
|
||
|
}
|