Skip to content

Commit 0fb067c

Browse files
author
Diego Ferrari
committed
Merge branch 'net/refactor-nics-ips'
# Conflicts: # shared/ui/draw/draw.c # user/default_process.c
2 parents d6ad6f2 + 28717f4 commit 0fb067c

81 files changed

Lines changed: 6172 additions & 2297 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎Makefile‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,20 @@ endif
1111

1212
.PHONY: all shared user kernel clean raspi virt run debug dump prepare-fs help install
1313

14-
all: shared kernel user utils
14+
all: kshared kernel shared user utils
1515
@echo "Build complete."
1616
./createfs
1717

18-
shared:
19-
$(MAKE) -C shared
18+
kshared:
19+
$(MAKE) -C shared SH_FLAGS=-DKERNEL BUILD_DIR=./kbuild TARGET=klibshared.a
20+
21+
shared:
22+
$(MAKE) -C shared BUILD_DIR=./build
2023

2124
user: shared prepare-fs
2225
$(MAKE) -C user
2326

24-
kernel: shared
27+
kernel: kshared
2528
$(MAKE) -C kernel LOAD_ADDR=$(LOAD_ADDR) XHCI_CTX_SIZE=$(XHCI_CTX_SIZE) QEMU=$(QEMU)
2629

2730
utils: shared prepare-fs

‎README.md‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ The Raspberry Pi emulation has the following limitations:
7777

7878
## Networking
7979

