feat: scheduling, usermode, shell
This commit is contained in:
+61
-27
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user