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