Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
43da2bb
remove l2l3ep, removed l3 in dispatcher
CodeAnarchist Aug 13, 2025
b42433f
Merge remote-tracking branch 'upstream/main' into net_l3if_refactor
CodeAnarchist Sep 3, 2025
50f41d0
merge
CodeAnarchist Sep 3, 2025
61a0071
net: fix/opt driver and add L2/L3 interfaces header
CodeAnarchist Sep 5, 2025
8851bc5
Merge remote-tracking branch 'upstream/main' into net_l3if_refactor
CodeAnarchist Sep 5, 2025
52cac45
palloc on virtio net driver
CodeAnarchist Sep 5, 2025
2ce7be0
removed unnecessary declaration
CodeAnarchist Sep 5, 2025
a99552e
net: add multi-nic support, dynamic init, virtio updates and minor fixes
CodeAnarchist Sep 6, 2025
196d47a
net: improve l2/l3 separation, eth handles frames and minor fixes
CodeAnarchist Sep 8, 2025
7bf0862
net: add O1 ifindex--nic_id map, keep nic_id kernel-internal
CodeAnarchist Sep 8, 2025
4bc877c
net: added logical interface init
CodeAnarchist Sep 10, 2025
33b7042
net: minor fixes and warning cleanup
CodeAnarchist Sep 11, 2025
c4f6ce0
net: fixed crash caused by network, minor bug fixes
CodeAnarchist Sep 11, 2025
570ac50
net: dhcp interface management
CodeAnarchist Sep 11, 2025
333b049
net: refactor link-layer and internet-layer
CodeAnarchist Sep 16, 2025
1ef8e68
net: update l4 and upper layers for multi-int support
CodeAnarchist Sep 27, 2025
c34d6c8
[PR] minor PR fixes
Sep 28, 2025
22c9052
Merge remote-tracking branch 'upstream/main' into net_l3if_refactor
CodeAnarchist Sep 28, 2025
c0cbbef
merge
CodeAnarchist Sep 28, 2025
3e2e1d5
net: fix dns bug
CodeAnarchist Sep 28, 2025
cad4da2
Merge remote-tracking branch 'upstream/main' into net_l3if_refactor
CodeAnarchist Sep 28, 2025
1419c4b
unused method no error
CodeAnarchist Sep 28, 2025
b30e123
-Wno-unused-function
CodeAnarchist Sep 28, 2025
0bcf024
[MEMORY] memset32
Sep 28, 2025
2527ab1
net: removed legacy methods
CodeAnarchist Sep 28, 2025
9e9646c
Update README.md
CodeAnarchist Sep 29, 2025
fa28670
Update README.md
CodeAnarchist Sep 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ The Raspberry Pi emulation has the following limitations:

## Networking