80-
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.
80+
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.
81+
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.
82+
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.
83+
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.
8184
An implementation of the server can be found at the [RedactedOS Firmware Server Repository](https://github.com/differrari/RedactedOS_firmware_server/tree/main)
82-

‎common.mk‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ BUILD_DIR := ./build
1010
COMMON_FLAGS ?= -ffreestanding -nostdlib -fno-exceptions -fno-unwind-tables \
1111
-fno-asynchronous-unwind-tables -g -O0 -Wall -Wextra \
1212
-Wno-unused-parameter -Wno-address-of-packed-member \
13-
-mcpu=cortex-a72 -Werror -Wno-error=sized-deallocation
13+
-mcpu=cortex-a72 -Werror -Wno-error=sized-deallocation \
14+
-Wno-unused-function
1415

1516
CFLAGS_BASE ?= $(COMMON_FLAGS) -std=c99
1617
CXXFLAGS_BASE ?= $(COMMON_FLAGS) -fno-rtti

‎kernel/Makefile‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ all: $(TARGET)
3131
prepare:
3232
mkdir -p $(BUILD_DIR)
3333

34-
$(TARGET): ../shared/libshared.a prepare $(OBJ)
34+
$(TARGET): ../shared/klibshared.a prepare $(OBJ)
3535
echo $(LDFLAGS)
36-
$(VLD) $(LDFLAGS) -o $(ELF) $(OBJL) ../shared/libshared.a $(BUILD_DIR)/boot.o
36+
$(VLD) $(LDFLAGS) -o $(ELF) $(OBJL) ../shared/klibshared.a $(BUILD_DIR)/boot.o
3737
$(OBJCOPY) -O binary $(ELF) $@
3838

3939
$(BUILD_DIR)/%.o: %.S

‎kernel/exceptions/irq.c‎

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "networking/network.h"
1010
#include "hw/hw.h"
1111
#include "audio/audio.h"
12+
#include "networking/interface_manager.h"
1213
#include "process/syscall.h"
1314

1415
#define IRQ_TIMER 30
@@ -46,8 +47,11 @@ void irq_init() {
4647

4748
gic_enable_irq(IRQ_TIMER, 0x80, 0);
4849
gic_enable_irq(MSI_OFFSET + INPUT_IRQ, 0x80, 0);
49-
gic_enable_irq(MSI_OFFSET + NET_IRQ, 0x80, 0);
50-
gic_enable_irq(MSI_OFFSET + NET_IRQ + 1, 0x80, 0);
50+
51+
for (uint32_t i = 0; i < (uint32_t)MAX_L2_INTERFACES; ++i) {
52+
gic_enable_irq(MSI_OFFSET + NET_IRQ_BASE + (2*i), 0x80, 0);
53+
gic_enable_irq(MSI_OFFSET + NET_IRQ_BASE + (2*i+1), 0x80, 0);
54+
}
5155
gic_enable_irq(SLEEP_TIMER, 0x80, 0);
5256

5357
if (RPI_BOARD != 3){
@@ -91,12 +95,12 @@ void irq_el1_handler() {
9195
wake_processes();
9296
if (RPI_BOARD != 3) write32(GICC_BASE + 0x10, irq);
9397
process_restore();
94-
} else if (irq == MSI_OFFSET + NET_IRQ){
95-
network_handle_download_interrupt();
96-
if (RPI_BOARD != 3) write32(GICC_BASE + 0x10, irq);
97-
process_restore();
98-
} else if (irq == MSI_OFFSET + NET_IRQ + 1){
99-
network_handle_upload_interrupt();
98+
} else if (irq >= MSI_OFFSET + NET_IRQ_BASE && irq < MSI_OFFSET + NET_IRQ_BASE + (2*MAX_L2_INTERFACES)){
99+
uint32_t rel = irq - (MSI_OFFSET + NET_IRQ_BASE);
100+
uint16_t nic_id = (uint16_t)(rel >> 1);
101+
uint8_t is_rx = (rel & 1) == 0;
102+
if (is_rx) network_handle_download_interrupt_nic(nic_id);
103+
else network_handle_upload_interrupt_nic(nic_id);
100104
if (RPI_BOARD != 3) write32(GICC_BASE + 0x10, irq);
101105
process_restore();
102106
} else {

‎kernel/kernel.c‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,10 @@ void kernel_main() {
5555

5656
bool input_available = load_module(&input_module);
5757
bool network_available = false;
58-
5958
if (BOARD_TYPE == 1){
6059
//TODO: disabling networking until it is refactored to prevent memory issues
61-
network_available = false;// load_module(&net_module);
62-
60+
network_available = load_module(&net_module);
61+
6362
load_module(&audio_module);
6463

6564
init_audio_mixer();

‎kernel/memory/page_allocator.c‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "std/memory.h"
77
#include "math/math.h"
88
#include "console/kio.h"
9+
#include "process/scheduler.h"
910

1011
#define PD_TABLE 0b11
1112
#define PD_BLOCK 0b01
@@ -186,6 +187,14 @@ void mark_used(uintptr_t address, size_t pages)
186187
}
187188
}
188189

190+
void* malloc(size_t size){
191+
return kalloc((void*)get_proc_by_pid(1)->heap, size, ALIGN_16B, get_current_privilege());
192+
}
193+
194+
void free(void*ptr, size_t size){
195+
kfree(ptr, size);
196+
}
197+
189198
//TODO: maybe alloc to different base pages based on alignment? Then it's easier to keep track of full pages, freeing and sizes
190199
void* kalloc(void *page, uint64_t size, uint16_t alignment, uint8_t level){
191200
//TODO: we're changing the size but not reporting it back, which means the free function does not fully free the allocd memory
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
#include "net_bus.hpp"
2+
#include "net_driver.hpp"
3+
#include "virtio_net_pci/virtio_net_pci.hpp"
4+
#include "pci.h"
5+
#include "std/std.h"
6+
#include "console/kio.h"
7+
#include "types.h"
8+
#include "networking/interface_manager.h"
9+
#include "networking/network.h"
10+
11+
#define kprintfv(fmt, ...) ({ if (verbose){ kprintf(fmt, ##__VA_ARGS__); } })
12+
13+
typedef struct {
14+
NetDriver* drv;
15+
char ifname[16];
16+
char hw_ifname[32];
17+
uint8_t mac[6];
18+
uint16_t mtu;
19+
uint16_t header_size;
20+
uint8_t kind;
21+
uint32_t speed_mbps;
22+
uint8_t duplex;
23+
} net_nic_desc_t;
24+
25+
static net_nic_desc_t g_nics[MAX_L2_INTERFACES];
26+
static size_t g_count = 0;
27+
static int g_eth_next = 0;
28+
static int g_wif_next = 0;
29+
static int g_net_next = 0;
30+
static bool g_lo_added = false;
31+
static bool verbose = true;
32+
33+
static void memzero(void* p, size_t n){
34+
memset(p,0,n);
35+
}
36+
37+
static size_t u32_to_dec(char* dst, size_t cap, unsigned v){
38+
char tmp[16];
39+
int n=0;
40+
if (cap==0) return 0;
41+
if (v==0){ if (cap>1){ dst[0]='0'; dst[1]=0; return 1; } dst[0]=0; return 0; }
42+
while (v>0 && n<16){ tmp[n++] = (char)('0' + (v%10)); v/=10; }
43+
size_t i=0;
44+
while (i<cap-1 && n>0){ dst[i++] = tmp[--n]; }
45+
dst[i]=0;
46+
return i;
47+
}
48+
49+
static void make_ifname(char* dst, size_t cap, const char* prefix){
50+
if (!dst || cap==0) return;
51+
int idx=0;
52+
if (prefix && prefix[0]=='e'){ idx = g_eth_next++; }
53+
else if (prefix && prefix[0]=='w'){ idx = g_wif_next++; }
54+
else { idx = g_net_next++; }
55+
size_t j=0;
56+
if (prefix){ j = strncpy(dst, cap, prefix); } else { dst[0]='n'; dst[1]='i'; dst[2]='c'; dst[3]=0; j=3; }
57+
if (j<cap-1) u32_to_dec(dst+j, cap-j, (unsigned)idx);
58+
}
59+
60+
static void add_loopback(){
61+
if (g_lo_added) return;
62+
if (g_count >= MAX_L2_INTERFACES) return;
63+
net_nic_desc_t* d = &g_nics[g_count++];
64+
d->drv = nullptr;
65+
memzero(d->ifname,sizeof(d->ifname));
66+
memzero(d->hw_ifname,sizeof(d->hw_ifname));
67+
d->ifname[0]='l'; d->ifname[1]='o'; d->ifname[2]='0'; d->ifname[3]=0;
68+
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;
69+
memzero(d->mac,6);
70+
d->mtu = 65535;
71+
d->header_size = 0;
72+
d->kind = NET_IFK_LOCALHOST;
73+
d->speed_mbps = 0xFFFFFFFFu;
74+
d->duplex = NET_IFK_LOCALHOST;
75+
g_lo_added = true;
76+
kprintfv("[net-bus] added loopback ifname=%s",d->ifname);
77+
}
78+
79+
static bool is_virtio_net(uint16_t vendor, uint16_t device, uint8_t class_code, uint8_t subclass){
80+
if (vendor != 0x1AF4) return false;
81+
if (class_code == 0x02) return true;
82+
if (device == 0x1000) return true;
83+
return false;
84+
}
85+
86+
int net_bus_init(){
87+
g_count = 0;
88+
g_eth_next = 0;
89+
g_wif_next = 0;
90+
g_net_next = 0;
91+
g_lo_added = false;
92+
93+
kprintfv("[net-bus] init");
94+
95+
pci_device_info infos[64];
96+
size_t n = pci_enumerate(infos, 64);
97+
kprintfv("[net-bus] pci_enumerate=%u",(unsigned)n);
98+
99+
int nic_ord = 0;
100+
101+
for (size_t i=0;i<n;i++){
102+
if (g_count >= MAX_L2_INTERFACES){ kprintfv("[net-bus] cap reached"); break; }
103+
104+
const uint16_t ven = infos[i].vendor;
105+
const uint16_t dev = infos[i].device;
106+
const uint8_t cls = infos[i].class_code;
107+
const uint8_t sub = infos[i].subclass;
108+
109+
if (cls != 0x02) continue;
110+
111+
kprintfv("[net-bus] net dev %u ven=%x dev=%x class=%x sub=%x prog=%x addr=%x",
112+
(unsigned)i, ven, dev, cls, sub, infos[i].prog_if, (uintptr_t)infos[i].addr);
113+
114+
const char* if_prefix = "net";
115+
uint8_t kind = NET_IFK_OTHER;
116+
if (sub == 0x00){ if_prefix = "eth"; kind = NET_IFK_ETH; }
117+
118+
bool matched = false;
119+
120+
if (is_virtio_net(ven, dev, cls, sub)){
121+
VirtioNetDriver* d = new VirtioNetDriver();
122+
if (!d){ kprintf("[net-bus][warn] virtio alloc failed"); continue; }
123+
124+
uint32_t irq_base = NET_IRQ_BASE + (uint32_t)(2*nic_ord);
125+
if (!d->init_at(infos[i].addr, irq_base)){
126+
kprintf("[net-bus][warn] virtio init_at failed");
127+
delete d;
128+
continue;
129+
}
130+
131+
net_nic_desc_t* e = &g_nics[g_count++];
132+
e->drv = d;
133+
134+
d->get_mac(e->mac);
135+
e->mtu = d->get_mtu();
136+
e->header_size = d->get_header_size();
137+
e->kind = kind;
138+
e->speed_mbps = d->get_speed_mbps();
139+
e->duplex = d->get_duplex();
140+
141+
make_ifname(e->ifname, sizeof(e->ifname), if_prefix);
142+
143+
const char* hw = d->hw_ifname();
144+
strncpy(e->hw_ifname, sizeof(e->hw_ifname), (hw && hw[0]) ? hw : "vnet");
145+
146+
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",
147+
e->ifname, e->mac[0],e->mac[1],e->mac[2],e->mac[3],e->mac[4],e->mac[5],
148+
e->mtu, e->header_size, e->hw_ifname, (unsigned)irq_base,
149+
(unsigned)e->speed_mbps, (unsigned)e->duplex);
150+
151+
nic_ord += 1;
152+
matched = true;
153+
}
154+
//else if future drivers
155+
156+
if (!matched){
157+
kprintf("[net-bus][warn] no driver for ven=%x dev=%x class=%x sub=%x", ven, dev, cls, sub);
158+
}
159+
}
160+
161+
if (!g_lo_added && g_count < MAX_L2_INTERFACES) add_loopback();
162+
163+
kprintfv("[net-bus] total_if=%u",(unsigned)g_count);
164+
return (int)g_count;
165+
}
166+
167+
168+
void net_bus_enable_verbose(){
169+
verbose = true;
170+
}
171+
172+
int net_bus_count(){
173+
return (int)g_count;
174+
}
175+
176+
NetDriver* net_bus_driver(int idx){
177+
if (idx < 0 || (size_t)idx >= g_count) return nullptr;
178+
return g_nics[idx].drv;
179+
}
180+
181+
const char* net_bus_ifname(int idx){
182+
if (idx < 0 || (size_t)idx >= g_count) return nullptr;
183+
return g_nics[idx].ifname;
184+
}
185+
186+
const char* net_bus_hw_ifname(int idx){
187+
if (idx < 0 || (size_t)idx >= g_count) return nullptr;
188+
return g_nics[idx].hw_ifname;
189+
}
190+
191+
void net_bus_get_mac(int idx, uint8_t out_mac[6]){
192+
if (idx < 0 || (size_t)idx >= g_count) { memzero(out_mac,6); return; }
193+
memcpy(out_mac, g_nics[idx].mac, 6);
194+
}
195+
196+
uint16_t net_bus_get_mtu(int idx){
197+
if (idx < 0 || (size_t)idx >= g_count) return 0;
198+
return g_nics[idx].mtu;
199+
}
200+
201+
uint16_t net_bus_get_header_size(int idx){
202+
if (idx < 0 || (size_t)idx >= g_count) return 0;
203+
return g_nics[idx].header_size;
204+
}
205+
206+
uint8_t net_bus_get_kind(int idx){
207+
if (idx < 0 || (size_t)idx >= g_count) return NET_IFK_UNKNOWN;
208+
return g_nics[idx].kind;
209+
}
210+
211+
uint32_t net_bus_get_speed_mbps(int idx){
212+
if (idx < 0 || (size_t)idx >= g_count) return 0xFFFFFFFFu;
213+
return g_nics[idx].speed_mbps;
214+
}
215+
216+
uint8_t net_bus_get_duplex(int idx){
217+
if (idx < 0 || (size_t)idx >= g_count) return 0xFFu;
218+
return g_nics[idx].duplex;
219+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#pragma once
2+
#include "net_driver.hpp"
3+
4+
enum NetIfKind : uint8_t {
5+
NET_IFK_ETH = 0x00,
6+
NET_IFK_WIFI = 0x01,
7+
NET_IFK_OTHER = 0x02,
8+
NET_IFK_LOCALHOST = 0xFE,
9+
NET_IFK_UNKNOWN = 0xFF
10+
};
11+
12+
int net_bus_init();
13+
int net_bus_count();
14+
NetDriver* net_bus_driver(int idx);
15+
const char* net_bus_ifname(int idx);
16+
const char* net_bus_hw_ifname(int idx);
17+
void net_bus_get_mac(int idx, uint8_t out_mac[6]);
18+
uint16_t net_bus_get_mtu(int idx);
19+
uint16_t net_bus_get_header_size(int idx);
20+
uint8_t net_bus_get_kind(int idx);
21+
uint32_t net_bus_get_speed_mbps(int idx);
22+
uint8_t net_bus_get_duplex(int idx);

0 commit comments

Comments
 (0)