108 lines
2.3 KiB
Rust
Raw Normal View History

#![feature(map_try_insert)]
#![allow(clippy::type_complexity)]
#![no_std]
extern crate alloc;
use core::mem::size_of;
use alloc::sync::Arc;
use ethernet::L2Packet;
use kernel_util::{mem::PageBox, runtime};
use l3::L3Packet;
use queue::Queue;
use yggdrasil_abi::{error::Error, net::protocols::EthernetFrame};
pub mod ethernet;
pub mod l3;
pub mod l4;
pub mod socket;
pub mod config;
pub mod interface;
pub mod queue;
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> {
runtime::spawn(l2_packet_handler_worker())?;
for _ in 0..4 {
runtime::spawn(l3_accept_worker())?;
}
runtime::spawn(config::network_config_service())?;
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: Arc::new(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);
}
}
}