2024-01-20 19:40:27 +02:00
|
|
|
#![feature(map_try_insert)]
|
2024-01-22 14:39:06 +02:00
|
|
|
#![allow(clippy::type_complexity)]
|
2024-01-20 19:40:27 +02:00
|
|
|
#![no_std]
|
|
|
|
|
|
|
|
extern crate alloc;
|
|
|
|
|
2024-01-22 14:39:06 +02:00
|
|
|
use core::mem::size_of;
|
2024-01-20 19:40:27 +02:00
|
|
|
|
2024-01-22 14:39:06 +02:00
|
|
|
use alloc::sync::Arc;
|
2024-01-22 23:59:42 +02:00
|
|
|
use bytemuck::Pod;
|
2024-01-22 14:39:06 +02:00
|
|
|
use ethernet::L2Packet;
|
2024-02-04 21:13:40 +02:00
|
|
|
use libk::{mem::PageBox, runtime, util::queue::UnboundedMpmcQueue};
|
2024-01-22 14:39:06 +02:00
|
|
|
use l3::L3Packet;
|
|
|
|
use yggdrasil_abi::{error::Error, net::protocols::EthernetFrame};
|
2024-01-20 19:40:27 +02:00
|
|
|
|
|
|
|
pub mod ethernet;
|
|
|
|
pub mod l3;
|
|
|
|
pub mod l4;
|
|
|
|
|
|
|
|
pub mod socket;
|
|
|
|
|
2024-01-22 14:39:06 +02:00
|
|
|
pub mod config;
|
2024-01-20 19:40:27 +02:00
|
|
|
pub mod interface;
|
2024-01-26 16:31:56 +02:00
|
|
|
pub mod util;
|
2024-01-20 19:40:27 +02:00
|
|
|
|
|
|
|
pub use interface::register_interface;
|
|
|
|
|
|
|
|
pub struct Packet {
|
|
|
|
// TODO info about "received" interface
|
|
|
|
buffer: PageBox<[u8]>,
|
|
|
|
offset: usize,
|
|
|
|
iface: u32,
|
|
|
|
}
|
|
|
|
|
2024-01-22 23:59:42 +02:00
|
|
|
pub struct PacketBuilder {
|
|
|
|
data: PageBox<[u8]>,
|
|
|
|
pos: usize,
|
|
|
|
len: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PacketBuilder {
|
2024-01-26 16:31:56 +02:00
|
|
|
pub fn new(l2_offset: usize, l2_size: usize) -> Result<Self, Error> {
|
|
|
|
let data = PageBox::new_slice(0, l2_offset + l2_size)?;
|
2024-01-22 23:59:42 +02:00
|
|
|
Ok(Self {
|
|
|
|
data,
|
|
|
|
pos: l2_offset,
|
|
|
|
len: l2_offset,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn push<T: Pod>(&mut self, value: &T) -> Result<(), Error> {
|
|
|
|
self.push_bytes(bytemuck::bytes_of(value))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn push_bytes(&mut self, bytes: &[u8]) -> Result<(), Error> {
|
|
|
|
if self.pos + bytes.len() > self.data.len() {
|
|
|
|
return Err(Error::OutOfMemory);
|
|
|
|
}
|
|
|
|
self.data[self.pos..self.pos + bytes.len()].copy_from_slice(bytes);
|
|
|
|
self.pos += bytes.len();
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn finish(self) -> (PageBox<[u8]>, usize) {
|
|
|
|
(self.data, self.len)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-20 19:40:27 +02:00
|
|
|
impl Packet {
|
|
|
|
#[inline]
|
|
|
|
pub fn new(buffer: PageBox<[u8]>, offset: usize, iface: u32) -> Self {
|
|
|
|
Self {
|
|
|
|
buffer,
|
|
|
|
offset,
|
|
|
|
iface,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-30 01:32:44 +02:00
|
|
|
static PACKET_QUEUE: UnboundedMpmcQueue<Packet> = UnboundedMpmcQueue::new();
|
|
|
|
static ACCEPT_QUEUE: UnboundedMpmcQueue<L3Packet> = UnboundedMpmcQueue::new();
|
2024-01-20 19:40:27 +02:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn receive_packet(packet: Packet) -> Result<(), Error> {
|
2024-01-30 01:32:44 +02:00
|
|
|
PACKET_QUEUE.push_back(packet);
|
|
|
|
Ok(())
|
2024-01-20 19:40:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn start_network_tasks() -> Result<(), Error> {
|
|
|
|
runtime::spawn(l2_packet_handler_worker())?;
|
2024-01-22 14:39:06 +02:00
|
|
|
for _ in 0..4 {
|
2024-01-20 19:40:27 +02:00
|
|
|
runtime::spawn(l3_accept_worker())?;
|
|
|
|
}
|
2024-01-22 14:39:06 +02:00
|
|
|
runtime::spawn(config::network_config_service())?;
|
|
|
|
|
2024-01-20 19:40:27 +02:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn l2_packet_handler_worker() {
|
|
|
|
loop {
|
2024-01-30 01:32:44 +02:00
|
|
|
let packet = PACKET_QUEUE.pop_front().await;
|
2024-01-20 19:40:27 +02:00
|
|
|
|
|
|
|
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>(),
|
|
|
|
|
2024-01-22 14:39:06 +02:00
|
|
|
data: Arc::new(packet.buffer),
|
2024-01-20 19:40:27 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
ethernet::handle(l2_packet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn l3_accept_worker() {
|
|
|
|
loop {
|
2024-01-30 01:32:44 +02:00
|
|
|
let l3_packet = ACCEPT_QUEUE.pop_front().await;
|
2024-01-20 19:40:27 +02:00
|
|
|
|
2024-01-22 23:59:42 +02:00
|
|
|
// log::debug!(
|
|
|
|
// "INPUT {} {}:{:?} -> {}:{:?}: ACCEPT",
|
|
|
|
// l3_packet.protocol,
|
|
|
|
// l3_packet.source_address,
|
|
|
|
// l3_packet.source_port,
|
|
|
|
// l3_packet.destination_address,
|
|
|
|
// l3_packet.destination_port
|
|
|
|
// );
|
2024-01-20 19:40:27 +02:00
|
|
|
|
2024-01-22 23:59:42 +02:00
|
|
|
if let Err(error) = l3::handle_accepted(l3_packet).await {
|
2024-01-20 19:40:27 +02:00
|
|
|
log::error!("L3 handle error: {:?}", error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|