feat: scheduling, usermode, shell

This commit is contained in:
2026-02-17 19:17:01 +01:00
parent 20fa8a9be2
commit 605fbcbe42
46 changed files with 2622 additions and 98 deletions
+3 -1
View File
@@ -7,6 +7,7 @@
#include "Arp.hpp"
#include <Net/ByteOrder.hpp>
#include <Net/Ethernet.hpp>
#include <Net/Ipv4.hpp>
#include <Net/NetConfig.hpp>
#include <Drivers/Net/E1000.hpp>
#include <Libraries/Memory.hpp>
@@ -91,8 +92,9 @@ namespace Net::Arp {
uint32_t senderIp = pkt->SenderIp; // Already in network byte order in struct
uint32_t targetIp = pkt->TargetIp;
// Cache the sender's IP->MAC mapping
// Cache the sender's IP->MAC mapping, then flush any packets waiting on it
CacheInsert(senderIp, pkt->SenderMac);
Ipv4::FlushPending();
uint16_t op = Ntohs(pkt->Operation);
+34
View File
@@ -15,10 +15,40 @@ using namespace Kt;
namespace Net::Icmp {
// Reply tracking for outgoing pings
static volatile bool g_replyReceived = false;
static volatile uint16_t g_replyId = 0;
static volatile uint16_t g_replySeq = 0;
void Initialize() {
KernelLogStream(OK, "Net") << "ICMP initialized";
}
void ResetReply() {
g_replyReceived = false;
}
bool HasReply(uint16_t identifier, uint16_t sequence) {
return g_replyReceived
&& g_replyId == identifier
&& g_replySeq == sequence;
}
void SendEchoRequest(uint32_t destIp, uint16_t identifier, uint16_t sequence) {
uint8_t packet[sizeof(Header)];
Header* hdr = (Header*)packet;
hdr->Type = TYPE_ECHO_REQUEST;
hdr->Code = 0;
hdr->Checksum = 0;
hdr->Identifier = Htons(identifier);
hdr->Sequence = Htons(sequence);
hdr->Checksum = Ipv4::Checksum(packet, sizeof(Header));
Ipv4::Send(destIp, Ipv4::PROTO_ICMP, packet, sizeof(Header));
}
void OnPacketReceived(uint32_t srcIp, const uint8_t* data, uint16_t length) {
if (length < sizeof(Header)) {
return;
@@ -54,6 +84,10 @@ namespace Net::Icmp {
replyHdr->Checksum = Ipv4::Checksum(reply, length);
Ipv4::Send(srcIp, Ipv4::PROTO_ICMP, reply, length);
} else if (hdr->Type == TYPE_ECHO_REPLY && hdr->Code == 0) {
g_replyId = Ntohs(hdr->Identifier);
g_replySeq = Ntohs(hdr->Sequence);
g_replyReceived = true;
}
}
+9
View File
@@ -26,4 +26,13 @@ namespace Net::Icmp {
// Handle an incoming ICMP packet (called by IPv4 layer)
void OnPacketReceived(uint32_t srcIp, const uint8_t* data, uint16_t length);
// Send an ICMP echo request to the given IP address
void SendEchoRequest(uint32_t destIp, uint16_t identifier, uint16_t sequence);
// Check if a reply was received for the given identifier/sequence
bool HasReply(uint16_t identifier, uint16_t sequence);
// Reset the reply tracker (call before sending a new ping)
void ResetReply();
}
+61 -27
View File
@@ -15,7 +15,6 @@
#include <Libraries/Memory.hpp>
#include <Terminal/Terminal.hpp>
#include <CppLib/Stream.hpp>
#include <Timekeeping/ApicTimer.hpp>
using namespace Kt;
@@ -23,6 +22,18 @@ namespace Net::Ipv4 {
static uint16_t g_identification = 0;
// Deferred packet queue for packets awaiting ARP resolution
struct PendingPacket {
uint32_t DestIp;
uint8_t Protocol;
uint8_t Data[Ethernet::MAX_PAYLOAD_SIZE - HEADER_SIZE];
uint16_t Length;
bool Active;
};
static constexpr uint32_t PENDING_QUEUE_SIZE = 8;
static PendingPacket g_pendingQueue[PENDING_QUEUE_SIZE] = {};
void Initialize() {
g_identification = 0;
KernelLogStream(OK, "Net") << "IPv4 initialized, IP: "
@@ -138,30 +149,9 @@ namespace Net::Ipv4 {
}
}
bool Send(uint32_t destIp, uint8_t protocol, const uint8_t* payload, uint16_t payloadLen) {
if (payloadLen > (Ethernet::MAX_PAYLOAD_SIZE - HEADER_SIZE)) {
return false;
}
// Determine next-hop IP and resolve MAC
uint32_t nextHop = GetNextHop(destIp);
uint8_t destMac[6];
if (!Arp::Resolve(nextHop, destMac)) {
// ARP request sent, wait briefly and retry
for (int attempt = 0; attempt < 3; attempt++) {
Timekeeping::Sleep(50);
if (Arp::Resolve(nextHop, destMac)) {
break;
}
}
// Final check
if (!Arp::Resolve(nextHop, destMac)) {
return false;
}
}
// Build IP packet
// Build and send an IP packet over Ethernet (MAC already resolved)
static bool SendDirect(uint32_t destIp, uint8_t protocol, const uint8_t* destMac,
const uint8_t* payload, uint16_t payloadLen) {
uint8_t packet[Ethernet::MAX_PAYLOAD_SIZE];
Header* hdr = (Header*)packet;
@@ -176,13 +166,57 @@ namespace Net::Ipv4 {
hdr->SrcIp = GetIpAddress();
hdr->DstIp = destIp;
// Calculate header checksum
hdr->Checksum = Checksum(hdr, HEADER_SIZE);
// Copy payload
memcpy(packet + HEADER_SIZE, payload, payloadLen);
return Ethernet::Send(destMac, Ethernet::ETHERTYPE_IPV4, packet, HEADER_SIZE + payloadLen);
}
bool Send(uint32_t destIp, uint8_t protocol, const uint8_t* payload, uint16_t payloadLen) {
if (payloadLen > (Ethernet::MAX_PAYLOAD_SIZE - HEADER_SIZE)) {
return false;
}
// Determine next-hop IP and resolve MAC
uint32_t nextHop = GetNextHop(destIp);
uint8_t destMac[6];
if (Arp::Resolve(nextHop, destMac)) {
return SendDirect(destIp, protocol, destMac, payload, payloadLen);
}
// ARP request already sent by Resolve(), queue the packet for later
for (uint32_t i = 0; i < PENDING_QUEUE_SIZE; i++) {
if (!g_pendingQueue[i].Active) {
g_pendingQueue[i].DestIp = destIp;
g_pendingQueue[i].Protocol = protocol;
g_pendingQueue[i].Length = payloadLen;
memcpy(g_pendingQueue[i].Data, payload, payloadLen);
g_pendingQueue[i].Active = true;
return true;
}
}
// Queue full, drop the packet
return false;
}
void FlushPending() {
for (uint32_t i = 0; i < PENDING_QUEUE_SIZE; i++) {
if (!g_pendingQueue[i].Active) {
continue;
}
uint32_t nextHop = GetNextHop(g_pendingQueue[i].DestIp);
uint8_t destMac[6];
if (Arp::Resolve(nextHop, destMac)) {
SendDirect(g_pendingQueue[i].DestIp, g_pendingQueue[i].Protocol,
destMac, g_pendingQueue[i].Data, g_pendingQueue[i].Length);
g_pendingQueue[i].Active = false;
}
}
}
}
+6 -1
View File
@@ -36,9 +36,14 @@ namespace Net::Ipv4 {
// Handle an incoming IP packet (called by Ethernet layer)
void OnPacketReceived(const uint8_t* data, uint16_t length);
// Send an IP packet with the given protocol and payload
// Send an IP packet with the given protocol and payload.
// If ARP resolution is pending, the packet is queued and sent when the reply arrives.
bool Send(uint32_t destIp, uint8_t protocol, const uint8_t* payload, uint16_t payloadLen);
// Flush any packets that were waiting for ARP resolution.
// Called by the ARP layer when a new cache entry is inserted.
void FlushPending();
// Compute the Internet checksum over a buffer
uint16_t Checksum(const void* data, uint16_t length);