The system has basic networking support. Currently, it performs DHCP discovery and request to receive an IP address on the local network, is capable of responding to Ping and ARP, and can connect to a server running on ports 8080 and 80, though it currently does nothing noteworthy.
The system provides medium level networking support. At startup, it scans for available network cards, loads the matching driver if present and creates a logical L2 interface for each device; a loopback interface is also added for both IPv4 and IPv6, though the current loopback implementation is partial and rejects all localhost packets. IPv4 networking is fully implemented, while IPv6 support is limited to interface structures and it cannot perform real communication.
Once interfaces and dispatcher are initialized, the system starts ARP, DHCP, DNS and SNTP processes. At the moment, SNTP sets the unix time and the time zone is configured manually since DHCP options 100 and 101 are not always included.
The stack supports UDP and TCP sockets, and an HTTP socket is implemented on top of TCP. ICMP is also supported with the system able to respond to ping requests. DNS resolution can be called directly by applications and is also used by sockets.
An embedded HTTP server is included and listens on port 80, serving a minimal page. Also discovery mechanism is available: the system probes the local network via UDP broadcast on port 8080, and when a responder replies it connects via HTTP on port 80, though it currently does nothing noteworthy.
An implementation of the server can be found at the [RedactedOS Firmware Server Repository](https://github.com/differrari/RedactedOS_firmware_server/tree/main)

3 changes: 2 additions & 1 deletion common.mk
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ BUILD_DIR := ./build
COMMON_FLAGS ?= -ffreestanding -nostdlib -fno-exceptions -fno-unwind-tables \
-fno-asynchronous-unwind-tables -g -O0 -Wall -Wextra \
-Wno-unused-parameter -Wno-address-of-packed-member \
-mcpu=cortex-a72 -Werror -Wno-error=sized-deallocation
-mcpu=cortex-a72 -Werror -Wno-error=sized-deallocation \
-Wno-unused-function

CFLAGS_BASE ?= $(COMMON_FLAGS) -std=c99
CXXFLAGS_BASE ?= $(COMMON_FLAGS) -fno-rtti
Expand Down
20 changes: 12 additions & 8 deletions kernel/exceptions/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "networking/network.h"
#include "hw/hw.h"
#include "audio/audio.h"
#include "networking/interface_manager.h"
#include "process/syscall.h"

#define IRQ_TIMER 30
Expand Down Expand Up @@ -46,8 +47,11 @@ void irq_init() {

gic_enable_irq(IRQ_TIMER, 0x80, 0);
gic_enable_irq(MSI_OFFSET + INPUT_IRQ, 0x80, 0);
gic_enable_irq(MSI_OFFSET + NET_IRQ, 0x80, 0);
gic_enable_irq(MSI_OFFSET + NET_IRQ + 1, 0x80, 0);

for (uint32_t i = 0; i < (uint32_t)MAX_L2_INTERFACES; ++i) {
gic_enable_irq(MSI_OFFSET + NET_IRQ_BASE + (2*i), 0x80, 0);
gic_enable_irq(MSI_OFFSET + NET_IRQ_BASE + (2*i+1), 0x80, 0);
}
gic_enable_irq(SLEEP_TIMER, 0x80, 0);

if (RPI_BOARD != 3){
Expand Down Expand Up @@ -92,12 +96,12 @@ void irq_el1_handler() {
wake_processes();
if (RPI_BOARD != 3) write32(GICC_BASE + 0x10, irq);
process_restore();
} else if (irq == MSI_OFFSET + NET_IRQ){
network_handle_download_interrupt();
if (RPI_BOARD != 3) write32(GICC_BASE + 0x10, irq);
process_restore();
} else if (irq == MSI_OFFSET + NET_IRQ + 1){
network_handle_upload_interrupt();
} else if (irq >= MSI_OFFSET + NET_IRQ_BASE && irq < MSI_OFFSET + NET_IRQ_BASE + (2*MAX_L2_INTERFACES)){
uint32_t rel = irq - (MSI_OFFSET + NET_IRQ_BASE);
uint16_t nic_id = (uint16_t)(rel >> 1);
uint8_t is_rx = (rel & 1) == 0;
if (is_rx) network_handle_download_interrupt_nic(nic_id);
else network_handle_upload_interrupt_nic(nic_id);
if (RPI_BOARD != 3) write32(GICC_BASE + 0x10, irq);
process_restore();
} else {
Expand Down
5 changes: 2 additions & 3 deletions kernel/kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,10 @@ void kernel_main() {

bool input_available = load_module(&input_module);
bool network_available = false;

if (BOARD_TYPE == 1){
//TODO: disabling networking until it is refactored to prevent memory issues
network_available = false;// load_module(&net_module);
network_available = load_module(&net_module);

load_module(&audio_module);

init_audio_mixer();
Expand Down
219 changes: 219 additions & 0 deletions kernel/networking/drivers/net_bus.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
#include "net_bus.hpp"
#include "net_driver.hpp"
#include "virtio_net_pci/virtio_net_pci.hpp"
#include "pci.h"
#include "std/std.h"
#include "console/kio.h"
#include "types.h"
#include "networking/interface_manager.h"
#include "networking/network.h"

#define kprintfv(fmt, ...) ({ if (verbose){ kprintf(fmt, ##__VA_ARGS__); } })

typedef struct {
NetDriver* drv;
char ifname[16];
char hw_ifname[32];
uint8_t mac[6];
uint16_t mtu;
uint16_t header_size;
uint8_t kind;
uint32_t speed_mbps;
uint8_t duplex;
} net_nic_desc_t;

static net_nic_desc_t g_nics[MAX_L2_INTERFACES];
static size_t g_count = 0;
static int g_eth_next = 0;
static int g_wif_next = 0;
static int g_net_next = 0;
static bool g_lo_added = false;
static bool verbose = true;

static void memzero(void* p, size_t n){
memset(p,0,n);
}

static size_t u32_to_dec(char* dst, size_t cap, unsigned v){
char tmp[16];
int n=0;
if (cap==0) return 0;
if (v==0){ if (cap>1){ dst[0]='0'; dst[1]=0; return 1; } dst[0]=0; return 0; }
while (v>0 && n<16){ tmp[n++] = (char)('0' + (v%10)); v/=10; }
size_t i=0;
while (i<cap-1 && n>0){ dst[i++] = tmp[--n]; }
dst[i]=0;
return i;
}

static void make_ifname(char* dst, size_t cap, const char* prefix){
if (!dst || cap==0) return;
int idx=0;
if (prefix && prefix[0]=='e'){ idx = g_eth_next++; }
else if (prefix && prefix[0]=='w'){ idx = g_wif_next++; }
else { idx = g_net_next++; }
size_t j=0;
if (prefix){ j = strncpy(dst, cap, prefix); } else { dst[0]='n'; dst[1]='i'; dst[2]='c'; dst[3]=0; j=3; }
if (j<cap-1) u32_to_dec(dst+j, cap-j, (unsigned)idx);
}

static void add_loopback(){
if (g_lo_added) return;
if (g_count >= MAX_L2_INTERFACES) return;
net_nic_desc_t* d = &g_nics[g_count++];
d->drv = nullptr;
memzero(d->ifname,sizeof(d->ifname));
memzero(d->hw_ifname,sizeof(d->hw_ifname));
d->ifname[0]='l'; d->ifname[1]='o'; d->ifname[2]='0'; d->ifname[3]=0;
d->hw_ifname[0]='l'; d->hw_ifname[1]='o'; d->hw_ifname[2]='o'; d->hw_ifname[3]='p'; d->hw_ifname[4]='b'; d->hw_ifname[5]='a'; d->hw_ifname[6]='c'; d->hw_ifname[7]='k'; d->hw_ifname[8]=0;
memzero(d->mac,6);
d->mtu = 65535;
d->header_size = 0;
d->kind = NET_IFK_LOCALHOST;
d->speed_mbps = 0xFFFFFFFFu;
d->duplex = NET_IFK_LOCALHOST;
g_lo_added = true;
kprintfv("[net-bus] added loopback ifname=%s",d->ifname);
}

static bool is_virtio_net(uint16_t vendor, uint16_t device, uint8_t class_code, uint8_t subclass){
if (vendor != 0x1AF4) return false;
if (class_code == 0x02) return true;
if (device == 0x1000) return true;
return false;
}

int net_bus_init(){
g_count = 0;
g_eth_next = 0;
g_wif_next = 0;
g_net_next = 0;
g_lo_added = false;

kprintfv("[net-bus] init");

pci_device_info infos[64];
size_t n = pci_enumerate(infos, 64);
kprintfv("[net-bus] pci_enumerate=%u",(unsigned)n);

int nic_ord = 0;

for (size_t i=0;i<n;i++){
if (g_count >= MAX_L2_INTERFACES){ kprintfv("[net-bus] cap reached"); break; }

const uint16_t ven = infos[i].vendor;
const uint16_t dev = infos[i].device;
const uint8_t cls = infos[i].class_code;
const uint8_t sub = infos[i].subclass;

if (cls != 0x02) continue;

kprintfv("[net-bus] net dev %u ven=%x dev=%x class=%x sub=%x prog=%x addr=%x",
(unsigned)i, ven, dev, cls, sub, infos[i].prog_if, (uintptr_t)infos[i].addr);

const char* if_prefix = "net";
uint8_t kind = NET_IFK_OTHER;
if (sub == 0x00){ if_prefix = "eth"; kind = NET_IFK_ETH; }

bool matched = false;

if (is_virtio_net(ven, dev, cls, sub)){
VirtioNetDriver* d = new VirtioNetDriver();
if (!d){ kprintf("[net-bus][warn] virtio alloc failed"); continue; }

uint32_t irq_base = NET_IRQ_BASE + (uint32_t)(2*nic_ord);
if (!d->init_at(infos[i].addr, irq_base)){
kprintf("[net-bus][warn] virtio init_at failed");
delete d;
continue;
}

net_nic_desc_t* e = &g_nics[g_count++];
e->drv = d;

d->get_mac(e->mac);
e->mtu = d->get_mtu();
e->header_size = d->get_header_size();
e->kind = kind;
e->speed_mbps = d->get_speed_mbps();
e->duplex = d->get_duplex();

make_ifname(e->ifname, sizeof(e->ifname), if_prefix);

const char* hw = d->hw_ifname();
strncpy(e->hw_ifname, sizeof(e->hw_ifname), (hw && hw[0]) ? hw : "vnet");

kprintfv("[net-bus] added if=%s mac=%x:%x:%x:%x:%x:%x mtu=%u hdr=%u hw=%s irq_base=%u spd=%u dup=%u",
e->ifname, e->mac[0],e->mac[1],e->mac[2],e->mac[3],e->mac[4],e->mac[5],
e->mtu, e->header_size, e->hw_ifname, (unsigned)irq_base,
(unsigned)e->speed_mbps, (unsigned)e->duplex);

nic_ord += 1;
matched = true;
}
//else if future drivers

if (!matched){
kprintf("[net-bus][warn] no driver for ven=%x dev=%x class=%x sub=%x", ven, dev, cls, sub);
}
}

if (!g_lo_added && g_count < MAX_L2_INTERFACES) add_loopback();

kprintfv("[net-bus] total_if=%u",(unsigned)g_count);
return (int)g_count;
}


void net_bus_enable_verbose(){
verbose = true;
}

int net_bus_count(){
return (int)g_count;
}

NetDriver* net_bus_driver(int idx){
if (idx < 0 || (size_t)idx >= g_count) return nullptr;
return g_nics[idx].drv;
}

const char* net_bus_ifname(int idx){
if (idx < 0 || (size_t)idx >= g_count) return nullptr;
return g_nics[idx].ifname;
}

const char* net_bus_hw_ifname(int idx){
if (idx < 0 || (size_t)idx >= g_count) return nullptr;
return g_nics[idx].hw_ifname;
}

void net_bus_get_mac(int idx, uint8_t out_mac[6]){
if (idx < 0 || (size_t)idx >= g_count) { memzero(out_mac,6); return; }
memcpy(out_mac, g_nics[idx].mac, 6);
}

uint16_t net_bus_get_mtu(int idx){
if (idx < 0 || (size_t)idx >= g_count) return 0;
return g_nics[idx].mtu;
}

uint16_t net_bus_get_header_size(int idx){
if (idx < 0 || (size_t)idx >= g_count) return 0;
return g_nics[idx].header_size;
}

uint8_t net_bus_get_kind(int idx){
if (idx < 0 || (size_t)idx >= g_count) return NET_IFK_UNKNOWN;
return g_nics[idx].kind;
}

uint32_t net_bus_get_speed_mbps(int idx){
if (idx < 0 || (size_t)idx >= g_count) return 0xFFFFFFFFu;
return g_nics[idx].speed_mbps;
}

uint8_t net_bus_get_duplex(int idx){
if (idx < 0 || (size_t)idx >= g_count) return 0xFFu;
return g_nics[idx].duplex;
}
22 changes: 22 additions & 0 deletions kernel/networking/drivers/net_bus.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once
#include "net_driver.hpp"

enum NetIfKind : uint8_t {
NET_IFK_ETH = 0x00,
NET_IFK_WIFI = 0x01,
NET_IFK_OTHER = 0x02,
NET_IFK_LOCALHOST = 0xFE,
NET_IFK_UNKNOWN = 0xFF
};

int net_bus_init();
int net_bus_count();
NetDriver* net_bus_driver(int idx);
const char* net_bus_ifname(int idx);
const char* net_bus_hw_ifname(int idx);
void net_bus_get_mac(int idx, uint8_t out_mac[6]);
uint16_t net_bus_get_mtu(int idx);
uint16_t net_bus_get_header_size(int idx);
uint8_t net_bus_get_kind(int idx);
uint32_t net_bus_get_speed_mbps(int idx);
uint8_t net_bus_get_duplex(int idx);
18 changes: 9 additions & 9 deletions kernel/networking/drivers/net_driver.hpp
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
#pragma once

#include "types.h"
#include "net/network_types.h"

class NetDriver {
public:
NetDriver() = default;
virtual bool init() = 0;

virtual ~NetDriver() = default;
virtual bool init_at(uint64_t pci_addr, uint32_t irq_base_vector) = 0;
virtual sizedptr allocate_packet(size_t size) = 0;
virtual sizedptr handle_receive_packet(void* buffer) = 0;
virtual sizedptr handle_receive_packet() = 0;
virtual void handle_sent_packet() = 0;
virtual void enable_verbose() = 0;
virtual void send_packet(sizedptr packet) = 0;
virtual void get_mac(net_l2l3_endpoint *context) = 0;

virtual ~NetDriver() = default;

uint16_t header_size;
virtual void get_mac(uint8_t out_mac[6]) const = 0;
virtual uint16_t get_mtu() const = 0;
virtual uint16_t get_header_size() const = 0;
virtual const char* hw_ifname() const = 0;
virtual uint32_t get_speed_mbps() const = 0;
virtual uint8_t get_duplex() const = 0;
};
Loading