From df0209a2d6d18a426a535fd4550417767f32b3e7 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sat, 14 Jun 2025 00:00:00 +0000 Subject: [PATCH 01/61] Initializing mulitple virtqueues for multiple devices --- kernel/networking/virtio_net_pci.c | 3 ++- kernel/virtio/virtio_pci.c | 38 +++++++++++++++++++----------- kernel/virtio/virtio_pci.h | 1 + 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/kernel/networking/virtio_net_pci.c b/kernel/networking/virtio_net_pci.c index 11b4322e..7755281e 100644 --- a/kernel/networking/virtio_net_pci.c +++ b/kernel/networking/virtio_net_pci.c @@ -17,10 +17,11 @@ bool vnp_find_network(){ } pci_enable_device(addr); - return true; uint64_t net_device_address, net_device_size; + kprintf("Configuring network device"); + virtio_get_capabilities(&vnp_net_dev, addr, &net_device_address, &net_device_size); pci_register(net_device_address, net_device_size); if (!virtio_init_device(&vnp_net_dev)) { diff --git a/kernel/virtio/virtio_pci.c b/kernel/virtio/virtio_pci.c index 52e92436..ba442493 100644 --- a/kernel/virtio/virtio_pci.c +++ b/kernel/virtio/virtio_pci.c @@ -132,29 +132,39 @@ bool virtio_init_device(virtio_device *dev) { return false; } - cfg->queue_select = 0; - uint32_t size = cfg->queue_size; - dev->memory_page = alloc_page(0x1000, true, true, false); - uint64_t base = (uintptr_t)allocate_in_page(dev->memory_page, 0x1000, ALIGN_64B, true, true); - uint64_t avail = (uintptr_t)allocate_in_page(dev->memory_page, 0x1000, ALIGN_64B, true, true); - uint64_t used = (uintptr_t)allocate_in_page(dev->memory_page, 0x1, ALIGN_64B, true, true); + uint32_t queue_index = 0; + while (select_queue(dev,queue_index)){ + uint64_t base = (uintptr_t)allocate_in_page(dev->memory_page, 0x1000, ALIGN_64B, true, true); + uint64_t avail = (uintptr_t)allocate_in_page(dev->memory_page, 0x1000, ALIGN_64B, true, true); + uint64_t used = (uintptr_t)allocate_in_page(dev->memory_page, 0x1, ALIGN_64B, true, true); + + kprintfv("[VIRTIO QUEUE %i] Device base %x",queue_index,base); + kprintfv("[VIRTIO QUEUE %i] Device avail %x",queue_index,avail); + kprintfv("[VIRTIO QUEUE %i] Device used %x",queue_index,used); + + cfg->queue_desc = base; + cfg->queue_driver = avail; + cfg->queue_device = used; + cfg->queue_enable = 1; + queue_index++; + } - kprintfv("[VIRTIO] Device base %x",base); - kprintfv("[VIRTIO] Device avail %x",avail); - kprintfv("[VIRTIO] Device used %x",used); + kprintfv("Device initialized %i virtqueues",queue_index); - cfg->queue_size = size; - cfg->queue_desc = base; - cfg->queue_driver = avail; - cfg->queue_device = used; - cfg->queue_enable = 1; + select_queue(dev,0); cfg->device_status |= VIRTIO_STATUS_DRIVER_OK; return true; } +uint32_t select_queue(virtio_device *dev, uint32_t index){ + dev->common_cfg->queue_select = index; + asm volatile ("dsb sy" ::: "memory"); + return dev->common_cfg->queue_size; +} + bool virtio_send(virtio_device *dev, uint64_t desc, uint64_t avail, uint64_t used, uint64_t cmd, uint32_t cmd_len, uint64_t resp, uint32_t resp_len, uint8_t flags) { struct virtq_desc* d = (struct virtq_desc*)(uintptr_t)desc; struct virtq_avail* a = (struct virtq_avail*)(uintptr_t)avail; diff --git a/kernel/virtio/virtio_pci.h b/kernel/virtio/virtio_pci.h index 14c5f5a1..215c648d 100644 --- a/kernel/virtio/virtio_pci.h +++ b/kernel/virtio/virtio_pci.h @@ -44,6 +44,7 @@ void virtio_get_capabilities(virtio_device *dev, uint64_t pci_addr, uint64_t *mm bool virtio_init_device(virtio_device *dev); bool virtio_send(virtio_device *dev, uint64_t desc, uint64_t avail, uint64_t used, uint64_t cmd, uint32_t cmd_len, uint64_t resp, uint32_t resp_len, uint8_t flags); bool virtio_send2(virtio_device *dev, uint64_t desc, uint64_t avail, uint64_t used, uint64_t cmd, uint32_t cmd_len, uint64_t resp, uint32_t resp_len, uint8_t flags); +uint32_t select_queue(virtio_device *dev, uint32_t index); #ifdef __cplusplus } From 5ccce8cd8bed530b23c7ef22bbb9543fc8a6761c Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sun, 15 Jun 2025 00:00:00 +0000 Subject: [PATCH 02/61] virtqueue proper size --- kernel/virtio/virtio_pci.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/kernel/virtio/virtio_pci.c b/kernel/virtio/virtio_pci.c index ba442493..b2827d5b 100644 --- a/kernel/virtio/virtio_pci.c +++ b/kernel/virtio/virtio_pci.c @@ -16,7 +16,7 @@ struct virtq_desc { struct virtq_avail { uint16_t flags; uint16_t idx; - uint16_t ring[128]; + uint16_t ring[]; } __attribute__((packed)); struct virtq_used_elem { @@ -135,10 +135,11 @@ bool virtio_init_device(virtio_device *dev) { dev->memory_page = alloc_page(0x1000, true, true, false); uint32_t queue_index = 0; - while (select_queue(dev,queue_index)){ - uint64_t base = (uintptr_t)allocate_in_page(dev->memory_page, 0x1000, ALIGN_64B, true, true); - uint64_t avail = (uintptr_t)allocate_in_page(dev->memory_page, 0x1000, ALIGN_64B, true, true); - uint64_t used = (uintptr_t)allocate_in_page(dev->memory_page, 0x1, ALIGN_64B, true, true); + uint32_t size; + while ((size = select_queue(dev,queue_index))){ + uint64_t base = (uintptr_t)allocate_in_page(dev->memory_page, 16 * size, ALIGN_64B, true, true); + uint64_t avail = (uintptr_t)allocate_in_page(dev->memory_page, 4 + (2 * size), ALIGN_64B, true, true); + uint64_t used = (uintptr_t)allocate_in_page(dev->memory_page, sizeof(uint16_t) * (2 + size), ALIGN_64B, true, true); kprintfv("[VIRTIO QUEUE %i] Device base %x",queue_index,base); kprintfv("[VIRTIO QUEUE %i] Device avail %x",queue_index,avail); From e44305b473002bb84068af3f130ccbdf94c8b03c Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Mon, 16 Jun 2025 00:00:00 +0000 Subject: [PATCH 03/61] Printing mac address --- kernel/networking/virtio_net_pci.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/networking/virtio_net_pci.c b/kernel/networking/virtio_net_pci.c index 7755281e..32c61b78 100644 --- a/kernel/networking/virtio_net_pci.c +++ b/kernel/networking/virtio_net_pci.c @@ -29,5 +29,8 @@ bool vnp_find_network(){ return false; } + uint8_t* mac = vnp_net_dev.device_cfg; + kprintf("%x:%x:%x:%x:%x:%x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return true; } \ No newline at end of file From a7509ec211aa4d52ee92154efafb4a44cef417a6 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Mon, 16 Jun 2025 00:00:00 +0000 Subject: [PATCH 04/61] Moved XHCI init to ensure it happens right before MMU enable --- kernel/kernel.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/kernel/kernel.c b/kernel/kernel.c index 10a8b8dd..1bf58015 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -46,11 +46,6 @@ void kernel_main() { kprintf("GPU initialized"); - // xhci_enable_verbose(); - if (!xhci_input_init()){ - panic("Input initialization failure"); - } - kprintf("Initializing disk..."); // disk_verbose(); @@ -60,6 +55,10 @@ void kernel_main() { if (!vnp_find_network()) panic("Network initialization failure"); + // xhci_enable_verbose(); + if (!xhci_input_init()){ + panic("Input initialization failure"); + } mmu_init(); kprintf("MMU Mapped"); From 61e177fb516e92a4c96592dba184f5dbbf32c534 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 17 Jun 2025 00:00:00 +0000 Subject: [PATCH 05/61] Added feature mask and correct notif for each queue --- kernel/virtio/virtio_pci.c | 39 ++++++++++++++++++++++++++++++++++++-- kernel/virtio/virtio_pci.h | 2 ++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/kernel/virtio/virtio_pci.c b/kernel/virtio/virtio_pci.c index b2827d5b..55d6bd6c 100644 --- a/kernel/virtio/virtio_pci.c +++ b/kernel/virtio/virtio_pci.c @@ -63,6 +63,8 @@ struct virtio_pci_cap { static bool virtio_verbose = false; +uint32_t feature_mask; + void virtio_enable_verbose(){ virtio_verbose = true; } @@ -75,6 +77,10 @@ void virtio_enable_verbose(){ }\ }) +void virtio_set_feature_mask(uint32_t mask){ + feature_mask = mask; +} + void virtio_get_capabilities(virtio_device *dev, uint64_t pci_addr, uint64_t *mmio_start, uint64_t *mmio_size) { uint64_t offset = read32(pci_addr + 0x34); while (offset) { @@ -123,6 +129,12 @@ bool virtio_init_device(virtio_device *dev) { cfg->device_feature_select = 0; uint32_t features = cfg->device_feature; + kprintfv("Features %x",features); + + features &= feature_mask; + + kprintfv("Negotiated features %x",features); + cfg->driver_feature_select = 0; cfg->driver_feature = features; @@ -191,7 +203,7 @@ bool virtio_send(virtio_device *dev, uint64_t desc, uint64_t avail, uint64_t use a->ring[a->idx % 128] = 0; a->idx++; - *(volatile uint16_t*)(uintptr_t)(dev->notify_cfg + dev->notify_off_multiplier * 0) = 0; + *(volatile uint16_t*)(uintptr_t)(dev->notify_cfg + dev->notify_off_multiplier * dev->common_cfg->queue_select) = 0; while (last_used_idx == u->idx); @@ -221,7 +233,30 @@ bool virtio_send2(virtio_device *dev, uint64_t desc, uint64_t avail, uint64_t us a->ring[a->idx % 128] = 0; a->idx++; - *(volatile uint16_t*)(uintptr_t)(dev->notify_cfg + dev->notify_off_multiplier * 0) = 0; + *(volatile uint16_t*)(uintptr_t)(dev->notify_cfg + dev->notify_off_multiplier * dev->common_cfg->queue_select) = 0; + + while (last_used_idx == u->idx); + + return true; +} + +bool virtio_send3(virtio_device *dev, uint64_t cmd, uint32_t cmd_len) { + + struct virtq_desc* d = (struct virtq_desc*)(uintptr_t)dev->common_cfg->queue_desc; + struct virtq_avail* a = (struct virtq_avail*)(uintptr_t)dev->common_cfg->queue_driver; + struct virtq_used* u = (struct virtq_used*)(uintptr_t)dev->common_cfg->queue_device; + uint16_t last_used_idx = u->idx; + + d[0].addr = cmd; + d[0].len = cmd_len; + d[0].flags = 0; + d[0].next = 0; + + a->ring[a->idx % 128] = 0; + + a->idx++; + + *(volatile uint16_t*)(uintptr_t)(dev->notify_cfg + dev->notify_off_multiplier * dev->common_cfg->queue_select) = 0; while (last_used_idx == u->idx); diff --git a/kernel/virtio/virtio_pci.h b/kernel/virtio/virtio_pci.h index 215c648d..abc8c184 100644 --- a/kernel/virtio/virtio_pci.h +++ b/kernel/virtio/virtio_pci.h @@ -39,11 +39,13 @@ typedef struct virtio_device { void *memory_page; } virtio_device; +void virtio_set_feature_mask(uint32_t mask); void virtio_enable_verbose(); void virtio_get_capabilities(virtio_device *dev, uint64_t pci_addr, uint64_t *mmio_start, uint64_t *mmio_size); bool virtio_init_device(virtio_device *dev); bool virtio_send(virtio_device *dev, uint64_t desc, uint64_t avail, uint64_t used, uint64_t cmd, uint32_t cmd_len, uint64_t resp, uint32_t resp_len, uint8_t flags); bool virtio_send2(virtio_device *dev, uint64_t desc, uint64_t avail, uint64_t used, uint64_t cmd, uint32_t cmd_len, uint64_t resp, uint32_t resp_len, uint8_t flags); +bool virtio_send3(virtio_device *dev, uint64_t cmd, uint32_t cmd_len); uint32_t select_queue(virtio_device *dev, uint32_t index); #ifdef __cplusplus From 4ad0cb8e8918e8b7b464c672959d51958a2cd631 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 17 Jun 2025 00:00:00 +0000 Subject: [PATCH 06/61] Sending a test udp packet broadcast on local network --- kernel/networking/packets.h | 29 ++++++ kernel/networking/virtio_net_pci.c | 154 ++++++++++++++++++++++++++++- run | 3 +- 3 files changed, 183 insertions(+), 3 deletions(-) create mode 100644 kernel/networking/packets.h diff --git a/kernel/networking/packets.h b/kernel/networking/packets.h new file mode 100644 index 00000000..72ca00aa --- /dev/null +++ b/kernel/networking/packets.h @@ -0,0 +1,29 @@ +#pragma once + +#include "types.h" + +typedef struct __attribute__((packed)) eth_hdr_t { + uint8_t dst_mac[6]; + uint8_t src_mac[6]; + uint16_t ethertype; +} eth_hdr_t; + +typedef struct __attribute__((packed)) ipv4_hdr_t { + uint8_t version_ihl; + uint8_t dscp_ecn; + uint16_t total_length; + uint16_t identification; + uint16_t flags_frag_offset; + uint8_t ttl; + uint8_t protocol; + uint16_t header_checksum; + uint32_t src_ip; + uint32_t dst_ip; +} ipv4_hdr_t; + +typedef struct __attribute__((packed)) udp_hdr_t { + uint16_t src_port; + uint16_t dst_port; + uint16_t length; + uint16_t checksum; +} udp_hdr_t; \ No newline at end of file diff --git a/kernel/networking/virtio_net_pci.c b/kernel/networking/virtio_net_pci.c index 32c61b78..5eec0be1 100644 --- a/kernel/networking/virtio_net_pci.c +++ b/kernel/networking/virtio_net_pci.c @@ -6,10 +6,128 @@ #include "pci.h" #include "virtio/virtio_pci.h" #include "std/memfunctions.h" +#include "packets.h" static virtio_device vnp_net_dev; +#define RECEIVE_QUEUE 0 +#define TRANSMIT_QUEUE 1 + +#define VIRTIO_NET_HDR_GSO_NONE 0 + +#define UDP_PACKET_SIZE sizeof(virtio_net_hdr_t) + sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) + +typedef struct __attribute__((packed)) virtio_net_hdr_t { + uint8_t flags; + uint8_t gso_type; + uint16_t hdr_len; + uint16_t gso_size; + uint16_t csum_start; + uint16_t num_buffers; +} virtio_net_hdr_t; + +uint16_t udp_checksum( + uint32_t src_ip, + uint32_t dst_ip, + uint8_t protocol, + const uint8_t* udp_header_and_payload, + uint16_t length +) { + uint32_t sum = 0; + + sum += (src_ip >> 16) & 0xFFFF; + sum += src_ip & 0xFFFF; + sum += (dst_ip >> 16) & 0xFFFF; + sum += dst_ip & 0xFFFF; + sum += __builtin_bswap16(protocol); + sum += __builtin_bswap16(length); + + for (uint16_t i = 0; i + 1 < length; i += 2) + sum += (udp_header_and_payload[i] << 8) | udp_header_and_payload[i + 1]; + + if (length & 1) + sum += udp_header_and_payload[length - 1] << 8; + + while (sum >> 16) + sum = (sum & 0xFFFF) + (sum >> 16); + + return ~sum; +} + +void create_udp_packet( + uint8_t* buf, + const uint8_t src_mac[6], + const uint8_t dst_mac[6], + uint32_t src_ip, + uint32_t dst_ip, + uint16_t src_port, + uint16_t dst_port, + const uint8_t* payload, + uint16_t payload_len +) { + uintptr_t p = (uintptr_t)buf; + + virtio_net_hdr_t* net = (virtio_net_hdr_t*)p; + + net->flags = 0; + net->gso_type = VIRTIO_NET_HDR_GSO_NONE; + net->hdr_len = 0; + net->gso_size = 0; + net->csum_start = 0; + net->num_buffers = 0; + + p += sizeof(virtio_net_hdr_t); + + eth_hdr_t* eth = (eth_hdr_t*)p; + for (int i = 0; i < 6; i++) eth->dst_mac[i] = dst_mac[i]; + for (int i = 0; i < 6; i++) eth->src_mac[i] = src_mac[i]; + eth->ethertype = __builtin_bswap16(0x0800); + p += sizeof(eth_hdr_t); + + ipv4_hdr_t* ip = (ipv4_hdr_t*)p; + ip->version_ihl = 0x45; + ip->dscp_ecn = 0; + ip->total_length = __builtin_bswap16(sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) + payload_len); + ip->identification = 0; + ip->flags_frag_offset = __builtin_bswap16(0x4000); + ip->ttl = 64; + ip->protocol = 17; + ip->header_checksum = 0; + ip->src_ip = __builtin_bswap32(src_ip); + ip->dst_ip = __builtin_bswap32(dst_ip); + uint16_t* ip_words = (uint16_t*)ip; + uint32_t sum = 0; + for (int i = 0; i < 10; i++) sum += ip_words[i]; + while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16); + ip->header_checksum = __builtin_bswap16(~sum); + p += sizeof(ipv4_hdr_t); + + udp_hdr_t* udp = (udp_hdr_t*)p; + udp->src_port = __builtin_bswap16(src_port); + udp->dst_port = __builtin_bswap16(dst_port); + udp->length = __builtin_bswap16(sizeof(udp_hdr_t) + payload_len); + udp->checksum = udp_checksum(ip->src_ip,ip->dst_ip,17,(uint8_t*)udp,sizeof(udp_hdr_t) + payload_len); + p += sizeof(udp_hdr_t); + + uint8_t* data = (uint8_t*)p; + for (int i = 0; i < payload_len; i++) data[i] = payload[i]; + +} + +typedef struct virtio_net_config { + uint8_t mac[6]; + uint16_t status; + uint16_t max_virtqueue_pairs; + uint16_t mtu; + uint32_t speed; + uint8_t duplex; + uint8_t rss_max_key_size; + uint16_t rss_max_indirection_table_length; + uint32_t supported_hash_types; +}__attribute__((packed)) virtio_net_config; + bool vnp_find_network(){ + virtio_enable_verbose(); uint64_t addr = find_pci_device(0x1AF4, 0x1000); if (!addr){ kprintf("Virtio network device not found"); @@ -29,8 +147,40 @@ bool vnp_find_network(){ return false; } - uint8_t* mac = vnp_net_dev.device_cfg; - kprintf("%x:%x:%x:%x:%x:%x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + virtio_net_config* net_config = (virtio_net_config*)vnp_net_dev.device_cfg; + kprintf("%x:%x:%x:%x:%x:%x", net_config->mac[0], net_config->mac[1], net_config->mac[2], net_config->mac[3], net_config->mac[4], net_config->mac[5]); + + kprintf("%i virtqueue pairs",net_config->max_virtqueue_pairs); + kprintf("%x speed", net_config->speed); + kprintf("status = %x", net_config->status); + + uint8_t dest[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + kprintf("%x:%x:%x:%x:%x:%x", dest[0], dest[1], dest[2], dest[3], dest[4], dest[5]); + + size_t payload_size = 6; + char hw[6] = {'h','e','l','l','o', '\0'}; + + void* test_packet = allocate_in_page(vnp_net_dev.memory_page, UDP_PACKET_SIZE + payload_size, ALIGN_64B, true, true); + create_udp_packet(test_packet,net_config->mac,dest,(192 << 24) | (168 << 16) | (1 << 8) | 131,(255 << 24) | (255 << 16) | (255 << 8) | 255,8888,8080,hw, payload_size); + + kprintf("Packet created"); + + select_queue(&vnp_net_dev, 1); + + size_t size = UDP_PACKET_SIZE + payload_size; + + kprintf("Upload queue selected for packet %x (size %i)",(uintptr_t)test_packet, size); + + // uint8_t *packet_bytes = (uint8_t*)test_packet; + + // for (size_t s = 0; s < size; s++){ + // kprintf("[%i] = %x",s,packet_bytes[s]); + // } + + virtio_send3(&vnp_net_dev, (uintptr_t)test_packet, size); + + kprintf("Packet sent"); return true; } \ No newline at end of file diff --git a/run b/run index 8a380ef2..5dc8ca7a 100755 --- a/run +++ b/run @@ -22,7 +22,8 @@ qemu-system-aarch64 \ -kernel kernel.elf \ -device virtio-gpu-pci \ -display sdl \ --device virtio-net-pci \ +-netdev vmnet-bridged,id=net0,ifname=en0 \ +-device virtio-net-pci,netdev=net0 \ -serial mon:stdio \ -drive file=disk.img,if=none,format=raw,id=hd0 \ -device virtio-blk-pci,drive=hd0 \ From 3f7bf4a36a250c49f0cfe40b01e06a720448c7f1 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 17 Jun 2025 00:00:00 +0000 Subject: [PATCH 07/61] Send3 -> send1d --- kernel/networking/virtio_net_pci.c | 2 +- kernel/virtio/virtio_pci.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/networking/virtio_net_pci.c b/kernel/networking/virtio_net_pci.c index 5eec0be1..c9fafcff 100644 --- a/kernel/networking/virtio_net_pci.c +++ b/kernel/networking/virtio_net_pci.c @@ -178,7 +178,7 @@ bool vnp_find_network(){ // kprintf("[%i] = %x",s,packet_bytes[s]); // } - virtio_send3(&vnp_net_dev, (uintptr_t)test_packet, size); + virtio_send_1d(&vnp_net_dev, (uintptr_t)test_packet, size); kprintf("Packet sent"); diff --git a/kernel/virtio/virtio_pci.c b/kernel/virtio/virtio_pci.c index 55d6bd6c..d7d58e8e 100644 --- a/kernel/virtio/virtio_pci.c +++ b/kernel/virtio/virtio_pci.c @@ -240,7 +240,7 @@ bool virtio_send2(virtio_device *dev, uint64_t desc, uint64_t avail, uint64_t us return true; } -bool virtio_send3(virtio_device *dev, uint64_t cmd, uint32_t cmd_len) { +bool virtio_send_1d(virtio_device *dev, uint64_t cmd, uint32_t cmd_len) { struct virtq_desc* d = (struct virtq_desc*)(uintptr_t)dev->common_cfg->queue_desc; struct virtq_avail* a = (struct virtq_avail*)(uintptr_t)dev->common_cfg->queue_driver; From 9d463478520dc46ddf25b7ba2ee1419ec1e98eaf Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 17 Jun 2025 00:00:00 +0000 Subject: [PATCH 08/61] Setup buffers for receiving --- kernel/networking/virtio_net_pci.c | 16 +++++++++------- kernel/virtio/virtio_pci.c | 17 +++++++++++++++++ kernel/virtio/virtio_pci.h | 3 ++- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/kernel/networking/virtio_net_pci.c b/kernel/networking/virtio_net_pci.c index c9fafcff..dbaace42 100644 --- a/kernel/networking/virtio_net_pci.c +++ b/kernel/networking/virtio_net_pci.c @@ -16,6 +16,7 @@ static virtio_device vnp_net_dev; #define VIRTIO_NET_HDR_GSO_NONE 0 #define UDP_PACKET_SIZE sizeof(virtio_net_hdr_t) + sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) +#define MAX_PACKET_SIZE 0x1000 typedef struct __attribute__((packed)) virtio_net_hdr_t { uint8_t flags; @@ -160,24 +161,25 @@ bool vnp_find_network(){ size_t payload_size = 6; char hw[6] = {'h','e','l','l','o', '\0'}; + + select_queue(&vnp_net_dev, RECEIVE_QUEUE); + + for (uint16_t i = 0; i < 128; i++){ + void* buf = allocate_in_page(vnp_net_dev.memory_page, MAX_PACKET_SIZE, ALIGN_64B, true, true); + virtio_add_buffer(&vnp_net_dev, i, (uintptr_t)buf, MAX_PACKET_SIZE); + } void* test_packet = allocate_in_page(vnp_net_dev.memory_page, UDP_PACKET_SIZE + payload_size, ALIGN_64B, true, true); create_udp_packet(test_packet,net_config->mac,dest,(192 << 24) | (168 << 16) | (1 << 8) | 131,(255 << 24) | (255 << 16) | (255 << 8) | 255,8888,8080,hw, payload_size); kprintf("Packet created"); - select_queue(&vnp_net_dev, 1); + select_queue(&vnp_net_dev, TRANSMIT_QUEUE); size_t size = UDP_PACKET_SIZE + payload_size; kprintf("Upload queue selected for packet %x (size %i)",(uintptr_t)test_packet, size); - // uint8_t *packet_bytes = (uint8_t*)test_packet; - - // for (size_t s = 0; s < size; s++){ - // kprintf("[%i] = %x",s,packet_bytes[s]); - // } - virtio_send_1d(&vnp_net_dev, (uintptr_t)test_packet, size); kprintf("Packet sent"); diff --git a/kernel/virtio/virtio_pci.c b/kernel/virtio/virtio_pci.c index d7d58e8e..1b371273 100644 --- a/kernel/virtio/virtio_pci.c +++ b/kernel/virtio/virtio_pci.c @@ -261,4 +261,21 @@ bool virtio_send_1d(virtio_device *dev, uint64_t cmd, uint32_t cmd_len) { while (last_used_idx == u->idx); return true; +} + +void virtio_add_buffer(virtio_device *dev, uint16_t index, uint64_t buf, uint32_t buf_len) { + + struct virtq_desc* d = (struct virtq_desc*)(uintptr_t)dev->common_cfg->queue_desc; + struct virtq_avail* a = (struct virtq_avail*)(uintptr_t)dev->common_cfg->queue_driver; + struct virtq_used* u = (struct virtq_used*)(uintptr_t)dev->common_cfg->queue_device; + + d[index].addr = buf; + d[index].len = buf_len; + d[index].flags = VIRTQ_DESC_F_WRITE; + d[index].next = 0; + + a->ring[a->idx % 128] = index; + a->idx++; + + *(volatile uint16_t*)(uintptr_t)(dev->notify_cfg + dev->notify_off_multiplier * dev->common_cfg->queue_select) = 0; } \ No newline at end of file diff --git a/kernel/virtio/virtio_pci.h b/kernel/virtio/virtio_pci.h index abc8c184..b8b33ce9 100644 --- a/kernel/virtio/virtio_pci.h +++ b/kernel/virtio/virtio_pci.h @@ -45,7 +45,8 @@ void virtio_get_capabilities(virtio_device *dev, uint64_t pci_addr, uint64_t *mm bool virtio_init_device(virtio_device *dev); bool virtio_send(virtio_device *dev, uint64_t desc, uint64_t avail, uint64_t used, uint64_t cmd, uint32_t cmd_len, uint64_t resp, uint32_t resp_len, uint8_t flags); bool virtio_send2(virtio_device *dev, uint64_t desc, uint64_t avail, uint64_t used, uint64_t cmd, uint32_t cmd_len, uint64_t resp, uint32_t resp_len, uint8_t flags); -bool virtio_send3(virtio_device *dev, uint64_t cmd, uint32_t cmd_len); +bool virtio_send_1d(virtio_device *dev, uint64_t cmd, uint32_t cmd_len); +void virtio_add_buffer(virtio_device *dev, uint16_t index, uint64_t buf, uint32_t buf_len); uint32_t select_queue(virtio_device *dev, uint32_t index); #ifdef __cplusplus From b97fa79416337deae918c8ce765f94205fb59761 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 17 Jun 2025 00:00:00 +0000 Subject: [PATCH 09/61] Fixed checksums --- kernel/networking/virtio_net_pci.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/kernel/networking/virtio_net_pci.c b/kernel/networking/virtio_net_pci.c index dbaace42..5b506c76 100644 --- a/kernel/networking/virtio_net_pci.c +++ b/kernel/networking/virtio_net_pci.c @@ -40,8 +40,8 @@ uint16_t udp_checksum( sum += src_ip & 0xFFFF; sum += (dst_ip >> 16) & 0xFFFF; sum += dst_ip & 0xFFFF; - sum += __builtin_bswap16(protocol); - sum += __builtin_bswap16(length); + sum += protocol; + sum += length; for (uint16_t i = 0; i + 1 < length; i += 2) sum += (udp_header_and_payload[i] << 8) | udp_header_and_payload[i + 1]; @@ -92,7 +92,7 @@ void create_udp_packet( ip->identification = 0; ip->flags_frag_offset = __builtin_bswap16(0x4000); ip->ttl = 64; - ip->protocol = 17; + ip->protocol = 0x11; ip->header_checksum = 0; ip->src_ip = __builtin_bswap32(src_ip); ip->dst_ip = __builtin_bswap32(dst_ip); @@ -100,18 +100,20 @@ void create_udp_packet( uint32_t sum = 0; for (int i = 0; i < 10; i++) sum += ip_words[i]; while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16); - ip->header_checksum = __builtin_bswap16(~sum); + ip->header_checksum = ~sum; p += sizeof(ipv4_hdr_t); udp_hdr_t* udp = (udp_hdr_t*)p; udp->src_port = __builtin_bswap16(src_port); udp->dst_port = __builtin_bswap16(dst_port); udp->length = __builtin_bswap16(sizeof(udp_hdr_t) + payload_len); - udp->checksum = udp_checksum(ip->src_ip,ip->dst_ip,17,(uint8_t*)udp,sizeof(udp_hdr_t) + payload_len); + p += sizeof(udp_hdr_t); uint8_t* data = (uint8_t*)p; for (int i = 0; i < payload_len; i++) data[i] = payload[i]; + + udp->checksum = __builtin_bswap16(udp_checksum(src_ip,dst_ip,ip->protocol,(uint8_t*)udp,sizeof(udp_hdr_t) + payload_len)); } From bc2c6ce6e4694de6f776ec09695f361801dc0f96 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 18 Jun 2025 00:00:00 +0000 Subject: [PATCH 10/61] Moved MAC/IP constants to own gitignored file --- .gitignore | 1 + kernel/networking/virtio_net_pci.c | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index b40b9743..d91839be 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ libshared.a *.a dump.dtb +net_constants.h diff --git a/kernel/networking/virtio_net_pci.c b/kernel/networking/virtio_net_pci.c index 5b506c76..fce4d8d9 100644 --- a/kernel/networking/virtio_net_pci.c +++ b/kernel/networking/virtio_net_pci.c @@ -7,6 +7,13 @@ #include "virtio/virtio_pci.h" #include "std/memfunctions.h" #include "packets.h" +/* +net_constants.h is gitignored and needs to be created. It should contain a {0xXX,0xXX,0xXX,0xXX,0xXX,0xXX}' uint8_t[6] called HOST_MAC and '(192 << 24) | (168 << 16) | (1 << 8) | x' uint64_t called HOST_IP. +These are used to test networking capabilities, if you want to test networking on the system, you should also set up a server on the receiving computer. It should be fine if packets sent from here are ignored on the receiving side. +Eventually, this networking functionality can be used to transfer data between the host computer (or another server) and REDACTED OS. +A separate project for the server code will be provided once that's necessary, but for now it just listens for UDP on port 8080 and optionally sends UDP packets as a response +*/ +#include "net_constants.h" static virtio_device vnp_net_dev; @@ -157,12 +164,12 @@ bool vnp_find_network(){ kprintf("%x speed", net_config->speed); kprintf("status = %x", net_config->status); - uint8_t dest[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + uint8_t dest[6] = HOST_MAC; kprintf("%x:%x:%x:%x:%x:%x", dest[0], dest[1], dest[2], dest[3], dest[4], dest[5]); - size_t payload_size = 6; - char hw[6] = {'h','e','l','l','o', '\0'}; + size_t payload_size = 5; + char hw[5] = {'h','e','l','l','o'}; select_queue(&vnp_net_dev, RECEIVE_QUEUE); @@ -172,7 +179,7 @@ bool vnp_find_network(){ } void* test_packet = allocate_in_page(vnp_net_dev.memory_page, UDP_PACKET_SIZE + payload_size, ALIGN_64B, true, true); - create_udp_packet(test_packet,net_config->mac,dest,(192 << 24) | (168 << 16) | (1 << 8) | 131,(255 << 24) | (255 << 16) | (255 << 8) | 255,8888,8080,hw, payload_size); + create_udp_packet(test_packet,net_config->mac,dest,(192 << 24) | (168 << 16) | (1 << 8) | 131,HOST_IP,8888,8080,hw, payload_size); kprintf("Packet created"); From 19e9460996974784f879e13724e7d18a5e452c2a Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 18 Jun 2025 00:00:00 +0000 Subject: [PATCH 11/61] Enabling interrupts for network --- kernel/exceptions/irq.c | 6 ++++ kernel/input/xhci.c | 30 ++++------------ kernel/kernel.c | 7 ++-- kernel/memory/kalloc.c | 3 ++ kernel/memory/kalloc.h | 4 ++- kernel/networking/virtio_net_pci.c | 58 +++++++++++++++++++++--------- kernel/networking/virtio_net_pci.h | 5 ++- kernel/pci.c | 41 +++++++++++++++++---- kernel/pci.h | 2 ++ 9 files changed, 105 insertions(+), 51 deletions(-) diff --git a/kernel/exceptions/irq.c b/kernel/exceptions/irq.c index e15c54b1..5996a5cc 100644 --- a/kernel/exceptions/irq.c +++ b/kernel/exceptions/irq.c @@ -6,6 +6,7 @@ #include "pci.h" #include "input/xhci.h" #include "console/serial/uart.h" +#include "networking/virtio_net_pci.h" #define IRQ_TIMER 30 #define SLEEP_TIMER 27 @@ -36,6 +37,7 @@ void irq_init() { gic_enable_irq(IRQ_TIMER, 0x80, 0); gic_enable_irq(MSI_OFFSET + XHCI_IRQ, 0x80, 0); + gic_enable_irq(MSI_OFFSET + NET_IRQ, 0x80, 0); gic_enable_irq(SLEEP_TIMER, 0x80, 0); write32(GICC_BASE + 0x004, 0xF0); //Priority @@ -75,6 +77,10 @@ void irq_el1_handler() { wake_processes(); write32(GICC_BASE + 0x10, irq); process_restore(); + } else if (irq == MSI_OFFSET + NET_IRQ){ + vnp_handle_interrupt(); + write32(GICC_BASE + 0x10, irq); + process_restore(); } else { kprintf_raw("[GIC error] Received unknown interrupt"); write32(GICC_BASE + 0x10, irq); diff --git a/kernel/input/xhci.c b/kernel/input/xhci.c index e98bfa4f..898be4fb 100644 --- a/kernel/input/xhci.c +++ b/kernel/input/xhci.c @@ -93,24 +93,6 @@ void make_ring_link(trb* ring, bool cycle){ make_ring_link_control(ring, cycle); } - -uint8_t xhci_init_interrupts(uint64_t pci_addr){ -#define MSIX_IRQ_LENGTH 1 - msix_irq_line irq_lines[MSIX_IRQ_LENGTH] = {(msix_irq_line){.addr_offset=0,.irq_num=XHCI_IRQ}}; - bool msix_ok = pci_setup_msix(pci_addr, irq_lines, MSIX_IRQ_LENGTH); - - if(msix_ok){ - return 1; - } - - bool msi_ok = pci_setup_msi(pci_addr, XHCI_IRQ); - if(msi_ok){ - return 2; - } - - return 0; -} - bool xhci_init(xhci_device *xhci, uint64_t pci_addr) { kprintfv("[xHCI] init"); if (!(read16(pci_addr + 0x06) & (1 << 4))){ @@ -118,6 +100,8 @@ bool xhci_init(xhci_device *xhci, uint64_t pci_addr) { return false; } + pci_enable_device(pci_addr); + if (!pci_setup_bar(pci_addr, 0, &xhci->mmio, &xhci->mmio_size)){ kprintfv("[xHCI] BARs not set up"); return false; @@ -125,20 +109,20 @@ bool xhci_init(xhci_device *xhci, uint64_t pci_addr) { pci_register(xhci->mmio, xhci->mmio_size); - uint8_t interrupts_ok = xhci_init_interrupts(pci_addr); + uint8_t interrupts_ok = pci_setup_interrupts(pci_addr, XHCI_IRQ); switch(interrupts_ok){ case 0: - kprintf_raw("[xHCI] Failed to setup interrupts\n"); + kprintf_raw("[xHCI] Failed to setup interrupts"); return false; case 1: - kprintf_raw("[xHCI] Interrupts setup with MSI-X"); + kprintf_raw("[xHCI] Interrupts setup with MSI-X %i",XHCI_IRQ); break; default: - kprintf_raw("[xHCI] Interrupts setup with MSI"); + kprintf_raw("[xHCI] Interrupts setup with MSI %i",XHCI_IRQ); break; } - pci_enable_device(pci_addr); + kprintfv("[xHCI] BARs set up @ %x (%x)",xhci->mmio,xhci->mmio_size); diff --git a/kernel/kernel.c b/kernel/kernel.c index 1bf58015..0549098e 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -52,13 +52,14 @@ void kernel_main() { if (!find_disk()) panic("Disk initialization failure"); - if (!vnp_find_network()) - panic("Network initialization failure"); - // xhci_enable_verbose(); if (!xhci_input_init()){ panic("Input initialization failure"); } + + if (!vnp_find_network()) + panic("Network initialization failure"); + mmu_init(); kprintf("MMU Mapped"); diff --git a/kernel/memory/kalloc.c b/kernel/memory/kalloc.c index 164ea766..089f7ee0 100644 --- a/kernel/memory/kalloc.c +++ b/kernel/memory/kalloc.c @@ -32,6 +32,9 @@ uint64_t alloc_mmio_region(uint64_t size) { return addr; } +bool is_mmio_allocated(uint64_t addr){ + return addr > PCI_MMIO_BASE && addr < next_mmio_base; +} extern uint64_t kernel_start; extern uint64_t heap_bottom; diff --git a/kernel/memory/kalloc.h b/kernel/memory/kalloc.h index d4a4828b..e946d3e4 100644 --- a/kernel/memory/kalloc.h +++ b/kernel/memory/kalloc.h @@ -22,4 +22,6 @@ uint64_t get_user_ram_end(); uint64_t get_shared_start(); uint64_t get_shared_end(); -uint64_t alloc_mmio_region(uint64_t size); \ No newline at end of file +uint64_t alloc_mmio_region(uint64_t size); + +bool is_mmio_allocated(uint64_t addr); \ No newline at end of file diff --git a/kernel/networking/virtio_net_pci.c b/kernel/networking/virtio_net_pci.c index fce4d8d9..eb6bc3a5 100644 --- a/kernel/networking/virtio_net_pci.c +++ b/kernel/networking/virtio_net_pci.c @@ -7,6 +7,7 @@ #include "virtio/virtio_pci.h" #include "std/memfunctions.h" #include "packets.h" +#include "exceptions/irq.h" /* net_constants.h is gitignored and needs to be created. It should contain a {0xXX,0xXX,0xXX,0xXX,0xXX,0xXX}' uint8_t[6] called HOST_MAC and '(192 << 24) | (168 << 16) | (1 << 8) | x' uint64_t called HOST_IP. These are used to test networking capabilities, if you want to test networking on the system, you should also set up a server on the receiving computer. It should be fine if packets sent from here are ignored on the receiving side. @@ -137,36 +138,49 @@ typedef struct virtio_net_config { }__attribute__((packed)) virtio_net_config; bool vnp_find_network(){ - virtio_enable_verbose(); uint64_t addr = find_pci_device(0x1AF4, 0x1000); if (!addr){ - kprintf("Virtio network device not found"); + kprintf("[VIRTIO_NET] Virtio network device not found"); return false; } - pci_enable_device(addr); - uint64_t net_device_address, net_device_size; - - kprintf("Configuring network device"); - + + kprintf("[VIRTIO_NET] Configuring network device"); + virtio_get_capabilities(&vnp_net_dev, addr, &net_device_address, &net_device_size); pci_register(net_device_address, net_device_size); + + uint8_t interrupts_ok = pci_setup_interrupts(addr, NET_IRQ); + switch(interrupts_ok){ + case 0: + kprintf_raw("[VIRTIO_NET] Failed to setup interrupts"); + return false; + case 1: + kprintf_raw("[VIRTIO_NET] Interrupts setup with MSI-X %i",NET_IRQ); + break; + default: + kprintf_raw("[VIRTIO_NET] Interrupts setup with MSI %i",NET_IRQ); + break; + } + + pci_enable_device(addr); + if (!virtio_init_device(&vnp_net_dev)) { - kprintf("Failed network initialization"); + kprintf("[VIRTIO_NET] Failed network initialization"); return false; } virtio_net_config* net_config = (virtio_net_config*)vnp_net_dev.device_cfg; - kprintf("%x:%x:%x:%x:%x:%x", net_config->mac[0], net_config->mac[1], net_config->mac[2], net_config->mac[3], net_config->mac[4], net_config->mac[5]); + kprintf("[VIRTIO_NET] %x:%x:%x:%x:%x:%x", net_config->mac[0], net_config->mac[1], net_config->mac[2], net_config->mac[3], net_config->mac[4], net_config->mac[5]); - kprintf("%i virtqueue pairs",net_config->max_virtqueue_pairs); - kprintf("%x speed", net_config->speed); - kprintf("status = %x", net_config->status); + kprintf("[VIRTIO_NET] %i virtqueue pairs",net_config->max_virtqueue_pairs); + kprintf("[VIRTIO_NET] %x speed", net_config->speed); + kprintf("[VIRTIO_NET] status = %x", net_config->status); uint8_t dest[6] = HOST_MAC; - kprintf("%x:%x:%x:%x:%x:%x", dest[0], dest[1], dest[2], dest[3], dest[4], dest[5]); + kprintf("[VIRTIO_NET] %x:%x:%x:%x:%x:%x", dest[0], dest[1], dest[2], dest[3], dest[4], dest[5]); size_t payload_size = 5; char hw[5] = {'h','e','l','l','o'}; @@ -177,21 +191,33 @@ bool vnp_find_network(){ void* buf = allocate_in_page(vnp_net_dev.memory_page, MAX_PACKET_SIZE, ALIGN_64B, true, true); virtio_add_buffer(&vnp_net_dev, i, (uintptr_t)buf, MAX_PACKET_SIZE); } + + kprintf("[VIRTIO_NET] Current MSI-X queue index %i",vnp_net_dev.common_cfg->queue_msix_vector); + vnp_net_dev.common_cfg->queue_msix_vector = 0; + if (vnp_net_dev.common_cfg->queue_msix_vector != 0){ + kprintf("[VIRTIO_NET error] failed to set interrupts on receive queue, network will be unable to receive packets"); + return false; + } void* test_packet = allocate_in_page(vnp_net_dev.memory_page, UDP_PACKET_SIZE + payload_size, ALIGN_64B, true, true); create_udp_packet(test_packet,net_config->mac,dest,(192 << 24) | (168 << 16) | (1 << 8) | 131,HOST_IP,8888,8080,hw, payload_size); - kprintf("Packet created"); + kprintf("[VIRTIO_NET] Packet created"); select_queue(&vnp_net_dev, TRANSMIT_QUEUE); + kprintf("[VIRTIO_NET] New MSI-X queue index %i",vnp_net_dev.common_cfg->msix_config); size_t size = UDP_PACKET_SIZE + payload_size; - kprintf("Upload queue selected for packet %x (size %i)",(uintptr_t)test_packet, size); + kprintf("[VIRTIO_NET] Upload queue selected for packet %x (size %i)",(uintptr_t)test_packet, size); virtio_send_1d(&vnp_net_dev, (uintptr_t)test_packet, size); - kprintf("Packet sent"); + kprintf("[VIRTIO_NET] Packet sent"); return true; +} + +void vnp_handle_interrupt(){ + kprintf("Received network interrupt"); } \ No newline at end of file diff --git a/kernel/networking/virtio_net_pci.h b/kernel/networking/virtio_net_pci.h index 7b141501..0ef85413 100644 --- a/kernel/networking/virtio_net_pci.h +++ b/kernel/networking/virtio_net_pci.h @@ -2,4 +2,7 @@ #include "types.h" -bool vnp_find_network(); \ No newline at end of file +#define NET_IRQ 32 + +bool vnp_find_network(); +void vnp_handle_interrupt(); \ No newline at end of file diff --git a/kernel/pci.c b/kernel/pci.c index 7fede964..55fe056d 100644 --- a/kernel/pci.c +++ b/kernel/pci.c @@ -1,5 +1,6 @@ #include "pci.h" #include "console/kio.h" +#include "exceptions/exception_handler.h" #include "memory/kalloc.h" #include "memory/dma.h" #include "fw/fw_cfg.h" @@ -185,13 +186,22 @@ uint64_t pci_setup_bar(uint64_t pci_addr, uint32_t bar_index, uint64_t *mmio_sta uint32_t new_lo = read32(bar_addr); kprintfv("[PCI] Two registers %x > %x",new_hi,new_lo); + uint64_t full = (new_hi << 32) | (new_lo & ~0xF); + if (full != config_base){ + if (is_mmio_allocated(full)) + panic_with_info("Device hardcoded address is already in use", full); + else + *mmio_start = full; + } } else { - bar_low &= ~0xF; - size = ~((uint64_t)bar_low) + 1; + uint32_t size32 = bar_low & ~0xF; + size32 = ~size32 + 1; - uint64_t config_base = alloc_mmio_region(size); + kprintfv("[PCI] Calculated bar size %x",size32); + + uint64_t config_base = alloc_mmio_region(size32); *mmio_start = config_base; - *mmio_size = size; + *mmio_size = size32; write32(bar_addr, config_base & 0xFFFFFFFF); } @@ -299,9 +309,10 @@ bool pci_setup_msix(uint64_t pci_addr, msix_irq_line* irq_lines, uint8_t line_si uint64_t table_addr = pci_read_address_bar(pci_addr, bir); if(!table_addr){ - kprintf_raw("[PCI] MSI-X setup error: Table address is null. Did you setup the bar memory before calling this function?"); - return false; - } + uint64_t bar_size; + pci_setup_bar(pci_addr, bir, &table_addr, &bar_size); + kprintfv("Setting up new bar for MSI-X %x + %x",table_addr, table_addr_offset); + } else kprintfv("Bar %i setup at %x + %x",bir, table_addr, table_addr_offset); msix_table_entry *msix_start = (msix_table_entry *)(uintptr_t)(table_addr + table_addr_offset); @@ -328,3 +339,19 @@ bool pci_setup_msix(uint64_t pci_addr, msix_irq_line* irq_lines, uint8_t line_si return true; } + +uint8_t pci_setup_interrupts(uint64_t pci_addr, uint8_t irq_line){ + msix_irq_line irq_lines[1] = {(msix_irq_line){.addr_offset=0,.irq_num=irq_line}}; + bool msix_ok = pci_setup_msix(pci_addr, irq_lines, 1); + + if(msix_ok){ + return 1; + } + + bool msi_ok = pci_setup_msi(pci_addr, irq_line); + if(msi_ok){ + return 2; + } + + return 0; +} \ No newline at end of file diff --git a/kernel/pci.h b/kernel/pci.h index 2c8faf17..9e2e7e96 100644 --- a/kernel/pci.h +++ b/kernel/pci.h @@ -24,6 +24,8 @@ void pci_enable_verbose(); bool pci_setup_msi(uint64_t pci_addr, uint8_t irq_vector); +uint8_t pci_setup_interrupts(uint64_t pci_addr, uint8_t irq_line); + typedef struct { uint32_t addr_offset; uint8_t irq_num; From 70b4afb5a313a1c9c180171871348ef0e2010fa3 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 18 Jun 2025 00:00:00 +0000 Subject: [PATCH 12/61] network verbosity --- kernel/networking/virtio_net_pci.c | 44 ++++++++++++++++++++---------- kernel/networking/virtio_net_pci.h | 3 +- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/kernel/networking/virtio_net_pci.c b/kernel/networking/virtio_net_pci.c index eb6bc3a5..a9a5df73 100644 --- a/kernel/networking/virtio_net_pci.c +++ b/kernel/networking/virtio_net_pci.c @@ -16,6 +16,20 @@ A separate project for the server code will be provided once that's necessary, b */ #include "net_constants.h" +static bool vnp_verbose = false; + +void vnp_enable_verbose(){ + vnp_verbose = true; +} + +#define kprintfv(fmt, ...) \ + ({ \ + if (vnp_verbose){\ + uint64_t _args[] = { __VA_ARGS__ }; \ + kprintf_args((fmt), _args, sizeof(_args) / sizeof(_args[0])); \ + }\ + }) + static virtio_device vnp_net_dev; #define RECEIVE_QUEUE 0 @@ -140,13 +154,13 @@ typedef struct virtio_net_config { bool vnp_find_network(){ uint64_t addr = find_pci_device(0x1AF4, 0x1000); if (!addr){ - kprintf("[VIRTIO_NET] Virtio network device not found"); + kprintf("[VIRTIO_NET error] Virtio network device not found"); return false; } uint64_t net_device_address, net_device_size; - kprintf("[VIRTIO_NET] Configuring network device"); + kprintfv("[VIRTIO_NET] Configuring network device"); virtio_get_capabilities(&vnp_net_dev, addr, &net_device_address, &net_device_size); pci_register(net_device_address, net_device_size); @@ -167,16 +181,16 @@ bool vnp_find_network(){ pci_enable_device(addr); if (!virtio_init_device(&vnp_net_dev)) { - kprintf("[VIRTIO_NET] Failed network initialization"); + kprintf("[VIRTIO_NET error] Failed network initialization"); return false; } virtio_net_config* net_config = (virtio_net_config*)vnp_net_dev.device_cfg; - kprintf("[VIRTIO_NET] %x:%x:%x:%x:%x:%x", net_config->mac[0], net_config->mac[1], net_config->mac[2], net_config->mac[3], net_config->mac[4], net_config->mac[5]); + kprintfv("[VIRTIO_NET] %x:%x:%x:%x:%x:%x", net_config->mac[0], net_config->mac[1], net_config->mac[2], net_config->mac[3], net_config->mac[4], net_config->mac[5]); - kprintf("[VIRTIO_NET] %i virtqueue pairs",net_config->max_virtqueue_pairs); - kprintf("[VIRTIO_NET] %x speed", net_config->speed); - kprintf("[VIRTIO_NET] status = %x", net_config->status); + kprintfv("[VIRTIO_NET] %i virtqueue pairs",net_config->max_virtqueue_pairs); + kprintfv("[VIRTIO_NET] %x speed", net_config->speed); + kprintfv("[VIRTIO_NET] status = %x", net_config->status); uint8_t dest[6] = HOST_MAC; @@ -192,32 +206,32 @@ bool vnp_find_network(){ virtio_add_buffer(&vnp_net_dev, i, (uintptr_t)buf, MAX_PACKET_SIZE); } - kprintf("[VIRTIO_NET] Current MSI-X queue index %i",vnp_net_dev.common_cfg->queue_msix_vector); + kprintfv("[VIRTIO_NET] Current MSI-X queue index %i",vnp_net_dev.common_cfg->queue_msix_vector); vnp_net_dev.common_cfg->queue_msix_vector = 0; if (vnp_net_dev.common_cfg->queue_msix_vector != 0){ - kprintf("[VIRTIO_NET error] failed to set interrupts on receive queue, network will be unable to receive packets"); + kprintfv("[VIRTIO_NET error] failed to set interrupts on receive queue, network will be unable to receive packets"); return false; } void* test_packet = allocate_in_page(vnp_net_dev.memory_page, UDP_PACKET_SIZE + payload_size, ALIGN_64B, true, true); create_udp_packet(test_packet,net_config->mac,dest,(192 << 24) | (168 << 16) | (1 << 8) | 131,HOST_IP,8888,8080,hw, payload_size); - kprintf("[VIRTIO_NET] Packet created"); + kprintfv("[VIRTIO_NET] Packet created"); select_queue(&vnp_net_dev, TRANSMIT_QUEUE); - kprintf("[VIRTIO_NET] New MSI-X queue index %i",vnp_net_dev.common_cfg->msix_config); + kprintfv("[VIRTIO_NET] New MSI-X queue index %x",vnp_net_dev.common_cfg->msix_config); size_t size = UDP_PACKET_SIZE + payload_size; - kprintf("[VIRTIO_NET] Upload queue selected for packet %x (size %i)",(uintptr_t)test_packet, size); + kprintfv("[VIRTIO_NET] Upload queue selected for packet %x (size %i)",(uintptr_t)test_packet, size); - virtio_send_1d(&vnp_net_dev, (uintptr_t)test_packet, size); + // virtio_send_1d(&vnp_net_dev, (uintptr_t)test_packet, size); - kprintf("[VIRTIO_NET] Packet sent"); + kprintfv("[VIRTIO_NET] Packet sent"); return true; } void vnp_handle_interrupt(){ - kprintf("Received network interrupt"); + kprintf(">>>>>>>>Received network interrupt"); } \ No newline at end of file diff --git a/kernel/networking/virtio_net_pci.h b/kernel/networking/virtio_net_pci.h index 0ef85413..aacf8f6c 100644 --- a/kernel/networking/virtio_net_pci.h +++ b/kernel/networking/virtio_net_pci.h @@ -5,4 +5,5 @@ #define NET_IRQ 32 bool vnp_find_network(); -void vnp_handle_interrupt(); \ No newline at end of file +void vnp_handle_interrupt(); +void vnp_enable_verbose(); \ No newline at end of file From 7a5dae1691d0083eefb8e8f1cbd5afad5444c42b Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 18 Jun 2025 00:00:00 +0000 Subject: [PATCH 13/61] Receive and parse UDP packets --- kernel/networking/virtio_net_pci.c | 56 ++++++++++++++++++++++++++++-- kernel/virtio/virtio_pci.c | 26 -------------- kernel/virtio/virtio_pci.h | 24 +++++++++++++ 3 files changed, 78 insertions(+), 28 deletions(-) diff --git a/kernel/networking/virtio_net_pci.c b/kernel/networking/virtio_net_pci.c index a9a5df73..ec98b9a8 100644 --- a/kernel/networking/virtio_net_pci.c +++ b/kernel/networking/virtio_net_pci.c @@ -225,13 +225,65 @@ bool vnp_find_network(){ kprintfv("[VIRTIO_NET] Upload queue selected for packet %x (size %i)",(uintptr_t)test_packet, size); - // virtio_send_1d(&vnp_net_dev, (uintptr_t)test_packet, size); + virtio_send_1d(&vnp_net_dev, (uintptr_t)test_packet, size); kprintfv("[VIRTIO_NET] Packet sent"); return true; } +static uint16_t last_used_receive_idx = 0; + +void vnp_parse_packet(uintptr_t packet_ptr){ + packet_ptr += sizeof(virtio_net_hdr_t); + + eth_hdr_t* eth = (eth_hdr_t*)packet_ptr; + uint8_t filter[6] = HOST_MAC; + if (filter[0] == eth->src_mac[0]) + kprintf(">>>>[VIRTIO_NET packet] SOURCE: %x:%x:%x:%x:%x:%x", eth->src_mac[0], eth->src_mac[1], eth->src_mac[2], eth->src_mac[3], eth->src_mac[4], eth->src_mac[5]); + + packet_ptr += sizeof(eth_hdr_t); + + if (__builtin_bswap16(eth->ethertype) == 0x800){ + ipv4_hdr_t* ip = (ipv4_hdr_t*)packet_ptr; + packet_ptr += sizeof(ipv4_hdr_t); + if (ip->protocol == 0x11){ + udp_hdr_t* udp = (udp_hdr_t*)packet_ptr; + packet_ptr += sizeof(udp_hdr_t); + uint8_t* data = (uint8_t*)packet_ptr; + uint16_t payload_len = __builtin_bswap16(udp->length) - sizeof(udp_hdr_t); + for (int i = 0; i < payload_len; i++) if (data[i] >= 0x20 && data[i] <= 0x7E) kprintf("%c",data[i]); + } else { + kprintf("[VIRTIO_NET packet] Not prepared to handle non-UDP packets %x",ip->protocol); + } + } + else { + kprintf("[VIRTIO_NET packet] Not prepared to handle non-ipv4 packets %x",__builtin_bswap16(eth->ethertype)); + } +} + void vnp_handle_interrupt(){ - kprintf(">>>>>>>>Received network interrupt"); + select_queue(&vnp_net_dev, RECEIVE_QUEUE); + struct virtq_used* used = (struct virtq_used*)(uintptr_t)vnp_net_dev.common_cfg->queue_device; + + uint16_t new_idx = used->idx; + if (new_idx != last_used_receive_idx) { + struct virtq_desc* desc = (struct virtq_desc*)(uintptr_t)vnp_net_dev.common_cfg->queue_desc; + struct virtq_avail* avail = (struct virtq_avail*)(uintptr_t)vnp_net_dev.common_cfg->queue_driver; + uint16_t used_ring_index = last_used_receive_idx % 128; + last_used_receive_idx = new_idx; + struct virtq_used_elem* e = &used->ring[used_ring_index]; + uint32_t desc_index = e->id; + uint32_t len = e->len; + kprintf("Received network packet %i at index %i (len %i)",used->idx, desc_index, len); + + uintptr_t packet = desc[desc_index].addr; + + vnp_parse_packet(packet); + + avail->ring[avail->idx % 128] = desc_index; + avail->idx++; + + *(volatile uint16_t*)(uintptr_t)(vnp_net_dev.notify_cfg + vnp_net_dev.notify_off_multiplier * RECEIVE_QUEUE) = 0; + } } \ No newline at end of file diff --git a/kernel/virtio/virtio_pci.c b/kernel/virtio/virtio_pci.c index 1b371273..b1254112 100644 --- a/kernel/virtio/virtio_pci.c +++ b/kernel/virtio/virtio_pci.c @@ -4,32 +4,6 @@ #include "memory/page_allocator.h" #include "virtio_pci.h" -//TODO: We're allocating way too much memory for each virtqueue element, we can reduce it down to the size of the structures, and use them more efficiently using rings instead of always writing the first command - -struct virtq_desc { - uint64_t addr; - uint32_t len; - uint16_t flags; - uint16_t next; -} __attribute__((packed)); - -struct virtq_avail { - uint16_t flags; - uint16_t idx; - uint16_t ring[]; -} __attribute__((packed)); - -struct virtq_used_elem { - uint32_t id; - uint32_t len; -} __attribute__((packed)); - -struct virtq_used { - uint16_t flags; - uint16_t idx; - struct virtq_used_elem ring[128]; -} __attribute__((packed)); - #define VIRTIO_STATUS_RESET 0x0 #define VIRTIO_STATUS_ACKNOWLEDGE 0x1 #define VIRTIO_STATUS_DRIVER 0x2 diff --git a/kernel/virtio/virtio_pci.h b/kernel/virtio/virtio_pci.h index b8b33ce9..d1518246 100644 --- a/kernel/virtio/virtio_pci.h +++ b/kernel/virtio/virtio_pci.h @@ -30,6 +30,30 @@ typedef struct virtio_pci_common_cfg { uint16_t queue_reset; }__attribute__((packed)) virtio_pci_common_cfg; +struct virtq_desc { + uint64_t addr; + uint32_t len; + uint16_t flags; + uint16_t next; +} __attribute__((packed)); + +struct virtq_avail { + uint16_t flags; + uint16_t idx; + uint16_t ring[]; +} __attribute__((packed)); + +struct virtq_used_elem { + uint32_t id; + uint32_t len; +} __attribute__((packed)); + +struct virtq_used { + uint16_t flags; + uint16_t idx; + struct virtq_used_elem ring[128]; +} __attribute__((packed)); + typedef struct virtio_device { struct virtio_pci_common_cfg* common_cfg; uint8_t* notify_cfg; From 4ca8095818569ca1be981a35ae2ee6286f508d70 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 18 Jun 2025 00:00:00 +0000 Subject: [PATCH 14/61] Created (currently unused) network dispatch --- kernel/networking/network_dispatch.cpp | 19 +++++++++++++++++++ kernel/networking/network_dispatch.hpp | 14 ++++++++++++++ shared/types.h | 1 + 3 files changed, 34 insertions(+) create mode 100644 kernel/networking/network_dispatch.cpp create mode 100644 kernel/networking/network_dispatch.hpp diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp new file mode 100644 index 00000000..4d3e67bf --- /dev/null +++ b/kernel/networking/network_dispatch.cpp @@ -0,0 +1,19 @@ +#include "network_dispatch.hpp" + +NetworkDispatch::NetworkDispatch(){ + ports = IndexMap(UINT16_MAX); + for (uint16_t i = 0; i < UINT16_MAX; i++) + ports[i] = UINT16_MAX; +} + +bool NetworkDispatch::bind_port(uint16_t port, uint16_t process){ + if (ports[port] != UINT16_MAX) return false; + ports[port] = process; + return true; +} + +bool NetworkDispatch::unbind_port(uint16_t port, uint16_t process){ + if (ports[port] != process) return false; + ports[port] = UINT16_MAX; + return true; +} \ No newline at end of file diff --git a/kernel/networking/network_dispatch.hpp b/kernel/networking/network_dispatch.hpp new file mode 100644 index 00000000..df53a5c5 --- /dev/null +++ b/kernel/networking/network_dispatch.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include "types.h" +#include "std/indexmap.hpp" + +class NetworkDispatch { +public: + NetworkDispatch(); + bool bind_port(uint16_t port, uint16_t process); + bool unbind_port(uint16_t port, uint16_t process); + +private: + IndexMap ports; +}; \ No newline at end of file diff --git a/shared/types.h b/shared/types.h index 5bbd4096..ad8c88c8 100644 --- a/shared/types.h +++ b/shared/types.h @@ -10,6 +10,7 @@ typedef unsigned short uint16_t; typedef unsigned char uint8_t; #define UINT64_MAX 0xFFFFFFFFFFFFFFFFULL +#define UINT16_MAX 0xFFFF typedef int int32_t; typedef long int64_t; From 764cf6e8e9d37b282d7cbb747f521e5288b18726 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 18 Jun 2025 00:00:00 +0000 Subject: [PATCH 15/61] Rewrite net driver in C++ --- kernel/exceptions/irq.c | 4 +- kernel/kernel.c | 5 +- kernel/networking/drivers/net_driver.hpp | 19 ++ .../drivers/virtio_net_pci/virtio_net_pci.cpp | 128 ++++++++ .../drivers/virtio_net_pci/virtio_net_pci.hpp | 24 ++ kernel/networking/network.cpp | 22 ++ kernel/networking/network.h | 18 ++ kernel/networking/network_dispatch.cpp | 14 + kernel/networking/network_dispatch.hpp | 4 + kernel/networking/packets.h | 16 +- kernel/networking/udp.c | 107 +++++++ kernel/networking/udp.h | 16 + kernel/networking/virtio_net_pci.c | 289 ------------------ kernel/networking/virtio_net_pci.h | 9 - 14 files changed, 371 insertions(+), 304 deletions(-) create mode 100644 kernel/networking/drivers/net_driver.hpp create mode 100644 kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp create mode 100644 kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp create mode 100644 kernel/networking/network.cpp create mode 100644 kernel/networking/network.h create mode 100644 kernel/networking/udp.c create mode 100644 kernel/networking/udp.h delete mode 100644 kernel/networking/virtio_net_pci.c delete mode 100644 kernel/networking/virtio_net_pci.h diff --git a/kernel/exceptions/irq.c b/kernel/exceptions/irq.c index 5996a5cc..196dbbee 100644 --- a/kernel/exceptions/irq.c +++ b/kernel/exceptions/irq.c @@ -6,7 +6,7 @@ #include "pci.h" #include "input/xhci.h" #include "console/serial/uart.h" -#include "networking/virtio_net_pci.h" +#include "networking/network.h" #define IRQ_TIMER 30 #define SLEEP_TIMER 27 @@ -78,7 +78,7 @@ void irq_el1_handler() { write32(GICC_BASE + 0x10, irq); process_restore(); } else if (irq == MSI_OFFSET + NET_IRQ){ - vnp_handle_interrupt(); + network_handle_interrupt(); write32(GICC_BASE + 0x10, irq); process_restore(); } else { diff --git a/kernel/kernel.c b/kernel/kernel.c index 0549098e..dfdb9ec3 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -15,8 +15,7 @@ #include "input/xhci.h" #include "kernel_processes/monitor/monitor_processes.h" #include "memory/page_allocator.h" - -#include "networking/virtio_net_pci.h" +#include "networking/network.h" void kernel_main() { @@ -57,7 +56,7 @@ void kernel_main() { panic("Input initialization failure"); } - if (!vnp_find_network()) + if (!network_init()) panic("Network initialization failure"); mmu_init(); diff --git a/kernel/networking/drivers/net_driver.hpp b/kernel/networking/drivers/net_driver.hpp new file mode 100644 index 00000000..8b84c938 --- /dev/null +++ b/kernel/networking/drivers/net_driver.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "types.h" +#include "std/string.h" +#include "ui/graphic_types.h" + +class NetDriver { +public: + NetDriver(){} + virtual bool init() = 0; + + virtual void handle_interrupt() = 0; + + virtual void send_packet(void* packet, size_t size) = 0; + + virtual void enable_verbose() = 0; + + virtual ~NetDriver() = default; +}; \ No newline at end of file diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp new file mode 100644 index 00000000..544b3dc2 --- /dev/null +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -0,0 +1,128 @@ +#include "virtio_net_pci.hpp" +#include "console/kio.h" +#include "networking/packets.h" +#include "networking/udp.h" +#include "networking/network.h" +#include "pci.h" + +#define RECEIVE_QUEUE 0 +#define TRANSMIT_QUEUE 1 +#define MAX_PACKET_SIZE 0x1000 + +#define kprintfv(fmt, ...) \ + ({ \ + if (verbose){\ + uint64_t _args[] = { __VA_ARGS__ }; \ + kprintf_args((fmt), _args, sizeof(_args) / sizeof(_args[0])); \ + }\ + }) + +typedef struct __attribute__((packed)) virtio_net_hdr_t { + uint8_t flags; + uint8_t gso_type; + uint16_t hdr_len; + uint16_t gso_size; + uint16_t csum_start; + uint16_t num_buffers; +} virtio_net_hdr_t; + +typedef struct virtio_net_config { + uint8_t mac[6]; + uint16_t status; + uint16_t max_virtqueue_pairs; + uint16_t mtu; + uint32_t speed; + uint8_t duplex; + uint8_t rss_max_key_size; + uint16_t rss_max_indirection_table_length; + uint32_t supported_hash_types; +}__attribute__((packed)) virtio_net_config; + +VirtioNetDriver* VirtioNetDriver::try_init(){ + VirtioNetDriver* driver = new VirtioNetDriver(); + if (driver->init()) + return driver; + delete driver; + return nullptr; +} + +bool VirtioNetDriver::init(){ + uint64_t addr = find_pci_device(0x1AF4, 0x1000); + if (!addr){ + kprintf("[VIRTIO_NET error] Virtio network device not found"); + return false; + } + + uint64_t net_device_address, net_device_size; + + kprintfv("[VIRTIO_NET] Configuring network device"); + + virtio_get_capabilities(&vnp_net_dev, addr, &net_device_address, &net_device_size); + pci_register(net_device_address, net_device_size); + + uint8_t interrupts_ok = pci_setup_interrupts(addr, NET_IRQ); + switch(interrupts_ok){ + case 0: + kprintf_raw("[VIRTIO_NET] Failed to setup interrupts"); + return false; + case 1: + kprintf_raw("[VIRTIO_NET] Interrupts setup with MSI-X %i",NET_IRQ); + break; + default: + kprintf_raw("[VIRTIO_NET] Interrupts setup with MSI %i",NET_IRQ); + break; + } + + pci_enable_device(addr); + + if (!virtio_init_device(&vnp_net_dev)) { + kprintf("[VIRTIO_NET error] Failed network initialization"); + return false; + } + + kprintf("[VIRTIO_NET] Device set up at %x",(uintptr_t)vnp_net_dev.device_cfg); + + virtio_net_config* net_config = (virtio_net_config*)vnp_net_dev.device_cfg; + kprintfv("[VIRTIO_NET] %x:%x:%x:%x:%x:%x", net_config->mac[0], net_config->mac[1], net_config->mac[2], net_config->mac[3], net_config->mac[4], net_config->mac[5]); + + kprintfv("[VIRTIO_NET] %i virtqueue pairs",net_config->max_virtqueue_pairs); + kprintfv("[VIRTIO_NET] %x speed", net_config->speed); + kprintfv("[VIRTIO_NET] status = %x", net_config->status); + + return true; +} + +void VirtioNetDriver::handle_interrupt(){ + select_queue(&vnp_net_dev, RECEIVE_QUEUE); + struct virtq_used* used = (struct virtq_used*)(uintptr_t)vnp_net_dev.common_cfg->queue_device; + + uint16_t new_idx = used->idx; + if (new_idx != last_used_receive_idx) { + struct virtq_desc* desc = (struct virtq_desc*)(uintptr_t)vnp_net_dev.common_cfg->queue_desc; + struct virtq_avail* avail = (struct virtq_avail*)(uintptr_t)vnp_net_dev.common_cfg->queue_driver; + uint16_t used_ring_index = last_used_receive_idx % 128; + last_used_receive_idx = new_idx; + struct virtq_used_elem* e = &used->ring[used_ring_index]; + uint32_t desc_index = e->id; + uint32_t len = e->len; + kprintf("Received network packet %i at index %i (len %i)",used->idx, desc_index, len); + + uintptr_t packet = desc[desc_index].addr; + + udp_parse_packet(packet); + + avail->ring[avail->idx % 128] = desc_index; + avail->idx++; + + *(volatile uint16_t*)(uintptr_t)(vnp_net_dev.notify_cfg + vnp_net_dev.notify_off_multiplier * RECEIVE_QUEUE) = 0; + } +} + +void VirtioNetDriver::send_packet(void* packet, size_t size){ + select_queue(&vnp_net_dev, TRANSMIT_QUEUE); + virtio_send_1d(&vnp_net_dev, (uintptr_t)packet, size); +} + +void VirtioNetDriver::enable_verbose(){ + verbose = true; +} \ No newline at end of file diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp new file mode 100644 index 00000000..50a54f9b --- /dev/null +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp @@ -0,0 +1,24 @@ +#include "../net_driver.hpp" +#include "virtio/virtio_pci.h" + +class VirtioNetDriver : public NetDriver { +public: + static VirtioNetDriver* try_init(); + + VirtioNetDriver(){} + + bool init() override; + + void handle_interrupt() override; + + void send_packet(void* packet, size_t size) override; + + void enable_verbose() override; + + ~VirtioNetDriver() = default; + +private: + bool verbose = false; + uint16_t last_used_receive_idx = 0; + virtio_device vnp_net_dev; +}; \ No newline at end of file diff --git a/kernel/networking/network.cpp b/kernel/networking/network.cpp new file mode 100644 index 00000000..0b932ae8 --- /dev/null +++ b/kernel/networking/network.cpp @@ -0,0 +1,22 @@ +#include "network.h" +#include "network_dispatch.hpp" +#include "std/allocator.hpp" + +NetworkDispatch *dispatch; + +bool network_init(){ + dispatch = new NetworkDispatch(); + return dispatch->init(); +} + +void network_handle_interrupt(){ + return dispatch->handle_interrupt(); +} + +bool network_bind_port(uint16_t port, uint16_t process){ + return dispatch->bind_port(port, process); +} + +bool network_unbindbind_port(uint16_t port, uint16_t process){ + return dispatch->unbind_port(port, process); +} diff --git a/kernel/networking/network.h b/kernel/networking/network.h new file mode 100644 index 00000000..9d388f70 --- /dev/null +++ b/kernel/networking/network.h @@ -0,0 +1,18 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "types.h" + +#define NET_IRQ 32 + +bool network_init(); +void network_handle_interrupt(); +bool network_bind_port(uint16_t port, uint16_t process); +bool network_unbindbind_port(uint16_t port, uint16_t process); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index 4d3e67bf..3e7df6f0 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -1,4 +1,5 @@ #include "network_dispatch.hpp" +#include "drivers/virtio_net_pci/virtio_net_pci.hpp" NetworkDispatch::NetworkDispatch(){ ports = IndexMap(UINT16_MAX); @@ -6,6 +7,14 @@ NetworkDispatch::NetworkDispatch(){ ports[i] = UINT16_MAX; } +bool NetworkDispatch::init(){ + if (VirtioNetDriver *vnd = VirtioNetDriver::try_init()){ + driver = vnd; + return true; + } + return false; +} + bool NetworkDispatch::bind_port(uint16_t port, uint16_t process){ if (ports[port] != UINT16_MAX) return false; ports[port] = process; @@ -16,4 +25,9 @@ bool NetworkDispatch::unbind_port(uint16_t port, uint16_t process){ if (ports[port] != process) return false; ports[port] = UINT16_MAX; return true; +} + +void NetworkDispatch::handle_interrupt(){ + if (driver) + driver->handle_interrupt(); } \ No newline at end of file diff --git a/kernel/networking/network_dispatch.hpp b/kernel/networking/network_dispatch.hpp index df53a5c5..b0cd3eef 100644 --- a/kernel/networking/network_dispatch.hpp +++ b/kernel/networking/network_dispatch.hpp @@ -2,13 +2,17 @@ #include "types.h" #include "std/indexmap.hpp" +#include "drivers/net_driver.hpp" class NetworkDispatch { public: NetworkDispatch(); + bool init(); bool bind_port(uint16_t port, uint16_t process); bool unbind_port(uint16_t port, uint16_t process); + void handle_interrupt(); private: IndexMap ports; + NetDriver *driver; }; \ No newline at end of file diff --git a/kernel/networking/packets.h b/kernel/networking/packets.h index 72ca00aa..4d9bc468 100644 --- a/kernel/networking/packets.h +++ b/kernel/networking/packets.h @@ -1,5 +1,9 @@ #pragma once +#ifdef __cplusplus +extern "C" { +#endif + #include "types.h" typedef struct __attribute__((packed)) eth_hdr_t { @@ -26,4 +30,14 @@ typedef struct __attribute__((packed)) udp_hdr_t { uint16_t dst_port; uint16_t length; uint16_t checksum; -} udp_hdr_t; \ No newline at end of file +} udp_hdr_t; + +typedef struct network_connection_ctx { + uint16_t port; + uint32_t ip; + uint8_t mac[6]; +} network_connection_ctx; + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/kernel/networking/udp.c b/kernel/networking/udp.c new file mode 100644 index 00000000..d7bcb85d --- /dev/null +++ b/kernel/networking/udp.c @@ -0,0 +1,107 @@ +#include "udp.h" +#include "console/kio.h" +#include "packets.h" +/* +net_constants.h is gitignored and needs to be created. It should contain a {0xXX,0xXX,0xXX,0xXX,0xXX,0xXX}' uint8_t[6] called HOST_MAC and '(192 << 24) | (168 << 16) | (1 << 8) | x' uint64_t called HOST_IP. +These are used to test networking capabilities, if you want to test networking on the system, you should also set up a server on the receiving computer. It should be fine if packets sent from here are ignored on the receiving side. +Eventually, this networking functionality can be used to transfer data between the host computer (or another server) and REDACTED OS. +A separate project for the server code will be provided once that's necessary, but for now it just listens for UDP on port 8080 and optionally sends UDP packets as a response +*/ +// #include "net_constants.h" + +uint16_t udp_checksum( + uint32_t src_ip, + uint32_t dst_ip, + uint8_t protocol, + const uint8_t* udp_header_and_payload, + uint16_t length +) { + uint32_t sum = 0; + + sum += (src_ip >> 16) & 0xFFFF; + sum += src_ip & 0xFFFF; + sum += (dst_ip >> 16) & 0xFFFF; + sum += dst_ip & 0xFFFF; + sum += protocol; + sum += length; + + for (uint16_t i = 0; i + 1 < length; i += 2) + sum += (udp_header_and_payload[i] << 8) | udp_header_and_payload[i + 1]; + + if (length & 1) + sum += udp_header_and_payload[length - 1] << 8; + + while (sum >> 16) + sum = (sum & 0xFFFF) + (sum >> 16); + + return ~sum; +} + +void create_udp_packet(uint8_t* buf, network_connection_ctx source, network_connection_ctx destination, const uint8_t* payload, uint16_t payload_len) { + uintptr_t p = (uintptr_t)buf; + + eth_hdr_t* eth = (eth_hdr_t*)p; + for (int i = 0; i < 6; i++) eth->dst_mac[i] = destination.mac[i]; + for (int i = 0; i < 6; i++) eth->src_mac[i] = source.mac[i]; + eth->ethertype = __builtin_bswap16(0x0800); + p += sizeof(eth_hdr_t); + + ipv4_hdr_t* ip = (ipv4_hdr_t*)p; + ip->version_ihl = 0x45; + ip->dscp_ecn = 0; + ip->total_length = __builtin_bswap16(sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) + payload_len); + ip->identification = 0; + ip->flags_frag_offset = __builtin_bswap16(0x4000); + ip->ttl = 64; + ip->protocol = 0x11; + ip->header_checksum = 0; + ip->src_ip = __builtin_bswap32(source.ip); + ip->dst_ip = __builtin_bswap32(destination.ip); + uint16_t* ip_words = (uint16_t*)ip; + uint32_t sum = 0; + for (int i = 0; i < 10; i++) sum += ip_words[i]; + while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16); + ip->header_checksum = ~sum; + p += sizeof(ipv4_hdr_t); + + udp_hdr_t* udp = (udp_hdr_t*)p; + udp->src_port = __builtin_bswap16(source.port); + udp->dst_port = __builtin_bswap16(destination.port); + udp->length = __builtin_bswap16(sizeof(udp_hdr_t) + payload_len); + + p += sizeof(udp_hdr_t); + + uint8_t* data = (uint8_t*)p; + for (int i = 0; i < payload_len; i++) data[i] = payload[i]; + + udp->checksum = __builtin_bswap16(udp_checksum(source.ip,destination.ip,ip->protocol,(uint8_t*)udp,sizeof(udp_hdr_t) + payload_len)); + +} + +void udp_parse_packet(uintptr_t packet_ptr){ + eth_hdr_t* eth = (eth_hdr_t*)packet_ptr; + kprintf(">>>>[UDP packet] SOURCE: %x:%x:%x:%x:%x:%x", eth->src_mac[0], eth->src_mac[1], eth->src_mac[2], eth->src_mac[3], eth->src_mac[4], eth->src_mac[5]); + + packet_ptr += sizeof(eth_hdr_t); + + if (__builtin_bswap16(eth->ethertype) == 0x800){ + ipv4_hdr_t* ip = (ipv4_hdr_t*)packet_ptr; + packet_ptr += sizeof(ipv4_hdr_t); + if (ip->protocol == 0x11){ + udp_hdr_t* udp = (udp_hdr_t*)packet_ptr; + packet_ptr += sizeof(udp_hdr_t); + uint8_t* data = (uint8_t*)packet_ptr; + uint16_t payload_len = __builtin_bswap16(udp->length) - sizeof(udp_hdr_t); + for (int i = 0; i < payload_len; i++) if (data[i] >= 0x20 && data[i] <= 0x7E) kprintf("%c",data[i]); + } else { + kprintf("[UDP packet] Not prepared to handle non-UDP packets %x",ip->protocol); + } + } + else { + kprintf("[UDP packet] Not prepared to handle non-ipv4 packets %x",__builtin_bswap16(eth->ethertype)); + } +} + +size_t calc_udp_packet_size(uint16_t payload_len){ + return sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) + payload_len; +} \ No newline at end of file diff --git a/kernel/networking/udp.h b/kernel/networking/udp.h new file mode 100644 index 00000000..9a7c6e5d --- /dev/null +++ b/kernel/networking/udp.h @@ -0,0 +1,16 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "types.h" +#include "packets.h" + +void create_udp_packet(uint8_t* buf, network_connection_ctx source, network_connection_ctx destination, const uint8_t* payload, uint16_t payload_len); +size_t calc_udp_packet_size(uint16_t payload_len); +void udp_parse_packet(uintptr_t packet_ptr); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/kernel/networking/virtio_net_pci.c b/kernel/networking/virtio_net_pci.c deleted file mode 100644 index ec98b9a8..00000000 --- a/kernel/networking/virtio_net_pci.c +++ /dev/null @@ -1,289 +0,0 @@ -#include "virtio_net_pci.h" -#include "std/string.h" -#include "memory/memory_access.h" -#include "memory/page_allocator.h" -#include "console/kio.h" -#include "pci.h" -#include "virtio/virtio_pci.h" -#include "std/memfunctions.h" -#include "packets.h" -#include "exceptions/irq.h" -/* -net_constants.h is gitignored and needs to be created. It should contain a {0xXX,0xXX,0xXX,0xXX,0xXX,0xXX}' uint8_t[6] called HOST_MAC and '(192 << 24) | (168 << 16) | (1 << 8) | x' uint64_t called HOST_IP. -These are used to test networking capabilities, if you want to test networking on the system, you should also set up a server on the receiving computer. It should be fine if packets sent from here are ignored on the receiving side. -Eventually, this networking functionality can be used to transfer data between the host computer (or another server) and REDACTED OS. -A separate project for the server code will be provided once that's necessary, but for now it just listens for UDP on port 8080 and optionally sends UDP packets as a response -*/ -#include "net_constants.h" - -static bool vnp_verbose = false; - -void vnp_enable_verbose(){ - vnp_verbose = true; -} - -#define kprintfv(fmt, ...) \ - ({ \ - if (vnp_verbose){\ - uint64_t _args[] = { __VA_ARGS__ }; \ - kprintf_args((fmt), _args, sizeof(_args) / sizeof(_args[0])); \ - }\ - }) - -static virtio_device vnp_net_dev; - -#define RECEIVE_QUEUE 0 -#define TRANSMIT_QUEUE 1 - -#define VIRTIO_NET_HDR_GSO_NONE 0 - -#define UDP_PACKET_SIZE sizeof(virtio_net_hdr_t) + sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) -#define MAX_PACKET_SIZE 0x1000 - -typedef struct __attribute__((packed)) virtio_net_hdr_t { - uint8_t flags; - uint8_t gso_type; - uint16_t hdr_len; - uint16_t gso_size; - uint16_t csum_start; - uint16_t num_buffers; -} virtio_net_hdr_t; - -uint16_t udp_checksum( - uint32_t src_ip, - uint32_t dst_ip, - uint8_t protocol, - const uint8_t* udp_header_and_payload, - uint16_t length -) { - uint32_t sum = 0; - - sum += (src_ip >> 16) & 0xFFFF; - sum += src_ip & 0xFFFF; - sum += (dst_ip >> 16) & 0xFFFF; - sum += dst_ip & 0xFFFF; - sum += protocol; - sum += length; - - for (uint16_t i = 0; i + 1 < length; i += 2) - sum += (udp_header_and_payload[i] << 8) | udp_header_and_payload[i + 1]; - - if (length & 1) - sum += udp_header_and_payload[length - 1] << 8; - - while (sum >> 16) - sum = (sum & 0xFFFF) + (sum >> 16); - - return ~sum; -} - -void create_udp_packet( - uint8_t* buf, - const uint8_t src_mac[6], - const uint8_t dst_mac[6], - uint32_t src_ip, - uint32_t dst_ip, - uint16_t src_port, - uint16_t dst_port, - const uint8_t* payload, - uint16_t payload_len -) { - uintptr_t p = (uintptr_t)buf; - - virtio_net_hdr_t* net = (virtio_net_hdr_t*)p; - - net->flags = 0; - net->gso_type = VIRTIO_NET_HDR_GSO_NONE; - net->hdr_len = 0; - net->gso_size = 0; - net->csum_start = 0; - net->num_buffers = 0; - - p += sizeof(virtio_net_hdr_t); - - eth_hdr_t* eth = (eth_hdr_t*)p; - for (int i = 0; i < 6; i++) eth->dst_mac[i] = dst_mac[i]; - for (int i = 0; i < 6; i++) eth->src_mac[i] = src_mac[i]; - eth->ethertype = __builtin_bswap16(0x0800); - p += sizeof(eth_hdr_t); - - ipv4_hdr_t* ip = (ipv4_hdr_t*)p; - ip->version_ihl = 0x45; - ip->dscp_ecn = 0; - ip->total_length = __builtin_bswap16(sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) + payload_len); - ip->identification = 0; - ip->flags_frag_offset = __builtin_bswap16(0x4000); - ip->ttl = 64; - ip->protocol = 0x11; - ip->header_checksum = 0; - ip->src_ip = __builtin_bswap32(src_ip); - ip->dst_ip = __builtin_bswap32(dst_ip); - uint16_t* ip_words = (uint16_t*)ip; - uint32_t sum = 0; - for (int i = 0; i < 10; i++) sum += ip_words[i]; - while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16); - ip->header_checksum = ~sum; - p += sizeof(ipv4_hdr_t); - - udp_hdr_t* udp = (udp_hdr_t*)p; - udp->src_port = __builtin_bswap16(src_port); - udp->dst_port = __builtin_bswap16(dst_port); - udp->length = __builtin_bswap16(sizeof(udp_hdr_t) + payload_len); - - p += sizeof(udp_hdr_t); - - uint8_t* data = (uint8_t*)p; - for (int i = 0; i < payload_len; i++) data[i] = payload[i]; - - udp->checksum = __builtin_bswap16(udp_checksum(src_ip,dst_ip,ip->protocol,(uint8_t*)udp,sizeof(udp_hdr_t) + payload_len)); - -} - -typedef struct virtio_net_config { - uint8_t mac[6]; - uint16_t status; - uint16_t max_virtqueue_pairs; - uint16_t mtu; - uint32_t speed; - uint8_t duplex; - uint8_t rss_max_key_size; - uint16_t rss_max_indirection_table_length; - uint32_t supported_hash_types; -}__attribute__((packed)) virtio_net_config; - -bool vnp_find_network(){ - uint64_t addr = find_pci_device(0x1AF4, 0x1000); - if (!addr){ - kprintf("[VIRTIO_NET error] Virtio network device not found"); - return false; - } - - uint64_t net_device_address, net_device_size; - - kprintfv("[VIRTIO_NET] Configuring network device"); - - virtio_get_capabilities(&vnp_net_dev, addr, &net_device_address, &net_device_size); - pci_register(net_device_address, net_device_size); - - uint8_t interrupts_ok = pci_setup_interrupts(addr, NET_IRQ); - switch(interrupts_ok){ - case 0: - kprintf_raw("[VIRTIO_NET] Failed to setup interrupts"); - return false; - case 1: - kprintf_raw("[VIRTIO_NET] Interrupts setup with MSI-X %i",NET_IRQ); - break; - default: - kprintf_raw("[VIRTIO_NET] Interrupts setup with MSI %i",NET_IRQ); - break; - } - - pci_enable_device(addr); - - if (!virtio_init_device(&vnp_net_dev)) { - kprintf("[VIRTIO_NET error] Failed network initialization"); - return false; - } - - virtio_net_config* net_config = (virtio_net_config*)vnp_net_dev.device_cfg; - kprintfv("[VIRTIO_NET] %x:%x:%x:%x:%x:%x", net_config->mac[0], net_config->mac[1], net_config->mac[2], net_config->mac[3], net_config->mac[4], net_config->mac[5]); - - kprintfv("[VIRTIO_NET] %i virtqueue pairs",net_config->max_virtqueue_pairs); - kprintfv("[VIRTIO_NET] %x speed", net_config->speed); - kprintfv("[VIRTIO_NET] status = %x", net_config->status); - - uint8_t dest[6] = HOST_MAC; - - kprintf("[VIRTIO_NET] %x:%x:%x:%x:%x:%x", dest[0], dest[1], dest[2], dest[3], dest[4], dest[5]); - - size_t payload_size = 5; - char hw[5] = {'h','e','l','l','o'}; - - select_queue(&vnp_net_dev, RECEIVE_QUEUE); - - for (uint16_t i = 0; i < 128; i++){ - void* buf = allocate_in_page(vnp_net_dev.memory_page, MAX_PACKET_SIZE, ALIGN_64B, true, true); - virtio_add_buffer(&vnp_net_dev, i, (uintptr_t)buf, MAX_PACKET_SIZE); - } - - kprintfv("[VIRTIO_NET] Current MSI-X queue index %i",vnp_net_dev.common_cfg->queue_msix_vector); - vnp_net_dev.common_cfg->queue_msix_vector = 0; - if (vnp_net_dev.common_cfg->queue_msix_vector != 0){ - kprintfv("[VIRTIO_NET error] failed to set interrupts on receive queue, network will be unable to receive packets"); - return false; - } - - void* test_packet = allocate_in_page(vnp_net_dev.memory_page, UDP_PACKET_SIZE + payload_size, ALIGN_64B, true, true); - create_udp_packet(test_packet,net_config->mac,dest,(192 << 24) | (168 << 16) | (1 << 8) | 131,HOST_IP,8888,8080,hw, payload_size); - - kprintfv("[VIRTIO_NET] Packet created"); - - select_queue(&vnp_net_dev, TRANSMIT_QUEUE); - kprintfv("[VIRTIO_NET] New MSI-X queue index %x",vnp_net_dev.common_cfg->msix_config); - - size_t size = UDP_PACKET_SIZE + payload_size; - - kprintfv("[VIRTIO_NET] Upload queue selected for packet %x (size %i)",(uintptr_t)test_packet, size); - - virtio_send_1d(&vnp_net_dev, (uintptr_t)test_packet, size); - - kprintfv("[VIRTIO_NET] Packet sent"); - - return true; -} - -static uint16_t last_used_receive_idx = 0; - -void vnp_parse_packet(uintptr_t packet_ptr){ - packet_ptr += sizeof(virtio_net_hdr_t); - - eth_hdr_t* eth = (eth_hdr_t*)packet_ptr; - uint8_t filter[6] = HOST_MAC; - if (filter[0] == eth->src_mac[0]) - kprintf(">>>>[VIRTIO_NET packet] SOURCE: %x:%x:%x:%x:%x:%x", eth->src_mac[0], eth->src_mac[1], eth->src_mac[2], eth->src_mac[3], eth->src_mac[4], eth->src_mac[5]); - - packet_ptr += sizeof(eth_hdr_t); - - if (__builtin_bswap16(eth->ethertype) == 0x800){ - ipv4_hdr_t* ip = (ipv4_hdr_t*)packet_ptr; - packet_ptr += sizeof(ipv4_hdr_t); - if (ip->protocol == 0x11){ - udp_hdr_t* udp = (udp_hdr_t*)packet_ptr; - packet_ptr += sizeof(udp_hdr_t); - uint8_t* data = (uint8_t*)packet_ptr; - uint16_t payload_len = __builtin_bswap16(udp->length) - sizeof(udp_hdr_t); - for (int i = 0; i < payload_len; i++) if (data[i] >= 0x20 && data[i] <= 0x7E) kprintf("%c",data[i]); - } else { - kprintf("[VIRTIO_NET packet] Not prepared to handle non-UDP packets %x",ip->protocol); - } - } - else { - kprintf("[VIRTIO_NET packet] Not prepared to handle non-ipv4 packets %x",__builtin_bswap16(eth->ethertype)); - } -} - -void vnp_handle_interrupt(){ - select_queue(&vnp_net_dev, RECEIVE_QUEUE); - struct virtq_used* used = (struct virtq_used*)(uintptr_t)vnp_net_dev.common_cfg->queue_device; - - uint16_t new_idx = used->idx; - if (new_idx != last_used_receive_idx) { - struct virtq_desc* desc = (struct virtq_desc*)(uintptr_t)vnp_net_dev.common_cfg->queue_desc; - struct virtq_avail* avail = (struct virtq_avail*)(uintptr_t)vnp_net_dev.common_cfg->queue_driver; - uint16_t used_ring_index = last_used_receive_idx % 128; - last_used_receive_idx = new_idx; - struct virtq_used_elem* e = &used->ring[used_ring_index]; - uint32_t desc_index = e->id; - uint32_t len = e->len; - kprintf("Received network packet %i at index %i (len %i)",used->idx, desc_index, len); - - uintptr_t packet = desc[desc_index].addr; - - vnp_parse_packet(packet); - - avail->ring[avail->idx % 128] = desc_index; - avail->idx++; - - *(volatile uint16_t*)(uintptr_t)(vnp_net_dev.notify_cfg + vnp_net_dev.notify_off_multiplier * RECEIVE_QUEUE) = 0; - } -} \ No newline at end of file diff --git a/kernel/networking/virtio_net_pci.h b/kernel/networking/virtio_net_pci.h deleted file mode 100644 index aacf8f6c..00000000 --- a/kernel/networking/virtio_net_pci.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include "types.h" - -#define NET_IRQ 32 - -bool vnp_find_network(); -void vnp_handle_interrupt(); -void vnp_enable_verbose(); \ No newline at end of file From d60056f452f42757799b6f1b09351713edda3a2c Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 18 Jun 2025 00:00:00 +0000 Subject: [PATCH 16/61] Send packets through cpp driver, receiving works but not from test server --- kernel/networking/drivers/net_driver.hpp | 5 +- .../drivers/virtio_net_pci/virtio_net_pci.cpp | 53 +++++++++++++++++-- .../drivers/virtio_net_pci/virtio_net_pci.hpp | 6 ++- kernel/networking/network.cpp | 4 ++ kernel/networking/network.h | 2 + kernel/networking/network_dispatch.cpp | 5 ++ kernel/networking/network_dispatch.hpp | 1 + kernel/networking/packets.h | 4 ++ kernel/networking/udp.c | 11 ++-- 9 files changed, 78 insertions(+), 13 deletions(-) diff --git a/kernel/networking/drivers/net_driver.hpp b/kernel/networking/drivers/net_driver.hpp index 8b84c938..027bad94 100644 --- a/kernel/networking/drivers/net_driver.hpp +++ b/kernel/networking/drivers/net_driver.hpp @@ -3,6 +3,7 @@ #include "types.h" #include "std/string.h" #include "ui/graphic_types.h" +#include "networking/packets.h" class NetDriver { public: @@ -11,9 +12,9 @@ class NetDriver { virtual void handle_interrupt() = 0; - virtual void send_packet(void* packet, size_t size) = 0; - virtual void enable_verbose() = 0; + virtual void send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len) = 0; + virtual ~NetDriver() = default; }; \ No newline at end of file diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index 544b3dc2..cf865fb1 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -4,6 +4,8 @@ #include "networking/udp.h" #include "networking/network.h" #include "pci.h" +#include "syscalls/syscalls.h" +#include "memory/page_allocator.h" #define RECEIVE_QUEUE 0 #define TRANSMIT_QUEUE 1 @@ -84,22 +86,42 @@ bool VirtioNetDriver::init(){ virtio_net_config* net_config = (virtio_net_config*)vnp_net_dev.device_cfg; kprintfv("[VIRTIO_NET] %x:%x:%x:%x:%x:%x", net_config->mac[0], net_config->mac[1], net_config->mac[2], net_config->mac[3], net_config->mac[4], net_config->mac[5]); + + connection_context = (network_connection_ctx){ + .port = 0, + .ip = (uint32_t)((192 << 24) | (168 << 16) | (1 << 8) | 131), + .mac = {net_config->mac[0],net_config->mac[1],net_config->mac[2],net_config->mac[3],net_config->mac[4],net_config->mac[5]}, + }; kprintfv("[VIRTIO_NET] %i virtqueue pairs",net_config->max_virtqueue_pairs); kprintfv("[VIRTIO_NET] %x speed", net_config->speed); kprintfv("[VIRTIO_NET] status = %x", net_config->status); + select_queue(&vnp_net_dev, RECEIVE_QUEUE); + + for (uint16_t i = 0; i < 128; i++){ + void* buf = allocate_in_page(vnp_net_dev.memory_page, MAX_PACKET_SIZE, ALIGN_64B, true, true); + virtio_add_buffer(&vnp_net_dev, i, (uintptr_t)buf, MAX_PACKET_SIZE); + } + + kprintfv("[VIRTIO_NET] Current MSI-X queue index %i",vnp_net_dev.common_cfg->queue_msix_vector); + vnp_net_dev.common_cfg->queue_msix_vector = 0; + if (vnp_net_dev.common_cfg->queue_msix_vector != 0){ + kprintfv("[VIRTIO_NET error] failed to set interrupts on receive queue, network will be unable to receive packets"); + return false; + } + return true; } void VirtioNetDriver::handle_interrupt(){ - select_queue(&vnp_net_dev, RECEIVE_QUEUE); + select_queue(&vnp_net_dev, RECEIVE_QUEUE); struct virtq_used* used = (struct virtq_used*)(uintptr_t)vnp_net_dev.common_cfg->queue_device; + struct virtq_desc* desc = (struct virtq_desc*)(uintptr_t)vnp_net_dev.common_cfg->queue_desc; + struct virtq_avail* avail = (struct virtq_avail*)(uintptr_t)vnp_net_dev.common_cfg->queue_driver; uint16_t new_idx = used->idx; if (new_idx != last_used_receive_idx) { - struct virtq_desc* desc = (struct virtq_desc*)(uintptr_t)vnp_net_dev.common_cfg->queue_desc; - struct virtq_avail* avail = (struct virtq_avail*)(uintptr_t)vnp_net_dev.common_cfg->queue_driver; uint16_t used_ring_index = last_used_receive_idx % 128; last_used_receive_idx = new_idx; struct virtq_used_elem* e = &used->ring[used_ring_index]; @@ -108,6 +130,7 @@ void VirtioNetDriver::handle_interrupt(){ kprintf("Received network packet %i at index %i (len %i)",used->idx, desc_index, len); uintptr_t packet = desc[desc_index].addr; + packet += sizeof(virtio_net_hdr_t); udp_parse_packet(packet); @@ -115,12 +138,32 @@ void VirtioNetDriver::handle_interrupt(){ avail->idx++; *(volatile uint16_t*)(uintptr_t)(vnp_net_dev.notify_cfg + vnp_net_dev.notify_off_multiplier * RECEIVE_QUEUE) = 0; + + return; + } + + select_queue(&vnp_net_dev, TRANSMIT_QUEUE); + new_idx = used->idx; + if (new_idx != last_used_receive_idx) { + uint16_t used_ring_index = last_used_receive_idx % 128; + last_used_receive_idx = new_idx; + struct virtq_used_elem* e = &used->ring[used_ring_index]; + uint32_t desc_index = e->id; + uint32_t len = e->len; + free_from_page((void*)desc[desc_index].addr, len); + kprintf("Freed memory"); + return; } } -void VirtioNetDriver::send_packet(void* packet, size_t size){ +void VirtioNetDriver::send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len){ select_queue(&vnp_net_dev, TRANSMIT_QUEUE); - virtio_send_1d(&vnp_net_dev, (uintptr_t)packet, size); + size_t size = calc_udp_packet_size(payload_len) + sizeof(virtio_net_hdr_t); + uintptr_t buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size, ALIGN_64B, true, true); + connection_context.port = port; + create_udp_packet((uint8_t*)(buf_ptr + sizeof(virtio_net_hdr_t)), connection_context, *destination, (uint8_t*)payload, payload_len); + virtio_send_1d(&vnp_net_dev, buf_ptr, size); + kprintf("Queued new packet"); } void VirtioNetDriver::enable_verbose(){ diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp index 50a54f9b..2bcd0f8d 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp @@ -1,5 +1,6 @@ #include "../net_driver.hpp" #include "virtio/virtio_pci.h" +#include "networking/packets.h" class VirtioNetDriver : public NetDriver { public: @@ -11,14 +12,15 @@ class VirtioNetDriver : public NetDriver { void handle_interrupt() override; - void send_packet(void* packet, size_t size) override; - void enable_verbose() override; + void send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len) override; + ~VirtioNetDriver() = default; private: bool verbose = false; uint16_t last_used_receive_idx = 0; virtio_device vnp_net_dev; + network_connection_ctx connection_context; }; \ No newline at end of file diff --git a/kernel/networking/network.cpp b/kernel/networking/network.cpp index 0b932ae8..5cfa6b2c 100644 --- a/kernel/networking/network.cpp +++ b/kernel/networking/network.cpp @@ -20,3 +20,7 @@ bool network_bind_port(uint16_t port, uint16_t process){ bool network_unbindbind_port(uint16_t port, uint16_t process){ return dispatch->unbind_port(port, process); } + +void network_send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len){ + return dispatch->send_packet(protocol, port, destination, payload, payload_len); +} \ No newline at end of file diff --git a/kernel/networking/network.h b/kernel/networking/network.h index 9d388f70..8a866767 100644 --- a/kernel/networking/network.h +++ b/kernel/networking/network.h @@ -5,6 +5,7 @@ extern "C" { #endif #include "types.h" +#include "packets.h" #define NET_IRQ 32 @@ -12,6 +13,7 @@ bool network_init(); void network_handle_interrupt(); bool network_bind_port(uint16_t port, uint16_t process); bool network_unbindbind_port(uint16_t port, uint16_t process); +void network_send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len); #ifdef __cplusplus } diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index 3e7df6f0..3705fe21 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -30,4 +30,9 @@ bool NetworkDispatch::unbind_port(uint16_t port, uint16_t process){ void NetworkDispatch::handle_interrupt(){ if (driver) driver->handle_interrupt(); +} + +void NetworkDispatch::send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len){ + if (driver) + driver->send_packet(protocol, port, destination, payload, payload_len); } \ No newline at end of file diff --git a/kernel/networking/network_dispatch.hpp b/kernel/networking/network_dispatch.hpp index b0cd3eef..879c1bca 100644 --- a/kernel/networking/network_dispatch.hpp +++ b/kernel/networking/network_dispatch.hpp @@ -11,6 +11,7 @@ class NetworkDispatch { bool bind_port(uint16_t port, uint16_t process); bool unbind_port(uint16_t port, uint16_t process); void handle_interrupt(); + void send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len); private: IndexMap ports; diff --git a/kernel/networking/packets.h b/kernel/networking/packets.h index 4d9bc468..8b2b1a6c 100644 --- a/kernel/networking/packets.h +++ b/kernel/networking/packets.h @@ -6,6 +6,10 @@ extern "C" { #include "types.h" +typedef enum NetProtocol { + UDP +} NetProtocol; + typedef struct __attribute__((packed)) eth_hdr_t { uint8_t dst_mac[6]; uint8_t src_mac[6]; diff --git a/kernel/networking/udp.c b/kernel/networking/udp.c index d7bcb85d..fa627ba1 100644 --- a/kernel/networking/udp.c +++ b/kernel/networking/udp.c @@ -80,25 +80,28 @@ void create_udp_packet(uint8_t* buf, network_connection_ctx source, network_conn void udp_parse_packet(uintptr_t packet_ptr){ eth_hdr_t* eth = (eth_hdr_t*)packet_ptr; - kprintf(">>>>[UDP packet] SOURCE: %x:%x:%x:%x:%x:%x", eth->src_mac[0], eth->src_mac[1], eth->src_mac[2], eth->src_mac[3], eth->src_mac[4], eth->src_mac[5]); + // kprintf("[UDP packet] SOURCE: %x:%x:%x:%x:%x:%x", eth->src_mac[0], eth->src_mac[1], eth->src_mac[2], eth->src_mac[3], eth->src_mac[4], eth->src_mac[5]); packet_ptr += sizeof(eth_hdr_t); if (__builtin_bswap16(eth->ethertype) == 0x800){ ipv4_hdr_t* ip = (ipv4_hdr_t*)packet_ptr; + uint32_t srcip = __builtin_bswap32(ip->src_ip); packet_ptr += sizeof(ipv4_hdr_t); if (ip->protocol == 0x11){ udp_hdr_t* udp = (udp_hdr_t*)packet_ptr; packet_ptr += sizeof(udp_hdr_t); + if (udp->dst_port != 8888) return; + kprintf(">>>>Source %i.%i.%i.%i:%i",srcip >> 24, (srcip >> 16) & 0xFF, (srcip >> 8) & 0xFF, srcip & 0xFF,udp->src_port); uint8_t* data = (uint8_t*)packet_ptr; uint16_t payload_len = __builtin_bswap16(udp->length) - sizeof(udp_hdr_t); - for (int i = 0; i < payload_len; i++) if (data[i] >= 0x20 && data[i] <= 0x7E) kprintf("%c",data[i]); + for (int i = 0; i < payload_len; i++) if (data[i] >= 0x20 && data[i] <= 0x7E) kputf_raw("%c",data[i]); } else { - kprintf("[UDP packet] Not prepared to handle non-UDP packets %x",ip->protocol); + // kprintf("[UDP packet] Not prepared to handle non-UDP packets %x",ip->protocol); } } else { - kprintf("[UDP packet] Not prepared to handle non-ipv4 packets %x",__builtin_bswap16(eth->ethertype)); + // kprintf("[UDP packet] Not prepared to handle non-ipv4 packets %x",__builtin_bswap16(eth->ethertype)); } } From c68566406a82414d3aa02b394542d5c8ffb70408 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Wed, 18 Jun 2025 00:00:00 +0000 Subject: [PATCH 17/61] Network process for testing (and probably config/monitoring) --- kernel/kernel.c | 3 +++ kernel/kernel_processes/net/net_proc.c | 23 +++++++++++++++++++++++ kernel/kernel_processes/net/net_proc.h | 5 +++++ 3 files changed, 31 insertions(+) create mode 100644 kernel/kernel_processes/net/net_proc.c create mode 100644 kernel/kernel_processes/net/net_proc.h diff --git a/kernel/kernel.c b/kernel/kernel.c index dfdb9ec3..26083c38 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -14,6 +14,7 @@ #include "input/xhci_bridge.h" #include "input/xhci.h" #include "kernel_processes/monitor/monitor_processes.h" +#include "kernel_processes/net/net_proc.h" #include "memory/page_allocator.h" #include "networking/network.h" @@ -71,6 +72,8 @@ void kernel_main() { // translate_enable_verbose(); + launch_net_process(); + init_bootprocess(); kprintf("Starting scheduler"); diff --git a/kernel/kernel_processes/net/net_proc.c b/kernel/kernel_processes/net/net_proc.c new file mode 100644 index 00000000..7cc85a14 --- /dev/null +++ b/kernel/kernel_processes/net/net_proc.c @@ -0,0 +1,23 @@ +#include "net_proc.h" +#include "../kprocess_loader.h" +#include "networking/network.h" +#include "process/scheduler.h" + +void test_network(){ + network_connection_ctx dest = (network_connection_ctx){ + .ip = (192 << 24) | (168 << 16) | (1 << 8) | 255, + .mac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + .port = 8080, + }; + + size_t payload_size = 5; + char hw[5] = {'h','e','l','l','o'}; + + network_send_packet(UDP, 8888, &dest, hw, payload_size); + + stop_current_process(); +} + +process_t* launch_net_process(){ + return create_kernel_process("nettest",test_network); +} \ No newline at end of file diff --git a/kernel/kernel_processes/net/net_proc.h b/kernel/kernel_processes/net/net_proc.h new file mode 100644 index 00000000..0a6e84ed --- /dev/null +++ b/kernel/kernel_processes/net/net_proc.h @@ -0,0 +1,5 @@ +#pragma once + +#include "process/process.h" + +process_t* launch_net_process(); \ No newline at end of file From d118a7b78eb3f1e19df100f12e441ec16b26793b Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Thu, 19 Jun 2025 00:00:00 +0000 Subject: [PATCH 18/61] Restored UDP packet parsing --- .../networking/drivers/virtio_net_pci/virtio_net_pci.cpp | 2 +- kernel/networking/udp.c | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index cf865fb1..b7fadf2c 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -127,7 +127,7 @@ void VirtioNetDriver::handle_interrupt(){ struct virtq_used_elem* e = &used->ring[used_ring_index]; uint32_t desc_index = e->id; uint32_t len = e->len; - kprintf("Received network packet %i at index %i (len %i)",used->idx, desc_index, len); + kprintf("Received network packet %i at index %i (len %i - %i)",used->idx, desc_index, len,sizeof(virtio_net_hdr_t)); uintptr_t packet = desc[desc_index].addr; packet += sizeof(virtio_net_hdr_t); diff --git a/kernel/networking/udp.c b/kernel/networking/udp.c index fa627ba1..3700350c 100644 --- a/kernel/networking/udp.c +++ b/kernel/networking/udp.c @@ -80,7 +80,6 @@ void create_udp_packet(uint8_t* buf, network_connection_ctx source, network_conn void udp_parse_packet(uintptr_t packet_ptr){ eth_hdr_t* eth = (eth_hdr_t*)packet_ptr; - // kprintf("[UDP packet] SOURCE: %x:%x:%x:%x:%x:%x", eth->src_mac[0], eth->src_mac[1], eth->src_mac[2], eth->src_mac[3], eth->src_mac[4], eth->src_mac[5]); packet_ptr += sizeof(eth_hdr_t); @@ -91,11 +90,13 @@ void udp_parse_packet(uintptr_t packet_ptr){ if (ip->protocol == 0x11){ udp_hdr_t* udp = (udp_hdr_t*)packet_ptr; packet_ptr += sizeof(udp_hdr_t); - if (udp->dst_port != 8888) return; - kprintf(">>>>Source %i.%i.%i.%i:%i",srcip >> 24, (srcip >> 16) & 0xFF, (srcip >> 8) & 0xFF, srcip & 0xFF,udp->src_port); + uint16_t port = __builtin_bswap16(udp->dst_port); + if (port != 8888) return; uint8_t* data = (uint8_t*)packet_ptr; uint16_t payload_len = __builtin_bswap16(udp->length) - sizeof(udp_hdr_t); + kputf_raw("Received UDP Packet from %i.%i.%i.%i:%i = ",srcip >> 24, (srcip >> 16) & 0xFF, (srcip >> 8) & 0xFF, srcip & 0xFF,__builtin_bswap16(udp->src_port)); for (int i = 0; i < payload_len; i++) if (data[i] >= 0x20 && data[i] <= 0x7E) kputf_raw("%c",data[i]); + kputf_raw("\n"); } else { // kprintf("[UDP packet] Not prepared to handle non-UDP packets %x",ip->protocol); } From 69599b3cd2947fc0ae7a0e3d6050071d895a933a Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Thu, 19 Jun 2025 00:00:00 +0000 Subject: [PATCH 19/61] Moved to network_types.h name, process port binding --- kernel/kernel_processes/net/net_proc.c | 2 + kernel/networking/drivers/net_driver.hpp | 4 +- .../drivers/virtio_net_pci/virtio_net_pci.cpp | 47 +++++++++++-------- .../drivers/virtio_net_pci/virtio_net_pci.hpp | 4 +- kernel/networking/network.cpp | 10 ++++ kernel/networking/network.h | 5 +- kernel/networking/network_dispatch.cpp | 14 +++++- .../networking/{packets.h => network_types.h} | 5 ++ kernel/networking/udp.c | 13 ++--- kernel/networking/udp.h | 5 +- kernel/process/scheduler.h | 9 ++-- kernel/theme/JesOS.h | 38 --------------- kernel/theme/theme.h | 1 - 13 files changed, 77 insertions(+), 80 deletions(-) rename kernel/networking/{packets.h => network_types.h} (89%) delete mode 100644 kernel/theme/JesOS.h diff --git a/kernel/kernel_processes/net/net_proc.c b/kernel/kernel_processes/net/net_proc.c index 7cc85a14..f9ae6346 100644 --- a/kernel/kernel_processes/net/net_proc.c +++ b/kernel/kernel_processes/net/net_proc.c @@ -4,6 +4,7 @@ #include "process/scheduler.h" void test_network(){ + network_bind_port_current(8888); network_connection_ctx dest = (network_connection_ctx){ .ip = (192 << 24) | (168 << 16) | (1 << 8) | 255, .mac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, @@ -16,6 +17,7 @@ void test_network(){ network_send_packet(UDP, 8888, &dest, hw, payload_size); stop_current_process(); + network_unbind_port_current(8888); } process_t* launch_net_process(){ diff --git a/kernel/networking/drivers/net_driver.hpp b/kernel/networking/drivers/net_driver.hpp index 027bad94..c9aad116 100644 --- a/kernel/networking/drivers/net_driver.hpp +++ b/kernel/networking/drivers/net_driver.hpp @@ -3,14 +3,14 @@ #include "types.h" #include "std/string.h" #include "ui/graphic_types.h" -#include "networking/packets.h" +#include "networking/network_types.h" class NetDriver { public: NetDriver(){} virtual bool init() = 0; - virtual void handle_interrupt() = 0; + virtual ReceivedPacket handle_receive_packet() = 0; virtual void enable_verbose() = 0; diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index b7fadf2c..ea91ba27 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -1,6 +1,6 @@ #include "virtio_net_pci.hpp" #include "console/kio.h" -#include "networking/packets.h" +#include "networking/network_types.h" #include "networking/udp.h" #include "networking/network.h" #include "pci.h" @@ -104,17 +104,26 @@ bool VirtioNetDriver::init(){ virtio_add_buffer(&vnp_net_dev, i, (uintptr_t)buf, MAX_PACKET_SIZE); } - kprintfv("[VIRTIO_NET] Current MSI-X queue index %i",vnp_net_dev.common_cfg->queue_msix_vector); + kprintf("[VIRTIO_NET] Current MSI-X queue index %i",vnp_net_dev.common_cfg->queue_msix_vector); vnp_net_dev.common_cfg->queue_msix_vector = 0; if (vnp_net_dev.common_cfg->queue_msix_vector != 0){ - kprintfv("[VIRTIO_NET error] failed to set interrupts on receive queue, network will be unable to receive packets"); + kprintf("[VIRTIO_NET error] failed to set interrupts on receive queue, network will be unable to receive packets"); + return false; + } + + select_queue(&vnp_net_dev, TRANSMIT_QUEUE); + + kprintf("[VIRTIO_NET] Current MSI-X queue index %i",vnp_net_dev.common_cfg->queue_msix_vector); + vnp_net_dev.common_cfg->queue_msix_vector = 0; + if (vnp_net_dev.common_cfg->queue_msix_vector != 0){ + kprintf("[VIRTIO_NET error] failed to set interrupts on transmit queue, network will be unable to cleanup transmitted packets"); return false; } return true; } -void VirtioNetDriver::handle_interrupt(){ +ReceivedPacket VirtioNetDriver::handle_receive_packet(){ select_queue(&vnp_net_dev, RECEIVE_QUEUE); struct virtq_used* used = (struct virtq_used*)(uintptr_t)vnp_net_dev.common_cfg->queue_device; struct virtq_desc* desc = (struct virtq_desc*)(uintptr_t)vnp_net_dev.common_cfg->queue_desc; @@ -127,33 +136,31 @@ void VirtioNetDriver::handle_interrupt(){ struct virtq_used_elem* e = &used->ring[used_ring_index]; uint32_t desc_index = e->id; uint32_t len = e->len; - kprintf("Received network packet %i at index %i (len %i - %i)",used->idx, desc_index, len,sizeof(virtio_net_hdr_t)); + kprintfv("Received network packet %i at index %i (len %i - %i)",used->idx, desc_index, len,sizeof(virtio_net_hdr_t)); uintptr_t packet = desc[desc_index].addr; packet += sizeof(virtio_net_hdr_t); - udp_parse_packet(packet); - avail->ring[avail->idx % 128] = desc_index; avail->idx++; *(volatile uint16_t*)(uintptr_t)(vnp_net_dev.notify_cfg + vnp_net_dev.notify_off_multiplier * RECEIVE_QUEUE) = 0; - return; + return (ReceivedPacket){packet,len}; } - select_queue(&vnp_net_dev, TRANSMIT_QUEUE); - new_idx = used->idx; - if (new_idx != last_used_receive_idx) { - uint16_t used_ring_index = last_used_receive_idx % 128; - last_used_receive_idx = new_idx; - struct virtq_used_elem* e = &used->ring[used_ring_index]; - uint32_t desc_index = e->id; - uint32_t len = e->len; - free_from_page((void*)desc[desc_index].addr, len); - kprintf("Freed memory"); - return; - } + // select_queue(&vnp_net_dev, TRANSMIT_QUEUE); + // new_idx = used->idx; + // if (new_idx != last_used_receive_idx) { + // uint16_t used_ring_index = last_used_receive_idx % 128; + // last_used_receive_idx = new_idx; + // struct virtq_used_elem* e = &used->ring[used_ring_index]; + // uint32_t desc_index = e->id; + // uint32_t len = e->len; + // free_from_page((void*)desc[desc_index].addr, len); + // kprintf("Freed memory"); + // return; + // } } void VirtioNetDriver::send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len){ diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp index 2bcd0f8d..bf837fad 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp @@ -1,6 +1,6 @@ #include "../net_driver.hpp" #include "virtio/virtio_pci.h" -#include "networking/packets.h" +#include "networking/network_types.h" class VirtioNetDriver : public NetDriver { public: @@ -10,7 +10,7 @@ class VirtioNetDriver : public NetDriver { bool init() override; - void handle_interrupt() override; + ReceivedPacket handle_receive_packet() override; void enable_verbose() override; diff --git a/kernel/networking/network.cpp b/kernel/networking/network.cpp index 5cfa6b2c..a5a8b7bf 100644 --- a/kernel/networking/network.cpp +++ b/kernel/networking/network.cpp @@ -1,6 +1,7 @@ #include "network.h" #include "network_dispatch.hpp" #include "std/allocator.hpp" +#include "process/scheduler.h" NetworkDispatch *dispatch; @@ -21,6 +22,15 @@ bool network_unbindbind_port(uint16_t port, uint16_t process){ return dispatch->unbind_port(port, process); } +bool network_bind_port_current(uint16_t port){ + return dispatch->bind_port(port, get_current_proc_pid()); +} + +bool network_unbind_port_current(uint16_t port){ + return dispatch->unbind_port(port, get_current_proc_pid()); +} + + void network_send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len){ return dispatch->send_packet(protocol, port, destination, payload, payload_len); } \ No newline at end of file diff --git a/kernel/networking/network.h b/kernel/networking/network.h index 8a866767..07b17690 100644 --- a/kernel/networking/network.h +++ b/kernel/networking/network.h @@ -5,7 +5,7 @@ extern "C" { #endif #include "types.h" -#include "packets.h" +#include "network_types.h" #define NET_IRQ 32 @@ -15,6 +15,9 @@ bool network_bind_port(uint16_t port, uint16_t process); bool network_unbindbind_port(uint16_t port, uint16_t process); void network_send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len); +bool network_bind_port_current(uint16_t port); +bool network_unbind_port_current(uint16_t port); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index 3705fe21..74c17532 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -1,5 +1,8 @@ #include "network_dispatch.hpp" #include "drivers/virtio_net_pci/virtio_net_pci.hpp" +#include "network_types.h" +#include "udp.h" +#include "console/kio.h" NetworkDispatch::NetworkDispatch(){ ports = IndexMap(UINT16_MAX); @@ -28,8 +31,15 @@ bool NetworkDispatch::unbind_port(uint16_t port, uint16_t process){ } void NetworkDispatch::handle_interrupt(){ - if (driver) - driver->handle_interrupt(); + if (driver){ + ReceivedPacket packet = driver->handle_receive_packet(); + if (packet.packet_ptr){ + uint16_t port = udp_parse_packet(packet.packet_ptr); + if (ports[port] != UINT16_MAX){ + kprintf("RECEIVED DATA TO A BOUND PORT TO %i",ports[port]); + } + } + } } void NetworkDispatch::send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len){ diff --git a/kernel/networking/packets.h b/kernel/networking/network_types.h similarity index 89% rename from kernel/networking/packets.h rename to kernel/networking/network_types.h index 8b2b1a6c..70c780c1 100644 --- a/kernel/networking/packets.h +++ b/kernel/networking/network_types.h @@ -10,6 +10,11 @@ typedef enum NetProtocol { UDP } NetProtocol; +typedef struct ReceivedPacket { + uintptr_t packet_ptr; + size_t packet_size; +} ReceivedPacket; + typedef struct __attribute__((packed)) eth_hdr_t { uint8_t dst_mac[6]; uint8_t src_mac[6]; diff --git a/kernel/networking/udp.c b/kernel/networking/udp.c index 3700350c..f6659bce 100644 --- a/kernel/networking/udp.c +++ b/kernel/networking/udp.c @@ -1,6 +1,6 @@ #include "udp.h" #include "console/kio.h" -#include "packets.h" +#include "network_types.h" /* net_constants.h is gitignored and needs to be created. It should contain a {0xXX,0xXX,0xXX,0xXX,0xXX,0xXX}' uint8_t[6] called HOST_MAC and '(192 << 24) | (168 << 16) | (1 << 8) | x' uint64_t called HOST_IP. These are used to test networking capabilities, if you want to test networking on the system, you should also set up a server on the receiving computer. It should be fine if packets sent from here are ignored on the receiving side. @@ -78,7 +78,7 @@ void create_udp_packet(uint8_t* buf, network_connection_ctx source, network_conn } -void udp_parse_packet(uintptr_t packet_ptr){ +uint16_t udp_parse_packet(uintptr_t packet_ptr){ eth_hdr_t* eth = (eth_hdr_t*)packet_ptr; packet_ptr += sizeof(eth_hdr_t); @@ -91,12 +91,7 @@ void udp_parse_packet(uintptr_t packet_ptr){ udp_hdr_t* udp = (udp_hdr_t*)packet_ptr; packet_ptr += sizeof(udp_hdr_t); uint16_t port = __builtin_bswap16(udp->dst_port); - if (port != 8888) return; - uint8_t* data = (uint8_t*)packet_ptr; - uint16_t payload_len = __builtin_bswap16(udp->length) - sizeof(udp_hdr_t); - kputf_raw("Received UDP Packet from %i.%i.%i.%i:%i = ",srcip >> 24, (srcip >> 16) & 0xFF, (srcip >> 8) & 0xFF, srcip & 0xFF,__builtin_bswap16(udp->src_port)); - for (int i = 0; i < payload_len; i++) if (data[i] >= 0x20 && data[i] <= 0x7E) kputf_raw("%c",data[i]); - kputf_raw("\n"); + return port; } else { // kprintf("[UDP packet] Not prepared to handle non-UDP packets %x",ip->protocol); } @@ -104,6 +99,8 @@ void udp_parse_packet(uintptr_t packet_ptr){ else { // kprintf("[UDP packet] Not prepared to handle non-ipv4 packets %x",__builtin_bswap16(eth->ethertype)); } + + return 0; } size_t calc_udp_packet_size(uint16_t payload_len){ diff --git a/kernel/networking/udp.h b/kernel/networking/udp.h index 9a7c6e5d..9dd62121 100644 --- a/kernel/networking/udp.h +++ b/kernel/networking/udp.h @@ -5,11 +5,12 @@ extern "C" { #endif #include "types.h" -#include "packets.h" +#include "network_types.h" void create_udp_packet(uint8_t* buf, network_connection_ctx source, network_connection_ctx destination, const uint8_t* payload, uint16_t payload_len); size_t calc_udp_packet_size(uint16_t payload_len); -void udp_parse_packet(uintptr_t packet_ptr); +uint16_t udp_parse_packet(uintptr_t packet_ptr); +uint16_t udp_parse_packet_length(uintptr_t packet_ptr); #ifdef __cplusplus } diff --git a/kernel/process/scheduler.h b/kernel/process/scheduler.h index 5360c7bd..6000326d 100644 --- a/kernel/process/scheduler.h +++ b/kernel/process/scheduler.h @@ -20,10 +20,6 @@ process_t* init_process(); void save_syscall_return(uint64_t value); void process_restore(); -process_t* get_current_proc(); -process_t* get_proc_by_pid(uint16_t pid); -uint16_t get_current_proc_pid(); - void stop_process(uint16_t pid); void stop_current_process(); @@ -35,6 +31,11 @@ void wake_processes(); #ifdef __cplusplus extern "C" { #endif + +process_t* get_current_proc(); +process_t* get_proc_by_pid(uint16_t pid); +uint16_t get_current_proc_pid(); + uintptr_t get_current_heap(); bool get_current_privilege(); #ifdef __cplusplus diff --git a/kernel/theme/JesOS.h b/kernel/theme/JesOS.h deleted file mode 100644 index ed706ded..00000000 --- a/kernel/theme/JesOS.h +++ /dev/null @@ -1,38 +0,0 @@ -#define BOOTSCREEN_TEXT "JesOS - The Christian Operating System" - -#define BOOTSCREEN_NUM_SYMBOLS 12 -#define BOOTSCREEN_NUM_STEPS 12 -#define BOOTSCREEN_NUM_LINES 1 - -#define BOOTSCREEN_REPEAT 1 - -#define BOOTSCREEN_DIV 15 - -#define BOOTSCREEN_OFFSETS {\ - {-3,1},\ - {-1,1},\ - {-1,5},\ - {1,5},\ - {1,1},\ - {3,1},\ - {3,-1},\ - {1,-1},\ - {1,-5},\ - {-1,-5},\ - {-1,-1},\ - {-3,-1},\ -} - -#define BOOTSCREEN_ASYMM (gpu_point){0,50} -#define BOOTSCREEN_PADDING 10 - -#define BOOTSCREEN_INNER_X_CONST 30 -#define BOOTSCREEN_OUTER_X_DIV 5 -#define BOOTSCREEN_UPPER_Y_DIV 3 -#define BOOTSCREEN_LOWER_Y_CONST 40 - -#define PANIC_TEXT "CARDINAL SIN" - -#define BG_COLOR 0x703285 - -#define default_pwd "amen" \ No newline at end of file diff --git a/kernel/theme/theme.h b/kernel/theme/theme.h index 3f445f92..aa804ec9 100644 --- a/kernel/theme/theme.h +++ b/kernel/theme/theme.h @@ -1,4 +1,3 @@ #pragma once -// #include "JesOS.h" #include "RedactedOS.h" \ No newline at end of file From a6517cd6d286ae0c4da9b4209ab3cc80f46bf7f2 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Thu, 19 Jun 2025 00:00:00 +0000 Subject: [PATCH 20/61] Receiver fix and network types to shared --- kernel/networking/drivers/net_driver.hpp | 2 +- kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp | 3 ++- kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp | 2 +- {kernel/networking => shared}/network_types.h | 0 4 files changed, 4 insertions(+), 3 deletions(-) rename {kernel/networking => shared}/network_types.h (100%) diff --git a/kernel/networking/drivers/net_driver.hpp b/kernel/networking/drivers/net_driver.hpp index c9aad116..38629c89 100644 --- a/kernel/networking/drivers/net_driver.hpp +++ b/kernel/networking/drivers/net_driver.hpp @@ -3,7 +3,7 @@ #include "types.h" #include "std/string.h" #include "ui/graphic_types.h" -#include "networking/network_types.h" +#include "network_types.h" class NetDriver { public: diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index ea91ba27..b6b33c5a 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -1,6 +1,5 @@ #include "virtio_net_pci.hpp" #include "console/kio.h" -#include "networking/network_types.h" #include "networking/udp.h" #include "networking/network.h" #include "pci.h" @@ -149,6 +148,8 @@ ReceivedPacket VirtioNetDriver::handle_receive_packet(){ return (ReceivedPacket){packet,len}; } + return (ReceivedPacket){0,0}; + // select_queue(&vnp_net_dev, TRANSMIT_QUEUE); // new_idx = used->idx; // if (new_idx != last_used_receive_idx) { diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp index bf837fad..b25dab9a 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp @@ -1,6 +1,6 @@ #include "../net_driver.hpp" #include "virtio/virtio_pci.h" -#include "networking/network_types.h" +#include "network_types.h" class VirtioNetDriver : public NetDriver { public: diff --git a/kernel/networking/network_types.h b/shared/network_types.h similarity index 100% rename from kernel/networking/network_types.h rename to shared/network_types.h From 44099641db1b09f9728c2c15bcc977590e5984c1 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Thu, 19 Jun 2025 00:00:00 +0000 Subject: [PATCH 21/61] Send data to process --- kernel/networking/network_dispatch.cpp | 18 ++++++++++++++++-- kernel/process/process.h | 9 +++++++++ kernel/process/scheduler.c | 5 +++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index 74c17532..a9aff380 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -1,8 +1,9 @@ #include "network_dispatch.hpp" #include "drivers/virtio_net_pci/virtio_net_pci.hpp" #include "network_types.h" -#include "udp.h" #include "console/kio.h" +#include "process/scheduler.h" +#include "udp.h" NetworkDispatch::NetworkDispatch(){ ports = IndexMap(UINT16_MAX); @@ -36,7 +37,20 @@ void NetworkDispatch::handle_interrupt(){ if (packet.packet_ptr){ uint16_t port = udp_parse_packet(packet.packet_ptr); if (ports[port] != UINT16_MAX){ - kprintf("RECEIVED DATA TO A BOUND PORT TO %i",ports[port]); + process_t *proc = get_proc_by_pid(ports[port]); + if (!proc) + unbind_port(port, ports[port]); + else { + packet_buffer_t* buf = &proc->packet_buffer; + uint32_t next_index = (buf->write_index + 1) % PACKET_BUFFER_CAPACITY; + + buf->entries[buf->write_index] = packet; + buf->write_index = next_index; + + if (buf->write_index == buf->read_index) + buf->read_index = (buf->read_index + 1) % PACKET_BUFFER_CAPACITY; + kprintf("RECEIVED DATA TO A BOUND PORT TO %i",ports[port]); + } } } } diff --git a/kernel/process/process.h b/kernel/process/process.h index 83d0ae39..b1071bea 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -6,8 +6,10 @@ extern "C" { #include "types.h" #include "keypress.h" +#include "network_types.h" #define INPUT_BUFFER_CAPACITY 64 +#define PACKET_BUFFER_CAPACITY 128 typedef struct { volatile uint32_t write_index; @@ -15,6 +17,12 @@ typedef struct { keypress entries[INPUT_BUFFER_CAPACITY]; } input_buffer_t; +typedef struct { + volatile uint32_t write_index; + volatile uint32_t read_index; + ReceivedPacket entries[PACKET_BUFFER_CAPACITY]; +} packet_buffer_t; + #define MAX_PROC_NAME_LENGTH 256 typedef struct { @@ -31,6 +39,7 @@ typedef struct { bool focused; enum process_state { STOPPED, READY, RUNNING, BLOCKED } state; input_buffer_t input_buffer; + packet_buffer_t packet_buffer; char name[MAX_PROC_NAME_LENGTH]; } process_t; diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index cd360bc8..f93f75b6 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -105,6 +105,11 @@ void reset_process(process_t *proc){ for (int k = 0; k < INPUT_BUFFER_CAPACITY; k++){ proc->input_buffer.entries[k] = (keypress){0}; } + proc->packet_buffer.read_index = 0; + proc->packet_buffer.write_index = 0; + for (int k = 0; k < PACKET_BUFFER_CAPACITY; k++){ + proc->packet_buffer.entries[k] = (ReceivedPacket){0}; + } } void init_main_process(){ From a9941c68acf0d5cf5694b8740a7db831d0487996 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Thu, 19 Jun 2025 00:00:00 +0000 Subject: [PATCH 22/61] Payload reading in process --- kernel/kernel_processes/net/net_proc.c | 17 +++++++++++++ .../drivers/virtio_net_pci/virtio_net_pci.cpp | 14 +++++------ kernel/networking/network.cpp | 10 +++++++- kernel/networking/network.h | 3 +++ kernel/networking/network_dispatch.cpp | 16 +++++++++++- kernel/networking/network_dispatch.hpp | 2 ++ kernel/networking/udp.c | 25 +++++++++++++++++++ kernel/networking/udp.h | 1 + 8 files changed, 79 insertions(+), 9 deletions(-) diff --git a/kernel/kernel_processes/net/net_proc.c b/kernel/kernel_processes/net/net_proc.c index f9ae6346..bcea869a 100644 --- a/kernel/kernel_processes/net/net_proc.c +++ b/kernel/kernel_processes/net/net_proc.c @@ -1,7 +1,10 @@ #include "net_proc.h" #include "../kprocess_loader.h" #include "networking/network.h" +#include "network_types.h" #include "process/scheduler.h" +#include "console/kio.h" +#include "networking/udp.h" void test_network(){ network_bind_port_current(8888); @@ -16,6 +19,20 @@ void test_network(){ network_send_packet(UDP, 8888, &dest, hw, payload_size); + ReceivedPacket pack; + + while (!network_read_packet_current(&pack)); + + ReceivedPacket payload = udp_parse_packet_payload(pack.packet_ptr); + + uint8_t *content = (uint8_t*)payload.packet_ptr; + + kputf_raw("PAYLOAD: "); + for (size_t i = 0; i < payload.packet_size; i++){ + kputf_raw("%c",content[i]); + } + kputf_raw("\n"); + stop_current_process(); network_unbind_port_current(8888); } diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index b6b33c5a..7d54e119 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -110,14 +110,14 @@ bool VirtioNetDriver::init(){ return false; } - select_queue(&vnp_net_dev, TRANSMIT_QUEUE); + // select_queue(&vnp_net_dev, TRANSMIT_QUEUE); - kprintf("[VIRTIO_NET] Current MSI-X queue index %i",vnp_net_dev.common_cfg->queue_msix_vector); - vnp_net_dev.common_cfg->queue_msix_vector = 0; - if (vnp_net_dev.common_cfg->queue_msix_vector != 0){ - kprintf("[VIRTIO_NET error] failed to set interrupts on transmit queue, network will be unable to cleanup transmitted packets"); - return false; - } + // kprintf("[VIRTIO_NET] Current MSI-X queue index %i",vnp_net_dev.common_cfg->queue_msix_vector); + // vnp_net_dev.common_cfg->queue_msix_vector = 0; + // if (vnp_net_dev.common_cfg->queue_msix_vector != 0){ + // kprintf("[VIRTIO_NET error] failed to set interrupts on transmit queue, network will be unable to cleanup transmitted packets"); + // return false; + // } return true; } diff --git a/kernel/networking/network.cpp b/kernel/networking/network.cpp index a5a8b7bf..1b3027c0 100644 --- a/kernel/networking/network.cpp +++ b/kernel/networking/network.cpp @@ -33,4 +33,12 @@ bool network_unbind_port_current(uint16_t port){ void network_send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len){ return dispatch->send_packet(protocol, port, destination, payload, payload_len); -} \ No newline at end of file +} + +bool network_read_packet(ReceivedPacket *packet, uint16_t process){ + return dispatch->read_packet(packet, process); +} + +bool network_read_packet_current(ReceivedPacket *packet){ + return dispatch->read_packet(packet, get_current_proc_pid()); +} diff --git a/kernel/networking/network.h b/kernel/networking/network.h index 07b17690..1165c455 100644 --- a/kernel/networking/network.h +++ b/kernel/networking/network.h @@ -18,6 +18,9 @@ void network_send_packet(NetProtocol protocol, uint16_t port, network_connection bool network_bind_port_current(uint16_t port); bool network_unbind_port_current(uint16_t port); +bool network_read_packet(ReceivedPacket *packet, uint16_t process); +bool network_read_packet_current(ReceivedPacket *packet); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index a9aff380..cd98f7c9 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -4,6 +4,8 @@ #include "console/kio.h" #include "process/scheduler.h" #include "udp.h" +#include "syscalls/syscalls.h" +#include "std/memfunctions.h" NetworkDispatch::NetworkDispatch(){ ports = IndexMap(UINT16_MAX); @@ -49,13 +51,25 @@ void NetworkDispatch::handle_interrupt(){ if (buf->write_index == buf->read_index) buf->read_index = (buf->read_index + 1) % PACKET_BUFFER_CAPACITY; - kprintf("RECEIVED DATA TO A BOUND PORT TO %i",ports[port]); } } } } } +bool NetworkDispatch::read_packet(ReceivedPacket *Packet, uint16_t process){ + process_t *proc = get_proc_by_pid(process); + if (proc->packet_buffer.read_index == proc->packet_buffer.write_index) return false; + + ReceivedPacket original = proc->packet_buffer.entries[proc->packet_buffer.read_index]; + + uintptr_t copy = malloc(original.packet_size); + memcpy((void*)copy,(void*)original.packet_ptr,original.packet_size); + *Packet = (ReceivedPacket){copy, original.packet_size}; + proc->packet_buffer.read_index = (proc->packet_buffer.read_index + 1) % PACKET_BUFFER_CAPACITY; + return true; +} + void NetworkDispatch::send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len){ if (driver) driver->send_packet(protocol, port, destination, payload, payload_len); diff --git a/kernel/networking/network_dispatch.hpp b/kernel/networking/network_dispatch.hpp index 879c1bca..c1ac8829 100644 --- a/kernel/networking/network_dispatch.hpp +++ b/kernel/networking/network_dispatch.hpp @@ -1,5 +1,6 @@ #pragma once +#include "network_types.h" #include "types.h" #include "std/indexmap.hpp" #include "drivers/net_driver.hpp" @@ -12,6 +13,7 @@ class NetworkDispatch { bool unbind_port(uint16_t port, uint16_t process); void handle_interrupt(); void send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len); + bool read_packet(ReceivedPacket *Packet, uint16_t process); private: IndexMap ports; diff --git a/kernel/networking/udp.c b/kernel/networking/udp.c index f6659bce..224e37db 100644 --- a/kernel/networking/udp.c +++ b/kernel/networking/udp.c @@ -103,6 +103,31 @@ uint16_t udp_parse_packet(uintptr_t packet_ptr){ return 0; } +ReceivedPacket udp_parse_packet_payload(uintptr_t packet_ptr){ + eth_hdr_t* eth = (eth_hdr_t*)packet_ptr; + + packet_ptr += sizeof(eth_hdr_t); + + if (__builtin_bswap16(eth->ethertype) == 0x800){ + ipv4_hdr_t* ip = (ipv4_hdr_t*)packet_ptr; + uint32_t srcip = __builtin_bswap32(ip->src_ip); + packet_ptr += sizeof(ipv4_hdr_t); + if (ip->protocol == 0x11){ + udp_hdr_t* udp = (udp_hdr_t*)packet_ptr; + packet_ptr += sizeof(udp_hdr_t); + uint16_t payload_len = __builtin_bswap16(udp->length) - sizeof(udp_hdr_t); + return (ReceivedPacket){packet_ptr,payload_len}; + } else { + // kprintf("[UDP packet] Not prepared to handle non-UDP packets %x",ip->protocol); + } + } + else { + // kprintf("[UDP packet] Not prepared to handle non-ipv4 packets %x",__builtin_bswap16(eth->ethertype)); + } + + return (ReceivedPacket){0,0}; +} + size_t calc_udp_packet_size(uint16_t payload_len){ return sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) + payload_len; } \ No newline at end of file diff --git a/kernel/networking/udp.h b/kernel/networking/udp.h index 9dd62121..c7a48458 100644 --- a/kernel/networking/udp.h +++ b/kernel/networking/udp.h @@ -10,6 +10,7 @@ extern "C" { void create_udp_packet(uint8_t* buf, network_connection_ctx source, network_connection_ctx destination, const uint8_t* payload, uint16_t payload_len); size_t calc_udp_packet_size(uint16_t payload_len); uint16_t udp_parse_packet(uintptr_t packet_ptr); +ReceivedPacket udp_parse_packet_payload(uintptr_t packet_ptr); uint16_t udp_parse_packet_length(uintptr_t packet_ptr); #ifdef __cplusplus From eedee5edad426ea6828291d14b9144684c51908a Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Thu, 19 Jun 2025 00:00:00 +0000 Subject: [PATCH 23/61] Renamed ReceivedPacket to sizedptr --- kernel/input/xhci.c | 8 ++--- kernel/input/xhci_types.h | 2 +- kernel/kernel_processes/net/net_proc.c | 8 ++--- kernel/networking/drivers/net_driver.hpp | 2 +- .../drivers/virtio_net_pci/virtio_net_pci.cpp | 14 ++++---- .../drivers/virtio_net_pci/virtio_net_pci.hpp | 2 +- kernel/networking/network.cpp | 4 +-- kernel/networking/network.h | 4 +-- kernel/networking/network_dispatch.cpp | 16 ++++----- kernel/networking/network_dispatch.hpp | 2 +- kernel/networking/udp.c | 34 +++++++++---------- kernel/networking/udp.h | 8 ++--- kernel/process/process.h | 2 +- kernel/process/scheduler.c | 2 +- shared/network_types.h | 5 --- shared/types.h | 7 ++++ 16 files changed, 61 insertions(+), 59 deletions(-) diff --git a/kernel/input/xhci.c b/kernel/input/xhci.c index 898be4fb..171a619d 100644 --- a/kernel/input/xhci.c +++ b/kernel/input/xhci.c @@ -309,7 +309,7 @@ bool issue_command(uint64_t param, uint32_t status, uint32_t control){ return AWAIT(cmd_addr, {ring_doorbell(0, 0);}, TRB_TYPE_COMMAND_COMPLETION); } -uint16_t packet_size(uint16_t port_speed){ +uint16_t size(uint16_t port_speed){ switch (port_speed) { case 2: return 8;//Low case 1: @@ -508,7 +508,7 @@ bool xhci_get_configuration(usb_configuration_descriptor *config, xhci_usb_devic ctx->device_context.endpoints[ep_num-1].endpoint_f0.endpoint_state = 0; ctx->device_context.endpoints[ep_num-1].endpoint_f1.endpoint_type = get_ep_type(endpoint); - ctx->device_context.endpoints[ep_num-1].endpoint_f1.max_packet_size = endpoint->wMaxPacketSize; + ctx->device_context.endpoints[ep_num-1].endpoint_f1.max_size = endpoint->wMaxPacketSize; ctx->device_context.endpoints[ep_num-1].endpoint_f4.max_esit_payload_lo = endpoint->wMaxPacketSize; ctx->device_context.endpoints[ep_num-1].endpoint_f1.error_count = 3; @@ -584,7 +584,7 @@ bool xhci_setup_device(uint16_t port){ ctx->device_context.endpoints[0].endpoint_f1.endpoint_type = 4;//Type = control ctx->device_context.endpoints[0].endpoint_f0.interval = 0; ctx->device_context.endpoints[0].endpoint_f1.error_count = 3;//3 errors allowed - ctx->device_context.endpoints[0].endpoint_f1.max_packet_size = packet_size(ctx->device_context.slot_f0.speed);//Packet size. Guessed from port speed + ctx->device_context.endpoints[0].endpoint_f1.max_size = size(ctx->device_context.slot_f0.speed);//Packet size. Guessed from port speed device->transfer_ring = (trb*)allocate_in_page(xhci_mem_page, MAX_TRB_AMOUNT * sizeof(trb), ALIGN_64B, true, true); kprintfv("Transfer ring at %x",(uintptr_t)device->transfer_ring); @@ -602,7 +602,7 @@ bool xhci_setup_device(uint16_t port){ xhci_device_context* context = (xhci_device_context*)(uintptr_t)(global_device.dcbaa[device->slot_id]); - kprintfv("[xHCI] ADDRESS_DEVICE command issued. Received package size %i",context->endpoints[0].endpoint_f1.max_packet_size); + kprintfv("[xHCI] ADDRESS_DEVICE command issued. Received package size %i",context->endpoints[0].endpoint_f1.max_size); usb_device_descriptor* descriptor = (usb_device_descriptor*)allocate_in_page(xhci_mem_page, sizeof(usb_device_descriptor), ALIGN_64B, true, true); diff --git a/kernel/input/xhci_types.h b/kernel/input/xhci_types.h index 5151afe5..319e7d90 100644 --- a/kernel/input/xhci_types.h +++ b/kernel/input/xhci_types.h @@ -218,7 +218,7 @@ typedef union uint32_t rsvd2 : 1; uint32_t host_initiate_disable : 1; uint32_t max_burst_size : 8; - uint32_t max_packet_size : 16; + uint32_t max_size : 16; }; uint32_t value; } endpoint_field1; diff --git a/kernel/kernel_processes/net/net_proc.c b/kernel/kernel_processes/net/net_proc.c index bcea869a..42f82732 100644 --- a/kernel/kernel_processes/net/net_proc.c +++ b/kernel/kernel_processes/net/net_proc.c @@ -19,16 +19,16 @@ void test_network(){ network_send_packet(UDP, 8888, &dest, hw, payload_size); - ReceivedPacket pack; + sizedptr pack; while (!network_read_packet_current(&pack)); - ReceivedPacket payload = udp_parse_packet_payload(pack.packet_ptr); + sizedptr payload = udp_parse_packet_payload(pack.ptr); - uint8_t *content = (uint8_t*)payload.packet_ptr; + uint8_t *content = (uint8_t*)payload.ptr; kputf_raw("PAYLOAD: "); - for (size_t i = 0; i < payload.packet_size; i++){ + for (size_t i = 0; i < payload.size; i++){ kputf_raw("%c",content[i]); } kputf_raw("\n"); diff --git a/kernel/networking/drivers/net_driver.hpp b/kernel/networking/drivers/net_driver.hpp index 38629c89..2196cddf 100644 --- a/kernel/networking/drivers/net_driver.hpp +++ b/kernel/networking/drivers/net_driver.hpp @@ -10,7 +10,7 @@ class NetDriver { NetDriver(){} virtual bool init() = 0; - virtual ReceivedPacket handle_receive_packet() = 0; + virtual sizedptr handle_receive_packet() = 0; virtual void enable_verbose() = 0; diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index 7d54e119..63783a6d 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -8,7 +8,7 @@ #define RECEIVE_QUEUE 0 #define TRANSMIT_QUEUE 1 -#define MAX_PACKET_SIZE 0x1000 +#define MAX_size 0x1000 #define kprintfv(fmt, ...) \ ({ \ @@ -99,8 +99,8 @@ bool VirtioNetDriver::init(){ select_queue(&vnp_net_dev, RECEIVE_QUEUE); for (uint16_t i = 0; i < 128; i++){ - void* buf = allocate_in_page(vnp_net_dev.memory_page, MAX_PACKET_SIZE, ALIGN_64B, true, true); - virtio_add_buffer(&vnp_net_dev, i, (uintptr_t)buf, MAX_PACKET_SIZE); + void* buf = allocate_in_page(vnp_net_dev.memory_page, MAX_size, ALIGN_64B, true, true); + virtio_add_buffer(&vnp_net_dev, i, (uintptr_t)buf, MAX_size); } kprintf("[VIRTIO_NET] Current MSI-X queue index %i",vnp_net_dev.common_cfg->queue_msix_vector); @@ -122,7 +122,7 @@ bool VirtioNetDriver::init(){ return true; } -ReceivedPacket VirtioNetDriver::handle_receive_packet(){ +sizedptr VirtioNetDriver::handle_receive_packet(){ select_queue(&vnp_net_dev, RECEIVE_QUEUE); struct virtq_used* used = (struct virtq_used*)(uintptr_t)vnp_net_dev.common_cfg->queue_device; struct virtq_desc* desc = (struct virtq_desc*)(uintptr_t)vnp_net_dev.common_cfg->queue_desc; @@ -145,10 +145,10 @@ ReceivedPacket VirtioNetDriver::handle_receive_packet(){ *(volatile uint16_t*)(uintptr_t)(vnp_net_dev.notify_cfg + vnp_net_dev.notify_off_multiplier * RECEIVE_QUEUE) = 0; - return (ReceivedPacket){packet,len}; + return (sizedptr){packet,len}; } - return (ReceivedPacket){0,0}; + return (sizedptr){0,0}; // select_queue(&vnp_net_dev, TRANSMIT_QUEUE); // new_idx = used->idx; @@ -166,7 +166,7 @@ ReceivedPacket VirtioNetDriver::handle_receive_packet(){ void VirtioNetDriver::send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len){ select_queue(&vnp_net_dev, TRANSMIT_QUEUE); - size_t size = calc_udp_packet_size(payload_len) + sizeof(virtio_net_hdr_t); + size_t size = calc_udp_size(payload_len) + sizeof(virtio_net_hdr_t); uintptr_t buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size, ALIGN_64B, true, true); connection_context.port = port; create_udp_packet((uint8_t*)(buf_ptr + sizeof(virtio_net_hdr_t)), connection_context, *destination, (uint8_t*)payload, payload_len); diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp index b25dab9a..20095881 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp @@ -10,7 +10,7 @@ class VirtioNetDriver : public NetDriver { bool init() override; - ReceivedPacket handle_receive_packet() override; + sizedptr handle_receive_packet() override; void enable_verbose() override; diff --git a/kernel/networking/network.cpp b/kernel/networking/network.cpp index 1b3027c0..84c93688 100644 --- a/kernel/networking/network.cpp +++ b/kernel/networking/network.cpp @@ -35,10 +35,10 @@ void network_send_packet(NetProtocol protocol, uint16_t port, network_connection return dispatch->send_packet(protocol, port, destination, payload, payload_len); } -bool network_read_packet(ReceivedPacket *packet, uint16_t process){ +bool network_read_packet(sizedptr *packet, uint16_t process){ return dispatch->read_packet(packet, process); } -bool network_read_packet_current(ReceivedPacket *packet){ +bool network_read_packet_current(sizedptr *packet){ return dispatch->read_packet(packet, get_current_proc_pid()); } diff --git a/kernel/networking/network.h b/kernel/networking/network.h index 1165c455..78e5bb17 100644 --- a/kernel/networking/network.h +++ b/kernel/networking/network.h @@ -18,8 +18,8 @@ void network_send_packet(NetProtocol protocol, uint16_t port, network_connection bool network_bind_port_current(uint16_t port); bool network_unbind_port_current(uint16_t port); -bool network_read_packet(ReceivedPacket *packet, uint16_t process); -bool network_read_packet_current(ReceivedPacket *packet); +bool network_read_packet(sizedptr *packet, uint16_t process); +bool network_read_packet_current(sizedptr *packet); #ifdef __cplusplus } diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index cd98f7c9..fb0b2a20 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -35,9 +35,9 @@ bool NetworkDispatch::unbind_port(uint16_t port, uint16_t process){ void NetworkDispatch::handle_interrupt(){ if (driver){ - ReceivedPacket packet = driver->handle_receive_packet(); - if (packet.packet_ptr){ - uint16_t port = udp_parse_packet(packet.packet_ptr); + sizedptr packet = driver->handle_receive_packet(); + if (packet.ptr){ + uint16_t port = udp_parse_packet(packet.ptr); if (ports[port] != UINT16_MAX){ process_t *proc = get_proc_by_pid(ports[port]); if (!proc) @@ -57,15 +57,15 @@ void NetworkDispatch::handle_interrupt(){ } } -bool NetworkDispatch::read_packet(ReceivedPacket *Packet, uint16_t process){ +bool NetworkDispatch::read_packet(sizedptr *Packet, uint16_t process){ process_t *proc = get_proc_by_pid(process); if (proc->packet_buffer.read_index == proc->packet_buffer.write_index) return false; - ReceivedPacket original = proc->packet_buffer.entries[proc->packet_buffer.read_index]; + sizedptr original = proc->packet_buffer.entries[proc->packet_buffer.read_index]; - uintptr_t copy = malloc(original.packet_size); - memcpy((void*)copy,(void*)original.packet_ptr,original.packet_size); - *Packet = (ReceivedPacket){copy, original.packet_size}; + uintptr_t copy = malloc(original.size); + memcpy((void*)copy,(void*)original.ptr,original.size); + *Packet = (sizedptr){copy, original.size}; proc->packet_buffer.read_index = (proc->packet_buffer.read_index + 1) % PACKET_BUFFER_CAPACITY; return true; } diff --git a/kernel/networking/network_dispatch.hpp b/kernel/networking/network_dispatch.hpp index c1ac8829..7417fdfa 100644 --- a/kernel/networking/network_dispatch.hpp +++ b/kernel/networking/network_dispatch.hpp @@ -13,7 +13,7 @@ class NetworkDispatch { bool unbind_port(uint16_t port, uint16_t process); void handle_interrupt(); void send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len); - bool read_packet(ReceivedPacket *Packet, uint16_t process); + bool read_packet(sizedptr *Packet, uint16_t process); private: IndexMap ports; diff --git a/kernel/networking/udp.c b/kernel/networking/udp.c index 224e37db..37daf890 100644 --- a/kernel/networking/udp.c +++ b/kernel/networking/udp.c @@ -78,18 +78,18 @@ void create_udp_packet(uint8_t* buf, network_connection_ctx source, network_conn } -uint16_t udp_parse_packet(uintptr_t packet_ptr){ - eth_hdr_t* eth = (eth_hdr_t*)packet_ptr; +uint16_t udp_parse_packet(uintptr_t ptr){ + eth_hdr_t* eth = (eth_hdr_t*)ptr; - packet_ptr += sizeof(eth_hdr_t); + ptr += sizeof(eth_hdr_t); if (__builtin_bswap16(eth->ethertype) == 0x800){ - ipv4_hdr_t* ip = (ipv4_hdr_t*)packet_ptr; + ipv4_hdr_t* ip = (ipv4_hdr_t*)ptr; uint32_t srcip = __builtin_bswap32(ip->src_ip); - packet_ptr += sizeof(ipv4_hdr_t); + ptr += sizeof(ipv4_hdr_t); if (ip->protocol == 0x11){ - udp_hdr_t* udp = (udp_hdr_t*)packet_ptr; - packet_ptr += sizeof(udp_hdr_t); + udp_hdr_t* udp = (udp_hdr_t*)ptr; + ptr += sizeof(udp_hdr_t); uint16_t port = __builtin_bswap16(udp->dst_port); return port; } else { @@ -103,20 +103,20 @@ uint16_t udp_parse_packet(uintptr_t packet_ptr){ return 0; } -ReceivedPacket udp_parse_packet_payload(uintptr_t packet_ptr){ - eth_hdr_t* eth = (eth_hdr_t*)packet_ptr; +sizedptr udp_parse_packet_payload(uintptr_t ptr){ + eth_hdr_t* eth = (eth_hdr_t*)ptr; - packet_ptr += sizeof(eth_hdr_t); + ptr += sizeof(eth_hdr_t); if (__builtin_bswap16(eth->ethertype) == 0x800){ - ipv4_hdr_t* ip = (ipv4_hdr_t*)packet_ptr; + ipv4_hdr_t* ip = (ipv4_hdr_t*)ptr; uint32_t srcip = __builtin_bswap32(ip->src_ip); - packet_ptr += sizeof(ipv4_hdr_t); + ptr += sizeof(ipv4_hdr_t); if (ip->protocol == 0x11){ - udp_hdr_t* udp = (udp_hdr_t*)packet_ptr; - packet_ptr += sizeof(udp_hdr_t); + udp_hdr_t* udp = (udp_hdr_t*)ptr; + ptr += sizeof(udp_hdr_t); uint16_t payload_len = __builtin_bswap16(udp->length) - sizeof(udp_hdr_t); - return (ReceivedPacket){packet_ptr,payload_len}; + return (sizedptr){ptr,payload_len}; } else { // kprintf("[UDP packet] Not prepared to handle non-UDP packets %x",ip->protocol); } @@ -125,9 +125,9 @@ ReceivedPacket udp_parse_packet_payload(uintptr_t packet_ptr){ // kprintf("[UDP packet] Not prepared to handle non-ipv4 packets %x",__builtin_bswap16(eth->ethertype)); } - return (ReceivedPacket){0,0}; + return (sizedptr){0,0}; } -size_t calc_udp_packet_size(uint16_t payload_len){ +size_t calc_udp_size(uint16_t payload_len){ return sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) + payload_len; } \ No newline at end of file diff --git a/kernel/networking/udp.h b/kernel/networking/udp.h index c7a48458..401c3cc8 100644 --- a/kernel/networking/udp.h +++ b/kernel/networking/udp.h @@ -8,10 +8,10 @@ extern "C" { #include "network_types.h" void create_udp_packet(uint8_t* buf, network_connection_ctx source, network_connection_ctx destination, const uint8_t* payload, uint16_t payload_len); -size_t calc_udp_packet_size(uint16_t payload_len); -uint16_t udp_parse_packet(uintptr_t packet_ptr); -ReceivedPacket udp_parse_packet_payload(uintptr_t packet_ptr); -uint16_t udp_parse_packet_length(uintptr_t packet_ptr); +size_t calc_udp_size(uint16_t payload_len); +uint16_t udp_parse_packet(uintptr_t ptr); +sizedptr udp_parse_packet_payload(uintptr_t ptr); +uint16_t udp_parse_packet_length(uintptr_t ptr); #ifdef __cplusplus } diff --git a/kernel/process/process.h b/kernel/process/process.h index b1071bea..8398f7f0 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -20,7 +20,7 @@ typedef struct { typedef struct { volatile uint32_t write_index; volatile uint32_t read_index; - ReceivedPacket entries[PACKET_BUFFER_CAPACITY]; + sizedptr entries[PACKET_BUFFER_CAPACITY]; } packet_buffer_t; #define MAX_PROC_NAME_LENGTH 256 diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index f93f75b6..303f7af0 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -108,7 +108,7 @@ void reset_process(process_t *proc){ proc->packet_buffer.read_index = 0; proc->packet_buffer.write_index = 0; for (int k = 0; k < PACKET_BUFFER_CAPACITY; k++){ - proc->packet_buffer.entries[k] = (ReceivedPacket){0}; + proc->packet_buffer.entries[k] = (sizedptr){0}; } } diff --git a/shared/network_types.h b/shared/network_types.h index 70c780c1..8b2b1a6c 100644 --- a/shared/network_types.h +++ b/shared/network_types.h @@ -10,11 +10,6 @@ typedef enum NetProtocol { UDP } NetProtocol; -typedef struct ReceivedPacket { - uintptr_t packet_ptr; - size_t packet_size; -} ReceivedPacket; - typedef struct __attribute__((packed)) eth_hdr_t { uint8_t dst_mac[6]; uint8_t src_mac[6]; diff --git a/shared/types.h b/shared/types.h index ad8c88c8..0b58af56 100644 --- a/shared/types.h +++ b/shared/types.h @@ -1,3 +1,5 @@ +#pragma once + #ifdef __cplusplus extern "C" { #endif @@ -18,6 +20,11 @@ typedef long intptr_t; typedef short int16_t; typedef char int8_t; +typedef struct sizedptr { + uintptr_t ptr; + size_t size; +} sizedptr; + #define NULL 0 #ifdef __cplusplus From 6c4cd0c38c487af516959c5b4162722e818de0d1 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Thu, 19 Jun 2025 00:00:00 +0000 Subject: [PATCH 24/61] syscalls for network --- kernel/kernel_processes/net/net_proc.c | 12 +++++++----- kernel/networking/network.cpp | 2 +- kernel/networking/network.h | 2 +- kernel/networking/network_dispatch.cpp | 4 ++-- kernel/process/syscall.c | 22 ++++++++++++++++++++++ shared/syscalls/syscalls.h | 5 +++++ shared/syscalls/syscalls_as.S | 9 ++++++++- 7 files changed, 46 insertions(+), 10 deletions(-) diff --git a/kernel/kernel_processes/net/net_proc.c b/kernel/kernel_processes/net/net_proc.c index 42f82732..f52b9689 100644 --- a/kernel/kernel_processes/net/net_proc.c +++ b/kernel/kernel_processes/net/net_proc.c @@ -1,13 +1,13 @@ #include "net_proc.h" #include "../kprocess_loader.h" -#include "networking/network.h" #include "network_types.h" #include "process/scheduler.h" #include "console/kio.h" #include "networking/udp.h" +#include "syscalls/syscalls.h" void test_network(){ - network_bind_port_current(8888); + bind_port(8888); network_connection_ctx dest = (network_connection_ctx){ .ip = (192 << 24) | (168 << 16) | (1 << 8) | 255, .mac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, @@ -17,11 +17,13 @@ void test_network(){ size_t payload_size = 5; char hw[5] = {'h','e','l','l','o'}; - network_send_packet(UDP, 8888, &dest, hw, payload_size); + send_packet(UDP, 8888, &dest, hw, payload_size); sizedptr pack; - while (!network_read_packet_current(&pack)); + while (!read_packet(&pack)); + + kprintf("DONE"); sizedptr payload = udp_parse_packet_payload(pack.ptr); @@ -34,7 +36,7 @@ void test_network(){ kputf_raw("\n"); stop_current_process(); - network_unbind_port_current(8888); + unbind_port(8888); } process_t* launch_net_process(){ diff --git a/kernel/networking/network.cpp b/kernel/networking/network.cpp index 84c93688..6de1910f 100644 --- a/kernel/networking/network.cpp +++ b/kernel/networking/network.cpp @@ -18,7 +18,7 @@ bool network_bind_port(uint16_t port, uint16_t process){ return dispatch->bind_port(port, process); } -bool network_unbindbind_port(uint16_t port, uint16_t process){ +bool network_unbind_port(uint16_t port, uint16_t process){ return dispatch->unbind_port(port, process); } diff --git a/kernel/networking/network.h b/kernel/networking/network.h index 78e5bb17..f88c2eb5 100644 --- a/kernel/networking/network.h +++ b/kernel/networking/network.h @@ -12,7 +12,7 @@ extern "C" { bool network_init(); void network_handle_interrupt(); bool network_bind_port(uint16_t port, uint16_t process); -bool network_unbindbind_port(uint16_t port, uint16_t process); +bool network_unbind_port(uint16_t port, uint16_t process); void network_send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len); bool network_bind_port_current(uint16_t port); diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index fb0b2a20..59b2ae58 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -4,7 +4,7 @@ #include "console/kio.h" #include "process/scheduler.h" #include "udp.h" -#include "syscalls/syscalls.h" +#include "memory/page_allocator.h" #include "std/memfunctions.h" NetworkDispatch::NetworkDispatch(){ @@ -63,7 +63,7 @@ bool NetworkDispatch::read_packet(sizedptr *Packet, uint16_t process){ sizedptr original = proc->packet_buffer.entries[proc->packet_buffer.read_index]; - uintptr_t copy = malloc(original.size); + uintptr_t copy = (uintptr_t)allocate_in_page((void*)get_current_heap(), original.size, ALIGN_16B, get_current_privilege(), false); memcpy((void*)copy,(void*)original.ptr,original.size); *Packet = (sizedptr){copy, original.size}; proc->packet_buffer.read_index = (proc->packet_buffer.read_index + 1) % PACKET_BUFFER_CAPACITY; diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index c9268fb4..540f3e6a 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -12,6 +12,7 @@ #include "std/memfunctions.h" #include "std/string.h" #include "exceptions/timer.h" +#include "networking/network.h" void sync_el0_handler_c(){ save_context_registers(); @@ -27,6 +28,8 @@ void sync_el0_handler_c(){ asm volatile ("mov %0, x9" : "=r"(x2)); uint64_t x3; asm volatile ("mov %0, x16" : "=r"(x3)); + uint64_t x4; + asm volatile ("mov %0, x4" : "=r"(x4)); uint64_t x29; asm volatile ("mov %0, x13" : "=r"(x29)); uint64_t x30; @@ -129,6 +132,25 @@ void sync_el0_handler_c(){ case 40: result = timer_now_msec(); break; + + case 51: + result = network_bind_port(x0, get_current_proc_pid()); + break; + + case 52: + result = network_unbind_port(x0, get_current_proc_pid()); + break; + + case 53: + network_connection_ctx *ctx = (network_connection_ctx*)x2; + void* payload = (void*)x3; + network_send_packet(x0, x1, ctx, payload, x4); + break; + + case 54: + sizedptr *ptr = (sizedptr*)x0; + result = network_read_packet_current(ptr); + break; default: handle_exception_with_info("Unknown syscall", iss); diff --git a/shared/syscalls/syscalls.h b/shared/syscalls/syscalls.h index 0ffb1069..049f0a18 100644 --- a/shared/syscalls/syscalls.h +++ b/shared/syscalls/syscalls.h @@ -33,6 +33,11 @@ extern void draw_primitive_string(string *text, gpu_point *p, uint32_t scale, ui extern uint64_t get_time(); +extern bool bind_port(uint16_t port); +extern bool unbind_port(uint16_t port); +extern void send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len); +extern bool read_packet(sizedptr *ptr); + void printf(const char *fmt, ...); #ifdef __cplusplus diff --git a/shared/syscalls/syscalls_as.S b/shared/syscalls/syscalls_as.S index 8667f428..c81f837f 100644 --- a/shared/syscalls/syscalls_as.S +++ b/shared/syscalls/syscalls_as.S @@ -33,4 +33,11 @@ syscall_def process_yield, 31 // syscall_def process_await, 32 syscall_def halt, 33 -syscall_def get_time, 40 \ No newline at end of file +//Time commands +syscall_def get_time, 40 + +//Network commands +syscall_def bind_port, 51 +syscall_def unbind_port, 52 +syscall_def send_packet, 53 +syscall_def read_packet, 54 \ No newline at end of file From f11a1f6c52e59375f689a79f7ee3216e5c93fe72 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Thu, 19 Jun 2025 00:00:00 +0000 Subject: [PATCH 25/61] Moved UDP parser to shared --- kernel/kernel_processes/net/net_proc.c | 2 +- kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp | 2 +- kernel/networking/network_dispatch.cpp | 2 +- {kernel/networking => shared/net}/udp.c | 0 {kernel/networking => shared/net}/udp.h | 0 shared/syscalls/syscalls.h | 1 + 6 files changed, 4 insertions(+), 3 deletions(-) rename {kernel/networking => shared/net}/udp.c (100%) rename {kernel/networking => shared/net}/udp.h (100%) diff --git a/kernel/kernel_processes/net/net_proc.c b/kernel/kernel_processes/net/net_proc.c index f52b9689..26a65665 100644 --- a/kernel/kernel_processes/net/net_proc.c +++ b/kernel/kernel_processes/net/net_proc.c @@ -3,7 +3,7 @@ #include "network_types.h" #include "process/scheduler.h" #include "console/kio.h" -#include "networking/udp.h" +#include "net/udp.h" #include "syscalls/syscalls.h" void test_network(){ diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index 63783a6d..14a9a8d0 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -1,6 +1,6 @@ #include "virtio_net_pci.hpp" #include "console/kio.h" -#include "networking/udp.h" +#include "net/udp.h" #include "networking/network.h" #include "pci.h" #include "syscalls/syscalls.h" diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index 59b2ae58..a18f6287 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -3,7 +3,7 @@ #include "network_types.h" #include "console/kio.h" #include "process/scheduler.h" -#include "udp.h" +#include "net/udp.h" #include "memory/page_allocator.h" #include "std/memfunctions.h" diff --git a/kernel/networking/udp.c b/shared/net/udp.c similarity index 100% rename from kernel/networking/udp.c rename to shared/net/udp.c diff --git a/kernel/networking/udp.h b/shared/net/udp.h similarity index 100% rename from kernel/networking/udp.h rename to shared/net/udp.h diff --git a/shared/syscalls/syscalls.h b/shared/syscalls/syscalls.h index 049f0a18..b71e97df 100644 --- a/shared/syscalls/syscalls.h +++ b/shared/syscalls/syscalls.h @@ -4,6 +4,7 @@ #include "ui/graphic_types.h" #include "keypress.h" #include "std/string.h" +#include "network_types.h" #ifdef __cplusplus extern "C" { From 9eca4e1be8a0fe22a7c8801995afd8ee83cc1cab Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Thu, 19 Jun 2025 00:00:00 +0000 Subject: [PATCH 26/61] Payload print and copy fixes --- kernel/kernel_processes/net/net_proc.c | 6 +----- kernel/networking/network_dispatch.cpp | 5 +++-- shared/net/udp.c | 8 +------- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/kernel/kernel_processes/net/net_proc.c b/kernel/kernel_processes/net/net_proc.c index 26a65665..9ce8f0b0 100644 --- a/kernel/kernel_processes/net/net_proc.c +++ b/kernel/kernel_processes/net/net_proc.c @@ -29,11 +29,7 @@ void test_network(){ uint8_t *content = (uint8_t*)payload.ptr; - kputf_raw("PAYLOAD: "); - for (size_t i = 0; i < payload.size; i++){ - kputf_raw("%c",content[i]); - } - kputf_raw("\n"); + kprintf("PAYLOAD: %s",(uintptr_t)string_ca_max(content, payload.size).data); stop_current_process(); unbind_port(8888); diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index a18f6287..3c9efebd 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -62,10 +62,11 @@ bool NetworkDispatch::read_packet(sizedptr *Packet, uint16_t process){ if (proc->packet_buffer.read_index == proc->packet_buffer.write_index) return false; sizedptr original = proc->packet_buffer.entries[proc->packet_buffer.read_index]; - + uintptr_t copy = (uintptr_t)allocate_in_page((void*)get_current_heap(), original.size, ALIGN_16B, get_current_privilege(), false); memcpy((void*)copy,(void*)original.ptr,original.size); - *Packet = (sizedptr){copy, original.size}; + Packet->ptr = copy; + Packet->size = original.size; proc->packet_buffer.read_index = (proc->packet_buffer.read_index + 1) % PACKET_BUFFER_CAPACITY; return true; } diff --git a/shared/net/udp.c b/shared/net/udp.c index 37daf890..46d28c1e 100644 --- a/shared/net/udp.c +++ b/shared/net/udp.c @@ -1,13 +1,7 @@ #include "udp.h" #include "console/kio.h" #include "network_types.h" -/* -net_constants.h is gitignored and needs to be created. It should contain a {0xXX,0xXX,0xXX,0xXX,0xXX,0xXX}' uint8_t[6] called HOST_MAC and '(192 << 24) | (168 << 16) | (1 << 8) | x' uint64_t called HOST_IP. -These are used to test networking capabilities, if you want to test networking on the system, you should also set up a server on the receiving computer. It should be fine if packets sent from here are ignored on the receiving side. -Eventually, this networking functionality can be used to transfer data between the host computer (or another server) and REDACTED OS. -A separate project for the server code will be provided once that's necessary, but for now it just listens for UDP on port 8080 and optionally sends UDP packets as a response -*/ -// #include "net_constants.h" +#include "syscalls/syscalls.h" uint16_t udp_checksum( uint32_t src_ip, From 2c612e872db1ff26cf34ec4b488741ea196c4c4e Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Thu, 19 Jun 2025 00:00:00 +0000 Subject: [PATCH 27/61] Moved network types to net folder --- kernel/kernel_processes/net/net_proc.c | 2 +- kernel/networking/drivers/net_driver.hpp | 2 +- .../networking/drivers/virtio_net_pci/virtio_net_pci.hpp | 2 +- kernel/networking/network.h | 2 +- kernel/networking/network_dispatch.cpp | 2 +- kernel/networking/network_dispatch.hpp | 2 +- kernel/process/process.h | 2 +- shared/{ => net}/network_types.h | 7 ------- shared/net/udp.c | 2 +- shared/net/udp.h | 9 ++++++++- shared/syscalls/syscalls.h | 2 +- 11 files changed, 17 insertions(+), 17 deletions(-) rename shared/{ => net}/network_types.h (82%) diff --git a/kernel/kernel_processes/net/net_proc.c b/kernel/kernel_processes/net/net_proc.c index 9ce8f0b0..52d0a850 100644 --- a/kernel/kernel_processes/net/net_proc.c +++ b/kernel/kernel_processes/net/net_proc.c @@ -1,6 +1,6 @@ #include "net_proc.h" #include "../kprocess_loader.h" -#include "network_types.h" +#include "net/network_types.h" #include "process/scheduler.h" #include "console/kio.h" #include "net/udp.h" diff --git a/kernel/networking/drivers/net_driver.hpp b/kernel/networking/drivers/net_driver.hpp index 2196cddf..16ec4f3c 100644 --- a/kernel/networking/drivers/net_driver.hpp +++ b/kernel/networking/drivers/net_driver.hpp @@ -3,7 +3,7 @@ #include "types.h" #include "std/string.h" #include "ui/graphic_types.h" -#include "network_types.h" +#include "net/network_types.h" class NetDriver { public: diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp index 20095881..5d43629a 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp @@ -1,6 +1,6 @@ #include "../net_driver.hpp" #include "virtio/virtio_pci.h" -#include "network_types.h" +#include "net/network_types.h" class VirtioNetDriver : public NetDriver { public: diff --git a/kernel/networking/network.h b/kernel/networking/network.h index f88c2eb5..f7a8b1fa 100644 --- a/kernel/networking/network.h +++ b/kernel/networking/network.h @@ -5,7 +5,7 @@ extern "C" { #endif #include "types.h" -#include "network_types.h" +#include "net/network_types.h" #define NET_IRQ 32 diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index 3c9efebd..37da9b29 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -1,6 +1,6 @@ #include "network_dispatch.hpp" #include "drivers/virtio_net_pci/virtio_net_pci.hpp" -#include "network_types.h" +#include "net/network_types.h" #include "console/kio.h" #include "process/scheduler.h" #include "net/udp.h" diff --git a/kernel/networking/network_dispatch.hpp b/kernel/networking/network_dispatch.hpp index 7417fdfa..c30d28f1 100644 --- a/kernel/networking/network_dispatch.hpp +++ b/kernel/networking/network_dispatch.hpp @@ -1,6 +1,6 @@ #pragma once -#include "network_types.h" +#include "net/network_types.h" #include "types.h" #include "std/indexmap.hpp" #include "drivers/net_driver.hpp" diff --git a/kernel/process/process.h b/kernel/process/process.h index 8398f7f0..be636578 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -6,7 +6,7 @@ extern "C" { #include "types.h" #include "keypress.h" -#include "network_types.h" +#include "net/network_types.h" #define INPUT_BUFFER_CAPACITY 64 #define PACKET_BUFFER_CAPACITY 128 diff --git a/shared/network_types.h b/shared/net/network_types.h similarity index 82% rename from shared/network_types.h rename to shared/net/network_types.h index 8b2b1a6c..2b0b3b6e 100644 --- a/shared/network_types.h +++ b/shared/net/network_types.h @@ -29,13 +29,6 @@ typedef struct __attribute__((packed)) ipv4_hdr_t { uint32_t dst_ip; } ipv4_hdr_t; -typedef struct __attribute__((packed)) udp_hdr_t { - uint16_t src_port; - uint16_t dst_port; - uint16_t length; - uint16_t checksum; -} udp_hdr_t; - typedef struct network_connection_ctx { uint16_t port; uint32_t ip; diff --git a/shared/net/udp.c b/shared/net/udp.c index 46d28c1e..42546113 100644 --- a/shared/net/udp.c +++ b/shared/net/udp.c @@ -1,6 +1,6 @@ #include "udp.h" #include "console/kio.h" -#include "network_types.h" +#include "net/network_types.h" #include "syscalls/syscalls.h" uint16_t udp_checksum( diff --git a/shared/net/udp.h b/shared/net/udp.h index 401c3cc8..81bb4782 100644 --- a/shared/net/udp.h +++ b/shared/net/udp.h @@ -5,7 +5,14 @@ extern "C" { #endif #include "types.h" -#include "network_types.h" +#include "net/network_types.h" + +typedef struct __attribute__((packed)) udp_hdr_t { + uint16_t src_port; + uint16_t dst_port; + uint16_t length; + uint16_t checksum; +} udp_hdr_t; void create_udp_packet(uint8_t* buf, network_connection_ctx source, network_connection_ctx destination, const uint8_t* payload, uint16_t payload_len); size_t calc_udp_size(uint16_t payload_len); diff --git a/shared/syscalls/syscalls.h b/shared/syscalls/syscalls.h index b71e97df..85cdcbfd 100644 --- a/shared/syscalls/syscalls.h +++ b/shared/syscalls/syscalls.h @@ -4,7 +4,7 @@ #include "ui/graphic_types.h" #include "keypress.h" #include "std/string.h" -#include "network_types.h" +#include "net/network_types.h" #ifdef __cplusplus extern "C" { From 13970719b510bdebad292506cdf854555896465a Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 20 Jun 2025 00:00:00 +0000 Subject: [PATCH 28/61] DHCP negotiation to receive an IP from router --- kernel/kernel_processes/net/net_proc.c | 41 +++++++++++++++-- kernel/networking/drivers/net_driver.hpp | 2 + .../drivers/virtio_net_pci/virtio_net_pci.cpp | 23 +++++++--- .../drivers/virtio_net_pci/virtio_net_pci.hpp | 1 - kernel/networking/network.cpp | 4 ++ kernel/networking/network.h | 2 + kernel/networking/network_dispatch.cpp | 4 ++ kernel/networking/network_dispatch.hpp | 2 + shared/net/dhcp.c | 45 +++++++++++++++++++ shared/net/dhcp.h | 36 +++++++++++++++ shared/net/network_types.h | 3 +- 11 files changed, 152 insertions(+), 11 deletions(-) create mode 100644 shared/net/dhcp.c create mode 100644 shared/net/dhcp.h diff --git a/kernel/kernel_processes/net/net_proc.c b/kernel/kernel_processes/net/net_proc.c index 52d0a850..8064fe3b 100644 --- a/kernel/kernel_processes/net/net_proc.c +++ b/kernel/kernel_processes/net/net_proc.c @@ -4,9 +4,12 @@ #include "process/scheduler.h" #include "console/kio.h" #include "net/udp.h" +#include "net/dhcp.h" +#include "networking/network.h" #include "syscalls/syscalls.h" void test_network(){ + bind_port(8888); network_connection_ctx dest = (network_connection_ctx){ .ip = (192 << 24) | (168 << 16) | (1 << 8) | 255, @@ -23,18 +26,48 @@ void test_network(){ while (!read_packet(&pack)); - kprintf("DONE"); - sizedptr payload = udp_parse_packet_payload(pack.ptr); uint8_t *content = (uint8_t*)payload.ptr; kprintf("PAYLOAD: %s",(uintptr_t)string_ca_max(content, payload.size).data); - stop_current_process(); unbind_port(8888); } +void negotiate_dhcp(){ + network_connection_ctx *ctx = network_get_context(); + bind_port(68); + if (ctx->ip == 0){ + send_packet(DHCP, 53, ctx, ctx->mac, 6); + } + + sizedptr ptr; + + while (!read_packet(&ptr)); + + kprintf("RECEIVED DHCP RESPONSE"); + + dhcp_packet *payload = dhcp_parse_packet_payload(ptr.ptr); + + if (payload){ + uint32_t local_ip = __builtin_bswap32(payload->yiaddr); + kprintf("Received local IP %i.%i.%i.%i",(local_ip >> 24) & 0xFF,(local_ip >> 16) & 0xFF,(local_ip >> 8) & 0xFF,(local_ip >> 0) & 0xFF); + + //We can parse options for + //Lease time + //DHCP Server identifier + //Subnet mask + //Router + //DNS (8 bytes) + ctx->ip = local_ip; + } + + // unbind_port(68); Do we need to keep this open? + test_network(); + stop_current_process(); +} + process_t* launch_net_process(){ - return create_kernel_process("nettest",test_network); + return create_kernel_process("nettest",negotiate_dhcp); } \ No newline at end of file diff --git a/kernel/networking/drivers/net_driver.hpp b/kernel/networking/drivers/net_driver.hpp index 16ec4f3c..99809719 100644 --- a/kernel/networking/drivers/net_driver.hpp +++ b/kernel/networking/drivers/net_driver.hpp @@ -17,4 +17,6 @@ class NetDriver { virtual void send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len) = 0; virtual ~NetDriver() = default; + + network_connection_ctx connection_context; }; \ No newline at end of file diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index 14a9a8d0..751317dc 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -1,6 +1,7 @@ #include "virtio_net_pci.hpp" #include "console/kio.h" #include "net/udp.h" +#include "net/dhcp.h" #include "networking/network.h" #include "pci.h" #include "syscalls/syscalls.h" @@ -88,7 +89,7 @@ bool VirtioNetDriver::init(){ connection_context = (network_connection_ctx){ .port = 0, - .ip = (uint32_t)((192 << 24) | (168 << 16) | (1 << 8) | 131), + .ip = 0, .mac = {net_config->mac[0],net_config->mac[1],net_config->mac[2],net_config->mac[3],net_config->mac[4],net_config->mac[5]}, }; @@ -166,11 +167,23 @@ sizedptr VirtioNetDriver::handle_receive_packet(){ void VirtioNetDriver::send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len){ select_queue(&vnp_net_dev, TRANSMIT_QUEUE); - size_t size = calc_udp_size(payload_len) + sizeof(virtio_net_hdr_t); - uintptr_t buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size, ALIGN_64B, true, true); - connection_context.port = port; - create_udp_packet((uint8_t*)(buf_ptr + sizeof(virtio_net_hdr_t)), connection_context, *destination, (uint8_t*)payload, payload_len); + size_t size; + uintptr_t buf_ptr; + switch (protocol) { + case UDP: + size = calc_udp_size(payload_len) + sizeof(virtio_net_hdr_t); + buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size, ALIGN_64B, true, true); + connection_context.port = port; + create_udp_packet((uint8_t*)(buf_ptr + sizeof(virtio_net_hdr_t)), connection_context, *destination, (uint8_t*)payload, payload_len); + break; + case DHCP: + size = DHCP_SIZE + sizeof(virtio_net_hdr_t); + buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, DHCP_SIZE, ALIGN_64B, true, true); + create_dhcp_packet((uint8_t*)(buf_ptr + sizeof(virtio_net_hdr_t)), (uint8_t*)payload); + break; + } virtio_send_1d(&vnp_net_dev, buf_ptr, size); + kprintf("Queued new packet"); } diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp index 5d43629a..1816e3ac 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp @@ -22,5 +22,4 @@ class VirtioNetDriver : public NetDriver { bool verbose = false; uint16_t last_used_receive_idx = 0; virtio_device vnp_net_dev; - network_connection_ctx connection_context; }; \ No newline at end of file diff --git a/kernel/networking/network.cpp b/kernel/networking/network.cpp index 6de1910f..88c096b4 100644 --- a/kernel/networking/network.cpp +++ b/kernel/networking/network.cpp @@ -42,3 +42,7 @@ bool network_read_packet(sizedptr *packet, uint16_t process){ bool network_read_packet_current(sizedptr *packet){ return dispatch->read_packet(packet, get_current_proc_pid()); } + +network_connection_ctx* network_get_context(){ + return dispatch->get_context(); +} \ No newline at end of file diff --git a/kernel/networking/network.h b/kernel/networking/network.h index f7a8b1fa..4e1ade92 100644 --- a/kernel/networking/network.h +++ b/kernel/networking/network.h @@ -21,6 +21,8 @@ bool network_unbind_port_current(uint16_t port); bool network_read_packet(sizedptr *packet, uint16_t process); bool network_read_packet_current(sizedptr *packet); +network_connection_ctx* network_get_context(); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index 37da9b29..7d142462 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -74,4 +74,8 @@ bool NetworkDispatch::read_packet(sizedptr *Packet, uint16_t process){ void NetworkDispatch::send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len){ if (driver) driver->send_packet(protocol, port, destination, payload, payload_len); +} + +network_connection_ctx* NetworkDispatch::get_context(){ + return &driver->connection_context; } \ No newline at end of file diff --git a/kernel/networking/network_dispatch.hpp b/kernel/networking/network_dispatch.hpp index c30d28f1..d7d59c11 100644 --- a/kernel/networking/network_dispatch.hpp +++ b/kernel/networking/network_dispatch.hpp @@ -15,6 +15,8 @@ class NetworkDispatch { void send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len); bool read_packet(sizedptr *Packet, uint16_t process); + network_connection_ctx* get_context(); + private: IndexMap ports; NetDriver *driver; diff --git a/shared/net/dhcp.c b/shared/net/dhcp.c new file mode 100644 index 00000000..7433422f --- /dev/null +++ b/shared/net/dhcp.c @@ -0,0 +1,45 @@ +#include "dhcp.h" +#include "std/memfunctions.h" + +void create_dhcp_packet(uint8_t* buf, uint8_t mac[6]){ + network_connection_ctx source = (network_connection_ctx){ + .port = 68, + }; + network_connection_ctx destination = (network_connection_ctx){ + .ip = (255 << 24) | (255 << 16) | (255 << 8) | 255, + .mac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + .port = 67, + }; + dhcp_packet packet = (dhcp_packet){ + .op = 1,//request + .htype = 1,//Ethernet + .hlen = 6,//Mac length + .hops = 0, + .xid = 372,//Transaction ID: Static, could be random + .secs = 0, + .flags = __builtin_bswap16(0x8000),//Broadcast + .ciaddr = 0, + .yiaddr = 0, + .siaddr = 0, + .giaddr = 0, + }; + memcpy(packet.chaddr, mac, 6); + memcpy(source.mac, mac, 6); + + packet.options[0] = 0x63; // magic + packet.options[1] = 0x82; + packet.options[2] = 0x53; + packet.options[3] = 0x63; // magic + + packet.options[4] = 53; // DHCP type + packet.options[5] = 1; // length + packet.options[6] = 1; // DHCPDISCOVER + + packet.options[7] = 255; // END + create_udp_packet(buf, source, destination, (uint8_t*)&packet, sizeof(dhcp_packet)); +} + +dhcp_packet* dhcp_parse_packet_payload(uintptr_t ptr){ + sizedptr sptr = udp_parse_packet_payload(ptr); + return (dhcp_packet*)sptr.ptr; +} \ No newline at end of file diff --git a/shared/net/dhcp.h b/shared/net/dhcp.h new file mode 100644 index 00000000..b33b450c --- /dev/null +++ b/shared/net/dhcp.h @@ -0,0 +1,36 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "types.h" +#include "network_types.h" +#include "udp.h" + +typedef struct __attribute__((packed)) dhcp_packet { + uint8_t op; + uint8_t htype; + uint8_t hlen; + uint8_t hops; + uint32_t xid; + uint16_t secs; + uint16_t flags; + uint32_t ciaddr; + uint32_t yiaddr; + uint32_t siaddr; + uint32_t giaddr; + uint8_t chaddr[16]; + uint8_t sname[64]; + uint8_t file[128]; + uint8_t options[312]; +} dhcp_packet; + +#define DHCP_SIZE sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) + sizeof(dhcp_packet) + +void create_dhcp_packet(uint8_t* buf, uint8_t mac[6]); +dhcp_packet* dhcp_parse_packet_payload(uintptr_t ptr); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/shared/net/network_types.h b/shared/net/network_types.h index 2b0b3b6e..74f12a8a 100644 --- a/shared/net/network_types.h +++ b/shared/net/network_types.h @@ -7,7 +7,8 @@ extern "C" { #include "types.h" typedef enum NetProtocol { - UDP + UDP, + DHCP } NetProtocol; typedef struct __attribute__((packed)) eth_hdr_t { From a2045d0e4b221ae11b7131b879b7cfd12487c14e Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 20 Jun 2025 00:00:00 +0000 Subject: [PATCH 29/61] Rearranged networking files --- kernel/kernel.c | 2 +- kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp | 2 +- .../net => networking/processes}/net_proc.c | 6 +++--- .../net => networking/processes}/net_proc.h | 0 {shared/net => kernel/networking/protocols}/dhcp.c | 0 {shared/net => kernel/networking/protocols}/dhcp.h | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) rename kernel/{kernel_processes/net => networking/processes}/net_proc.c (94%) rename kernel/{kernel_processes/net => networking/processes}/net_proc.h (100%) rename {shared/net => kernel/networking/protocols}/dhcp.c (100%) rename {shared/net => kernel/networking/protocols}/dhcp.h (92%) diff --git a/kernel/kernel.c b/kernel/kernel.c index 26083c38..da6362a9 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -14,7 +14,7 @@ #include "input/xhci_bridge.h" #include "input/xhci.h" #include "kernel_processes/monitor/monitor_processes.h" -#include "kernel_processes/net/net_proc.h" +#include "networking/processes/net_proc.h" #include "memory/page_allocator.h" #include "networking/network.h" diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index 751317dc..1127be84 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -1,7 +1,7 @@ #include "virtio_net_pci.hpp" #include "console/kio.h" #include "net/udp.h" -#include "net/dhcp.h" +#include "../../protocols/dhcp.h" #include "networking/network.h" #include "pci.h" #include "syscalls/syscalls.h" diff --git a/kernel/kernel_processes/net/net_proc.c b/kernel/networking/processes/net_proc.c similarity index 94% rename from kernel/kernel_processes/net/net_proc.c rename to kernel/networking/processes/net_proc.c index 8064fe3b..03085e5d 100644 --- a/kernel/kernel_processes/net/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -1,10 +1,10 @@ #include "net_proc.h" -#include "../kprocess_loader.h" +#include "kernel_processes/kprocess_loader.h" #include "net/network_types.h" #include "process/scheduler.h" #include "console/kio.h" #include "net/udp.h" -#include "net/dhcp.h" +#include "../protocols/dhcp.h" #include "networking/network.h" #include "syscalls/syscalls.h" @@ -63,7 +63,7 @@ void negotiate_dhcp(){ ctx->ip = local_ip; } - // unbind_port(68); Do we need to keep this open? + unbind_port(68); test_network(); stop_current_process(); } diff --git a/kernel/kernel_processes/net/net_proc.h b/kernel/networking/processes/net_proc.h similarity index 100% rename from kernel/kernel_processes/net/net_proc.h rename to kernel/networking/processes/net_proc.h diff --git a/shared/net/dhcp.c b/kernel/networking/protocols/dhcp.c similarity index 100% rename from shared/net/dhcp.c rename to kernel/networking/protocols/dhcp.c diff --git a/shared/net/dhcp.h b/kernel/networking/protocols/dhcp.h similarity index 92% rename from shared/net/dhcp.h rename to kernel/networking/protocols/dhcp.h index b33b450c..5e7fad68 100644 --- a/shared/net/dhcp.h +++ b/kernel/networking/protocols/dhcp.h @@ -5,8 +5,8 @@ extern "C" { #endif #include "types.h" -#include "network_types.h" -#include "udp.h" +#include "net/network_types.h" +#include "net/udp.h" typedef struct __attribute__((packed)) dhcp_packet { uint8_t op; From 82dd70341f77faa60f7a3c429a8c058810680b1f Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 20 Jun 2025 00:00:00 +0000 Subject: [PATCH 30/61] Started to implement ARP --- .../drivers/virtio_net_pci/virtio_net_pci.cpp | 10 ++++- kernel/networking/network_dispatch.cpp | 30 +++++++++------ kernel/networking/processes/net_proc.c | 3 +- kernel/networking/protocols/arp.c | 24 ++++++++++++ kernel/networking/protocols/arp.h | 26 +++++++++++++ shared/net/eth.c | 20 ++++++++++ shared/net/eth.h | 15 ++++++++ shared/net/network_types.h | 4 +- shared/net/udp.c | 38 ++++++------------- 9 files changed, 129 insertions(+), 41 deletions(-) create mode 100644 kernel/networking/protocols/arp.c create mode 100644 kernel/networking/protocols/arp.h create mode 100644 shared/net/eth.c create mode 100644 shared/net/eth.h diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index 1127be84..ac78841f 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -2,6 +2,7 @@ #include "console/kio.h" #include "net/udp.h" #include "../../protocols/dhcp.h" +#include "../../protocols/arp.h" #include "networking/network.h" #include "pci.h" #include "syscalls/syscalls.h" @@ -178,8 +179,15 @@ void VirtioNetDriver::send_packet(NetProtocol protocol, uint16_t port, network_c break; case DHCP: size = DHCP_SIZE + sizeof(virtio_net_hdr_t); - buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, DHCP_SIZE, ALIGN_64B, true, true); + buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size, ALIGN_64B, true, true); create_dhcp_packet((uint8_t*)(buf_ptr + sizeof(virtio_net_hdr_t)), (uint8_t*)payload); + break; + case ARP: + size = sizeof(eth_hdr_t) + sizeof(arp_hdr_t); + buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size, ALIGN_64B, true, true); + create_arp_packet((uint8_t*)(buf_ptr + sizeof(virtio_net_hdr_t)), connection_context.mac, connection_context.ip, destination->mac, destination->ip, *(bool*)payload); + break; + default: break; } virtio_send_1d(&vnp_net_dev, buf_ptr, size); diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index 7d142462..0410d8ce 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -4,6 +4,7 @@ #include "console/kio.h" #include "process/scheduler.h" #include "net/udp.h" +#include "net/eth.h" #include "memory/page_allocator.h" #include "std/memfunctions.h" @@ -37,20 +38,25 @@ void NetworkDispatch::handle_interrupt(){ if (driver){ sizedptr packet = driver->handle_receive_packet(); if (packet.ptr){ - uint16_t port = udp_parse_packet(packet.ptr); - if (ports[port] != UINT16_MAX){ - process_t *proc = get_proc_by_pid(ports[port]); - if (!proc) - unbind_port(port, ports[port]); - else { - packet_buffer_t* buf = &proc->packet_buffer; - uint32_t next_index = (buf->write_index + 1) % PACKET_BUFFER_CAPACITY; + uint16_t ethtype = eth_parse_packet_type(packet.ptr); + if (ethtype == 0x806){ + kprintf("We've received an ARP packet, but it's too late to write a parser for it rn. gn"); + } else if (ethtype == 0x800){//IPV4 + uint16_t port = udp_parse_packet(packet.ptr + sizeof(eth_hdr_t)); + if (ports[port] != UINT16_MAX){ + process_t *proc = get_proc_by_pid(ports[port]); + if (!proc) + unbind_port(port, ports[port]); + else { + packet_buffer_t* buf = &proc->packet_buffer; + uint32_t next_index = (buf->write_index + 1) % PACKET_BUFFER_CAPACITY; - buf->entries[buf->write_index] = packet; - buf->write_index = next_index; + buf->entries[buf->write_index] = packet; + buf->write_index = next_index; - if (buf->write_index == buf->read_index) - buf->read_index = (buf->read_index + 1) % PACKET_BUFFER_CAPACITY; + if (buf->write_index == buf->read_index) + buf->read_index = (buf->read_index + 1) % PACKET_BUFFER_CAPACITY; + } } } } diff --git a/kernel/networking/processes/net_proc.c b/kernel/networking/processes/net_proc.c index 03085e5d..56ae43a4 100644 --- a/kernel/networking/processes/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -36,6 +36,7 @@ void test_network(){ } void negotiate_dhcp(){ + kprintf("Sending DHCP request"); network_connection_ctx *ctx = network_get_context(); bind_port(68); if (ctx->ip == 0){ @@ -46,7 +47,7 @@ void negotiate_dhcp(){ while (!read_packet(&ptr)); - kprintf("RECEIVED DHCP RESPONSE"); + kprintf("Received DHCP response"); dhcp_packet *payload = dhcp_parse_packet_payload(ptr.ptr); diff --git a/kernel/networking/protocols/arp.c b/kernel/networking/protocols/arp.c new file mode 100644 index 00000000..9ef6c0b3 --- /dev/null +++ b/kernel/networking/protocols/arp.c @@ -0,0 +1,24 @@ +#include "arp.h" +#include "std/memfunctions.h" + +void create_arp_packet(uint8_t* buf, uint8_t* src_mac, uint32_t src_ip, uint8_t* dst_mac, uint32_t dst_ip, bool is_request){ + uintptr_t p = (uintptr_t)buf; + + eth_hdr_t* eth = (eth_hdr_t*)p; + for (int i = 0; i < 6; i++) eth->dst_mac[i] = is_request ? 0xFF : dst_mac[i]; + memcpy(eth->src_mac, src_mac, 6); + eth->ethertype = __builtin_bswap16(0x0806); + p += sizeof(eth_hdr_t); + + arp_hdr_t* arp = (arp_hdr_t*)p; + + arp->htype = 1; + arp->ptype = __builtin_bswap16(0x0800); + arp->hlen = 6; + arp->plen = 4; + arp->opcode = __builtin_bswap16(is_request ? 1 : 2); + memcpy(arp->sender_mac, src_mac, 6); + arp->sender_ip = src_ip; + memcpy(arp->target_mac, dst_mac, 6); + arp->target_ip = dst_ip; +} \ No newline at end of file diff --git a/kernel/networking/protocols/arp.h b/kernel/networking/protocols/arp.h new file mode 100644 index 00000000..f56e0a7a --- /dev/null +++ b/kernel/networking/protocols/arp.h @@ -0,0 +1,26 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "types.h" +#include "net/network_types.h" + +typedef struct __attribute__((packed)) arp_hdr_t { + uint16_t htype; + uint16_t ptype; + uint8_t hlen; + uint8_t plen; + uint16_t opcode; + uint8_t sender_mac[6]; + uint32_t sender_ip; + uint8_t target_mac[6]; + uint32_t target_ip; +} arp_hdr_t; + +void create_arp_packet(uint8_t* buf, uint8_t* src_mac, uint32_t src_ip, uint8_t* dst_mac, uint32_t dst_ip, bool is_request); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/shared/net/eth.c b/shared/net/eth.c new file mode 100644 index 00000000..45eea611 --- /dev/null +++ b/shared/net/eth.c @@ -0,0 +1,20 @@ +#include "eth.h" +#include "std/memfunctions.h" + +uintptr_t create_eth_packet(uint8_t* buf, uint8_t src_mac[6], uint8_t dst_mac[6], uint16_t type){ + uintptr_t p = (uintptr_t)buf; + + eth_hdr_t* eth = (eth_hdr_t*)p; + memcpy(eth->src_mac, src_mac, 6); + memcpy(eth->dst_mac, dst_mac, 6); + eth->ethertype = __builtin_bswap16(type); + return p + sizeof(eth_hdr_t); +} + +uint16_t eth_parse_packet_type(uintptr_t ptr){ + eth_hdr_t* eth = (eth_hdr_t*)ptr; + + ptr += sizeof(eth_hdr_t); + + return __builtin_bswap16(eth->ethertype); +} \ No newline at end of file diff --git a/shared/net/eth.h b/shared/net/eth.h new file mode 100644 index 00000000..2add12c9 --- /dev/null +++ b/shared/net/eth.h @@ -0,0 +1,15 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "types.h" +#include "net/network_types.h" + +uint16_t eth_parse_packet_type(uintptr_t ptr); +uintptr_t create_eth_packet(uint8_t* buf, uint8_t src_mac[6], uint8_t dst_mac[6], uint16_t type); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/shared/net/network_types.h b/shared/net/network_types.h index 74f12a8a..3e59713e 100644 --- a/shared/net/network_types.h +++ b/shared/net/network_types.h @@ -8,7 +8,9 @@ extern "C" { typedef enum NetProtocol { UDP, - DHCP + DHCP, + ARP, + TCP } NetProtocol; typedef struct __attribute__((packed)) eth_hdr_t { diff --git a/shared/net/udp.c b/shared/net/udp.c index 42546113..f21d5428 100644 --- a/shared/net/udp.c +++ b/shared/net/udp.c @@ -2,6 +2,7 @@ #include "console/kio.h" #include "net/network_types.h" #include "syscalls/syscalls.h" +#include "eth.h" uint16_t udp_checksum( uint32_t src_ip, @@ -32,13 +33,7 @@ uint16_t udp_checksum( } void create_udp_packet(uint8_t* buf, network_connection_ctx source, network_connection_ctx destination, const uint8_t* payload, uint16_t payload_len) { - uintptr_t p = (uintptr_t)buf; - - eth_hdr_t* eth = (eth_hdr_t*)p; - for (int i = 0; i < 6; i++) eth->dst_mac[i] = destination.mac[i]; - for (int i = 0; i < 6; i++) eth->src_mac[i] = source.mac[i]; - eth->ethertype = __builtin_bswap16(0x0800); - p += sizeof(eth_hdr_t); + uintptr_t p = create_eth_packet(buf, source.mac, destination.mac, 0x800); ipv4_hdr_t* ip = (ipv4_hdr_t*)p; ip->version_ihl = 0x45; @@ -73,25 +68,16 @@ void create_udp_packet(uint8_t* buf, network_connection_ctx source, network_conn } uint16_t udp_parse_packet(uintptr_t ptr){ - eth_hdr_t* eth = (eth_hdr_t*)ptr; - - ptr += sizeof(eth_hdr_t); - - if (__builtin_bswap16(eth->ethertype) == 0x800){ - ipv4_hdr_t* ip = (ipv4_hdr_t*)ptr; - uint32_t srcip = __builtin_bswap32(ip->src_ip); - ptr += sizeof(ipv4_hdr_t); - if (ip->protocol == 0x11){ - udp_hdr_t* udp = (udp_hdr_t*)ptr; - ptr += sizeof(udp_hdr_t); - uint16_t port = __builtin_bswap16(udp->dst_port); - return port; - } else { - // kprintf("[UDP packet] Not prepared to handle non-UDP packets %x",ip->protocol); - } - } - else { - // kprintf("[UDP packet] Not prepared to handle non-ipv4 packets %x",__builtin_bswap16(eth->ethertype)); + ipv4_hdr_t* ip = (ipv4_hdr_t*)ptr; + uint32_t srcip = __builtin_bswap32(ip->src_ip); + ptr += sizeof(ipv4_hdr_t); + if (ip->protocol == 0x11){ + udp_hdr_t* udp = (udp_hdr_t*)ptr; + ptr += sizeof(udp_hdr_t); + uint16_t port = __builtin_bswap16(udp->dst_port); + return port; + } else { + // kprintf("[UDP packet] Not prepared to handle non-UDP packets %x",ip->protocol); } return 0; From b1887da8325cc0d67048d903f5ecbab5da19de7c Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 20 Jun 2025 00:00:00 +0000 Subject: [PATCH 31/61] Finished DHCP and continuing ARP --- .../drivers/virtio_net_pci/virtio_net_pci.cpp | 2 +- kernel/networking/network_dispatch.cpp | 5 ++- kernel/networking/processes/net_proc.c | 44 ++++++++++++++++--- kernel/networking/protocols/arp.c | 6 +++ kernel/networking/protocols/arp.h | 1 + kernel/networking/protocols/dhcp.c | 33 +++++++++++--- kernel/networking/protocols/dhcp.h | 9 +++- 7 files changed, 85 insertions(+), 15 deletions(-) diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index ac78841f..c566704b 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -180,7 +180,7 @@ void VirtioNetDriver::send_packet(NetProtocol protocol, uint16_t port, network_c case DHCP: size = DHCP_SIZE + sizeof(virtio_net_hdr_t); buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size, ALIGN_64B, true, true); - create_dhcp_packet((uint8_t*)(buf_ptr + sizeof(virtio_net_hdr_t)), (uint8_t*)payload); + create_dhcp_packet((uint8_t*)(buf_ptr + sizeof(virtio_net_hdr_t)), (dhcp_request*)payload); break; case ARP: size = sizeof(eth_hdr_t) + sizeof(arp_hdr_t); diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index 0410d8ce..27564f78 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -7,6 +7,7 @@ #include "net/eth.h" #include "memory/page_allocator.h" #include "std/memfunctions.h" +#include "protocols/arp.h" NetworkDispatch::NetworkDispatch(){ ports = IndexMap(UINT16_MAX); @@ -40,7 +41,9 @@ void NetworkDispatch::handle_interrupt(){ if (packet.ptr){ uint16_t ethtype = eth_parse_packet_type(packet.ptr); if (ethtype == 0x806){ - kprintf("We've received an ARP packet, but it's too late to write a parser for it rn. gn"); + if (arp_should_handle(packet.ptr + sizeof(eth_hdr_t), get_context()->ip)) + kprintf("We've received an ARP packet, but it's too late to write a parser for it rn. gn"); + //create_arp_packet((uint8_t*)(buf_ptr + sizeof(virtio_net_hdr_t)), connection_context.mac, connection_context.ip, destination->mac, destination->ip, *(bool*)payload); } else if (ethtype == 0x800){//IPV4 uint16_t port = udp_parse_packet(packet.ptr + sizeof(eth_hdr_t)); if (ports[port] != UINT16_MAX){ diff --git a/kernel/networking/processes/net_proc.c b/kernel/networking/processes/net_proc.c index 56ae43a4..07a0db6c 100644 --- a/kernel/networking/processes/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -5,6 +5,8 @@ #include "console/kio.h" #include "net/udp.h" #include "../protocols/dhcp.h" +#include "../protocols/dhcp.h" +#include "std/memfunctions.h" #include "networking/network.h" #include "syscalls/syscalls.h" @@ -39,9 +41,15 @@ void negotiate_dhcp(){ kprintf("Sending DHCP request"); network_connection_ctx *ctx = network_get_context(); bind_port(68); - if (ctx->ip == 0){ - send_packet(DHCP, 53, ctx, ctx->mac, 6); - } + if (ctx->ip != 0) + return; + dhcp_request request = (dhcp_request){ + .mac = 0, + .offered_ip = 0, + .server_ip = 0, + }; + memcpy(request.mac, ctx->mac, 6); + send_packet(DHCP, 53, ctx, &request, sizeof(dhcp_request)); sizedptr ptr; @@ -54,13 +62,37 @@ void negotiate_dhcp(){ if (payload){ uint32_t local_ip = __builtin_bswap32(payload->yiaddr); kprintf("Received local IP %i.%i.%i.%i",(local_ip >> 24) & 0xFF,(local_ip >> 16) & 0xFF,(local_ip >> 8) & 0xFF,(local_ip >> 0) & 0xFF); + request.offered_ip = payload->yiaddr; + + uint16_t opt_index = dhcp_parse_option(payload, 53); + if (payload->options[opt_index + 2] != 2){ + negotiate_dhcp(); + return; + } + + uint16_t serv_index = dhcp_parse_option(payload, 54); + memcpy((void*)&request.server_ip, (void*)(payload->options + serv_index + 2), payload->options[serv_index+1]); + + send_packet(DHCP, 53, ctx, &request, sizeof(dhcp_request)); + + while (!read_packet(&ptr)); + + payload = dhcp_parse_packet_payload(ptr.ptr); + opt_index = dhcp_parse_option(payload, 53); + if (payload->options[opt_index + 2] != 5){ + kprintf("Did not receive acknowledge for DHCP"); + negotiate_dhcp(); + return; + } + + kprintf("DHCP negotiation finished"); //We can parse options for - //Lease time + //Lease time (51) //DHCP Server identifier //Subnet mask - //Router - //DNS (8 bytes) + //Router (3) + //DNS (8 bytes) (6) ctx->ip = local_ip; } diff --git a/kernel/networking/protocols/arp.c b/kernel/networking/protocols/arp.c index 9ef6c0b3..0862743a 100644 --- a/kernel/networking/protocols/arp.c +++ b/kernel/networking/protocols/arp.c @@ -21,4 +21,10 @@ void create_arp_packet(uint8_t* buf, uint8_t* src_mac, uint32_t src_ip, uint8_t* arp->sender_ip = src_ip; memcpy(arp->target_mac, dst_mac, 6); arp->target_ip = dst_ip; +} + +bool arp_should_handle(uintptr_t ptr, uint32_t ip){ + arp_hdr_t* arp = (arp_hdr_t*)ptr; + + return arp->target_ip == ip; } \ No newline at end of file diff --git a/kernel/networking/protocols/arp.h b/kernel/networking/protocols/arp.h index f56e0a7a..b5e47080 100644 --- a/kernel/networking/protocols/arp.h +++ b/kernel/networking/protocols/arp.h @@ -20,6 +20,7 @@ typedef struct __attribute__((packed)) arp_hdr_t { } arp_hdr_t; void create_arp_packet(uint8_t* buf, uint8_t* src_mac, uint32_t src_ip, uint8_t* dst_mac, uint32_t dst_ip, bool is_request); +bool arp_should_handle(uintptr_t ptr, uint32_t ip); #ifdef __cplusplus } diff --git a/kernel/networking/protocols/dhcp.c b/kernel/networking/protocols/dhcp.c index 7433422f..b346b862 100644 --- a/kernel/networking/protocols/dhcp.c +++ b/kernel/networking/protocols/dhcp.c @@ -1,7 +1,7 @@ #include "dhcp.h" #include "std/memfunctions.h" -void create_dhcp_packet(uint8_t* buf, uint8_t mac[6]){ +void create_dhcp_packet(uint8_t* buf, dhcp_request *payload){ network_connection_ctx source = (network_connection_ctx){ .port = 68, }; @@ -23,8 +23,8 @@ void create_dhcp_packet(uint8_t* buf, uint8_t mac[6]){ .siaddr = 0, .giaddr = 0, }; - memcpy(packet.chaddr, mac, 6); - memcpy(source.mac, mac, 6); + memcpy(packet.chaddr, payload->mac, 6); + memcpy(source.mac, payload->mac, 6); packet.options[0] = 0x63; // magic packet.options[1] = 0x82; @@ -33,13 +33,34 @@ void create_dhcp_packet(uint8_t* buf, uint8_t mac[6]){ packet.options[4] = 53; // DHCP type packet.options[5] = 1; // length - packet.options[6] = 1; // DHCPDISCOVER + if (payload->server_ip != 0 && payload->offered_ip != 0){ + packet.options[6] = 3; // DHCPREQUEST - packet.options[7] = 255; // END - create_udp_packet(buf, source, destination, (uint8_t*)&packet, sizeof(dhcp_packet)); + packet.options[7] = 50; + packet.options[8] = 4; + memcpy(&packet.options[9], &payload->offered_ip, 4); + + packet.options[13] = 54; + packet.options[14] = 4; + memcpy(&packet.options[15], &payload->server_ip, 4); + packet.options[19] = 255; + } else { + packet.options[6] = 1; // DHCPDISCOVER + + packet.options[7] = 255; // END + } + + create_udp_packet(buf, source, destination, (uint8_t*)&packet, sizeof(dhcp_packet)); } dhcp_packet* dhcp_parse_packet_payload(uintptr_t ptr){ sizedptr sptr = udp_parse_packet_payload(ptr); return (dhcp_packet*)sptr.ptr; +} + +uint16_t dhcp_parse_option(dhcp_packet *pack, uint16_t option){ + for (int i = 0; i < 312; i++) + if (pack->options[i] == option) return i; + + return 0; } \ No newline at end of file diff --git a/kernel/networking/protocols/dhcp.h b/kernel/networking/protocols/dhcp.h index 5e7fad68..88e1f137 100644 --- a/kernel/networking/protocols/dhcp.h +++ b/kernel/networking/protocols/dhcp.h @@ -26,10 +26,17 @@ typedef struct __attribute__((packed)) dhcp_packet { uint8_t options[312]; } dhcp_packet; +typedef struct dhcp_request { + uint8_t mac[6]; + uint32_t server_ip; + uint32_t offered_ip; +} dhcp_request; + #define DHCP_SIZE sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) + sizeof(dhcp_packet) -void create_dhcp_packet(uint8_t* buf, uint8_t mac[6]); +void create_dhcp_packet(uint8_t* buf, dhcp_request *data); dhcp_packet* dhcp_parse_packet_payload(uintptr_t ptr); +uint16_t dhcp_parse_option(dhcp_packet *pack, uint16_t option); #ifdef __cplusplus } From b5b1e4d853228b7b4e9f7854fd5db00e38a37877 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 20 Jun 2025 00:00:00 +0000 Subject: [PATCH 32/61] Untested, possibly broken ARP responses --- kernel/networking/network_dispatch.cpp | 12 +++++++++--- kernel/networking/protocols/arp.c | 8 ++++++-- kernel/networking/protocols/arp.h | 3 ++- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index 27564f78..5e949d69 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -41,9 +41,15 @@ void NetworkDispatch::handle_interrupt(){ if (packet.ptr){ uint16_t ethtype = eth_parse_packet_type(packet.ptr); if (ethtype == 0x806){ - if (arp_should_handle(packet.ptr + sizeof(eth_hdr_t), get_context()->ip)) - kprintf("We've received an ARP packet, but it's too late to write a parser for it rn. gn"); - //create_arp_packet((uint8_t*)(buf_ptr + sizeof(virtio_net_hdr_t)), connection_context.mac, connection_context.ip, destination->mac, destination->ip, *(bool*)payload); + arp_hdr_t *arp = (arp_hdr_t*)(packet.ptr + sizeof(eth_hdr_t)); + if (arp_should_handle(arp, get_context()->ip)){ + kprintf("Received an ARP request"); + bool req = 0; + network_connection_ctx conn; + arp_populate_response(&conn, arp); + send_packet(ARP, 0, &conn, &req, 1); + } + //Should also look for responses to our own queries } else if (ethtype == 0x800){//IPV4 uint16_t port = udp_parse_packet(packet.ptr + sizeof(eth_hdr_t)); if (ports[port] != UINT16_MAX){ diff --git a/kernel/networking/protocols/arp.c b/kernel/networking/protocols/arp.c index 0862743a..4c6d7e4a 100644 --- a/kernel/networking/protocols/arp.c +++ b/kernel/networking/protocols/arp.c @@ -23,8 +23,12 @@ void create_arp_packet(uint8_t* buf, uint8_t* src_mac, uint32_t src_ip, uint8_t* arp->target_ip = dst_ip; } -bool arp_should_handle(uintptr_t ptr, uint32_t ip){ - arp_hdr_t* arp = (arp_hdr_t*)ptr; +void arp_populate_response(network_connection_ctx *ctx, arp_hdr_t* arp){ + memcpy(ctx->mac, arp->sender_mac, 6); + ctx->ip = arp->sender_ip; +} + +bool arp_should_handle(arp_hdr_t *arp, uint32_t ip){ return arp->target_ip == ip; } \ No newline at end of file diff --git a/kernel/networking/protocols/arp.h b/kernel/networking/protocols/arp.h index b5e47080..14f7497a 100644 --- a/kernel/networking/protocols/arp.h +++ b/kernel/networking/protocols/arp.h @@ -20,7 +20,8 @@ typedef struct __attribute__((packed)) arp_hdr_t { } arp_hdr_t; void create_arp_packet(uint8_t* buf, uint8_t* src_mac, uint32_t src_ip, uint8_t* dst_mac, uint32_t dst_ip, bool is_request); -bool arp_should_handle(uintptr_t ptr, uint32_t ip); +bool arp_should_handle(arp_hdr_t *arp, uint32_t ip); +void arp_populate_response(network_connection_ctx *ctx, arp_hdr_t* arp); #ifdef __cplusplus } From f09614c4378ac32d93e637ba6f44595ec9dc577c Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 20 Jun 2025 00:00:00 +0000 Subject: [PATCH 33/61] IPV4 into own files, starting to implement ICMP --- .../drivers/virtio_net_pci/virtio_net_pci.cpp | 6 +-- kernel/networking/network_dispatch.cpp | 37 +++++++++------- kernel/networking/protocols/arp.c | 4 +- kernel/networking/protocols/arp.h | 2 +- kernel/networking/protocols/dhcp.c | 4 +- kernel/networking/protocols/dhcp.h | 2 +- kernel/networking/protocols/icmp.h | 26 +++++++++++ shared/net/eth.c | 4 +- shared/net/eth.h | 2 +- shared/net/ipv4.c | 26 +++++++++++ shared/net/ipv4.h | 15 +++++++ shared/net/udp.c | 44 +++++-------------- shared/net/udp.h | 2 +- 13 files changed, 110 insertions(+), 64 deletions(-) create mode 100644 kernel/networking/protocols/icmp.h create mode 100644 shared/net/ipv4.c create mode 100644 shared/net/ipv4.h diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index c566704b..de6c67c0 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -175,17 +175,17 @@ void VirtioNetDriver::send_packet(NetProtocol protocol, uint16_t port, network_c size = calc_udp_size(payload_len) + sizeof(virtio_net_hdr_t); buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size, ALIGN_64B, true, true); connection_context.port = port; - create_udp_packet((uint8_t*)(buf_ptr + sizeof(virtio_net_hdr_t)), connection_context, *destination, (uint8_t*)payload, payload_len); + create_udp_packet(buf_ptr + sizeof(virtio_net_hdr_t), connection_context, *destination, (uint8_t*)payload, payload_len); break; case DHCP: size = DHCP_SIZE + sizeof(virtio_net_hdr_t); buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size, ALIGN_64B, true, true); - create_dhcp_packet((uint8_t*)(buf_ptr + sizeof(virtio_net_hdr_t)), (dhcp_request*)payload); + create_dhcp_packet(buf_ptr + sizeof(virtio_net_hdr_t), (dhcp_request*)payload); break; case ARP: size = sizeof(eth_hdr_t) + sizeof(arp_hdr_t); buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size, ALIGN_64B, true, true); - create_arp_packet((uint8_t*)(buf_ptr + sizeof(virtio_net_hdr_t)), connection_context.mac, connection_context.ip, destination->mac, destination->ip, *(bool*)payload); + create_arp_packet(buf_ptr + sizeof(virtio_net_hdr_t), connection_context.mac, connection_context.ip, destination->mac, destination->ip, *(bool*)payload); break; default: break; diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index 5e949d69..d716933f 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -5,6 +5,7 @@ #include "process/scheduler.h" #include "net/udp.h" #include "net/eth.h" +#include "net/ipv4.h" #include "memory/page_allocator.h" #include "std/memfunctions.h" #include "protocols/arp.h" @@ -38,10 +39,12 @@ bool NetworkDispatch::unbind_port(uint16_t port, uint16_t process){ void NetworkDispatch::handle_interrupt(){ if (driver){ sizedptr packet = driver->handle_receive_packet(); - if (packet.ptr){ - uint16_t ethtype = eth_parse_packet_type(packet.ptr); + uintptr_t ptr = packet.ptr; + if (ptr){ + uint16_t ethtype = eth_parse_packet_type(ptr); + ptr += sizeof(eth_hdr_t); if (ethtype == 0x806){ - arp_hdr_t *arp = (arp_hdr_t*)(packet.ptr + sizeof(eth_hdr_t)); + arp_hdr_t *arp = (arp_hdr_t*)ptr; if (arp_should_handle(arp, get_context()->ip)){ kprintf("Received an ARP request"); bool req = 0; @@ -51,20 +54,24 @@ void NetworkDispatch::handle_interrupt(){ } //Should also look for responses to our own queries } else if (ethtype == 0x800){//IPV4 - uint16_t port = udp_parse_packet(packet.ptr + sizeof(eth_hdr_t)); - if (ports[port] != UINT16_MAX){ - process_t *proc = get_proc_by_pid(ports[port]); - if (!proc) - unbind_port(port, ports[port]); - else { - packet_buffer_t* buf = &proc->packet_buffer; - uint32_t next_index = (buf->write_index + 1) % PACKET_BUFFER_CAPACITY; + uint8_t protocol = ipv4_get_protocol(ptr); + ptr += sizeof(ipv4_hdr_t); + if (protocol == 0x11){ + uint16_t port = udp_parse_packet(ptr); + if (ports[port] != UINT16_MAX){ + process_t *proc = get_proc_by_pid(ports[port]); + if (!proc) + unbind_port(port, ports[port]); + else { + packet_buffer_t* buf = &proc->packet_buffer; + uint32_t next_index = (buf->write_index + 1) % PACKET_BUFFER_CAPACITY; - buf->entries[buf->write_index] = packet; - buf->write_index = next_index; + buf->entries[buf->write_index] = packet; + buf->write_index = next_index; - if (buf->write_index == buf->read_index) - buf->read_index = (buf->read_index + 1) % PACKET_BUFFER_CAPACITY; + if (buf->write_index == buf->read_index) + buf->read_index = (buf->read_index + 1) % PACKET_BUFFER_CAPACITY; + } } } } diff --git a/kernel/networking/protocols/arp.c b/kernel/networking/protocols/arp.c index 4c6d7e4a..7d377d69 100644 --- a/kernel/networking/protocols/arp.c +++ b/kernel/networking/protocols/arp.c @@ -1,9 +1,7 @@ #include "arp.h" #include "std/memfunctions.h" -void create_arp_packet(uint8_t* buf, uint8_t* src_mac, uint32_t src_ip, uint8_t* dst_mac, uint32_t dst_ip, bool is_request){ - uintptr_t p = (uintptr_t)buf; - +void create_arp_packet(uintptr_t p, uint8_t* src_mac, uint32_t src_ip, uint8_t* dst_mac, uint32_t dst_ip, bool is_request){ eth_hdr_t* eth = (eth_hdr_t*)p; for (int i = 0; i < 6; i++) eth->dst_mac[i] = is_request ? 0xFF : dst_mac[i]; memcpy(eth->src_mac, src_mac, 6); diff --git a/kernel/networking/protocols/arp.h b/kernel/networking/protocols/arp.h index 14f7497a..d29e1144 100644 --- a/kernel/networking/protocols/arp.h +++ b/kernel/networking/protocols/arp.h @@ -19,7 +19,7 @@ typedef struct __attribute__((packed)) arp_hdr_t { uint32_t target_ip; } arp_hdr_t; -void create_arp_packet(uint8_t* buf, uint8_t* src_mac, uint32_t src_ip, uint8_t* dst_mac, uint32_t dst_ip, bool is_request); +void create_arp_packet(uintptr_t p, uint8_t* src_mac, uint32_t src_ip, uint8_t* dst_mac, uint32_t dst_ip, bool is_request); bool arp_should_handle(arp_hdr_t *arp, uint32_t ip); void arp_populate_response(network_connection_ctx *ctx, arp_hdr_t* arp); diff --git a/kernel/networking/protocols/dhcp.c b/kernel/networking/protocols/dhcp.c index b346b862..b538ea8d 100644 --- a/kernel/networking/protocols/dhcp.c +++ b/kernel/networking/protocols/dhcp.c @@ -1,7 +1,7 @@ #include "dhcp.h" #include "std/memfunctions.h" -void create_dhcp_packet(uint8_t* buf, dhcp_request *payload){ +void create_dhcp_packet(uintptr_t p, dhcp_request *payload){ network_connection_ctx source = (network_connection_ctx){ .port = 68, }; @@ -50,7 +50,7 @@ void create_dhcp_packet(uint8_t* buf, dhcp_request *payload){ packet.options[7] = 255; // END } - create_udp_packet(buf, source, destination, (uint8_t*)&packet, sizeof(dhcp_packet)); + create_udp_packet(p, source, destination, (uint8_t*)&packet, sizeof(dhcp_packet)); } dhcp_packet* dhcp_parse_packet_payload(uintptr_t ptr){ diff --git a/kernel/networking/protocols/dhcp.h b/kernel/networking/protocols/dhcp.h index 88e1f137..9035e5b8 100644 --- a/kernel/networking/protocols/dhcp.h +++ b/kernel/networking/protocols/dhcp.h @@ -34,7 +34,7 @@ typedef struct dhcp_request { #define DHCP_SIZE sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) + sizeof(dhcp_packet) -void create_dhcp_packet(uint8_t* buf, dhcp_request *data); +void create_dhcp_packet(uintptr_t p, dhcp_request *data); dhcp_packet* dhcp_parse_packet_payload(uintptr_t ptr); uint16_t dhcp_parse_option(dhcp_packet *pack, uint16_t option); diff --git a/kernel/networking/protocols/icmp.h b/kernel/networking/protocols/icmp.h new file mode 100644 index 00000000..79bd4ca4 --- /dev/null +++ b/kernel/networking/protocols/icmp.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#ifdef __cplusplus +extern "C" { +#endif + +#include "types.h" +#include "net/network_types.h" + +typedef struct __attribute__((packed)) icmp_packet { + uint8_t type; + uint8_t code; + uint16_t checksum; + uint16_t id; + uint16_t seq; +} icmp_packet; + +void create_icmp_packet(uintptr_t p); +bool icmp_should_handle(icmp_packet *icmp, uint32_t ip); +void icmp_populate_response(network_connection_ctx *ctx, icmp_packet* icmp); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/shared/net/eth.c b/shared/net/eth.c index 45eea611..bd57f6c8 100644 --- a/shared/net/eth.c +++ b/shared/net/eth.c @@ -1,9 +1,7 @@ #include "eth.h" #include "std/memfunctions.h" -uintptr_t create_eth_packet(uint8_t* buf, uint8_t src_mac[6], uint8_t dst_mac[6], uint16_t type){ - uintptr_t p = (uintptr_t)buf; - +uintptr_t create_eth_packet(uintptr_t p, uint8_t src_mac[6], uint8_t dst_mac[6], uint16_t type){ eth_hdr_t* eth = (eth_hdr_t*)p; memcpy(eth->src_mac, src_mac, 6); memcpy(eth->dst_mac, dst_mac, 6); diff --git a/shared/net/eth.h b/shared/net/eth.h index 2add12c9..e931feb1 100644 --- a/shared/net/eth.h +++ b/shared/net/eth.h @@ -8,7 +8,7 @@ extern "C" { #include "net/network_types.h" uint16_t eth_parse_packet_type(uintptr_t ptr); -uintptr_t create_eth_packet(uint8_t* buf, uint8_t src_mac[6], uint8_t dst_mac[6], uint16_t type); +uintptr_t create_eth_packet(uintptr_t ptr, uint8_t src_mac[6], uint8_t dst_mac[6], uint16_t type); #ifdef __cplusplus } diff --git a/shared/net/ipv4.c b/shared/net/ipv4.c new file mode 100644 index 00000000..d955b74f --- /dev/null +++ b/shared/net/ipv4.c @@ -0,0 +1,26 @@ +#include "ipv4.h" +#include "console/kio.h" + +uintptr_t create_ipv4_packet(uintptr_t p, uint32_t payload_len, uint8_t protocol, uint32_t source_ip, uint32_t destination_ip){ + ipv4_hdr_t* ip = (ipv4_hdr_t*)p; + ip->version_ihl = 0x45; + ip->dscp_ecn = 0; + ip->total_length = __builtin_bswap16(sizeof(ipv4_hdr_t) + payload_len); + ip->identification = 0; + ip->flags_frag_offset = __builtin_bswap16(0x4000); + ip->ttl = 64; + ip->protocol = protocol; + ip->header_checksum = 0; + ip->src_ip = __builtin_bswap32(source_ip); + ip->dst_ip = __builtin_bswap32(destination_ip); + uint16_t* ip_words = (uint16_t*)ip; + uint32_t sum = 0; + for (int i = 0; i < 10; i++) sum += ip_words[i]; + while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16); + ip->header_checksum = ~sum; + return p + sizeof(ipv4_hdr_t); +} + +uint8_t ipv4_get_protocol(uintptr_t ptr){ + return ((ipv4_hdr_t*)ptr)->protocol; +} \ No newline at end of file diff --git a/shared/net/ipv4.h b/shared/net/ipv4.h new file mode 100644 index 00000000..f8c88a1f --- /dev/null +++ b/shared/net/ipv4.h @@ -0,0 +1,15 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "types.h" +#include "net/network_types.h" + +uint8_t ipv4_get_protocol(uintptr_t ptr); +uintptr_t create_ipv4_packet(uintptr_t p, uint32_t payload_len, uint8_t protocol, uint32_t source_ip, uint32_t destination_ip); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/shared/net/udp.c b/shared/net/udp.c index f21d5428..9d80ff0c 100644 --- a/shared/net/udp.c +++ b/shared/net/udp.c @@ -3,6 +3,7 @@ #include "net/network_types.h" #include "syscalls/syscalls.h" #include "eth.h" +#include "ipv4.h" uint16_t udp_checksum( uint32_t src_ip, @@ -32,26 +33,10 @@ uint16_t udp_checksum( return ~sum; } -void create_udp_packet(uint8_t* buf, network_connection_ctx source, network_connection_ctx destination, const uint8_t* payload, uint16_t payload_len) { - uintptr_t p = create_eth_packet(buf, source.mac, destination.mac, 0x800); - - ipv4_hdr_t* ip = (ipv4_hdr_t*)p; - ip->version_ihl = 0x45; - ip->dscp_ecn = 0; - ip->total_length = __builtin_bswap16(sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) + payload_len); - ip->identification = 0; - ip->flags_frag_offset = __builtin_bswap16(0x4000); - ip->ttl = 64; - ip->protocol = 0x11; - ip->header_checksum = 0; - ip->src_ip = __builtin_bswap32(source.ip); - ip->dst_ip = __builtin_bswap32(destination.ip); - uint16_t* ip_words = (uint16_t*)ip; - uint32_t sum = 0; - for (int i = 0; i < 10; i++) sum += ip_words[i]; - while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16); - ip->header_checksum = ~sum; - p += sizeof(ipv4_hdr_t); +void create_udp_packet(uintptr_t p, network_connection_ctx source, network_connection_ctx destination, const uint8_t* payload, uint16_t payload_len) { + p = create_eth_packet(p, source.mac, destination.mac, 0x800); + + p = create_ipv4_packet(p, sizeof(udp_hdr_t) + payload_len, 0x11, source.ip, destination.ip); udp_hdr_t* udp = (udp_hdr_t*)p; udp->src_port = __builtin_bswap16(source.port); @@ -63,24 +48,15 @@ void create_udp_packet(uint8_t* buf, network_connection_ctx source, network_conn uint8_t* data = (uint8_t*)p; for (int i = 0; i < payload_len; i++) data[i] = payload[i]; - udp->checksum = __builtin_bswap16(udp_checksum(source.ip,destination.ip,ip->protocol,(uint8_t*)udp,sizeof(udp_hdr_t) + payload_len)); + udp->checksum = __builtin_bswap16(udp_checksum(source.ip,destination.ip,0x11,(uint8_t*)udp,sizeof(udp_hdr_t) + payload_len)); } uint16_t udp_parse_packet(uintptr_t ptr){ - ipv4_hdr_t* ip = (ipv4_hdr_t*)ptr; - uint32_t srcip = __builtin_bswap32(ip->src_ip); - ptr += sizeof(ipv4_hdr_t); - if (ip->protocol == 0x11){ - udp_hdr_t* udp = (udp_hdr_t*)ptr; - ptr += sizeof(udp_hdr_t); - uint16_t port = __builtin_bswap16(udp->dst_port); - return port; - } else { - // kprintf("[UDP packet] Not prepared to handle non-UDP packets %x",ip->protocol); - } - - return 0; + udp_hdr_t* udp = (udp_hdr_t*)ptr; + ptr += sizeof(udp_hdr_t); + uint16_t port = __builtin_bswap16(udp->dst_port); + return port; } sizedptr udp_parse_packet_payload(uintptr_t ptr){ diff --git a/shared/net/udp.h b/shared/net/udp.h index 81bb4782..63de74a2 100644 --- a/shared/net/udp.h +++ b/shared/net/udp.h @@ -14,7 +14,7 @@ typedef struct __attribute__((packed)) udp_hdr_t { uint16_t checksum; } udp_hdr_t; -void create_udp_packet(uint8_t* buf, network_connection_ctx source, network_connection_ctx destination, const uint8_t* payload, uint16_t payload_len); +void create_udp_packet(uintptr_t p, network_connection_ctx source, network_connection_ctx destination, const uint8_t* payload, uint16_t payload_len); size_t calc_udp_size(uint16_t payload_len); uint16_t udp_parse_packet(uintptr_t ptr); sizedptr udp_parse_packet_payload(uintptr_t ptr); From 10212fab7e15eb88846bf7cd659ce742cd43d441 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 20 Jun 2025 00:00:00 +0000 Subject: [PATCH 34/61] ARP fixes --- .../networking/drivers/virtio_net_pci/virtio_net_pci.cpp | 2 +- kernel/networking/protocols/arp.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index de6c67c0..5256db2c 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -183,7 +183,7 @@ void VirtioNetDriver::send_packet(NetProtocol protocol, uint16_t port, network_c create_dhcp_packet(buf_ptr + sizeof(virtio_net_hdr_t), (dhcp_request*)payload); break; case ARP: - size = sizeof(eth_hdr_t) + sizeof(arp_hdr_t); + size = sizeof(eth_hdr_t) + sizeof(arp_hdr_t) + sizeof(virtio_net_hdr_t); buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size, ALIGN_64B, true, true); create_arp_packet(buf_ptr + sizeof(virtio_net_hdr_t), connection_context.mac, connection_context.ip, destination->mac, destination->ip, *(bool*)payload); break; diff --git a/kernel/networking/protocols/arp.c b/kernel/networking/protocols/arp.c index 7d377d69..97de0e10 100644 --- a/kernel/networking/protocols/arp.c +++ b/kernel/networking/protocols/arp.c @@ -10,15 +10,15 @@ void create_arp_packet(uintptr_t p, uint8_t* src_mac, uint32_t src_ip, uint8_t* arp_hdr_t* arp = (arp_hdr_t*)p; - arp->htype = 1; + arp->htype = __builtin_bswap16(1); arp->ptype = __builtin_bswap16(0x0800); arp->hlen = 6; arp->plen = 4; arp->opcode = __builtin_bswap16(is_request ? 1 : 2); memcpy(arp->sender_mac, src_mac, 6); - arp->sender_ip = src_ip; + arp->sender_ip = __builtin_bswap32(src_ip); memcpy(arp->target_mac, dst_mac, 6); - arp->target_ip = dst_ip; + arp->target_ip = __builtin_bswap32(dst_ip); } void arp_populate_response(network_connection_ctx *ctx, arp_hdr_t* arp){ @@ -28,5 +28,5 @@ void arp_populate_response(network_connection_ctx *ctx, arp_hdr_t* arp){ bool arp_should_handle(arp_hdr_t *arp, uint32_t ip){ - return arp->target_ip == ip; + return __builtin_bswap32(arp->target_ip) == ip; } \ No newline at end of file From ed182195f800fb058278abc74573a8d112ffeaac Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 20 Jun 2025 00:00:00 +0000 Subject: [PATCH 35/61] Half functioning ping response --- .../drivers/virtio_net_pci/virtio_net_pci.cpp | 6 +++ kernel/networking/network_dispatch.cpp | 14 ++++++ kernel/networking/protocols/icmp.c | 50 +++++++++++++++++++ kernel/networking/protocols/icmp.h | 17 +++++-- shared/net/ipv4.c | 6 +++ shared/net/ipv4.h | 1 + shared/net/network_types.h | 3 +- 7 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 kernel/networking/protocols/icmp.c diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index 5256db2c..7dcbfd4e 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -3,6 +3,7 @@ #include "net/udp.h" #include "../../protocols/dhcp.h" #include "../../protocols/arp.h" +#include "../../protocols/icmp.h" #include "networking/network.h" #include "pci.h" #include "syscalls/syscalls.h" @@ -187,6 +188,11 @@ void VirtioNetDriver::send_packet(NetProtocol protocol, uint16_t port, network_c buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size, ALIGN_64B, true, true); create_arp_packet(buf_ptr + sizeof(virtio_net_hdr_t), connection_context.mac, connection_context.ip, destination->mac, destination->ip, *(bool*)payload); break; + case ICMP: + size = sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(virtio_net_hdr_t) + sizeof(icmp_packet); + buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size, ALIGN_64B, true, true); + create_icmp_packet(buf_ptr + sizeof(virtio_net_hdr_t), connection_context, *destination, (icmp_data*)payload); + break; default: break; } diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index d716933f..118da943 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -7,6 +7,7 @@ #include "net/eth.h" #include "net/ipv4.h" #include "memory/page_allocator.h" +#include "protocols/icmp.h" #include "std/memfunctions.h" #include "protocols/arp.h" @@ -41,6 +42,7 @@ void NetworkDispatch::handle_interrupt(){ sizedptr packet = driver->handle_receive_packet(); uintptr_t ptr = packet.ptr; if (ptr){ + eth_hdr_t *eth = (eth_hdr_t*)ptr; uint16_t ethtype = eth_parse_packet_type(ptr); ptr += sizeof(eth_hdr_t); if (ethtype == 0x806){ @@ -54,6 +56,7 @@ void NetworkDispatch::handle_interrupt(){ } //Should also look for responses to our own queries } else if (ethtype == 0x800){//IPV4 + ipv4_hdr_t *ipv4 = (ipv4_hdr_t*)ptr; uint8_t protocol = ipv4_get_protocol(ptr); ptr += sizeof(ipv4_hdr_t); if (protocol == 0x11){ @@ -73,6 +76,17 @@ void NetworkDispatch::handle_interrupt(){ buf->read_index = (buf->read_index + 1) % PACKET_BUFFER_CAPACITY; } } + } else if (protocol == 0x1) { + icmp_data data = (icmp_data){ + .response = true + }; + network_connection_ctx conn; + icmp_packet *icmp = (icmp_packet*)ptr; + data.seq = icmp_get_sequence(icmp); + data.id = icmp_get_id(icmp); + icmp_copy_payload(&data.payload, icmp); + ipv4_populate_response(&conn, eth, ipv4); + send_packet(ICMP, 0, &conn, &data, sizeof(icmp_data)); } } } diff --git a/kernel/networking/protocols/icmp.c b/kernel/networking/protocols/icmp.c new file mode 100644 index 00000000..a6f5a594 --- /dev/null +++ b/kernel/networking/protocols/icmp.c @@ -0,0 +1,50 @@ +#include "icmp.h" +#include "net/udp.h" +#include "net/eth.h" +#include "net/ipv4.h" +#include "std/memfunctions.h" + +uint16_t icmp_checksum(uint16_t *data, size_t len) { + uint16_t sum = 0; + + while (len > 1) { + sum += *data++; + len -= 2; + } + + if (len == 1) { + sum += *(const uint8_t *)data; + } + + while (sum >> 16) { + sum = (sum & 0xFFFF) + (sum >> 16); + } + + return ~sum; +} + +void create_icmp_packet(uintptr_t p, network_connection_ctx source, network_connection_ctx destination, icmp_data* data){ + p = create_eth_packet(p, source.mac, destination.mac, 0x800); + + p = create_ipv4_packet(p, sizeof(icmp_packet), 0x01, source.ip, destination.ip); + + icmp_packet *packet = (icmp_packet*)p; + + packet->type = data->response ? 0 : 8; + packet->seq = __builtin_bswap16(data->seq); + packet->id = __builtin_bswap16(data->id); + memcpy(packet->payload, data->payload, 56); + packet->checksum = icmp_checksum((uint16_t*)packet, sizeof(icmp_packet)); +} + +uint16_t icmp_get_sequence(icmp_packet *packet){ + return __builtin_bswap16(packet->seq); +} + +uint16_t icmp_get_id(icmp_packet *packet){ + return __builtin_bswap16(packet->id); +} + +void icmp_copy_payload(void* dest, icmp_packet *packet){ + memcpy(dest, packet->payload, 56); +} \ No newline at end of file diff --git a/kernel/networking/protocols/icmp.h b/kernel/networking/protocols/icmp.h index 79bd4ca4..59dd4410 100644 --- a/kernel/networking/protocols/icmp.h +++ b/kernel/networking/protocols/icmp.h @@ -1,7 +1,5 @@ #pragma once -#include -#include #ifdef __cplusplus extern "C" { #endif @@ -15,11 +13,20 @@ typedef struct __attribute__((packed)) icmp_packet { uint16_t checksum; uint16_t id; uint16_t seq; + uint8_t payload[56]; } icmp_packet; -void create_icmp_packet(uintptr_t p); -bool icmp_should_handle(icmp_packet *icmp, uint32_t ip); -void icmp_populate_response(network_connection_ctx *ctx, icmp_packet* icmp); +typedef struct icmp_data { + uint8_t response; + uint16_t seq; + uint16_t id; + uint8_t payload[56]; +} icmp_data; + +void create_icmp_packet(uintptr_t p, network_connection_ctx source, network_connection_ctx destination, icmp_data *data); +uint16_t icmp_get_sequence(icmp_packet *packet); +uint16_t icmp_get_id(icmp_packet *packet); +void icmp_copy_payload(void* dest, icmp_packet *packet); #ifdef __cplusplus } diff --git a/shared/net/ipv4.c b/shared/net/ipv4.c index d955b74f..f7c7f65e 100644 --- a/shared/net/ipv4.c +++ b/shared/net/ipv4.c @@ -1,5 +1,6 @@ #include "ipv4.h" #include "console/kio.h" +#include "std/memfunctions.h" uintptr_t create_ipv4_packet(uintptr_t p, uint32_t payload_len, uint8_t protocol, uint32_t source_ip, uint32_t destination_ip){ ipv4_hdr_t* ip = (ipv4_hdr_t*)p; @@ -23,4 +24,9 @@ uintptr_t create_ipv4_packet(uintptr_t p, uint32_t payload_len, uint8_t protocol uint8_t ipv4_get_protocol(uintptr_t ptr){ return ((ipv4_hdr_t*)ptr)->protocol; +} + +void ipv4_populate_response(network_connection_ctx *ctx, eth_hdr_t *eth, ipv4_hdr_t* ipv4){ + ctx->ip = __builtin_bswap32(ipv4->src_ip); + memcpy(ctx->mac, eth->src_mac, 6); } \ No newline at end of file diff --git a/shared/net/ipv4.h b/shared/net/ipv4.h index f8c88a1f..94be5f4d 100644 --- a/shared/net/ipv4.h +++ b/shared/net/ipv4.h @@ -9,6 +9,7 @@ extern "C" { uint8_t ipv4_get_protocol(uintptr_t ptr); uintptr_t create_ipv4_packet(uintptr_t p, uint32_t payload_len, uint8_t protocol, uint32_t source_ip, uint32_t destination_ip); +void ipv4_populate_response(network_connection_ctx *ctx, eth_hdr_t *eth, ipv4_hdr_t* ipv4); #ifdef __cplusplus } diff --git a/shared/net/network_types.h b/shared/net/network_types.h index 3e59713e..632c61c1 100644 --- a/shared/net/network_types.h +++ b/shared/net/network_types.h @@ -10,7 +10,8 @@ typedef enum NetProtocol { UDP, DHCP, ARP, - TCP + TCP, + ICMP } NetProtocol; typedef struct __attribute__((packed)) eth_hdr_t { From 0d57c0345daa67f6b0ff970172928fd1220a2311 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 20 Jun 2025 00:00:00 +0000 Subject: [PATCH 36/61] Fixed checksum for ipv4 and icmp --- kernel/networking/protocols/icmp.c | 23 ++--------------------- shared/net/ipv4.c | 8 ++------ shared/net/network_types.h | 7 +++++++ 3 files changed, 11 insertions(+), 27 deletions(-) diff --git a/kernel/networking/protocols/icmp.c b/kernel/networking/protocols/icmp.c index a6f5a594..cd79dc87 100644 --- a/kernel/networking/protocols/icmp.c +++ b/kernel/networking/protocols/icmp.c @@ -4,25 +4,6 @@ #include "net/ipv4.h" #include "std/memfunctions.h" -uint16_t icmp_checksum(uint16_t *data, size_t len) { - uint16_t sum = 0; - - while (len > 1) { - sum += *data++; - len -= 2; - } - - if (len == 1) { - sum += *(const uint8_t *)data; - } - - while (sum >> 16) { - sum = (sum & 0xFFFF) + (sum >> 16); - } - - return ~sum; -} - void create_icmp_packet(uintptr_t p, network_connection_ctx source, network_connection_ctx destination, icmp_data* data){ p = create_eth_packet(p, source.mac, destination.mac, 0x800); @@ -30,11 +11,11 @@ void create_icmp_packet(uintptr_t p, network_connection_ctx source, network_conn icmp_packet *packet = (icmp_packet*)p; - packet->type = data->response ? 0 : 8; + packet->type = __builtin_bswap16(data->response ? 0 : 8); packet->seq = __builtin_bswap16(data->seq); packet->id = __builtin_bswap16(data->id); memcpy(packet->payload, data->payload, 56); - packet->checksum = icmp_checksum((uint16_t*)packet, sizeof(icmp_packet)); + packet->checksum = checksum16((uint16_t*)packet, sizeof(icmp_packet)); } uint16_t icmp_get_sequence(icmp_packet *packet){ diff --git a/shared/net/ipv4.c b/shared/net/ipv4.c index f7c7f65e..47e4de3b 100644 --- a/shared/net/ipv4.c +++ b/shared/net/ipv4.c @@ -1,5 +1,6 @@ #include "ipv4.h" #include "console/kio.h" +#include "network_types.h" #include "std/memfunctions.h" uintptr_t create_ipv4_packet(uintptr_t p, uint32_t payload_len, uint8_t protocol, uint32_t source_ip, uint32_t destination_ip){ @@ -11,14 +12,9 @@ uintptr_t create_ipv4_packet(uintptr_t p, uint32_t payload_len, uint8_t protocol ip->flags_frag_offset = __builtin_bswap16(0x4000); ip->ttl = 64; ip->protocol = protocol; - ip->header_checksum = 0; ip->src_ip = __builtin_bswap32(source_ip); ip->dst_ip = __builtin_bswap32(destination_ip); - uint16_t* ip_words = (uint16_t*)ip; - uint32_t sum = 0; - for (int i = 0; i < 10; i++) sum += ip_words[i]; - while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16); - ip->header_checksum = ~sum; + ip->header_checksum = checksum16((uint16_t*)ip, 10); return p + sizeof(ipv4_hdr_t); } diff --git a/shared/net/network_types.h b/shared/net/network_types.h index 632c61c1..3a4801ba 100644 --- a/shared/net/network_types.h +++ b/shared/net/network_types.h @@ -14,6 +14,13 @@ typedef enum NetProtocol { ICMP } NetProtocol; +static uint16_t checksum16(uint16_t *data, size_t len) { + uint32_t sum = 0; + for (int i = 0; i < len; i++) sum += data[i]; + while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16); + return ~sum; +} + typedef struct __attribute__((packed)) eth_hdr_t { uint8_t dst_mac[6]; uint8_t src_mac[6]; From fc4d7b32b4ea98b1a203bcca874a8bb886bbefff Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 20 Jun 2025 00:00:00 +0000 Subject: [PATCH 37/61] Cleaned up the DHCP negotiation code with 5 retries (no timeout) --- kernel/networking/processes/net_proc.c | 62 ++++++++++++++------------ 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/kernel/networking/processes/net_proc.c b/kernel/networking/processes/net_proc.c index 07a0db6c..17071575 100644 --- a/kernel/networking/processes/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -52,49 +52,55 @@ void negotiate_dhcp(){ send_packet(DHCP, 53, ctx, &request, sizeof(dhcp_request)); sizedptr ptr; + + dhcp_packet *payload; - while (!read_packet(&ptr)); - - kprintf("Received DHCP response"); - - dhcp_packet *payload = dhcp_parse_packet_payload(ptr.ptr); - - if (payload){ - uint32_t local_ip = __builtin_bswap32(payload->yiaddr); - kprintf("Received local IP %i.%i.%i.%i",(local_ip >> 24) & 0xFF,(local_ip >> 16) & 0xFF,(local_ip >> 8) & 0xFF,(local_ip >> 0) & 0xFF); - request.offered_ip = payload->yiaddr; - + for (int i = 5; i >= 0; i--){ + while (!read_packet(&ptr)); + kprintf("Received DHCP response"); + payload = dhcp_parse_packet_payload(ptr.ptr); uint16_t opt_index = dhcp_parse_option(payload, 53); - if (payload->options[opt_index + 2] != 2){ + if (payload->options[opt_index + 2] == 2) + break; + if (i == 0){ + sleep(60000); negotiate_dhcp(); return; } + } - uint16_t serv_index = dhcp_parse_option(payload, 54); - memcpy((void*)&request.server_ip, (void*)(payload->options + serv_index + 2), payload->options[serv_index+1]); + uint32_t local_ip = __builtin_bswap32(payload->yiaddr); + kprintf("Received local IP %i.%i.%i.%i",(local_ip >> 24) & 0xFF,(local_ip >> 16) & 0xFF,(local_ip >> 8) & 0xFF,(local_ip >> 0) & 0xFF); + request.offered_ip = payload->yiaddr; - send_packet(DHCP, 53, ctx, &request, sizeof(dhcp_request)); + uint16_t serv_index = dhcp_parse_option(payload, 54); + memcpy((void*)&request.server_ip, (void*)(payload->options + serv_index + 2), payload->options[serv_index+1]); - while (!read_packet(&ptr)); + send_packet(DHCP, 53, ctx, &request, sizeof(dhcp_request)); + for (int i = 5; i >= 0; i--){ + while (!read_packet(&ptr)); + kprintf("Received DHCP response"); payload = dhcp_parse_packet_payload(ptr.ptr); - opt_index = dhcp_parse_option(payload, 53); - if (payload->options[opt_index + 2] != 5){ - kprintf("Did not receive acknowledge for DHCP"); + uint16_t opt_index = dhcp_parse_option(payload, 53); + if (payload->options[opt_index + 2] == 5) + break; + if (i == 0){ + sleep(60000); negotiate_dhcp(); return; } + } - kprintf("DHCP negotiation finished"); + kprintf("DHCP negotiation finished"); - //We can parse options for - //Lease time (51) - //DHCP Server identifier - //Subnet mask - //Router (3) - //DNS (8 bytes) (6) - ctx->ip = local_ip; - } + //We can parse options for + //Lease time (51) + //DHCP Server identifier + //Subnet mask + //Router (3) + //DNS (8 bytes) (6) + ctx->ip = local_ip; unbind_port(68); test_network(); From 78f593d327b8a8ca9c13700eb092ff60913e3dc6 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 20 Jun 2025 00:00:00 +0000 Subject: [PATCH 38/61] Lease renegotiation --- kernel/networking/processes/net_proc.c | 47 +++++++++++++++----------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/kernel/networking/processes/net_proc.c b/kernel/networking/processes/net_proc.c index 17071575..577d86fc 100644 --- a/kernel/networking/processes/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -9,6 +9,7 @@ #include "std/memfunctions.h" #include "networking/network.h" #include "syscalls/syscalls.h" +#include "math/math.h" void test_network(){ @@ -37,12 +38,9 @@ void test_network(){ unbind_port(8888); } -void negotiate_dhcp(){ +uint32_t negotiate_dhcp(){ kprintf("Sending DHCP request"); network_connection_ctx *ctx = network_get_context(); - bind_port(68); - if (ctx->ip != 0) - return; dhcp_request request = (dhcp_request){ .mac = 0, .offered_ip = 0, @@ -62,11 +60,8 @@ void negotiate_dhcp(){ uint16_t opt_index = dhcp_parse_option(payload, 53); if (payload->options[opt_index + 2] == 2) break; - if (i == 0){ - sleep(60000); - negotiate_dhcp(); - return; - } + if (i == 0) + return 60000; } uint32_t local_ip = __builtin_bswap32(payload->yiaddr); @@ -74,7 +69,13 @@ void negotiate_dhcp(){ request.offered_ip = payload->yiaddr; uint16_t serv_index = dhcp_parse_option(payload, 54); - memcpy((void*)&request.server_ip, (void*)(payload->options + serv_index + 2), payload->options[serv_index+1]); + memcpy((void*)&request.server_ip, (void*)(payload->options + serv_index + 2), min(4,payload->options[serv_index+1])); + + uint16_t lease_index = dhcp_parse_option(payload, 51); + uint32_t lease_time; + memcpy((void*)&lease_time, (void*)(payload->options + lease_index + 2), min(4,payload->options[lease_index+1])); + + lease_time /= 2; send_packet(DHCP, 53, ctx, &request, sizeof(dhcp_request)); @@ -85,28 +86,36 @@ void negotiate_dhcp(){ uint16_t opt_index = dhcp_parse_option(payload, 53); if (payload->options[opt_index + 2] == 5) break; - if (i == 0){ - sleep(60000); - negotiate_dhcp(); - return; - } + if (i == 0) + return 60000; } - kprintf("DHCP negotiation finished"); + kprintf("DHCP negotiation finished. Lease %i",lease_time); //We can parse options for - //Lease time (51) //DHCP Server identifier //Subnet mask //Router (3) //DNS (8 bytes) (6) ctx->ip = local_ip; - unbind_port(68); test_network(); + + return lease_time; +} + +void dhcp_daemon(){ + bind_port(68); + while (true){ + uint32_t await = negotiate_dhcp(); + if (await == 0) break; + kprintf("DHCP Negotiated for %i",await); + sleep(await); + } + bind_port(68); stop_current_process(); } process_t* launch_net_process(){ - return create_kernel_process("nettest",negotiate_dhcp); + return create_kernel_process("dhcp_daemon",dhcp_daemon); } \ No newline at end of file From 5a5c8d3ddafb5a3cf2256dcbfcc8adaff7732944 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 20 Jun 2025 00:00:00 +0000 Subject: [PATCH 39/61] Sending one TCP packet --- .../drivers/virtio_net_pci/virtio_net_pci.cpp | 10 +++- kernel/networking/network_dispatch.cpp | 2 +- kernel/networking/processes/net_proc.c | 32 +++++++++---- shared/net/network_types.h | 28 +++++++++++ shared/net/tcp.c | 40 ++++++++++++++++ shared/net/tcp.h | 48 +++++++++++++++++++ shared/net/udp.c | 30 +----------- shared/net/udp.h | 1 - 8 files changed, 149 insertions(+), 42 deletions(-) create mode 100644 shared/net/tcp.c create mode 100644 shared/net/tcp.h diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index 7dcbfd4e..fa605fbc 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -1,6 +1,7 @@ #include "virtio_net_pci.hpp" #include "console/kio.h" #include "net/udp.h" +#include "net/tcp.h" #include "../../protocols/dhcp.h" #include "../../protocols/arp.h" #include "../../protocols/icmp.h" @@ -193,8 +194,13 @@ void VirtioNetDriver::send_packet(NetProtocol protocol, uint16_t port, network_c buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size, ALIGN_64B, true, true); create_icmp_packet(buf_ptr + sizeof(virtio_net_hdr_t), connection_context, *destination, (icmp_data*)payload); break; - default: - break; + case TCP: + tcp_data *data = (tcp_data*)payload; + size = sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(virtio_net_hdr_t) + sizeof(tcp_hdr_t) + data->options.size + data->payload.size; + buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size, ALIGN_64B, true, true); + connection_context.port = port; + create_tcp_packet(buf_ptr + sizeof(virtio_net_hdr_t), connection_context, *destination, (sizedptr){(uintptr_t)data, sizeof(tcp_data)}); + break; } virtio_send_1d(&vnp_net_dev, buf_ptr, size); diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index 118da943..5f18f830 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -59,7 +59,7 @@ void NetworkDispatch::handle_interrupt(){ ipv4_hdr_t *ipv4 = (ipv4_hdr_t*)ptr; uint8_t protocol = ipv4_get_protocol(ptr); ptr += sizeof(ipv4_hdr_t); - if (protocol == 0x11){ + if (protocol == 0x11 || protocol == 0x06){ uint16_t port = udp_parse_packet(ptr); if (ports[port] != UINT16_MAX){ process_t *proc = get_proc_by_pid(ports[port]); diff --git a/kernel/networking/processes/net_proc.c b/kernel/networking/processes/net_proc.c index 577d86fc..c43d2c6d 100644 --- a/kernel/networking/processes/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -10,30 +10,43 @@ #include "networking/network.h" #include "syscalls/syscalls.h" #include "math/math.h" +#include "../net_constants.h" +#include "net/tcp.h" void test_network(){ bind_port(8888); network_connection_ctx dest = (network_connection_ctx){ - .ip = (192 << 24) | (168 << 16) | (1 << 8) | 255, - .mac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, - .port = 8080, + .ip = HOST_IP, + .mac = HOST_MAC, + .port = 80, }; - size_t payload_size = 5; - char hw[5] = {'h','e','l','l','o'}; + tcp_data data = (tcp_data){ + .sequence = 0, + .ack = 0, + .flags = (1 << SYN_F), + .window = UINT16_MAX, + // sizedptr options; + // sizedptr payload; + }; + + // size_t payload_size = 5; + // char hw[5] = {'h','e','l','l','o'}; - send_packet(UDP, 8888, &dest, hw, payload_size); + send_packet(TCP, 8888, &dest, &data, sizeof(tcp_data)); sizedptr pack; while (!read_packet(&pack)); - sizedptr payload = udp_parse_packet_payload(pack.ptr); + kprintf("We got a response from the server. I'll parse it after dinner"); + + // sizedptr payload = udp_parse_packet_payload(pack.ptr); - uint8_t *content = (uint8_t*)payload.ptr; + // uint8_t *content = (uint8_t*)payload.ptr; - kprintf("PAYLOAD: %s",(uintptr_t)string_ca_max(content, payload.size).data); + // kprintf("PAYLOAD: %s",(uintptr_t)string_ca_max(content, payload.size).data); unbind_port(8888); } @@ -97,6 +110,7 @@ uint32_t negotiate_dhcp(){ //Subnet mask //Router (3) //DNS (8 bytes) (6) + //TODO: Make subsequent DHCP requests (renewals and requests) directed to the server ctx->ip = local_ip; test_network(); diff --git a/shared/net/network_types.h b/shared/net/network_types.h index 3a4801ba..480d2633 100644 --- a/shared/net/network_types.h +++ b/shared/net/network_types.h @@ -21,6 +21,34 @@ static uint16_t checksum16(uint16_t *data, size_t len) { return ~sum; } +static uint16_t checksum16_pipv4( + uint32_t src_ip, + uint32_t dst_ip, + uint8_t protocol, + const uint8_t* udp_header_and_payload, + uint16_t length +) { + uint32_t sum = 0; + + sum += (src_ip >> 16) & 0xFFFF; + sum += src_ip & 0xFFFF; + sum += (dst_ip >> 16) & 0xFFFF; + sum += dst_ip & 0xFFFF; + sum += protocol; + sum += length; + + for (uint16_t i = 0; i + 1 < length; i += 2) + sum += (udp_header_and_payload[i] << 8) | udp_header_and_payload[i + 1]; + + if (length & 1) + sum += udp_header_and_payload[length - 1] << 8; + + while (sum >> 16) + sum = (sum & 0xFFFF) + (sum >> 16); + + return ~sum; +} + typedef struct __attribute__((packed)) eth_hdr_t { uint8_t dst_mac[6]; uint8_t src_mac[6]; diff --git a/shared/net/tcp.c b/shared/net/tcp.c new file mode 100644 index 00000000..ef7daff4 --- /dev/null +++ b/shared/net/tcp.c @@ -0,0 +1,40 @@ +#include "tcp.h" +#include "console/kio.h" +#include "net/network_types.h" +#include "network_types.h" +#include "syscalls/syscalls.h" +#include "std/memfunctions.h" +#include "eth.h" +#include "ipv4.h" + +void create_tcp_packet(uintptr_t p, network_connection_ctx source, network_connection_ctx destination, sizedptr payload){ + p = create_eth_packet(p, source.mac, destination.mac, 0x800); + + tcp_data *data = (tcp_data*)payload.ptr; + + size_t full_size = sizeof(tcp_hdr_t) + data->options.size + data->payload.size; + + p = create_ipv4_packet(p, full_size, 0x06, source.ip, destination.ip); + + tcp_hdr_t* tcp = (tcp_hdr_t*)p; + tcp->src_port = __builtin_bswap16(source.port); + tcp->dst_port = __builtin_bswap16(destination.port); + + if (payload.size != sizeof(tcp_data)){ + kprintf("[TCP Packet creation error] wrong payload size %i (expected %i)",payload.size, sizeof(tcp_data)); + } + + memcpy((void*)&tcp->sequence,(void*)payload.ptr, 12); + + p += sizeof(tcp_hdr_t); + + memcpy((void*)p,(void*)data->options.ptr, data->options.size); + + p += data->options.size; + + tcp->data_offset_reserved = ((sizeof(tcp_hdr_t) + data->options.size + 3) / 4) << 4; + + memcpy((void*)p,(void*)data->payload.ptr, data->payload.size); + + tcp->checksum = __builtin_bswap16(checksum16_pipv4(source.ip,destination.ip,0x06,(uint8_t*)tcp, full_size)); +} \ No newline at end of file diff --git a/shared/net/tcp.h b/shared/net/tcp.h new file mode 100644 index 00000000..5b1bb05d --- /dev/null +++ b/shared/net/tcp.h @@ -0,0 +1,48 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "types.h" +#include "net/network_types.h" + +#define FIN_F 0 +#define SYN_F 1 +#define RST_F 2 +#define PSH_F 3 +#define ACK_F 4 +#define URG_F 5 +#define ECE_F 6 +#define CWR_F 7 + +typedef struct __attribute__((packed)) tcp_hdr_t { + uint16_t src_port; + uint16_t dst_port; + uint32_t sequence; + uint32_t ack; + uint8_t data_offset_reserved;// upper offset, lower reserved + uint8_t flags; + uint16_t window; + uint16_t checksum; + uint16_t urgent_ptr; +} tcp_hdr_t; + +typedef struct tcp_data { + uint32_t sequence; + uint32_t ack; + uint8_t padding; + uint8_t flags; + uint16_t window; + sizedptr options; + sizedptr payload; +} tcp_data; + +void create_tcp_packet(uintptr_t p, network_connection_ctx source, network_connection_ctx destination, sizedptr payload); +size_t calc_tcp_size(uint16_t payload_len); +uint16_t tcp_parse_packet(uintptr_t ptr); +sizedptr tcp_parse_packet_payload(uintptr_t ptr); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/shared/net/udp.c b/shared/net/udp.c index 9d80ff0c..5e6037d6 100644 --- a/shared/net/udp.c +++ b/shared/net/udp.c @@ -5,34 +5,6 @@ #include "eth.h" #include "ipv4.h" -uint16_t udp_checksum( - uint32_t src_ip, - uint32_t dst_ip, - uint8_t protocol, - const uint8_t* udp_header_and_payload, - uint16_t length -) { - uint32_t sum = 0; - - sum += (src_ip >> 16) & 0xFFFF; - sum += src_ip & 0xFFFF; - sum += (dst_ip >> 16) & 0xFFFF; - sum += dst_ip & 0xFFFF; - sum += protocol; - sum += length; - - for (uint16_t i = 0; i + 1 < length; i += 2) - sum += (udp_header_and_payload[i] << 8) | udp_header_and_payload[i + 1]; - - if (length & 1) - sum += udp_header_and_payload[length - 1] << 8; - - while (sum >> 16) - sum = (sum & 0xFFFF) + (sum >> 16); - - return ~sum; -} - void create_udp_packet(uintptr_t p, network_connection_ctx source, network_connection_ctx destination, const uint8_t* payload, uint16_t payload_len) { p = create_eth_packet(p, source.mac, destination.mac, 0x800); @@ -48,7 +20,7 @@ void create_udp_packet(uintptr_t p, network_connection_ctx source, network_conne uint8_t* data = (uint8_t*)p; for (int i = 0; i < payload_len; i++) data[i] = payload[i]; - udp->checksum = __builtin_bswap16(udp_checksum(source.ip,destination.ip,0x11,(uint8_t*)udp,sizeof(udp_hdr_t) + payload_len)); + udp->checksum = __builtin_bswap16(checksum16_pipv4(source.ip,destination.ip,0x11,(uint8_t*)udp,sizeof(udp_hdr_t) + payload_len)); } diff --git a/shared/net/udp.h b/shared/net/udp.h index 63de74a2..323c53d2 100644 --- a/shared/net/udp.h +++ b/shared/net/udp.h @@ -18,7 +18,6 @@ void create_udp_packet(uintptr_t p, network_connection_ctx source, network_conne size_t calc_udp_size(uint16_t payload_len); uint16_t udp_parse_packet(uintptr_t ptr); sizedptr udp_parse_packet_payload(uintptr_t ptr); -uint16_t udp_parse_packet_length(uintptr_t ptr); #ifdef __cplusplus } From 4890064b9a07cbc01e74dc4b102d7eaf84d2432f Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 20 Jun 2025 00:00:00 +0000 Subject: [PATCH 40/61] Moved checksums --- shared/net/checksums.c | 36 ++++++++++++++++++++++++++++++++++++ shared/net/network_types.h | 35 ++--------------------------------- 2 files changed, 38 insertions(+), 33 deletions(-) create mode 100644 shared/net/checksums.c diff --git a/shared/net/checksums.c b/shared/net/checksums.c new file mode 100644 index 00000000..d5f45bb7 --- /dev/null +++ b/shared/net/checksums.c @@ -0,0 +1,36 @@ +#include "network_types.h" + +uint16_t checksum16(uint16_t *data, size_t len) { + uint32_t sum = 0; + for (int i = 0; i < len; i++) sum += data[i]; + while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16); + return ~sum; +} + +uint16_t checksum16_pipv4( + uint32_t src_ip, + uint32_t dst_ip, + uint8_t protocol, + const uint8_t* udp_header_and_payload, + uint16_t length +) { + uint32_t sum = 0; + + sum += (src_ip >> 16) & 0xFFFF; + sum += src_ip & 0xFFFF; + sum += (dst_ip >> 16) & 0xFFFF; + sum += dst_ip & 0xFFFF; + sum += protocol; + sum += length; + + for (uint16_t i = 0; i + 1 < length; i += 2) + sum += (udp_header_and_payload[i] << 8) | udp_header_and_payload[i + 1]; + + if (length & 1) + sum += udp_header_and_payload[length - 1] << 8; + + while (sum >> 16) + sum = (sum & 0xFFFF) + (sum >> 16); + + return ~sum; +} \ No newline at end of file diff --git a/shared/net/network_types.h b/shared/net/network_types.h index 480d2633..f37d2611 100644 --- a/shared/net/network_types.h +++ b/shared/net/network_types.h @@ -14,40 +14,9 @@ typedef enum NetProtocol { ICMP } NetProtocol; -static uint16_t checksum16(uint16_t *data, size_t len) { - uint32_t sum = 0; - for (int i = 0; i < len; i++) sum += data[i]; - while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16); - return ~sum; -} - -static uint16_t checksum16_pipv4( - uint32_t src_ip, - uint32_t dst_ip, - uint8_t protocol, - const uint8_t* udp_header_and_payload, - uint16_t length -) { - uint32_t sum = 0; - - sum += (src_ip >> 16) & 0xFFFF; - sum += src_ip & 0xFFFF; - sum += (dst_ip >> 16) & 0xFFFF; - sum += dst_ip & 0xFFFF; - sum += protocol; - sum += length; - - for (uint16_t i = 0; i + 1 < length; i += 2) - sum += (udp_header_and_payload[i] << 8) | udp_header_and_payload[i + 1]; +uint16_t checksum16(uint16_t *data, size_t len); - if (length & 1) - sum += udp_header_and_payload[length - 1] << 8; - - while (sum >> 16) - sum = (sum & 0xFFFF) + (sum >> 16); - - return ~sum; -} +uint16_t checksum16_pipv4(uint32_t src_ip, uint32_t dst_ip, uint8_t protocol, const uint8_t* udp_header_and_payload, uint16_t length); typedef struct __attribute__((packed)) eth_hdr_t { uint8_t dst_mac[6]; From 1fac1e0f475898764fd9c1627d349df1cd2860e3 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sat, 21 Jun 2025 00:00:00 +0000 Subject: [PATCH 41/61] Messy but tcp 3w handshake --- kernel/networking/processes/net_proc.c | 81 ++++++++++++++++++++------ shared/net/tcp.c | 18 ++++++ shared/net/udp.c | 5 -- 3 files changed, 80 insertions(+), 24 deletions(-) diff --git a/kernel/networking/processes/net_proc.c b/kernel/networking/processes/net_proc.c index c43d2c6d..774b7516 100644 --- a/kernel/networking/processes/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -13,8 +13,65 @@ #include "../net_constants.h" #include "net/tcp.h" -void test_network(){ +tcp_hdr_t* tcp_handskake(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry){ + if (retry == 5){ + kprintf("Exceeded max number of retries"); + return 0x0; + } + + send_packet(TCP, port, dest, data, sizeof(tcp_data)); + + sizedptr pack; + + uint16_t timeout = 10; + while (!read_packet(&pack)){ + sleep(1000); + if (timeout-- == 0){ + return tcp_handskake(dest, port, data, retry+1); + } + } + + sizedptr payload = tcp_parse_packet_payload(pack.ptr); + + if (!payload.ptr) { + kprintf("Wrong payload pointer. Retrying"); + sleep(1000); + return tcp_handskake(dest, port, data, retry+1); + } + + tcp_hdr_t *response = (tcp_hdr_t*)payload.ptr; + if ((response->data_offset_reserved >> 4) * 4 != payload.size){ + kprintf("Wrong payload size %i vs %i. Retrying", (response->data_offset_reserved >> 4) * 4, payload.size); + sleep(1000); + return tcp_handskake(dest, port, data, retry+1); + } + + if (response->flags != (data->flags | (1 << ACK_F))){ + kprintf("Wrong flags %b vs %b. Retrying",response->flags, data->flags | (1 << ACK_F)); + sleep(1000); + return tcp_handskake(dest, port, data, retry+1); + } + + uint32_t ack = __builtin_bswap32(response->ack); + uint32_t seq = __builtin_bswap32(response->sequence); + if (ack != data->sequence + 1){ + kprintf("Wrong ack %i vs %i. Retrying", response->ack, data->sequence + 1); + sleep(1000); + return tcp_handskake(dest, port, data, retry+1); + } + data->sequence = __builtin_bswap32(ack); + data->ack = __builtin_bswap32(seq+1); + data->flags = (1 << ACK_F); + + send_packet(TCP, port, dest, data, sizeof(tcp_data)); + + kprintf("Acknowledgement of acknowledgemnt sent. Server seq = %i",seq); + + return response; +} + +void test_network(){ bind_port(8888); network_connection_ctx dest = (network_connection_ctx){ .ip = HOST_IP, @@ -27,26 +84,12 @@ void test_network(){ .ack = 0, .flags = (1 << SYN_F), .window = UINT16_MAX, - // sizedptr options; - // sizedptr payload; }; - // size_t payload_size = 5; - // char hw[5] = {'h','e','l','l','o'}; - - send_packet(TCP, 8888, &dest, &data, sizeof(tcp_data)); - - sizedptr pack; - - while (!read_packet(&pack)); - - kprintf("We got a response from the server. I'll parse it after dinner"); - - // sizedptr payload = udp_parse_packet_payload(pack.ptr); - - // uint8_t *content = (uint8_t*)payload.ptr; - - // kprintf("PAYLOAD: %s",(uintptr_t)string_ca_max(content, payload.size).data); + if (!tcp_handskake(&dest, 8888, &data, 0)){ + kprintf("TCP Error"); + return; + } unbind_port(8888); } diff --git a/shared/net/tcp.c b/shared/net/tcp.c index ef7daff4..1cb25860 100644 --- a/shared/net/tcp.c +++ b/shared/net/tcp.c @@ -37,4 +37,22 @@ void create_tcp_packet(uintptr_t p, network_connection_ctx source, network_conne memcpy((void*)p,(void*)data->payload.ptr, data->payload.size); tcp->checksum = __builtin_bswap16(checksum16_pipv4(source.ip,destination.ip,0x06,(uint8_t*)tcp, full_size)); +} + +sizedptr tcp_parse_packet_payload(uintptr_t ptr){ + eth_hdr_t* eth = (eth_hdr_t*)ptr; + + ptr += sizeof(eth_hdr_t); + + if (__builtin_bswap16(eth->ethertype) == 0x800){ + ipv4_hdr_t* ip = (ipv4_hdr_t*)ptr; + uint32_t srcip = __builtin_bswap32(ip->src_ip); + ptr += sizeof(ipv4_hdr_t); + if (ip->protocol == 0x06){ + tcp_hdr_t* tcp = (tcp_hdr_t*)ptr; + return (sizedptr){ptr,((tcp->data_offset_reserved >> 4) & 0xF) * 4}; + } + } + + return (sizedptr){0,0}; } \ No newline at end of file diff --git a/shared/net/udp.c b/shared/net/udp.c index 5e6037d6..728baf9d 100644 --- a/shared/net/udp.c +++ b/shared/net/udp.c @@ -45,13 +45,8 @@ sizedptr udp_parse_packet_payload(uintptr_t ptr){ ptr += sizeof(udp_hdr_t); uint16_t payload_len = __builtin_bswap16(udp->length) - sizeof(udp_hdr_t); return (sizedptr){ptr,payload_len}; - } else { - // kprintf("[UDP packet] Not prepared to handle non-UDP packets %x",ip->protocol); } } - else { - // kprintf("[UDP packet] Not prepared to handle non-ipv4 packets %x",__builtin_bswap16(eth->ethertype)); - } return (sizedptr){0,0}; } From 9a7af298b6aac304a6696fb8eeda0db03fbc0fd1 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sat, 21 Jun 2025 00:00:00 +0000 Subject: [PATCH 42/61] Connection reset, reusable TCP functions --- kernel/networking/processes/net_proc.c | 139 +++++++++++++++++++------ shared/net/tcp.h | 1 + 2 files changed, 111 insertions(+), 29 deletions(-) diff --git a/kernel/networking/processes/net_proc.c b/kernel/networking/processes/net_proc.c index 774b7516..13c9e7f5 100644 --- a/kernel/networking/processes/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -13,62 +13,139 @@ #include "../net_constants.h" #include "net/tcp.h" -tcp_hdr_t* tcp_handskake(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry){ - if (retry == 5){ - kprintf("Exceeded max number of retries"); - return 0x0; - } - - send_packet(TCP, port, dest, data, sizeof(tcp_data)); +#define TCP_RESET 2 +#define TCP_RETRY 1 +#define TCP_OK 0 + +void tcp_send(uint16_t port, network_connection_ctx *destination, tcp_data* data){ + send_packet(TCP, port, destination, data, sizeof(tcp_data)); + data->expected_ack = __builtin_bswap32(data->sequence) + 1; + if ((data->flags & ~(1 << ACK_F)) != 0) + data->sequence += __builtin_bswap32(max(1,data->payload.size)); + // kprintf("Next seq %i", __builtin_bswap32(data->sequence)); +} - sizedptr pack; +void tcp_reset(uint16_t port, network_connection_ctx *destination, tcp_data* data){ + data->flags = (1 << RST_F); + tcp_send(port, destination, data); +} +bool expect_response(sizedptr *pack){ uint16_t timeout = 10; - while (!read_packet(&pack)){ + while (!read_packet(pack)){ sleep(1000); if (timeout-- == 0){ - return tcp_handskake(dest, port, data, retry+1); + kprintf("Response timeout"); + return false; } } + return true; +} - sizedptr payload = tcp_parse_packet_payload(pack.ptr); +uint8_t tcp_check_response(tcp_data *data){ + + sizedptr pack; + if (!expect_response(&pack) || !pack.ptr){ + kprintf("Response timeout. Retrying"); + return TCP_RETRY; + } + + sizedptr payload = tcp_parse_packet_payload(pack.ptr); if (!payload.ptr) { kprintf("Wrong payload pointer. Retrying"); - sleep(1000); - return tcp_handskake(dest, port, data, retry+1); + return TCP_RETRY; } tcp_hdr_t *response = (tcp_hdr_t*)payload.ptr; - if ((response->data_offset_reserved >> 4) * 4 != payload.size){ - kprintf("Wrong payload size %i vs %i. Retrying", (response->data_offset_reserved >> 4) * 4, payload.size); + + uint32_t ack = __builtin_bswap32(response->ack); + uint32_t seq = __builtin_bswap32(response->sequence); + if (ack != data->expected_ack){ + kprintf("Wrong ack %i vs %i. Resetting", ack, data->sequence + 1); + return TCP_RESET; + } + + if (response->flags != (data->flags | (1 << ACK_F))){ + kprintf("Wrong flags %b vs %b. Resetting",response->flags, data->flags | (1 << ACK_F)); + return TCP_RESET; + } + + data->ack = __builtin_bswap32(seq+max(1,(payload.size - sizeof(tcp_hdr_t) - ((response->data_offset_reserved >> 4) * 4)))); + + return TCP_OK; +} + +bool tcp_handskake(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry){ + if (retry == 5){ + kprintf("Exceeded max number of retries"); + return false; + } + + data->sequence = 0; + data->ack = 0; + data->flags = (1 << SYN_F); + + tcp_send(port, dest, data); + + uint8_t resp = tcp_check_response(data); + if (resp == TCP_RETRY){ sleep(1000); return tcp_handskake(dest, port, data, retry+1); + } else if (resp == TCP_RESET){ + tcp_reset(port, dest, data); + return false; } - if (response->flags != (data->flags | (1 << ACK_F))){ - kprintf("Wrong flags %b vs %b. Retrying",response->flags, data->flags | (1 << ACK_F)); + data->flags = (1 << ACK_F); + + tcp_send(port, dest, data); + + kprintf("Acknowledgement of acknowledgemnt sent"); + + return true; +} + +bool tcp_close(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry, uint32_t orig_seq, uint32_t orig_ack){ + if (retry == 5){ + kprintf("Exceeded max number of retries"); + return false; + } + + data->sequence = orig_seq; + data->ack = orig_ack; + data->flags = (1 << FIN_F) | (1 << ACK_F); + + tcp_send(port, dest, data); + + data->flags = (1 << ACK_F); + uint8_t resp = tcp_check_response(data); + if (resp == TCP_RETRY){ sleep(1000); return tcp_handskake(dest, port, data, retry+1); + } else if (resp == TCP_RESET){ + tcp_reset(port, dest, data); + return false; } - uint32_t ack = __builtin_bswap32(response->ack); - uint32_t seq = __builtin_bswap32(response->sequence); - if (ack != data->sequence + 1){ - kprintf("Wrong ack %i vs %i. Retrying", response->ack, data->sequence + 1); + data->flags = (1 << FIN_F); + + resp = tcp_check_response(data); + if (resp == TCP_RETRY){ sleep(1000); return tcp_handskake(dest, port, data, retry+1); + } else if (resp == TCP_RESET){ + tcp_reset(port, dest, data); + return true; } - data->sequence = __builtin_bswap32(ack); - data->ack = __builtin_bswap32(seq+1); data->flags = (1 << ACK_F); - send_packet(TCP, port, dest, data, sizeof(tcp_data)); + tcp_send(port, dest, data); - kprintf("Acknowledgement of acknowledgemnt sent. Server seq = %i",seq); + kprintf("Connection closed"); - return response; + return true; } void test_network(){ @@ -80,9 +157,6 @@ void test_network(){ }; tcp_data data = (tcp_data){ - .sequence = 0, - .ack = 0, - .flags = (1 << SYN_F), .window = UINT16_MAX, }; @@ -91,6 +165,13 @@ void test_network(){ return; } + kprintf("Handshake completed"); + + if (!tcp_close(&dest, 8888, &data, 0, data.sequence, data.ack)){ + kprintf("TCP Connnection not closed"); + return; + } + unbind_port(8888); } diff --git a/shared/net/tcp.h b/shared/net/tcp.h index 5b1bb05d..c1963760 100644 --- a/shared/net/tcp.h +++ b/shared/net/tcp.h @@ -36,6 +36,7 @@ typedef struct tcp_data { uint16_t window; sizedptr options; sizedptr payload; + uint32_t expected_ack; } tcp_data; void create_tcp_packet(uintptr_t p, network_connection_ctx source, network_connection_ctx destination, sizedptr payload); From 80b059be595a1080c76c6dc16def853e07becc30 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sat, 21 Jun 2025 00:00:00 +0000 Subject: [PATCH 43/61] Moving tcp code to tcp library --- kernel/networking/processes/net_proc.c | 135 ------------------------- shared/net/tcp.c | 132 ++++++++++++++++++++++++ shared/net/tcp.h | 11 ++ 3 files changed, 143 insertions(+), 135 deletions(-) diff --git a/kernel/networking/processes/net_proc.c b/kernel/networking/processes/net_proc.c index 13c9e7f5..d0e71d83 100644 --- a/kernel/networking/processes/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -13,141 +13,6 @@ #include "../net_constants.h" #include "net/tcp.h" -#define TCP_RESET 2 -#define TCP_RETRY 1 -#define TCP_OK 0 - -void tcp_send(uint16_t port, network_connection_ctx *destination, tcp_data* data){ - send_packet(TCP, port, destination, data, sizeof(tcp_data)); - data->expected_ack = __builtin_bswap32(data->sequence) + 1; - if ((data->flags & ~(1 << ACK_F)) != 0) - data->sequence += __builtin_bswap32(max(1,data->payload.size)); - // kprintf("Next seq %i", __builtin_bswap32(data->sequence)); -} - -void tcp_reset(uint16_t port, network_connection_ctx *destination, tcp_data* data){ - data->flags = (1 << RST_F); - tcp_send(port, destination, data); -} - -bool expect_response(sizedptr *pack){ - uint16_t timeout = 10; - while (!read_packet(pack)){ - sleep(1000); - if (timeout-- == 0){ - kprintf("Response timeout"); - return false; - } - } - return true; -} - -uint8_t tcp_check_response(tcp_data *data){ - - sizedptr pack; - - if (!expect_response(&pack) || !pack.ptr){ - kprintf("Response timeout. Retrying"); - return TCP_RETRY; - } - - sizedptr payload = tcp_parse_packet_payload(pack.ptr); - if (!payload.ptr) { - kprintf("Wrong payload pointer. Retrying"); - return TCP_RETRY; - } - - tcp_hdr_t *response = (tcp_hdr_t*)payload.ptr; - - uint32_t ack = __builtin_bswap32(response->ack); - uint32_t seq = __builtin_bswap32(response->sequence); - if (ack != data->expected_ack){ - kprintf("Wrong ack %i vs %i. Resetting", ack, data->sequence + 1); - return TCP_RESET; - } - - if (response->flags != (data->flags | (1 << ACK_F))){ - kprintf("Wrong flags %b vs %b. Resetting",response->flags, data->flags | (1 << ACK_F)); - return TCP_RESET; - } - - data->ack = __builtin_bswap32(seq+max(1,(payload.size - sizeof(tcp_hdr_t) - ((response->data_offset_reserved >> 4) * 4)))); - - return TCP_OK; -} - -bool tcp_handskake(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry){ - if (retry == 5){ - kprintf("Exceeded max number of retries"); - return false; - } - - data->sequence = 0; - data->ack = 0; - data->flags = (1 << SYN_F); - - tcp_send(port, dest, data); - - uint8_t resp = tcp_check_response(data); - if (resp == TCP_RETRY){ - sleep(1000); - return tcp_handskake(dest, port, data, retry+1); - } else if (resp == TCP_RESET){ - tcp_reset(port, dest, data); - return false; - } - - data->flags = (1 << ACK_F); - - tcp_send(port, dest, data); - - kprintf("Acknowledgement of acknowledgemnt sent"); - - return true; -} - -bool tcp_close(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry, uint32_t orig_seq, uint32_t orig_ack){ - if (retry == 5){ - kprintf("Exceeded max number of retries"); - return false; - } - - data->sequence = orig_seq; - data->ack = orig_ack; - data->flags = (1 << FIN_F) | (1 << ACK_F); - - tcp_send(port, dest, data); - - data->flags = (1 << ACK_F); - uint8_t resp = tcp_check_response(data); - if (resp == TCP_RETRY){ - sleep(1000); - return tcp_handskake(dest, port, data, retry+1); - } else if (resp == TCP_RESET){ - tcp_reset(port, dest, data); - return false; - } - - data->flags = (1 << FIN_F); - - resp = tcp_check_response(data); - if (resp == TCP_RETRY){ - sleep(1000); - return tcp_handskake(dest, port, data, retry+1); - } else if (resp == TCP_RESET){ - tcp_reset(port, dest, data); - return true; - } - - data->flags = (1 << ACK_F); - - tcp_send(port, dest, data); - - kprintf("Connection closed"); - - return true; -} - void test_network(){ bind_port(8888); network_connection_ctx dest = (network_connection_ctx){ diff --git a/shared/net/tcp.c b/shared/net/tcp.c index 1cb25860..653b580f 100644 --- a/shared/net/tcp.c +++ b/shared/net/tcp.c @@ -6,6 +6,7 @@ #include "std/memfunctions.h" #include "eth.h" #include "ipv4.h" +#include "math/math.h" void create_tcp_packet(uintptr_t p, network_connection_ctx source, network_connection_ctx destination, sizedptr payload){ p = create_eth_packet(p, source.mac, destination.mac, 0x800); @@ -55,4 +56,135 @@ sizedptr tcp_parse_packet_payload(uintptr_t ptr){ } return (sizedptr){0,0}; +} + +void tcp_send(uint16_t port, network_connection_ctx *destination, tcp_data* data){ + send_packet(TCP, port, destination, data, sizeof(tcp_data)); + data->expected_ack = __builtin_bswap32(data->sequence) + 1; + if ((data->flags & ~(1 << ACK_F)) != 0) + data->sequence += __builtin_bswap32(max(1,data->payload.size)); + // kprintf("Next seq %i", __builtin_bswap32(data->sequence)); +} + +void tcp_reset(uint16_t port, network_connection_ctx *destination, tcp_data* data){ + data->flags = (1 << RST_F); + tcp_send(port, destination, data); +} + +bool tcp_expect_response(sizedptr *pack){ + uint16_t timeout = 10; + while (!read_packet(pack)){ + sleep(1000); + if (timeout-- == 0){ + kprintf("Response timeout"); + return false; + } + } + return true; +} + +uint8_t tcp_check_response(tcp_data *data){ + + sizedptr pack; + + if (!tcp_expect_response(&pack) || !pack.ptr){ + kprintf("Response timeout. Retrying"); + return TCP_RETRY; + } + + sizedptr payload = tcp_parse_packet_payload(pack.ptr); + if (!payload.ptr) { + kprintf("Wrong payload pointer. Retrying"); + return TCP_RETRY; + } + + tcp_hdr_t *response = (tcp_hdr_t*)payload.ptr; + + uint32_t ack = __builtin_bswap32(response->ack); + uint32_t seq = __builtin_bswap32(response->sequence); + if (ack != data->expected_ack){ + kprintf("Wrong ack %i vs %i. Resetting", ack, data->sequence + 1); + return TCP_RESET; + } + + if (response->flags != (data->flags | (1 << ACK_F))){ + kprintf("Wrong flags %b vs %b. Resetting",response->flags, data->flags | (1 << ACK_F)); + return TCP_RESET; + } + + data->ack = __builtin_bswap32(seq+max(1,(payload.size - sizeof(tcp_hdr_t) - ((response->data_offset_reserved >> 4) * 4)))); + + return TCP_OK; +} + +bool tcp_handskake(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry){ + if (retry == 5){ + kprintf("Exceeded max number of retries"); + return false; + } + + data->sequence = 0; + data->ack = 0; + data->flags = (1 << SYN_F); + + tcp_send(port, dest, data); + + uint8_t resp = tcp_check_response(data); + if (resp == TCP_RETRY){ + sleep(1000); + return tcp_handskake(dest, port, data, retry+1); + } else if (resp == TCP_RESET){ + tcp_reset(port, dest, data); + return false; + } + + data->flags = (1 << ACK_F); + + tcp_send(port, dest, data); + + kprintf("Acknowledgement of acknowledgemnt sent"); + + return true; +} + +bool tcp_close(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry, uint32_t orig_seq, uint32_t orig_ack){ + if (retry == 5){ + kprintf("Exceeded max number of retries"); + return false; + } + + data->sequence = orig_seq; + data->ack = orig_ack; + data->flags = (1 << FIN_F) | (1 << ACK_F); + + tcp_send(port, dest, data); + + data->flags = (1 << ACK_F); + uint8_t resp = tcp_check_response(data); + if (resp == TCP_RETRY){ + sleep(1000); + return tcp_handskake(dest, port, data, retry+1); + } else if (resp == TCP_RESET){ + tcp_reset(port, dest, data); + return false; + } + + data->flags = (1 << FIN_F); + + resp = tcp_check_response(data); + if (resp == TCP_RETRY){ + sleep(1000); + return tcp_handskake(dest, port, data, retry+1); + } else if (resp == TCP_RESET){ + tcp_reset(port, dest, data); + return true; + } + + data->flags = (1 << ACK_F); + + tcp_send(port, dest, data); + + kprintf("Connection closed"); + + return true; } \ No newline at end of file diff --git a/shared/net/tcp.h b/shared/net/tcp.h index c1963760..a9fa0758 100644 --- a/shared/net/tcp.h +++ b/shared/net/tcp.h @@ -16,6 +16,10 @@ extern "C" { #define ECE_F 6 #define CWR_F 7 +#define TCP_RESET 2 +#define TCP_RETRY 1 +#define TCP_OK 0 + typedef struct __attribute__((packed)) tcp_hdr_t { uint16_t src_port; uint16_t dst_port; @@ -44,6 +48,13 @@ size_t calc_tcp_size(uint16_t payload_len); uint16_t tcp_parse_packet(uintptr_t ptr); sizedptr tcp_parse_packet_payload(uintptr_t ptr); +void tcp_send(uint16_t port, network_connection_ctx *destination, tcp_data* data); +void tcp_reset(uint16_t port, network_connection_ctx *destination, tcp_data* data); +bool expect_response(sizedptr *pack); +uint8_t tcp_check_response(tcp_data *data); +bool tcp_handskake(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry); +bool tcp_close(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry, uint32_t orig_seq, uint32_t orig_ack); + #ifdef __cplusplus } #endif \ No newline at end of file From c930b9dda9621ba1777b8852f66b0f4453797775 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sat, 21 Jun 2025 00:00:00 +0000 Subject: [PATCH 44/61] printf and out response payload --- shared/net/tcp.c | 39 +++++++++++++++++++++++---------------- shared/net/tcp.h | 2 +- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/shared/net/tcp.c b/shared/net/tcp.c index 653b580f..794fbbff 100644 --- a/shared/net/tcp.c +++ b/shared/net/tcp.c @@ -22,7 +22,7 @@ void create_tcp_packet(uintptr_t p, network_connection_ctx source, network_conne tcp->dst_port = __builtin_bswap16(destination.port); if (payload.size != sizeof(tcp_data)){ - kprintf("[TCP Packet creation error] wrong payload size %i (expected %i)",payload.size, sizeof(tcp_data)); + printf("[TCP Packet creation error] wrong payload size %i (expected %i)",payload.size, sizeof(tcp_data)); } memcpy((void*)&tcp->sequence,(void*)payload.ptr, 12); @@ -63,7 +63,7 @@ void tcp_send(uint16_t port, network_connection_ctx *destination, tcp_data* data data->expected_ack = __builtin_bswap32(data->sequence) + 1; if ((data->flags & ~(1 << ACK_F)) != 0) data->sequence += __builtin_bswap32(max(1,data->payload.size)); - // kprintf("Next seq %i", __builtin_bswap32(data->sequence)); + // printf("Next seq %i", __builtin_bswap32(data->sequence)); } void tcp_reset(uint16_t port, network_connection_ctx *destination, tcp_data* data){ @@ -76,25 +76,25 @@ bool tcp_expect_response(sizedptr *pack){ while (!read_packet(pack)){ sleep(1000); if (timeout-- == 0){ - kprintf("Response timeout"); + printf("Response timeout"); return false; } } return true; } -uint8_t tcp_check_response(tcp_data *data){ +uint8_t tcp_check_response(tcp_data *data, sizedptr *out){ sizedptr pack; if (!tcp_expect_response(&pack) || !pack.ptr){ - kprintf("Response timeout. Retrying"); + printf("Response timeout. Retrying"); return TCP_RETRY; } sizedptr payload = tcp_parse_packet_payload(pack.ptr); if (!payload.ptr) { - kprintf("Wrong payload pointer. Retrying"); + printf("Wrong payload pointer. Retrying"); return TCP_RETRY; } @@ -103,23 +103,30 @@ uint8_t tcp_check_response(tcp_data *data){ uint32_t ack = __builtin_bswap32(response->ack); uint32_t seq = __builtin_bswap32(response->sequence); if (ack != data->expected_ack){ - kprintf("Wrong ack %i vs %i. Resetting", ack, data->sequence + 1); + printf("Wrong ack %i vs %i. Resetting", ack, data->sequence + 1); return TCP_RESET; } if (response->flags != (data->flags | (1 << ACK_F))){ - kprintf("Wrong flags %b vs %b. Resetting",response->flags, data->flags | (1 << ACK_F)); + printf("Wrong flags %b vs %b. Resetting",response->flags, data->flags | (1 << ACK_F)); return TCP_RESET; } - data->ack = __builtin_bswap32(seq+max(1,(payload.size - sizeof(tcp_hdr_t) - ((response->data_offset_reserved >> 4) * 4)))); + size_t opt_size = ((response->data_offset_reserved >> 4) * 4); + size_t payload_size = (payload.size - sizeof(tcp_hdr_t) - opt_size); + data->ack = __builtin_bswap32(seq+max(1,payload_size)); + + if (out){ + out->ptr = payload.ptr + sizeof(tcp_hdr_t) + opt_size; + out->size = payload_size; + } return TCP_OK; } bool tcp_handskake(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry){ if (retry == 5){ - kprintf("Exceeded max number of retries"); + printf("Exceeded max number of retries"); return false; } @@ -129,7 +136,7 @@ bool tcp_handskake(network_connection_ctx *dest, uint16_t port, tcp_data *data, tcp_send(port, dest, data); - uint8_t resp = tcp_check_response(data); + uint8_t resp = tcp_check_response(data, 0); if (resp == TCP_RETRY){ sleep(1000); return tcp_handskake(dest, port, data, retry+1); @@ -142,14 +149,14 @@ bool tcp_handskake(network_connection_ctx *dest, uint16_t port, tcp_data *data, tcp_send(port, dest, data); - kprintf("Acknowledgement of acknowledgemnt sent"); + printf("Acknowledgement of acknowledgemnt sent"); return true; } bool tcp_close(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry, uint32_t orig_seq, uint32_t orig_ack){ if (retry == 5){ - kprintf("Exceeded max number of retries"); + printf("Exceeded max number of retries"); return false; } @@ -160,7 +167,7 @@ bool tcp_close(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint tcp_send(port, dest, data); data->flags = (1 << ACK_F); - uint8_t resp = tcp_check_response(data); + uint8_t resp = tcp_check_response(data, 0); if (resp == TCP_RETRY){ sleep(1000); return tcp_handskake(dest, port, data, retry+1); @@ -171,7 +178,7 @@ bool tcp_close(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint data->flags = (1 << FIN_F); - resp = tcp_check_response(data); + resp = tcp_check_response(data, 0); if (resp == TCP_RETRY){ sleep(1000); return tcp_handskake(dest, port, data, retry+1); @@ -184,7 +191,7 @@ bool tcp_close(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint tcp_send(port, dest, data); - kprintf("Connection closed"); + printf("Connection closed"); return true; } \ No newline at end of file diff --git a/shared/net/tcp.h b/shared/net/tcp.h index a9fa0758..0d0cb9a6 100644 --- a/shared/net/tcp.h +++ b/shared/net/tcp.h @@ -51,7 +51,7 @@ sizedptr tcp_parse_packet_payload(uintptr_t ptr); void tcp_send(uint16_t port, network_connection_ctx *destination, tcp_data* data); void tcp_reset(uint16_t port, network_connection_ctx *destination, tcp_data* data); bool expect_response(sizedptr *pack); -uint8_t tcp_check_response(tcp_data *data); +uint8_t tcp_check_response(tcp_data *data, sizedptr *out); bool tcp_handskake(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry); bool tcp_close(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry, uint32_t orig_seq, uint32_t orig_ack); From 27e05b862a887f9c72a0aba5a2aa3da7f3b72f0d Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sat, 21 Jun 2025 00:00:00 +0000 Subject: [PATCH 45/61] Temporarily moved all TCP/HTTP code back to kernel cause I'm too lazy to fix a printf issue, but receiving HTTP data --- kernel/networking/processes/net_proc.c | 243 +++++++++++++++++++++++-- shared/net/http.c | 6 + shared/net/http.h | 14 ++ shared/net/ipv4.c | 5 + shared/net/ipv4.h | 2 + shared/net/tcp.c | 138 -------------- 6 files changed, 257 insertions(+), 151 deletions(-) create mode 100644 shared/net/http.c create mode 100644 shared/net/http.h diff --git a/kernel/networking/processes/net_proc.c b/kernel/networking/processes/net_proc.c index d0e71d83..496af73e 100644 --- a/kernel/networking/processes/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -12,31 +12,248 @@ #include "math/math.h" #include "../net_constants.h" #include "net/tcp.h" +#include "net/http.h" +#include "net/ipv4.h" -void test_network(){ - bind_port(8888); - network_connection_ctx dest = (network_connection_ctx){ - .ip = HOST_IP, - .mac = HOST_MAC, - .port = 80, - }; +void tcp_send(uint16_t port, network_connection_ctx *destination, tcp_data* data){ + send_packet(TCP, port, destination, data, sizeof(tcp_data)); + if ((data->flags & ~(1 << ACK_F)) != 0 || data->payload.size > 0){ + kprintf("The payload is %i size",data->payload.size); + data->sequence += __builtin_bswap32(max(1,data->payload.size)); + } + data->expected_ack = __builtin_bswap32(data->sequence); + kprintf("Next seq %i", __builtin_bswap32(data->sequence)); +} + +void tcp_reset(uint16_t port, network_connection_ctx *destination, tcp_data* data){ + data->flags = (1 << RST_F) | (1 << ACK_F); + tcp_send(port, destination, data); +} + +bool tcp_expect_response(sizedptr *pack){ + uint16_t timeout = 10; + while (!read_packet(pack)){ + sleep(1000); + if (timeout-- == 0){ + kprintf("Response timeout"); + return false; + } + } + return true; +} + +uint8_t tcp_check_response(tcp_data *data, sizedptr *out){ + + sizedptr pack; + + if (!tcp_expect_response(&pack) || !pack.ptr){ + kprintf("Response timeout. Retrying"); + return TCP_RETRY; + } + + sizedptr payload = tcp_parse_packet_payload(pack.ptr); + if (!payload.ptr) { + kprintf("Wrong payload pointer. Retrying"); + return TCP_RETRY; + } + + tcp_hdr_t *response = (tcp_hdr_t*)payload.ptr; + + uint32_t ack = __builtin_bswap32(response->ack); + uint32_t seq = __builtin_bswap32(response->sequence); + + size_t hdr_size = (response->data_offset_reserved >> 4) * 4; + size_t payload_size = payload.size - hdr_size; + data->ack = __builtin_bswap32(seq+max(1,payload_size)); + + if (ack != data->expected_ack){ + kprintf("Wrong ack %i vs %i. Resetting", ack, data->expected_ack); + return TCP_RESET; + } else kprintf("Received ack %i", ack); + + if (response->flags != (data->flags | (1 << ACK_F))){ + kprintf("Wrong flags %b vs %b. Resetting",response->flags, data->flags | (1 << ACK_F)); + return TCP_RESET; + } + + if (out){ + out->ptr = payload.ptr + hdr_size; + out->size = payload_size; + } + + return TCP_OK; +} + +bool tcp_handskake(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry){ + if (retry == 5){ + kprintf("Exceeded max number of retries"); + return false; + } + + data->sequence = 0; + data->ack = 0; + data->flags = (1 << SYN_F); + + tcp_send(port, dest, data); + + uint8_t resp = tcp_check_response(data, 0); + if (resp == TCP_RETRY){ + sleep(1000); + return tcp_handskake(dest, port, data, retry+1); + } else if (resp == TCP_RESET){ + tcp_reset(port, dest, data); + return false; + } + + data->flags = (1 << ACK_F); + + tcp_send(port, dest, data); + + kprintf("Acknowledgement of acknowledgemnt sent"); + + return true; +} + +bool tcp_close(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry, uint32_t orig_seq, uint32_t orig_ack){ + if (retry == 5){ + kprintf("Exceeded max number of retries"); + return false; + } + + data->sequence = orig_seq; + data->ack = orig_ack; + data->flags = (1 << FIN_F) | (1 << ACK_F); + + tcp_send(port, dest, data); + + data->flags = (1 << ACK_F); + uint8_t resp = tcp_check_response(data, 0); + if (resp == TCP_RETRY){ + sleep(1000); + return tcp_handskake(dest, port, data, retry+1); + } else if (resp == TCP_RESET){ + tcp_reset(port, dest, data); + return false; + } + data->flags = (1 << FIN_F); + + resp = tcp_check_response(data, 0); + if (resp == TCP_RETRY){ + sleep(1000); + return tcp_handskake(dest, port, data, retry+1); + } else if (resp == TCP_RESET){ + tcp_reset(port, dest, data); + return true; + } + + data->flags = (1 << ACK_F); + + tcp_send(port, dest, data); + + kprintf("Connection closed"); + + return true; +} + +string make_http_request(HTTPRequest request, char *domain, char *agent){ + //TODO: request instead of hardcoded GET + return string_format("GET / HTTP/1.1\r\nHost: %s\r\nUser-Agent: %s\r\nAccept: */*\r\n\r\n",domain, agent); +} + +sizedptr http_data_transfer(network_connection_ctx *dest, sizedptr payload, uint16_t port, tcp_data *data, uint8_t retry, uint32_t orig_seq, uint32_t orig_ack){ + if (retry == 5){ + kprintf("Exceeded max number of retries"); + return (sizedptr){0}; + } + + data->sequence = orig_seq; + data->ack = orig_ack; + data->flags = (1 << PSH_F) | (1 << ACK_F); + + data->payload = payload; + + tcp_send(port, dest, data); + + data->flags = (1 << ACK_F); + + uint8_t resp; + do { + resp = tcp_check_response(data, 0); + if (resp == TCP_OK) + break; + if (resp == TCP_RESET)//We don't reset, we ignore irrelevant packets (or we could parse them tbh) + continue; + if (resp == TCP_RETRY) + return http_data_transfer(dest, payload, port, data, retry+1, orig_seq, orig_ack); + } while (1); + + data->flags = (1 << PSH_F) | (1 << ACK_F); + + sizedptr http_content; + + resp = tcp_check_response(data, &http_content); + if (resp == TCP_RETRY){ + sleep(1000); + return http_data_transfer(dest, payload, port, data, retry+1, orig_seq, orig_ack); + } else if (resp == TCP_RESET){ + tcp_reset(port, dest, data); + return (sizedptr){0}; + } + + data->payload = (sizedptr){0}; + + data->flags = (1 << ACK_F); + tcp_send(port, dest, data); + + return http_content; +} + +sizedptr request_http_data(HTTPRequest request, network_connection_ctx *dest, uint16_t port){ tcp_data data = (tcp_data){ .window = UINT16_MAX, }; - if (!tcp_handskake(&dest, 8888, &data, 0)){ - kprintf("TCP Error"); - return; + if (!tcp_handskake(dest, 8888, &data, 0)){ + kprintf("TCP Handshake Error"); + return (sizedptr){0}; } - kprintf("Handshake completed"); + string serverstr = ipv4_to_string(dest->ip); + string req = make_http_request(request, serverstr.data, "redactedos/0.0.1"); + + free(serverstr.data, serverstr.mem_length); + + kprintf("Request"); - if (!tcp_close(&dest, 8888, &data, 0, data.sequence, data.ack)){ + sizedptr http_response = http_data_transfer(dest, (sizedptr){(uintptr_t)req.data, req.length}, port, &data, 0, data.sequence, data.ack); + + kprintf("END"); + + free(req.data, req.mem_length); + + if (!tcp_close(dest, 8888, &data, 0, data.sequence, data.ack)){ kprintf("TCP Connnection not closed"); - return; + return (sizedptr){0}; } + return http_response; +} + +void test_network(){ + bind_port(8888); + network_connection_ctx dest = (network_connection_ctx){ + .ip = HOST_IP, + .mac = HOST_MAC, + .port = 80, + }; + + sizedptr http = request_http_data(GET, &dest, 8888); + + kprintf("Received payload? %x",(uintptr_t)&http); + + kprintf("Received payload? %s",(uintptr_t)http.ptr); + unbind_port(8888); } diff --git a/shared/net/http.c b/shared/net/http.c new file mode 100644 index 00000000..a200a28a --- /dev/null +++ b/shared/net/http.c @@ -0,0 +1,6 @@ +#include "http.h" +#include "std/string.h" +#include "tcp.h" +#include "syscalls/syscalls.h" +#include "ipv4.h" + diff --git a/shared/net/http.h b/shared/net/http.h new file mode 100644 index 00000000..4ac08f1e --- /dev/null +++ b/shared/net/http.h @@ -0,0 +1,14 @@ +#pragma once + +#include "tcp.h" +#include "types.h" +#include "network_types.h" + +typedef enum HTTPRequest { + GET, + POST, + PUT, + DELETE +} HTTPRequest; + +// sizedptr request_http_data(HTTPRequest request, network_connection_ctx *dest, uint16_t port); \ No newline at end of file diff --git a/shared/net/ipv4.c b/shared/net/ipv4.c index 47e4de3b..2f09f149 100644 --- a/shared/net/ipv4.c +++ b/shared/net/ipv4.c @@ -1,6 +1,7 @@ #include "ipv4.h" #include "console/kio.h" #include "network_types.h" +#include "std/string.h" #include "std/memfunctions.h" uintptr_t create_ipv4_packet(uintptr_t p, uint32_t payload_len, uint8_t protocol, uint32_t source_ip, uint32_t destination_ip){ @@ -25,4 +26,8 @@ uint8_t ipv4_get_protocol(uintptr_t ptr){ void ipv4_populate_response(network_connection_ctx *ctx, eth_hdr_t *eth, ipv4_hdr_t* ipv4){ ctx->ip = __builtin_bswap32(ipv4->src_ip); memcpy(ctx->mac, eth->src_mac, 6); +} + +string ipv4_to_string(uint32_t ip){ + return string_format("%i.%i.%i.%i",(ip >> 24) & 0xFF,(ip >> 16) & 0xFF,(ip >> 8) & 0xFF,(ip >> 0) & 0xFF); } \ No newline at end of file diff --git a/shared/net/ipv4.h b/shared/net/ipv4.h index 94be5f4d..2ee9bb9a 100644 --- a/shared/net/ipv4.h +++ b/shared/net/ipv4.h @@ -6,10 +6,12 @@ extern "C" { #include "types.h" #include "net/network_types.h" +#include "std/string.h" uint8_t ipv4_get_protocol(uintptr_t ptr); uintptr_t create_ipv4_packet(uintptr_t p, uint32_t payload_len, uint8_t protocol, uint32_t source_ip, uint32_t destination_ip); void ipv4_populate_response(network_connection_ctx *ctx, eth_hdr_t *eth, ipv4_hdr_t* ipv4); +string ipv4_to_string(uint32_t ip); #ifdef __cplusplus } diff --git a/shared/net/tcp.c b/shared/net/tcp.c index 794fbbff..7e8ad0bb 100644 --- a/shared/net/tcp.c +++ b/shared/net/tcp.c @@ -56,142 +56,4 @@ sizedptr tcp_parse_packet_payload(uintptr_t ptr){ } return (sizedptr){0,0}; -} - -void tcp_send(uint16_t port, network_connection_ctx *destination, tcp_data* data){ - send_packet(TCP, port, destination, data, sizeof(tcp_data)); - data->expected_ack = __builtin_bswap32(data->sequence) + 1; - if ((data->flags & ~(1 << ACK_F)) != 0) - data->sequence += __builtin_bswap32(max(1,data->payload.size)); - // printf("Next seq %i", __builtin_bswap32(data->sequence)); -} - -void tcp_reset(uint16_t port, network_connection_ctx *destination, tcp_data* data){ - data->flags = (1 << RST_F); - tcp_send(port, destination, data); -} - -bool tcp_expect_response(sizedptr *pack){ - uint16_t timeout = 10; - while (!read_packet(pack)){ - sleep(1000); - if (timeout-- == 0){ - printf("Response timeout"); - return false; - } - } - return true; -} - -uint8_t tcp_check_response(tcp_data *data, sizedptr *out){ - - sizedptr pack; - - if (!tcp_expect_response(&pack) || !pack.ptr){ - printf("Response timeout. Retrying"); - return TCP_RETRY; - } - - sizedptr payload = tcp_parse_packet_payload(pack.ptr); - if (!payload.ptr) { - printf("Wrong payload pointer. Retrying"); - return TCP_RETRY; - } - - tcp_hdr_t *response = (tcp_hdr_t*)payload.ptr; - - uint32_t ack = __builtin_bswap32(response->ack); - uint32_t seq = __builtin_bswap32(response->sequence); - if (ack != data->expected_ack){ - printf("Wrong ack %i vs %i. Resetting", ack, data->sequence + 1); - return TCP_RESET; - } - - if (response->flags != (data->flags | (1 << ACK_F))){ - printf("Wrong flags %b vs %b. Resetting",response->flags, data->flags | (1 << ACK_F)); - return TCP_RESET; - } - - size_t opt_size = ((response->data_offset_reserved >> 4) * 4); - size_t payload_size = (payload.size - sizeof(tcp_hdr_t) - opt_size); - data->ack = __builtin_bswap32(seq+max(1,payload_size)); - - if (out){ - out->ptr = payload.ptr + sizeof(tcp_hdr_t) + opt_size; - out->size = payload_size; - } - - return TCP_OK; -} - -bool tcp_handskake(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry){ - if (retry == 5){ - printf("Exceeded max number of retries"); - return false; - } - - data->sequence = 0; - data->ack = 0; - data->flags = (1 << SYN_F); - - tcp_send(port, dest, data); - - uint8_t resp = tcp_check_response(data, 0); - if (resp == TCP_RETRY){ - sleep(1000); - return tcp_handskake(dest, port, data, retry+1); - } else if (resp == TCP_RESET){ - tcp_reset(port, dest, data); - return false; - } - - data->flags = (1 << ACK_F); - - tcp_send(port, dest, data); - - printf("Acknowledgement of acknowledgemnt sent"); - - return true; -} - -bool tcp_close(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry, uint32_t orig_seq, uint32_t orig_ack){ - if (retry == 5){ - printf("Exceeded max number of retries"); - return false; - } - - data->sequence = orig_seq; - data->ack = orig_ack; - data->flags = (1 << FIN_F) | (1 << ACK_F); - - tcp_send(port, dest, data); - - data->flags = (1 << ACK_F); - uint8_t resp = tcp_check_response(data, 0); - if (resp == TCP_RETRY){ - sleep(1000); - return tcp_handskake(dest, port, data, retry+1); - } else if (resp == TCP_RESET){ - tcp_reset(port, dest, data); - return false; - } - - data->flags = (1 << FIN_F); - - resp = tcp_check_response(data, 0); - if (resp == TCP_RETRY){ - sleep(1000); - return tcp_handskake(dest, port, data, retry+1); - } else if (resp == TCP_RESET){ - tcp_reset(port, dest, data); - return true; - } - - data->flags = (1 << ACK_F); - - tcp_send(port, dest, data); - - printf("Connection closed"); - - return true; } \ No newline at end of file From 94ddbab6c0123fb7fc986d7c18853c94d9e75d8b Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sun, 22 Jun 2025 00:00:00 +0000 Subject: [PATCH 46/61] Moved all packets to shared lib --- kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp | 6 +++--- kernel/networking/network_dispatch.cpp | 4 ++-- kernel/networking/processes/net_proc.c | 3 +-- {kernel/networking/protocols => shared/net}/arp.c | 0 {kernel/networking/protocols => shared/net}/arp.h | 0 {kernel/networking/protocols => shared/net}/dhcp.c | 0 {kernel/networking/protocols => shared/net}/dhcp.h | 0 {kernel/networking/protocols => shared/net}/icmp.c | 0 {kernel/networking/protocols => shared/net}/icmp.h | 0 9 files changed, 6 insertions(+), 7 deletions(-) rename {kernel/networking/protocols => shared/net}/arp.c (100%) rename {kernel/networking/protocols => shared/net}/arp.h (100%) rename {kernel/networking/protocols => shared/net}/dhcp.c (100%) rename {kernel/networking/protocols => shared/net}/dhcp.h (100%) rename {kernel/networking/protocols => shared/net}/icmp.c (100%) rename {kernel/networking/protocols => shared/net}/icmp.h (100%) diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index fa605fbc..b3648e3b 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -2,9 +2,9 @@ #include "console/kio.h" #include "net/udp.h" #include "net/tcp.h" -#include "../../protocols/dhcp.h" -#include "../../protocols/arp.h" -#include "../../protocols/icmp.h" +#include "net/dhcp.h" +#include "net/arp.h" +#include "net/icmp.h" #include "networking/network.h" #include "pci.h" #include "syscalls/syscalls.h" diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index 5f18f830..f1ef7bcc 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -7,9 +7,9 @@ #include "net/eth.h" #include "net/ipv4.h" #include "memory/page_allocator.h" -#include "protocols/icmp.h" +#include "net/icmp.h" #include "std/memfunctions.h" -#include "protocols/arp.h" +#include "net/arp.h" NetworkDispatch::NetworkDispatch(){ ports = IndexMap(UINT16_MAX); diff --git a/kernel/networking/processes/net_proc.c b/kernel/networking/processes/net_proc.c index 496af73e..e562e333 100644 --- a/kernel/networking/processes/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -4,8 +4,7 @@ #include "process/scheduler.h" #include "console/kio.h" #include "net/udp.h" -#include "../protocols/dhcp.h" -#include "../protocols/dhcp.h" +#include "net/dhcp.h" #include "std/memfunctions.h" #include "networking/network.h" #include "syscalls/syscalls.h" diff --git a/kernel/networking/protocols/arp.c b/shared/net/arp.c similarity index 100% rename from kernel/networking/protocols/arp.c rename to shared/net/arp.c diff --git a/kernel/networking/protocols/arp.h b/shared/net/arp.h similarity index 100% rename from kernel/networking/protocols/arp.h rename to shared/net/arp.h diff --git a/kernel/networking/protocols/dhcp.c b/shared/net/dhcp.c similarity index 100% rename from kernel/networking/protocols/dhcp.c rename to shared/net/dhcp.c diff --git a/kernel/networking/protocols/dhcp.h b/shared/net/dhcp.h similarity index 100% rename from kernel/networking/protocols/dhcp.h rename to shared/net/dhcp.h diff --git a/kernel/networking/protocols/icmp.c b/shared/net/icmp.c similarity index 100% rename from kernel/networking/protocols/icmp.c rename to shared/net/icmp.c diff --git a/kernel/networking/protocols/icmp.h b/shared/net/icmp.h similarity index 100% rename from kernel/networking/protocols/icmp.h rename to shared/net/icmp.h From 35bae500ed4967029146eca6c989b085ecc08e2f Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sun, 22 Jun 2025 00:00:00 +0000 Subject: [PATCH 47/61] Fixed printf and empty http responses --- kernel/kernel_processes/monitor/monitor_processes.c | 2 +- kernel/networking/processes/net_proc.c | 3 ++- shared/std/string.c | 11 +++++++---- shared/std/string.h | 1 + shared/syscalls/syscalls.c | 4 +++- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/kernel/kernel_processes/monitor/monitor_processes.c b/kernel/kernel_processes/monitor/monitor_processes.c index 9001ea61..18149b56 100644 --- a/kernel/kernel_processes/monitor/monitor_processes.c +++ b/kernel/kernel_processes/monitor/monitor_processes.c @@ -43,7 +43,7 @@ void print_process_info(){ for (int i = 0; i < MAX_PROCS; i++){ process_t *proc = &processes[i]; if (proc->id != 0 && proc->state != STOPPED){ - printf("Process [%i]: %s [pid = %i | status = %s]",i,(uintptr_t)proc->name,proc->id,(uint64_t)parse_proc_state(proc->state)); + printf("Process [%i]: %s [pid = %i | status = %s]",i,(uintptr_t)proc->name,proc->id,(uintptr_t)parse_proc_state(proc->state)); printf("Stack: %x (%x). SP: %x",proc->stack, proc->stack_size, proc->sp); printf("Heap: %x (%x)",proc->heap, calc_heap(proc->heap)); printf("Flags: %x", proc->spsr); diff --git a/kernel/networking/processes/net_proc.c b/kernel/networking/processes/net_proc.c index e562e333..bf1f5f24 100644 --- a/kernel/networking/processes/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -251,7 +251,8 @@ void test_network(){ kprintf("Received payload? %x",(uintptr_t)&http); - kprintf("Received payload? %s",(uintptr_t)http.ptr); + if (http.ptr != 0) + kprintf("Received payload? %s",(uintptr_t)http.ptr); unbind_port(8888); } diff --git a/shared/std/string.c b/shared/std/string.c index e5dc3819..78779707 100644 --- a/shared/std/string.c +++ b/shared/std/string.c @@ -110,13 +110,17 @@ bool string_equals(string a, string b) { } string string_format(const char *fmt, ...) { + va_list args; + va_start(args, fmt); + string_format_va(fmt, args); + va_end(args); +} + +string string_format_va(const char *fmt, va_list args){ char *buf = (char*)malloc(256); uint32_t len = 0; uint32_t arg_index = 0; - va_list args; - va_start(args, fmt); - for (uint32_t i = 0; fmt[i] && len < 255; i++) { if (fmt[i] == '%' && fmt[i+1]) { i++; @@ -193,7 +197,6 @@ string string_format(const char *fmt, ...) { } buf[len] = 0; - va_end(args); return (string){ .data = buf, .length = len, .mem_length = 256 }; } diff --git a/shared/std/string.h b/shared/std/string.h index da206c0e..39ceb853 100644 --- a/shared/std/string.h +++ b/shared/std/string.h @@ -20,6 +20,7 @@ string string_c(const char c); string string_from_hex(uint64_t value); bool string_equals(string a, string b); string string_format(const char *fmt, ...); +string string_format_va(const char *fmt, va_list args); string string_tail(const char *array, uint32_t max_length); string string_repeat(char symbol, uint32_t amount); diff --git a/shared/syscalls/syscalls.c b/shared/syscalls/syscalls.c index 0127f6a0..5811ee72 100644 --- a/shared/syscalls/syscalls.c +++ b/shared/syscalls/syscalls.c @@ -3,7 +3,9 @@ void printf(const char *fmt, ...){ va_list args; - string str = string_format(fmt, args); + va_start(args, fmt); + string str = string_format_va(fmt, args); + va_end(args); printl(str.data); free(str.data, str.mem_length); } \ No newline at end of file From da3e4b3e10abb713d28eef80669cf660a90bc539 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sun, 22 Jun 2025 00:00:00 +0000 Subject: [PATCH 48/61] Restored http and tcp to their library --- kernel/networking/processes/net_proc.c | 225 ------------------------- shared/net/http.c | 83 +++++++++ shared/net/http.h | 2 +- shared/net/tcp.c | 141 ++++++++++++++++ 4 files changed, 225 insertions(+), 226 deletions(-) diff --git a/kernel/networking/processes/net_proc.c b/kernel/networking/processes/net_proc.c index bf1f5f24..593c590c 100644 --- a/kernel/networking/processes/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -14,231 +14,6 @@ #include "net/http.h" #include "net/ipv4.h" -void tcp_send(uint16_t port, network_connection_ctx *destination, tcp_data* data){ - send_packet(TCP, port, destination, data, sizeof(tcp_data)); - if ((data->flags & ~(1 << ACK_F)) != 0 || data->payload.size > 0){ - kprintf("The payload is %i size",data->payload.size); - data->sequence += __builtin_bswap32(max(1,data->payload.size)); - } - data->expected_ack = __builtin_bswap32(data->sequence); - kprintf("Next seq %i", __builtin_bswap32(data->sequence)); -} - -void tcp_reset(uint16_t port, network_connection_ctx *destination, tcp_data* data){ - data->flags = (1 << RST_F) | (1 << ACK_F); - tcp_send(port, destination, data); -} - -bool tcp_expect_response(sizedptr *pack){ - uint16_t timeout = 10; - while (!read_packet(pack)){ - sleep(1000); - if (timeout-- == 0){ - kprintf("Response timeout"); - return false; - } - } - return true; -} - -uint8_t tcp_check_response(tcp_data *data, sizedptr *out){ - - sizedptr pack; - - if (!tcp_expect_response(&pack) || !pack.ptr){ - kprintf("Response timeout. Retrying"); - return TCP_RETRY; - } - - sizedptr payload = tcp_parse_packet_payload(pack.ptr); - if (!payload.ptr) { - kprintf("Wrong payload pointer. Retrying"); - return TCP_RETRY; - } - - tcp_hdr_t *response = (tcp_hdr_t*)payload.ptr; - - uint32_t ack = __builtin_bswap32(response->ack); - uint32_t seq = __builtin_bswap32(response->sequence); - - size_t hdr_size = (response->data_offset_reserved >> 4) * 4; - size_t payload_size = payload.size - hdr_size; - data->ack = __builtin_bswap32(seq+max(1,payload_size)); - - if (ack != data->expected_ack){ - kprintf("Wrong ack %i vs %i. Resetting", ack, data->expected_ack); - return TCP_RESET; - } else kprintf("Received ack %i", ack); - - if (response->flags != (data->flags | (1 << ACK_F))){ - kprintf("Wrong flags %b vs %b. Resetting",response->flags, data->flags | (1 << ACK_F)); - return TCP_RESET; - } - - if (out){ - out->ptr = payload.ptr + hdr_size; - out->size = payload_size; - } - - return TCP_OK; -} - -bool tcp_handskake(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry){ - if (retry == 5){ - kprintf("Exceeded max number of retries"); - return false; - } - - data->sequence = 0; - data->ack = 0; - data->flags = (1 << SYN_F); - - tcp_send(port, dest, data); - - uint8_t resp = tcp_check_response(data, 0); - if (resp == TCP_RETRY){ - sleep(1000); - return tcp_handskake(dest, port, data, retry+1); - } else if (resp == TCP_RESET){ - tcp_reset(port, dest, data); - return false; - } - - data->flags = (1 << ACK_F); - - tcp_send(port, dest, data); - - kprintf("Acknowledgement of acknowledgemnt sent"); - - return true; -} - -bool tcp_close(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry, uint32_t orig_seq, uint32_t orig_ack){ - if (retry == 5){ - kprintf("Exceeded max number of retries"); - return false; - } - - data->sequence = orig_seq; - data->ack = orig_ack; - data->flags = (1 << FIN_F) | (1 << ACK_F); - - tcp_send(port, dest, data); - - data->flags = (1 << ACK_F); - uint8_t resp = tcp_check_response(data, 0); - if (resp == TCP_RETRY){ - sleep(1000); - return tcp_handskake(dest, port, data, retry+1); - } else if (resp == TCP_RESET){ - tcp_reset(port, dest, data); - return false; - } - - data->flags = (1 << FIN_F); - - resp = tcp_check_response(data, 0); - if (resp == TCP_RETRY){ - sleep(1000); - return tcp_handskake(dest, port, data, retry+1); - } else if (resp == TCP_RESET){ - tcp_reset(port, dest, data); - return true; - } - - data->flags = (1 << ACK_F); - - tcp_send(port, dest, data); - - kprintf("Connection closed"); - - return true; -} - -string make_http_request(HTTPRequest request, char *domain, char *agent){ - //TODO: request instead of hardcoded GET - return string_format("GET / HTTP/1.1\r\nHost: %s\r\nUser-Agent: %s\r\nAccept: */*\r\n\r\n",domain, agent); -} - -sizedptr http_data_transfer(network_connection_ctx *dest, sizedptr payload, uint16_t port, tcp_data *data, uint8_t retry, uint32_t orig_seq, uint32_t orig_ack){ - if (retry == 5){ - kprintf("Exceeded max number of retries"); - return (sizedptr){0}; - } - - data->sequence = orig_seq; - data->ack = orig_ack; - data->flags = (1 << PSH_F) | (1 << ACK_F); - - data->payload = payload; - - tcp_send(port, dest, data); - - data->flags = (1 << ACK_F); - - uint8_t resp; - do { - resp = tcp_check_response(data, 0); - if (resp == TCP_OK) - break; - if (resp == TCP_RESET)//We don't reset, we ignore irrelevant packets (or we could parse them tbh) - continue; - if (resp == TCP_RETRY) - return http_data_transfer(dest, payload, port, data, retry+1, orig_seq, orig_ack); - } while (1); - - data->flags = (1 << PSH_F) | (1 << ACK_F); - - sizedptr http_content; - - resp = tcp_check_response(data, &http_content); - if (resp == TCP_RETRY){ - sleep(1000); - return http_data_transfer(dest, payload, port, data, retry+1, orig_seq, orig_ack); - } else if (resp == TCP_RESET){ - tcp_reset(port, dest, data); - return (sizedptr){0}; - } - - data->payload = (sizedptr){0}; - - data->flags = (1 << ACK_F); - tcp_send(port, dest, data); - - return http_content; -} - -sizedptr request_http_data(HTTPRequest request, network_connection_ctx *dest, uint16_t port){ - tcp_data data = (tcp_data){ - .window = UINT16_MAX, - }; - - if (!tcp_handskake(dest, 8888, &data, 0)){ - kprintf("TCP Handshake Error"); - return (sizedptr){0}; - } - - string serverstr = ipv4_to_string(dest->ip); - string req = make_http_request(request, serverstr.data, "redactedos/0.0.1"); - - free(serverstr.data, serverstr.mem_length); - - kprintf("Request"); - - sizedptr http_response = http_data_transfer(dest, (sizedptr){(uintptr_t)req.data, req.length}, port, &data, 0, data.sequence, data.ack); - - kprintf("END"); - - free(req.data, req.mem_length); - - if (!tcp_close(dest, 8888, &data, 0, data.sequence, data.ack)){ - kprintf("TCP Connnection not closed"); - return (sizedptr){0}; - } - - return http_response; -} - void test_network(){ bind_port(8888); network_connection_ctx dest = (network_connection_ctx){ diff --git a/shared/net/http.c b/shared/net/http.c index a200a28a..0438b955 100644 --- a/shared/net/http.c +++ b/shared/net/http.c @@ -4,3 +4,86 @@ #include "syscalls/syscalls.h" #include "ipv4.h" +string make_http_request(HTTPRequest request, char *domain, char *agent){ + //TODO: request instead of hardcoded GET + return string_format("GET / HTTP/1.1\r\nHost: %s\r\nUser-Agent: %s\r\nAccept: */*\r\n\r\n",domain, agent); +} + +sizedptr http_data_transfer(network_connection_ctx *dest, sizedptr payload, uint16_t port, tcp_data *data, uint8_t retry, uint32_t orig_seq, uint32_t orig_ack){ + if (retry == 5){ + printf("Exceeded max number of retries"); + return (sizedptr){0}; + } + + data->sequence = orig_seq; + data->ack = orig_ack; + data->flags = (1 << PSH_F) | (1 << ACK_F); + + data->payload = payload; + + tcp_send(port, dest, data); + + data->flags = (1 << ACK_F); + + uint8_t resp; + do { + resp = tcp_check_response(data, 0); + if (resp == TCP_OK) + break; + if (resp == TCP_RESET)//We don't reset, we ignore irrelevant packets (or we could parse them tbh) + continue; + if (resp == TCP_RETRY) + return http_data_transfer(dest, payload, port, data, retry+1, orig_seq, orig_ack); + } while (1); + + data->flags = (1 << PSH_F) | (1 << ACK_F); + + sizedptr http_content; + + resp = tcp_check_response(data, &http_content); + if (resp == TCP_RETRY){ + sleep(1000); + return http_data_transfer(dest, payload, port, data, retry+1, orig_seq, orig_ack); + } else if (resp == TCP_RESET){ + tcp_reset(port, dest, data); + return (sizedptr){0}; + } + + data->payload = (sizedptr){0}; + + data->flags = (1 << ACK_F); + tcp_send(port, dest, data); + + return http_content; +} + +sizedptr request_http_data(HTTPRequest request, network_connection_ctx *dest, uint16_t port){ + tcp_data data = (tcp_data){ + .window = UINT16_MAX, + }; + + if (!tcp_handskake(dest, 8888, &data, 0)){ + printf("TCP Handshake Error"); + return (sizedptr){0}; + } + + string serverstr = ipv4_to_string(dest->ip); + string req = make_http_request(request, serverstr.data, "redactedos/0.0.1"); + + free(serverstr.data, serverstr.mem_length); + + printf("Request"); + + sizedptr http_response = http_data_transfer(dest, (sizedptr){(uintptr_t)req.data, req.length}, port, &data, 0, data.sequence, data.ack); + + printf("END"); + + free(req.data, req.mem_length); + + if (!tcp_close(dest, 8888, &data, 0, data.sequence, data.ack)){ + printf("TCP Connnection not closed"); + return (sizedptr){0}; + } + + return http_response; +} \ No newline at end of file diff --git a/shared/net/http.h b/shared/net/http.h index 4ac08f1e..5aea9cc3 100644 --- a/shared/net/http.h +++ b/shared/net/http.h @@ -11,4 +11,4 @@ typedef enum HTTPRequest { DELETE } HTTPRequest; -// sizedptr request_http_data(HTTPRequest request, network_connection_ctx *dest, uint16_t port); \ No newline at end of file +sizedptr request_http_data(HTTPRequest request, network_connection_ctx *dest, uint16_t port); \ No newline at end of file diff --git a/shared/net/tcp.c b/shared/net/tcp.c index 7e8ad0bb..e298fab8 100644 --- a/shared/net/tcp.c +++ b/shared/net/tcp.c @@ -56,4 +56,145 @@ sizedptr tcp_parse_packet_payload(uintptr_t ptr){ } return (sizedptr){0,0}; +} + +void tcp_send(uint16_t port, network_connection_ctx *destination, tcp_data* data){ + send_packet(TCP, port, destination, data, sizeof(tcp_data)); + if ((data->flags & ~(1 << ACK_F)) != 0 || data->payload.size > 0){ + printf("The payload is %i size",data->payload.size); + data->sequence += __builtin_bswap32(max(1,data->payload.size)); + } + data->expected_ack = __builtin_bswap32(data->sequence); + printf("Next seq %i", __builtin_bswap32(data->sequence)); +} + +void tcp_reset(uint16_t port, network_connection_ctx *destination, tcp_data* data){ + data->flags = (1 << RST_F) | (1 << ACK_F); + tcp_send(port, destination, data); +} + +bool tcp_expect_response(sizedptr *pack){ + uint16_t timeout = 10; + while (!read_packet(pack)){ + sleep(1000); + if (timeout-- == 0){ + printf("Response timeout"); + return false; + } + } + return true; +} + +uint8_t tcp_check_response(tcp_data *data, sizedptr *out){ + + sizedptr pack; + + if (!tcp_expect_response(&pack) || !pack.ptr){ + printf("Response timeout. Retrying"); + return TCP_RETRY; + } + + sizedptr payload = tcp_parse_packet_payload(pack.ptr); + if (!payload.ptr) { + printf("Wrong payload pointer. Retrying"); + return TCP_RETRY; + } + + tcp_hdr_t *response = (tcp_hdr_t*)payload.ptr; + + uint32_t ack = __builtin_bswap32(response->ack); + uint32_t seq = __builtin_bswap32(response->sequence); + + size_t hdr_size = (response->data_offset_reserved >> 4) * 4; + size_t payload_size = payload.size - hdr_size; + data->ack = __builtin_bswap32(seq+max(1,payload_size)); + + if (ack != data->expected_ack){ + printf("Wrong ack %i vs %i. Resetting", ack, data->expected_ack); + return TCP_RESET; + } else printf("Received ack %i", ack); + + if (response->flags != (data->flags | (1 << ACK_F))){ + printf("Wrong flags %b vs %b. Resetting",response->flags, data->flags | (1 << ACK_F)); + return TCP_RESET; + } + + if (out){ + out->ptr = payload.ptr + hdr_size; + out->size = payload_size; + } + + return TCP_OK; +} + +bool tcp_handskake(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry){ + if (retry == 5){ + printf("Exceeded max number of retries"); + return false; + } + + data->sequence = 0; + data->ack = 0; + data->flags = (1 << SYN_F); + + tcp_send(port, dest, data); + + uint8_t resp = tcp_check_response(data, 0); + if (resp == TCP_RETRY){ + sleep(1000); + return tcp_handskake(dest, port, data, retry+1); + } else if (resp == TCP_RESET){ + tcp_reset(port, dest, data); + return false; + } + + data->flags = (1 << ACK_F); + + tcp_send(port, dest, data); + + printf("Acknowledgement of acknowledgemnt sent"); + + return true; +} + +bool tcp_close(network_connection_ctx *dest, uint16_t port, tcp_data *data, uint8_t retry, uint32_t orig_seq, uint32_t orig_ack){ + if (retry == 5){ + printf("Exceeded max number of retries"); + return false; + } + + data->sequence = orig_seq; + data->ack = orig_ack; + data->flags = (1 << FIN_F) | (1 << ACK_F); + + tcp_send(port, dest, data); + + data->flags = (1 << ACK_F); + uint8_t resp = tcp_check_response(data, 0); + if (resp == TCP_RETRY){ + sleep(1000); + return tcp_handskake(dest, port, data, retry+1); + } else if (resp == TCP_RESET){ + tcp_reset(port, dest, data); + return false; + } + + data->flags = (1 << FIN_F); + + resp = tcp_check_response(data, 0); + if (resp == TCP_RETRY){ + sleep(1000); + return tcp_handskake(dest, port, data, retry+1); + } else if (resp == TCP_RESET){ + tcp_reset(port, dest, data); + return true; + } + + data->flags = (1 << ACK_F); + + tcp_send(port, dest, data); + + printf("Connection closed"); + + return true; } \ No newline at end of file From 5c14db49a79d8567b122b77c5ee6350300d465e1 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sun, 22 Jun 2025 00:00:00 +0000 Subject: [PATCH 49/61] Full HTTP payload parsing --- kernel/networking/processes/net_proc.c | 8 ++++++-- shared/net/http.c | 20 ++++++++++++++++++++ shared/net/http.h | 5 ++++- shared/net/tcp.c | 2 +- shared/std/string.c | 25 ++++++++++++++++++++++++- shared/std/string.h | 3 +++ 6 files changed, 58 insertions(+), 5 deletions(-) diff --git a/kernel/networking/processes/net_proc.c b/kernel/networking/processes/net_proc.c index 593c590c..5479e478 100644 --- a/kernel/networking/processes/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -26,8 +26,12 @@ void test_network(){ kprintf("Received payload? %x",(uintptr_t)&http); - if (http.ptr != 0) - kprintf("Received payload? %s",(uintptr_t)http.ptr); + if (http.ptr != 0){ + kprintf("Parsing payload"); + sizedptr payload = http_get_payload(http); + string content = http_get_chunked_payload(payload); + printf("Received payload? %s",(uintptr_t)content.data); + } unbind_port(8888); } diff --git a/shared/net/http.c b/shared/net/http.c index 0438b955..e002692d 100644 --- a/shared/net/http.c +++ b/shared/net/http.c @@ -3,6 +3,7 @@ #include "tcp.h" #include "syscalls/syscalls.h" #include "ipv4.h" +#include "std/memfunctions.h" string make_http_request(HTTPRequest request, char *domain, char *agent){ //TODO: request instead of hardcoded GET @@ -86,4 +87,23 @@ sizedptr request_http_data(HTTPRequest request, network_connection_ctx *dest, ui } return http_response; +} + +sizedptr http_get_payload(sizedptr header){ + if (header.ptr && header.size > 0){ + int start = strindex((char*)header.ptr, "\r\n\r\n"); + if (start < header.size){ + return (sizedptr){header.ptr + start + 4,header.size-start-4}; + } + } + return (sizedptr){0,0}; +} + +string http_get_chunked_payload(sizedptr chunk){ + if (chunk.ptr && chunk.size > 0){ + int sizetrm = strindex((char*)chunk.ptr, "\r\n"); + uint64_t chunk_size = parse_hex_u64((char*)chunk.ptr,sizetrm); + return string_ca_max((char*)(chunk.ptr + sizetrm + 2),chunk_size); + } + return (string){0}; } \ No newline at end of file diff --git a/shared/net/http.h b/shared/net/http.h index 5aea9cc3..fd94bdab 100644 --- a/shared/net/http.h +++ b/shared/net/http.h @@ -3,6 +3,7 @@ #include "tcp.h" #include "types.h" #include "network_types.h" +#include "std/string.h" typedef enum HTTPRequest { GET, @@ -11,4 +12,6 @@ typedef enum HTTPRequest { DELETE } HTTPRequest; -sizedptr request_http_data(HTTPRequest request, network_connection_ctx *dest, uint16_t port); \ No newline at end of file +sizedptr request_http_data(HTTPRequest request, network_connection_ctx *dest, uint16_t port); +sizedptr http_get_payload(sizedptr header); +string http_get_chunked_payload(sizedptr chunk); \ No newline at end of file diff --git a/shared/net/tcp.c b/shared/net/tcp.c index e298fab8..d0f6962b 100644 --- a/shared/net/tcp.c +++ b/shared/net/tcp.c @@ -51,7 +51,7 @@ sizedptr tcp_parse_packet_payload(uintptr_t ptr){ ptr += sizeof(ipv4_hdr_t); if (ip->protocol == 0x06){ tcp_hdr_t* tcp = (tcp_hdr_t*)ptr; - return (sizedptr){ptr,((tcp->data_offset_reserved >> 4) & 0xF) * 4}; + return (sizedptr){ptr,__builtin_bswap16(ip->total_length) - sizeof(ipv4_hdr_t)}; } } diff --git a/shared/std/string.c b/shared/std/string.c index 78779707..4f6c6892 100644 --- a/shared/std/string.c +++ b/shared/std/string.c @@ -133,7 +133,7 @@ string string_format_va(const char *fmt, va_list args){ for (uint32_t j = 0; j < bin.length && len < 255; j++) buf[len++] = bin.data[j]; free(bin.data,bin.mem_length); } else if (fmt[i] == 'c') { - uint64_t val = va_arg(args, uint8_t); + uint64_t val = va_arg(args, uint64_t); buf[len++] = (char)val; } else if (fmt[i] == 's') { const char *str = (const char *)va_arg(args, uintptr_t); @@ -216,6 +216,15 @@ int strstart(const char *a, const char *b) { return 0; } +int strindex(const char *a, const char *b) { + for (int i = 0; a[i]; i++) { + int j = 0; + while (b[j] && a[i + j] == b[j]) j++; + if (!b[j]) return i; + } + return -1; +} + int strend(const char *a, const char *b) { while (*a && *b) { if (*a == *b) { @@ -251,4 +260,18 @@ bool utf16tochar(const uint16_t* str_in, char* out_str, size_t max_len) { } out_str[out_i] = '\0'; return true; +} + +uint64_t parse_hex_u64(char* str, size_t size) { + uint64_t result = 0; + for (uint32_t i = 0; i < size; i++) { + char c = str[i]; + uint8_t digit = 0; + if (c >= '0' && c <= '9') digit = c - '0'; + else if (c >= 'a' && c <= 'f') digit = c - 'a' + 10; + else if (c >= 'A' && c <= 'F') digit = c - 'A' + 10; + else break; + result = (result << 4) | digit; + } + return result; } \ No newline at end of file diff --git a/shared/std/string.h b/shared/std/string.h index 39ceb853..bb61cfc2 100644 --- a/shared/std/string.h +++ b/shared/std/string.h @@ -28,5 +28,8 @@ int strcmp(const char *a, const char *b); bool strcont(const char *a, const char *b); int strstart(const char *a, const char *b); int strend(const char *a, const char *b); +int strindex(const char *a, const char *b); + +uint64_t parse_hex_u64(char* str, size_t size); bool utf16tochar(const uint16_t* str_in, char* out_str, size_t max_len); \ No newline at end of file From b49fe137bd40f109071d4b297c9791ca71104125 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sun, 22 Jun 2025 00:00:00 +0000 Subject: [PATCH 50/61] Interrupts for upload, freeing memory --- kernel/exceptions/irq.c | 7 ++- kernel/input/xhci.c | 4 +- kernel/networking/drivers/net_driver.hpp | 2 + .../drivers/virtio_net_pci/virtio_net_pci.cpp | 51 ++++++++++--------- .../drivers/virtio_net_pci/virtio_net_pci.hpp | 2 + kernel/networking/network.cpp | 10 ++-- kernel/networking/network.h | 3 +- kernel/networking/network_dispatch.cpp | 6 ++- kernel/networking/network_dispatch.hpp | 3 +- kernel/pci.c | 13 +++-- kernel/pci.h | 2 +- 11 files changed, 65 insertions(+), 38 deletions(-) diff --git a/kernel/exceptions/irq.c b/kernel/exceptions/irq.c index 196dbbee..08d3d56c 100644 --- a/kernel/exceptions/irq.c +++ b/kernel/exceptions/irq.c @@ -38,6 +38,7 @@ void irq_init() { gic_enable_irq(IRQ_TIMER, 0x80, 0); gic_enable_irq(MSI_OFFSET + XHCI_IRQ, 0x80, 0); gic_enable_irq(MSI_OFFSET + NET_IRQ, 0x80, 0); + gic_enable_irq(MSI_OFFSET + NET_IRQ + 1, 0x80, 0); gic_enable_irq(SLEEP_TIMER, 0x80, 0); write32(GICC_BASE + 0x004, 0xF0); //Priority @@ -78,7 +79,11 @@ void irq_el1_handler() { write32(GICC_BASE + 0x10, irq); process_restore(); } else if (irq == MSI_OFFSET + NET_IRQ){ - network_handle_interrupt(); + network_handle_download_interrupt(); + write32(GICC_BASE + 0x10, irq); + process_restore(); + } else if (irq == MSI_OFFSET + NET_IRQ + 1){ + network_handle_upload_interrupt(); write32(GICC_BASE + 0x10, irq); process_restore(); } else { diff --git a/kernel/input/xhci.c b/kernel/input/xhci.c index 171a619d..a66ba41e 100644 --- a/kernel/input/xhci.c +++ b/kernel/input/xhci.c @@ -109,7 +109,7 @@ bool xhci_init(xhci_device *xhci, uint64_t pci_addr) { pci_register(xhci->mmio, xhci->mmio_size); - uint8_t interrupts_ok = pci_setup_interrupts(pci_addr, XHCI_IRQ); + uint8_t interrupts_ok = pci_setup_interrupts(pci_addr, XHCI_IRQ, 1); switch(interrupts_ok){ case 0: kprintf_raw("[xHCI] Failed to setup interrupts"); @@ -122,8 +122,6 @@ bool xhci_init(xhci_device *xhci, uint64_t pci_addr) { break; } - - kprintfv("[xHCI] BARs set up @ %x (%x)",xhci->mmio,xhci->mmio_size); xhci->cap = (xhci_cap_regs*)(uintptr_t)xhci->mmio; diff --git a/kernel/networking/drivers/net_driver.hpp b/kernel/networking/drivers/net_driver.hpp index 99809719..3ba4d4b5 100644 --- a/kernel/networking/drivers/net_driver.hpp +++ b/kernel/networking/drivers/net_driver.hpp @@ -12,6 +12,8 @@ class NetDriver { virtual sizedptr handle_receive_packet() = 0; + virtual void handle_sent_packet() = 0; + virtual void enable_verbose() = 0; virtual void send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len) = 0; diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index b3648e3b..df498311 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -65,16 +65,16 @@ bool VirtioNetDriver::init(){ virtio_get_capabilities(&vnp_net_dev, addr, &net_device_address, &net_device_size); pci_register(net_device_address, net_device_size); - uint8_t interrupts_ok = pci_setup_interrupts(addr, NET_IRQ); + uint8_t interrupts_ok = pci_setup_interrupts(addr, NET_IRQ, 2); switch(interrupts_ok){ case 0: kprintf_raw("[VIRTIO_NET] Failed to setup interrupts"); return false; case 1: - kprintf_raw("[VIRTIO_NET] Interrupts setup with MSI-X %i",NET_IRQ); + kprintf_raw("[VIRTIO_NET] Interrupts setup with MSI-X %i, %i",NET_IRQ,NET_IRQ+1); break; default: - kprintf_raw("[VIRTIO_NET] Interrupts setup with MSI %i",NET_IRQ); + kprintf_raw("[VIRTIO_NET] Interrupts setup with MSI %i,%i",NET_IRQ,NET_IRQ+1); break; } @@ -107,21 +107,19 @@ bool VirtioNetDriver::init(){ virtio_add_buffer(&vnp_net_dev, i, (uintptr_t)buf, MAX_size); } - kprintf("[VIRTIO_NET] Current MSI-X queue index %i",vnp_net_dev.common_cfg->queue_msix_vector); vnp_net_dev.common_cfg->queue_msix_vector = 0; if (vnp_net_dev.common_cfg->queue_msix_vector != 0){ kprintf("[VIRTIO_NET error] failed to set interrupts on receive queue, network will be unable to receive packets"); return false; } - // select_queue(&vnp_net_dev, TRANSMIT_QUEUE); + select_queue(&vnp_net_dev, TRANSMIT_QUEUE); - // kprintf("[VIRTIO_NET] Current MSI-X queue index %i",vnp_net_dev.common_cfg->queue_msix_vector); - // vnp_net_dev.common_cfg->queue_msix_vector = 0; - // if (vnp_net_dev.common_cfg->queue_msix_vector != 0){ - // kprintf("[VIRTIO_NET error] failed to set interrupts on transmit queue, network will be unable to cleanup transmitted packets"); - // return false; - // } + vnp_net_dev.common_cfg->queue_msix_vector = 1; + if (vnp_net_dev.common_cfg->queue_msix_vector != 1){ + kprintf("[VIRTIO_NET error] failed to set interrupts on transmit queue, network will be unable to cleanup transmitted packets"); + return false; + } return true; } @@ -153,19 +151,26 @@ sizedptr VirtioNetDriver::handle_receive_packet(){ } return (sizedptr){0,0}; +} + +void VirtioNetDriver::handle_sent_packet(){ + select_queue(&vnp_net_dev, TRANSMIT_QUEUE); + + struct virtq_used* used = (struct virtq_used*)(uintptr_t)vnp_net_dev.common_cfg->queue_device; + struct virtq_desc* desc = (struct virtq_desc*)(uintptr_t)vnp_net_dev.common_cfg->queue_desc; + struct virtq_avail* avail = (struct virtq_avail*)(uintptr_t)vnp_net_dev.common_cfg->queue_driver; + + uint16_t new_idx = used->idx; - // select_queue(&vnp_net_dev, TRANSMIT_QUEUE); - // new_idx = used->idx; - // if (new_idx != last_used_receive_idx) { - // uint16_t used_ring_index = last_used_receive_idx % 128; - // last_used_receive_idx = new_idx; - // struct virtq_used_elem* e = &used->ring[used_ring_index]; - // uint32_t desc_index = e->id; - // uint32_t len = e->len; - // free_from_page((void*)desc[desc_index].addr, len); - // kprintf("Freed memory"); - // return; - // } + if (new_idx != last_used_sent_idx) { + uint16_t used_ring_index = last_used_sent_idx % 128; + last_used_sent_idx = new_idx; + struct virtq_used_elem* e = &used->ring[used_ring_index]; + uint32_t desc_index = e->id; + uint32_t len = e->len; + free_from_page((void*)desc[desc_index].addr, len); + return; + } } void VirtioNetDriver::send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len){ diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp index 1816e3ac..38c676dc 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp @@ -11,6 +11,7 @@ class VirtioNetDriver : public NetDriver { bool init() override; sizedptr handle_receive_packet() override; + void handle_sent_packet() override; void enable_verbose() override; @@ -21,5 +22,6 @@ class VirtioNetDriver : public NetDriver { private: bool verbose = false; uint16_t last_used_receive_idx = 0; + uint16_t last_used_sent_idx = 0; virtio_device vnp_net_dev; }; \ No newline at end of file diff --git a/kernel/networking/network.cpp b/kernel/networking/network.cpp index 88c096b4..fe4a170d 100644 --- a/kernel/networking/network.cpp +++ b/kernel/networking/network.cpp @@ -10,10 +10,15 @@ bool network_init(){ return dispatch->init(); } -void network_handle_interrupt(){ - return dispatch->handle_interrupt(); +void network_handle_download_interrupt(){ + return dispatch->handle_download_interrupt(); } +void network_handle_upload_interrupt(){ + return dispatch->handle_upload_interrupt(); +} + + bool network_bind_port(uint16_t port, uint16_t process){ return dispatch->bind_port(port, process); } @@ -30,7 +35,6 @@ bool network_unbind_port_current(uint16_t port){ return dispatch->unbind_port(port, get_current_proc_pid()); } - void network_send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len){ return dispatch->send_packet(protocol, port, destination, payload, payload_len); } diff --git a/kernel/networking/network.h b/kernel/networking/network.h index 4e1ade92..8872326a 100644 --- a/kernel/networking/network.h +++ b/kernel/networking/network.h @@ -10,7 +10,8 @@ extern "C" { #define NET_IRQ 32 bool network_init(); -void network_handle_interrupt(); +void network_handle_download_interrupt(); +void network_handle_upload_interrupt(); bool network_bind_port(uint16_t port, uint16_t process); bool network_unbind_port(uint16_t port, uint16_t process); void network_send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len); diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index f1ef7bcc..e592c7ab 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -37,7 +37,7 @@ bool NetworkDispatch::unbind_port(uint16_t port, uint16_t process){ return true; } -void NetworkDispatch::handle_interrupt(){ +void NetworkDispatch::handle_download_interrupt(){ if (driver){ sizedptr packet = driver->handle_receive_packet(); uintptr_t ptr = packet.ptr; @@ -93,6 +93,10 @@ void NetworkDispatch::handle_interrupt(){ } } +void NetworkDispatch::handle_upload_interrupt(){ + driver->handle_sent_packet(); +} + bool NetworkDispatch::read_packet(sizedptr *Packet, uint16_t process){ process_t *proc = get_proc_by_pid(process); if (proc->packet_buffer.read_index == proc->packet_buffer.write_index) return false; diff --git a/kernel/networking/network_dispatch.hpp b/kernel/networking/network_dispatch.hpp index d7d59c11..0ab31ccd 100644 --- a/kernel/networking/network_dispatch.hpp +++ b/kernel/networking/network_dispatch.hpp @@ -11,7 +11,8 @@ class NetworkDispatch { bool init(); bool bind_port(uint16_t port, uint16_t process); bool unbind_port(uint16_t port, uint16_t process); - void handle_interrupt(); + void handle_upload_interrupt(); + void handle_download_interrupt(); void send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len); bool read_packet(sizedptr *Packet, uint16_t process); diff --git a/kernel/pci.c b/kernel/pci.c index 55fe056d..7eff280a 100644 --- a/kernel/pci.c +++ b/kernel/pci.c @@ -340,15 +340,20 @@ bool pci_setup_msix(uint64_t pci_addr, msix_irq_line* irq_lines, uint8_t line_si return true; } -uint8_t pci_setup_interrupts(uint64_t pci_addr, uint8_t irq_line){ - msix_irq_line irq_lines[1] = {(msix_irq_line){.addr_offset=0,.irq_num=irq_line}}; - bool msix_ok = pci_setup_msix(pci_addr, irq_lines, 1); +uint8_t pci_setup_interrupts(uint64_t pci_addr, uint8_t irq_line, uint8_t amount){ + msix_irq_line irq_lines[amount]; + for (uint8_t i = 0; i < amount; i++) + irq_lines[i] = (msix_irq_line){.addr_offset=0,.irq_num=irq_line+i}; + + bool msix_ok = pci_setup_msix(pci_addr, irq_lines, amount); if(msix_ok){ return 1; } - bool msi_ok = pci_setup_msi(pci_addr, irq_line); + bool msi_ok = true; + for (uint8_t i = 0; i < amount; i++) + msi_ok &= pci_setup_msi(pci_addr, irq_line+i); if(msi_ok){ return 2; } diff --git a/kernel/pci.h b/kernel/pci.h index 9e2e7e96..f2b17652 100644 --- a/kernel/pci.h +++ b/kernel/pci.h @@ -24,7 +24,7 @@ void pci_enable_verbose(); bool pci_setup_msi(uint64_t pci_addr, uint8_t irq_vector); -uint8_t pci_setup_interrupts(uint64_t pci_addr, uint8_t irq_line); +uint8_t pci_setup_interrupts(uint64_t pci_addr, uint8_t irq_line, uint8_t amount); typedef struct { uint32_t addr_offset; From 64caf776a92974a45f024797210f5a34488d1cff Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sun, 22 Jun 2025 00:00:00 +0000 Subject: [PATCH 51/61] Free received packets --- kernel/memory/page_allocator.c | 4 ++++ kernel/memory/page_allocator.h | 2 ++ kernel/networking/network_dispatch.cpp | 7 +++++++ kernel/process/scheduler.c | 3 +++ 4 files changed, 16 insertions(+) diff --git a/kernel/memory/page_allocator.c b/kernel/memory/page_allocator.c index ef612f3e..6a60103e 100644 --- a/kernel/memory/page_allocator.c +++ b/kernel/memory/page_allocator.c @@ -170,4 +170,8 @@ void free_from_page(void* ptr, uint64_t size) { block->next = page->free_list; page->free_list = block; page->size -= size; +} + +void free_sized(sizedptr ptr){ + free_from_page((void*)ptr.ptr, ptr.size); } \ No newline at end of file diff --git a/kernel/memory/page_allocator.h b/kernel/memory/page_allocator.h index 09e8defe..37bb79e3 100644 --- a/kernel/memory/page_allocator.h +++ b/kernel/memory/page_allocator.h @@ -19,6 +19,8 @@ void free_page(void* ptr, uint64_t size); void* allocate_in_page(void *page, uint64_t size, uint16_t alignment, bool kernel, bool device); void free_from_page(void* ptr, uint64_t size); +void free_sized(sizedptr ptr); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index e592c7ab..fd7ca476 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -40,6 +40,7 @@ bool NetworkDispatch::unbind_port(uint16_t port, uint16_t process){ void NetworkDispatch::handle_download_interrupt(){ if (driver){ sizedptr packet = driver->handle_receive_packet(); + bool need_free = true; uintptr_t ptr = packet.ptr; if (ptr){ eth_hdr_t *eth = (eth_hdr_t*)ptr; @@ -72,6 +73,8 @@ void NetworkDispatch::handle_download_interrupt(){ buf->entries[buf->write_index] = packet; buf->write_index = next_index; + need_free = false; + if (buf->write_index == buf->read_index) buf->read_index = (buf->read_index + 1) % PACKET_BUFFER_CAPACITY; } @@ -90,6 +93,9 @@ void NetworkDispatch::handle_download_interrupt(){ } } } + if (need_free){ + free_sized(packet); + } } } @@ -107,6 +113,7 @@ bool NetworkDispatch::read_packet(sizedptr *Packet, uint16_t process){ memcpy((void*)copy,(void*)original.ptr,original.size); Packet->ptr = copy; Packet->size = original.size; + free_sized(original); proc->packet_buffer.read_index = (proc->packet_buffer.read_index + 1) % PACKET_BUFFER_CAPACITY; return true; } diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 303f7af0..214aab0e 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -108,6 +108,9 @@ void reset_process(process_t *proc){ proc->packet_buffer.read_index = 0; proc->packet_buffer.write_index = 0; for (int k = 0; k < PACKET_BUFFER_CAPACITY; k++){ + sizedptr p = proc->packet_buffer.entries[k]; + if (p.ptr) + free_sized(p); proc->packet_buffer.entries[k] = (sizedptr){0}; } } From a872c8fd3f08556288644190f751a3d975d7bcae Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Mon, 23 Jun 2025 00:00:00 +0000 Subject: [PATCH 52/61] Moving packet creation to dispatch --- kernel/exceptions/exception_handler.c | 4 +- kernel/networking/drivers/net_driver.hpp | 6 ++- .../drivers/virtio_net_pci/virtio_net_pci.cpp | 49 ++++--------------- .../drivers/virtio_net_pci/virtio_net_pci.hpp | 4 +- kernel/networking/network_dispatch.cpp | 34 +++++++++++-- kernel/networking/network_dispatch.hpp | 2 + kernel/virtio/virtio_pci.c | 8 +-- shared/net/udp.c | 4 -- shared/net/udp.h | 1 - 9 files changed, 57 insertions(+), 55 deletions(-) diff --git a/kernel/exceptions/exception_handler.c b/kernel/exceptions/exception_handler.c index 8332440e..3f34039b 100644 --- a/kernel/exceptions/exception_handler.c +++ b/kernel/exceptions/exception_handler.c @@ -66,7 +66,7 @@ void panic(const char* panic_msg) { kstring s = kstring_format("%s\n%s\nSystem Halted",(uint64_t)PANIC_TEXT,(uint64_t)panic_msg); draw_panic_screen(s); } - while (1); + while (1);//TODO: OPT } void panic_with_info(const char* msg, uint64_t info) { @@ -92,5 +92,5 @@ void panic_with_info(const char* msg, uint64_t info) { kstring s = kstring_format("%s\n%s\nError code: %x\nSystem Halted",(uint64_t)PANIC_TEXT,(uint64_t)msg,info); draw_panic_screen(s); } - while (1); + while (1);//TODO: OPT } \ No newline at end of file diff --git a/kernel/networking/drivers/net_driver.hpp b/kernel/networking/drivers/net_driver.hpp index 3ba4d4b5..6df5e34d 100644 --- a/kernel/networking/drivers/net_driver.hpp +++ b/kernel/networking/drivers/net_driver.hpp @@ -10,15 +10,19 @@ class NetDriver { NetDriver(){} virtual bool init() = 0; + virtual sizedptr allocate_packet(size_t size) = 0; + virtual sizedptr handle_receive_packet() = 0; virtual void handle_sent_packet() = 0; virtual void enable_verbose() = 0; - virtual void send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len) = 0; + virtual void send_packet(sizedptr packet) = 0; virtual ~NetDriver() = default; network_connection_ctx connection_context; + + uint16_t header_size; }; \ No newline at end of file diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index df498311..a93bf961 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -1,10 +1,5 @@ #include "virtio_net_pci.hpp" #include "console/kio.h" -#include "net/udp.h" -#include "net/tcp.h" -#include "net/dhcp.h" -#include "net/arp.h" -#include "net/icmp.h" #include "networking/network.h" #include "pci.h" #include "syscalls/syscalls.h" @@ -121,9 +116,15 @@ bool VirtioNetDriver::init(){ return false; } + header_size = sizeof(virtio_net_hdr_t); + return true; } +sizedptr VirtioNetDriver::allocate_packet(size_t size){ + return (sizedptr){(uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size + header_size, ALIGN_64B, true, true),size + header_size}; +} + sizedptr VirtioNetDriver::handle_receive_packet(){ select_queue(&vnp_net_dev, RECEIVE_QUEUE); struct virtq_used* used = (struct virtq_used*)(uintptr_t)vnp_net_dev.common_cfg->queue_device; @@ -173,41 +174,11 @@ void VirtioNetDriver::handle_sent_packet(){ } } -void VirtioNetDriver::send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len){ +void VirtioNetDriver::send_packet(sizedptr packet){ select_queue(&vnp_net_dev, TRANSMIT_QUEUE); - size_t size; - uintptr_t buf_ptr; - switch (protocol) { - case UDP: - size = calc_udp_size(payload_len) + sizeof(virtio_net_hdr_t); - buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size, ALIGN_64B, true, true); - connection_context.port = port; - create_udp_packet(buf_ptr + sizeof(virtio_net_hdr_t), connection_context, *destination, (uint8_t*)payload, payload_len); - break; - case DHCP: - size = DHCP_SIZE + sizeof(virtio_net_hdr_t); - buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size, ALIGN_64B, true, true); - create_dhcp_packet(buf_ptr + sizeof(virtio_net_hdr_t), (dhcp_request*)payload); - break; - case ARP: - size = sizeof(eth_hdr_t) + sizeof(arp_hdr_t) + sizeof(virtio_net_hdr_t); - buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size, ALIGN_64B, true, true); - create_arp_packet(buf_ptr + sizeof(virtio_net_hdr_t), connection_context.mac, connection_context.ip, destination->mac, destination->ip, *(bool*)payload); - break; - case ICMP: - size = sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(virtio_net_hdr_t) + sizeof(icmp_packet); - buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size, ALIGN_64B, true, true); - create_icmp_packet(buf_ptr + sizeof(virtio_net_hdr_t), connection_context, *destination, (icmp_data*)payload); - break; - case TCP: - tcp_data *data = (tcp_data*)payload; - size = sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(virtio_net_hdr_t) + sizeof(tcp_hdr_t) + data->options.size + data->payload.size; - buf_ptr = (uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size, ALIGN_64B, true, true); - connection_context.port = port; - create_tcp_packet(buf_ptr + sizeof(virtio_net_hdr_t), connection_context, *destination, (sizedptr){(uintptr_t)data, sizeof(tcp_data)}); - break; - } - virtio_send_1d(&vnp_net_dev, buf_ptr, size); + + if (packet.ptr && packet.size) + virtio_send_1d(&vnp_net_dev, packet.ptr, packet.size); kprintf("Queued new packet"); } diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp index 38c676dc..ab84f2ad 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp @@ -10,12 +10,14 @@ class VirtioNetDriver : public NetDriver { bool init() override; + sizedptr allocate_packet(size_t size) override; + sizedptr handle_receive_packet() override; void handle_sent_packet() override; void enable_verbose() override; - void send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len) override; + void send_packet(sizedptr packet) override; ~VirtioNetDriver() = default; diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index fd7ca476..cf17e2ad 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -4,12 +4,14 @@ #include "console/kio.h" #include "process/scheduler.h" #include "net/udp.h" +#include "net/tcp.h" +#include "net/dhcp.h" +#include "net/arp.h" #include "net/eth.h" #include "net/ipv4.h" -#include "memory/page_allocator.h" #include "net/icmp.h" +#include "memory/page_allocator.h" #include "std/memfunctions.h" -#include "net/arp.h" NetworkDispatch::NetworkDispatch(){ ports = IndexMap(UINT16_MAX); @@ -119,8 +121,34 @@ bool NetworkDispatch::read_packet(sizedptr *Packet, uint16_t process){ } void NetworkDispatch::send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len){ + sizedptr packet_buffer; + switch (protocol) { + case UDP: + packet_buffer = driver->allocate_packet(sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) + payload_len); + driver->connection_context.port = port; + create_udp_packet(packet_buffer.ptr + driver->header_size, driver->connection_context, *destination, (uint8_t*)payload, payload_len); + break; + case DHCP: + packet_buffer = driver->allocate_packet(DHCP_SIZE); + create_dhcp_packet(packet_buffer.ptr + driver->header_size, (dhcp_request*)payload); + break; + case ARP: + packet_buffer = driver->allocate_packet(sizeof(eth_hdr_t) + sizeof(arp_hdr_t)); + create_arp_packet(packet_buffer.ptr + driver->header_size, driver->connection_context.mac, driver->connection_context.ip, destination->mac, destination->ip, *(bool*)payload); + break; + case ICMP: + packet_buffer = driver->allocate_packet(sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(icmp_packet)); + create_icmp_packet(packet_buffer.ptr + driver->header_size, driver->connection_context, *destination, (icmp_data*)payload); + break; + case TCP: + tcp_data *data = (tcp_data*)payload; + packet_buffer = driver->allocate_packet(sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(tcp_hdr_t) + data->options.size + data->payload.size); + driver->connection_context.port = port; + create_tcp_packet(packet_buffer.ptr + driver->header_size, driver->connection_context, *destination, (sizedptr){(uintptr_t)data, sizeof(tcp_data)}); + break; + } if (driver) - driver->send_packet(protocol, port, destination, payload, payload_len); + driver->send_packet(packet_buffer); } network_connection_ctx* NetworkDispatch::get_context(){ diff --git a/kernel/networking/network_dispatch.hpp b/kernel/networking/network_dispatch.hpp index 0ab31ccd..3ade7ec1 100644 --- a/kernel/networking/network_dispatch.hpp +++ b/kernel/networking/network_dispatch.hpp @@ -21,4 +21,6 @@ class NetworkDispatch { private: IndexMap ports; NetDriver *driver; + + sizedptr allocate_packet(size_t size); }; \ No newline at end of file diff --git a/kernel/virtio/virtio_pci.c b/kernel/virtio/virtio_pci.c index b1254112..a7a11ddb 100644 --- a/kernel/virtio/virtio_pci.c +++ b/kernel/virtio/virtio_pci.c @@ -95,7 +95,7 @@ bool virtio_init_device(virtio_device *dev) { struct virtio_pci_common_cfg* cfg = dev->common_cfg; cfg->device_status = 0; - while (cfg->device_status != 0); + while (cfg->device_status != 0);//TODO: OPT cfg->device_status |= VIRTIO_STATUS_ACKNOWLEDGE; cfg->device_status |= VIRTIO_STATUS_DRIVER; @@ -179,7 +179,7 @@ bool virtio_send(virtio_device *dev, uint64_t desc, uint64_t avail, uint64_t use *(volatile uint16_t*)(uintptr_t)(dev->notify_cfg + dev->notify_off_multiplier * dev->common_cfg->queue_select) = 0; - while (last_used_idx == u->idx); + while (last_used_idx == u->idx);//TODO: OPT if (status != 0) kprintf("[VIRTIO OPERATION ERROR]: Wrong status %x",status); @@ -209,7 +209,7 @@ bool virtio_send2(virtio_device *dev, uint64_t desc, uint64_t avail, uint64_t us *(volatile uint16_t*)(uintptr_t)(dev->notify_cfg + dev->notify_off_multiplier * dev->common_cfg->queue_select) = 0; - while (last_used_idx == u->idx); + while (last_used_idx == u->idx);//TODO: OPT return true; } @@ -232,7 +232,7 @@ bool virtio_send_1d(virtio_device *dev, uint64_t cmd, uint32_t cmd_len) { *(volatile uint16_t*)(uintptr_t)(dev->notify_cfg + dev->notify_off_multiplier * dev->common_cfg->queue_select) = 0; - while (last_used_idx == u->idx); + while (last_used_idx == u->idx);//TODO: OPT return true; } diff --git a/shared/net/udp.c b/shared/net/udp.c index 728baf9d..51ec3002 100644 --- a/shared/net/udp.c +++ b/shared/net/udp.c @@ -49,8 +49,4 @@ sizedptr udp_parse_packet_payload(uintptr_t ptr){ } return (sizedptr){0,0}; -} - -size_t calc_udp_size(uint16_t payload_len){ - return sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) + payload_len; } \ No newline at end of file diff --git a/shared/net/udp.h b/shared/net/udp.h index 323c53d2..760af6d7 100644 --- a/shared/net/udp.h +++ b/shared/net/udp.h @@ -15,7 +15,6 @@ typedef struct __attribute__((packed)) udp_hdr_t { } udp_hdr_t; void create_udp_packet(uintptr_t p, network_connection_ctx source, network_connection_ctx destination, const uint8_t* payload, uint16_t payload_len); -size_t calc_udp_size(uint16_t payload_len); uint16_t udp_parse_packet(uintptr_t ptr); sizedptr udp_parse_packet_payload(uintptr_t ptr); From 7506dc4b0afc9057a18a021344ffe002a606491c Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Mon, 23 Jun 2025 00:00:00 +0000 Subject: [PATCH 53/61] Moved context out of driver --- kernel/networking/drivers/net_driver.hpp | 4 +-- .../drivers/virtio_net_pci/virtio_net_pci.cpp | 25 +++++++++---------- .../drivers/virtio_net_pci/virtio_net_pci.hpp | 2 ++ kernel/networking/network_dispatch.cpp | 23 ++++++++++------- kernel/networking/network_dispatch.hpp | 3 +++ 5 files changed, 33 insertions(+), 24 deletions(-) diff --git a/kernel/networking/drivers/net_driver.hpp b/kernel/networking/drivers/net_driver.hpp index 6df5e34d..bcdd6801 100644 --- a/kernel/networking/drivers/net_driver.hpp +++ b/kernel/networking/drivers/net_driver.hpp @@ -20,9 +20,9 @@ class NetDriver { virtual void send_packet(sizedptr packet) = 0; - virtual ~NetDriver() = default; + virtual void get_mac(network_connection_ctx *context) = 0; - network_connection_ctx connection_context; + virtual ~NetDriver() = default; uint16_t header_size; }; \ No newline at end of file diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index a93bf961..dac5244d 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -4,6 +4,7 @@ #include "pci.h" #include "syscalls/syscalls.h" #include "memory/page_allocator.h" +#include "std/memfunctions.h" #define RECEIVE_QUEUE 0 #define TRANSMIT_QUEUE 1 @@ -82,19 +83,6 @@ bool VirtioNetDriver::init(){ kprintf("[VIRTIO_NET] Device set up at %x",(uintptr_t)vnp_net_dev.device_cfg); - virtio_net_config* net_config = (virtio_net_config*)vnp_net_dev.device_cfg; - kprintfv("[VIRTIO_NET] %x:%x:%x:%x:%x:%x", net_config->mac[0], net_config->mac[1], net_config->mac[2], net_config->mac[3], net_config->mac[4], net_config->mac[5]); - - connection_context = (network_connection_ctx){ - .port = 0, - .ip = 0, - .mac = {net_config->mac[0],net_config->mac[1],net_config->mac[2],net_config->mac[3],net_config->mac[4],net_config->mac[5]}, - }; - - kprintfv("[VIRTIO_NET] %i virtqueue pairs",net_config->max_virtqueue_pairs); - kprintfv("[VIRTIO_NET] %x speed", net_config->speed); - kprintfv("[VIRTIO_NET] status = %x", net_config->status); - select_queue(&vnp_net_dev, RECEIVE_QUEUE); for (uint16_t i = 0; i < 128; i++){ @@ -121,6 +109,17 @@ bool VirtioNetDriver::init(){ return true; } +void VirtioNetDriver::get_mac(network_connection_ctx *context){ + virtio_net_config* net_config = (virtio_net_config*)vnp_net_dev.device_cfg; + kprintfv("[VIRTIO_NET] %x:%x:%x:%x:%x:%x", net_config->mac[0], net_config->mac[1], net_config->mac[2], net_config->mac[3], net_config->mac[4], net_config->mac[5]); + + memcpy((void*)&context->mac,(void*)&net_config->mac,6); + + kprintfv("[VIRTIO_NET] %i virtqueue pairs",net_config->max_virtqueue_pairs); + kprintfv("[VIRTIO_NET] %x speed", net_config->speed); + kprintfv("[VIRTIO_NET] status = %x", net_config->status); +} + sizedptr VirtioNetDriver::allocate_packet(size_t size){ return (sizedptr){(uintptr_t)allocate_in_page(vnp_net_dev.memory_page, size + header_size, ALIGN_64B, true, true),size + header_size}; } diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp index ab84f2ad..d9685ef3 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.hpp @@ -19,6 +19,8 @@ class VirtioNetDriver : public NetDriver { void send_packet(sizedptr packet) override; + void get_mac(network_connection_ctx *context) override; + ~VirtioNetDriver() = default; private: diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index cf17e2ad..52d91304 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -17,11 +17,16 @@ NetworkDispatch::NetworkDispatch(){ ports = IndexMap(UINT16_MAX); for (uint16_t i = 0; i < UINT16_MAX; i++) ports[i] = UINT16_MAX; + context = (network_connection_ctx) {0}; +} + +NetDriver* NetworkDispatch::select_driver(){ + return VirtioNetDriver::try_init(); } bool NetworkDispatch::init(){ - if (VirtioNetDriver *vnd = VirtioNetDriver::try_init()){ - driver = vnd; + if ((driver = select_driver())){ + driver->get_mac(&context); return true; } return false; @@ -125,8 +130,8 @@ void NetworkDispatch::send_packet(NetProtocol protocol, uint16_t port, network_c switch (protocol) { case UDP: packet_buffer = driver->allocate_packet(sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) + payload_len); - driver->connection_context.port = port; - create_udp_packet(packet_buffer.ptr + driver->header_size, driver->connection_context, *destination, (uint8_t*)payload, payload_len); + context.port = port; + create_udp_packet(packet_buffer.ptr + driver->header_size, context, *destination, (uint8_t*)payload, payload_len); break; case DHCP: packet_buffer = driver->allocate_packet(DHCP_SIZE); @@ -134,17 +139,17 @@ void NetworkDispatch::send_packet(NetProtocol protocol, uint16_t port, network_c break; case ARP: packet_buffer = driver->allocate_packet(sizeof(eth_hdr_t) + sizeof(arp_hdr_t)); - create_arp_packet(packet_buffer.ptr + driver->header_size, driver->connection_context.mac, driver->connection_context.ip, destination->mac, destination->ip, *(bool*)payload); + create_arp_packet(packet_buffer.ptr + driver->header_size, context.mac, context.ip, destination->mac, destination->ip, *(bool*)payload); break; case ICMP: packet_buffer = driver->allocate_packet(sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(icmp_packet)); - create_icmp_packet(packet_buffer.ptr + driver->header_size, driver->connection_context, *destination, (icmp_data*)payload); + create_icmp_packet(packet_buffer.ptr + driver->header_size, context, *destination, (icmp_data*)payload); break; case TCP: tcp_data *data = (tcp_data*)payload; packet_buffer = driver->allocate_packet(sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(tcp_hdr_t) + data->options.size + data->payload.size); - driver->connection_context.port = port; - create_tcp_packet(packet_buffer.ptr + driver->header_size, driver->connection_context, *destination, (sizedptr){(uintptr_t)data, sizeof(tcp_data)}); + context.port = port; + create_tcp_packet(packet_buffer.ptr + driver->header_size, context, *destination, (sizedptr){(uintptr_t)data, sizeof(tcp_data)}); break; } if (driver) @@ -152,5 +157,5 @@ void NetworkDispatch::send_packet(NetProtocol protocol, uint16_t port, network_c } network_connection_ctx* NetworkDispatch::get_context(){ - return &driver->connection_context; + return &context; } \ No newline at end of file diff --git a/kernel/networking/network_dispatch.hpp b/kernel/networking/network_dispatch.hpp index 3ade7ec1..6dd27463 100644 --- a/kernel/networking/network_dispatch.hpp +++ b/kernel/networking/network_dispatch.hpp @@ -22,5 +22,8 @@ class NetworkDispatch { IndexMap ports; NetDriver *driver; + NetDriver* select_driver(); + sizedptr allocate_packet(size_t size); + network_connection_ctx context; }; \ No newline at end of file From c39ee20a728b8f6ac57b235a236885ad0d9ce899 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 24 Jun 2025 00:00:00 +0000 Subject: [PATCH 54/61] Use UDP for server discovery --- kernel/networking/processes/net_proc.c | 42 +++++++++++++++++++++----- shared/net/eth.c | 5 +++ shared/net/eth.h | 1 + shared/net/ipv4.c | 4 +++ shared/net/ipv4.h | 1 + 5 files changed, 46 insertions(+), 7 deletions(-) diff --git a/kernel/networking/processes/net_proc.c b/kernel/networking/processes/net_proc.c index 5479e478..1ac3c484 100644 --- a/kernel/networking/processes/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -9,20 +9,48 @@ #include "networking/network.h" #include "syscalls/syscalls.h" #include "math/math.h" -#include "../net_constants.h" #include "net/tcp.h" #include "net/http.h" #include "net/ipv4.h" +#include "net/eth.h" + +network_connection_ctx server; + +void find_server(){ + bind_port(7777); + server = (network_connection_ctx){ + .ip = (192 << 24) | (168 << 16) | (1 << 8) | 255, + .mac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + .port = 8080, + }; + + size_t payload_size = 5; + char hw[5] = {'h','e','l','l','o'}; + + send_packet(UDP, 7777, &server, hw, payload_size); + + sizedptr pack; + + while (!read_packet(&pack)); + + memcpy((void*)&server.mac, (void*)eth_get_source(pack.ptr), 6); + + server.ip = ipv4_get_source(pack.ptr + sizeof(eth_hdr_t)); + + sizedptr payload = udp_parse_packet_payload(pack.ptr); + + uint8_t *content = (uint8_t*)payload.ptr; + + kprintf("PAYLOAD: %s",(uintptr_t)string_ca_max(content, payload.size).data); + + unbind_port(7777); +} void test_network(){ + find_server(); bind_port(8888); - network_connection_ctx dest = (network_connection_ctx){ - .ip = HOST_IP, - .mac = HOST_MAC, - .port = 80, - }; - sizedptr http = request_http_data(GET, &dest, 8888); + sizedptr http = request_http_data(GET, &server, 8888); kprintf("Received payload? %x",(uintptr_t)&http); diff --git a/shared/net/eth.c b/shared/net/eth.c index bd57f6c8..e1933d75 100644 --- a/shared/net/eth.c +++ b/shared/net/eth.c @@ -15,4 +15,9 @@ uint16_t eth_parse_packet_type(uintptr_t ptr){ ptr += sizeof(eth_hdr_t); return __builtin_bswap16(eth->ethertype); +} + +uintptr_t eth_get_source(uintptr_t ptr){ + eth_hdr_t* eth = (eth_hdr_t*)ptr; + return (uintptr_t)ð->src_mac; } \ No newline at end of file diff --git a/shared/net/eth.h b/shared/net/eth.h index e931feb1..09600344 100644 --- a/shared/net/eth.h +++ b/shared/net/eth.h @@ -9,6 +9,7 @@ extern "C" { uint16_t eth_parse_packet_type(uintptr_t ptr); uintptr_t create_eth_packet(uintptr_t ptr, uint8_t src_mac[6], uint8_t dst_mac[6], uint16_t type); +uintptr_t eth_get_source(uintptr_t ptr); #ifdef __cplusplus } diff --git a/shared/net/ipv4.c b/shared/net/ipv4.c index 2f09f149..638b20c0 100644 --- a/shared/net/ipv4.c +++ b/shared/net/ipv4.c @@ -30,4 +30,8 @@ void ipv4_populate_response(network_connection_ctx *ctx, eth_hdr_t *eth, ipv4_hd string ipv4_to_string(uint32_t ip){ return string_format("%i.%i.%i.%i",(ip >> 24) & 0xFF,(ip >> 16) & 0xFF,(ip >> 8) & 0xFF,(ip >> 0) & 0xFF); +} + +uint32_t ipv4_get_source(uintptr_t ptr){ + return __builtin_bswap32(((ipv4_hdr_t*)ptr)->src_ip); } \ No newline at end of file diff --git a/shared/net/ipv4.h b/shared/net/ipv4.h index 2ee9bb9a..df196884 100644 --- a/shared/net/ipv4.h +++ b/shared/net/ipv4.h @@ -12,6 +12,7 @@ uint8_t ipv4_get_protocol(uintptr_t ptr); uintptr_t create_ipv4_packet(uintptr_t p, uint32_t payload_len, uint8_t protocol, uint32_t source_ip, uint32_t destination_ip); void ipv4_populate_response(network_connection_ctx *ctx, eth_hdr_t *eth, ipv4_hdr_t* ipv4); string ipv4_to_string(uint32_t ip); +uint32_t ipv4_get_source(uintptr_t ptr); #ifdef __cplusplus } From 78eb6c26506ef089ce919ab91c4adeefecda65e9 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 24 Jun 2025 00:00:00 +0000 Subject: [PATCH 55/61] Fixed port --- kernel/networking/processes/net_proc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/networking/processes/net_proc.c b/kernel/networking/processes/net_proc.c index 1ac3c484..42d02425 100644 --- a/kernel/networking/processes/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -50,6 +50,8 @@ void test_network(){ find_server(); bind_port(8888); + server.port = 80; + sizedptr http = request_http_data(GET, &server, 8888); kprintf("Received payload? %x",(uintptr_t)&http); From 4bce5729d24c15c056950cfb422d44662536d5af Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 24 Jun 2025 00:00:00 +0000 Subject: [PATCH 56/61] Expecting 'world' from server --- kernel/networking/processes/net_proc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/kernel/networking/processes/net_proc.c b/kernel/networking/processes/net_proc.c index 42d02425..3e11d9a0 100644 --- a/kernel/networking/processes/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -16,7 +16,7 @@ network_connection_ctx server; -void find_server(){ +bool find_server(){ bind_port(7777); server = (network_connection_ctx){ .ip = (192 << 24) | (168 << 16) | (1 << 8) | 255, @@ -44,10 +44,15 @@ void find_server(){ kprintf("PAYLOAD: %s",(uintptr_t)string_ca_max(content, payload.size).data); unbind_port(7777); + + return strcmp(content, "world") == 0; } void test_network(){ - find_server(); + if (!find_server()){ + kprintf("Could not find update server"); + return; + } bind_port(8888); server.port = 80; From 7e3aef705a6a82d402c117cfdc51551437b3fdf3 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 24 Jun 2025 00:00:00 +0000 Subject: [PATCH 57/61] Updated README --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bf230907..8d10ebe0 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ Once the system is initialized, most of the system's functionality is provided b Certain parts of the system initialization, such as GPU initialization and XHCI input code initialization rely on some syscalls that expect a process to be running, so an initial kernel.c process is created to hold their data. In the future they'll each have their own process. Everything about kernel processes and the pseudo-processes mentioned for GPU/XHCI will most likley be improved in the future, to make the system more modular, and kernel processes might get loaded from filesystem, in a similar way to how user processes are loaded. In order to do this, they either need to not rely on any kernel-only code (as several of them currently do) and rely on syscalls entirely, or (less ideal) dynamically link to the kernel. Doing this will increase the kernel's modularity. -The system currently heavily relies on symbols defined in the linker to run, and these symbols are not available in the stripped binary version of the kernel, so REDACTED OS must be run through the kernel.elf file rather than the kernel.bin file. -This limitation will be lifted in the future, removing reliance on these symbols altogether when possible, and creating alternatives for them when they're needed. +The system must be run through the .elf file, since the .img file overwrites the device's DTB, making it impossible to detect certain features of the system. +This limitation will be lifted in the future. ### Shared @@ -64,3 +64,8 @@ In order to run the OS, you'll need to create a folder called fs inside the proj Github Actions should automatically compile changes made to the `main` branch using Mac, so a compiled version of the system with all the files needed to run it should be found there. This includes the fs folder, containing the filesystem, but you'll need to recompile the `disk.img` filesystem with `createfs` for any changes made to this folder to be reflected. +## Networking + +The system has basic networking support. Currently, it performs DHCP a 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. +An implementation of the server can be found at the [RedactedOS Firmware Server Repository](https://github.com/differrari/RedactedOS_firmware_server/tree/main) + From d63d0311f9b10630e3be8b1c494a737fd415749f Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 24 Jun 2025 00:00:00 +0000 Subject: [PATCH 58/61] removed gitignored file --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index d91839be..b40b9743 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,3 @@ libshared.a *.a dump.dtb -net_constants.h From 4c14a0b475e08ad9e1fc80c83380d14bd031f82c Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 24 Jun 2025 00:00:00 +0000 Subject: [PATCH 59/61] Restored max_packet_size --- kernel/input/xhci.c | 8 ++++---- kernel/input/xhci_types.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/kernel/input/xhci.c b/kernel/input/xhci.c index a66ba41e..e56cff43 100644 --- a/kernel/input/xhci.c +++ b/kernel/input/xhci.c @@ -307,7 +307,7 @@ bool issue_command(uint64_t param, uint32_t status, uint32_t control){ return AWAIT(cmd_addr, {ring_doorbell(0, 0);}, TRB_TYPE_COMMAND_COMPLETION); } -uint16_t size(uint16_t port_speed){ +uint16_t packet_size(uint16_t port_speed){ switch (port_speed) { case 2: return 8;//Low case 1: @@ -506,7 +506,7 @@ bool xhci_get_configuration(usb_configuration_descriptor *config, xhci_usb_devic ctx->device_context.endpoints[ep_num-1].endpoint_f0.endpoint_state = 0; ctx->device_context.endpoints[ep_num-1].endpoint_f1.endpoint_type = get_ep_type(endpoint); - ctx->device_context.endpoints[ep_num-1].endpoint_f1.max_size = endpoint->wMaxPacketSize; + ctx->device_context.endpoints[ep_num-1].endpoint_f1.max_packet_size = endpoint->wMaxPacketSize; ctx->device_context.endpoints[ep_num-1].endpoint_f4.max_esit_payload_lo = endpoint->wMaxPacketSize; ctx->device_context.endpoints[ep_num-1].endpoint_f1.error_count = 3; @@ -582,7 +582,7 @@ bool xhci_setup_device(uint16_t port){ ctx->device_context.endpoints[0].endpoint_f1.endpoint_type = 4;//Type = control ctx->device_context.endpoints[0].endpoint_f0.interval = 0; ctx->device_context.endpoints[0].endpoint_f1.error_count = 3;//3 errors allowed - ctx->device_context.endpoints[0].endpoint_f1.max_size = size(ctx->device_context.slot_f0.speed);//Packet size. Guessed from port speed + ctx->device_context.endpoints[0].endpoint_f1.max_packet_size = packet_size(ctx->device_context.slot_f0.speed);//Packet size. Guessed from port speed device->transfer_ring = (trb*)allocate_in_page(xhci_mem_page, MAX_TRB_AMOUNT * sizeof(trb), ALIGN_64B, true, true); kprintfv("Transfer ring at %x",(uintptr_t)device->transfer_ring); @@ -600,7 +600,7 @@ bool xhci_setup_device(uint16_t port){ xhci_device_context* context = (xhci_device_context*)(uintptr_t)(global_device.dcbaa[device->slot_id]); - kprintfv("[xHCI] ADDRESS_DEVICE command issued. Received package size %i",context->endpoints[0].endpoint_f1.max_size); + kprintfv("[xHCI] ADDRESS_DEVICE command issued. Received package size %i",context->endpoints[0].endpoint_f1.max_packet_size); usb_device_descriptor* descriptor = (usb_device_descriptor*)allocate_in_page(xhci_mem_page, sizeof(usb_device_descriptor), ALIGN_64B, true, true); diff --git a/kernel/input/xhci_types.h b/kernel/input/xhci_types.h index 319e7d90..5151afe5 100644 --- a/kernel/input/xhci_types.h +++ b/kernel/input/xhci_types.h @@ -218,7 +218,7 @@ typedef union uint32_t rsvd2 : 1; uint32_t host_initiate_disable : 1; uint32_t max_burst_size : 8; - uint32_t max_size : 16; + uint32_t max_packet_size : 16; }; uint32_t value; } endpoint_field1; From 9a7c4530a29031795422bf14b42cebf3f297c61d Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 24 Jun 2025 00:00:00 +0000 Subject: [PATCH 60/61] UDP uses sizedptr --- kernel/networking/network_dispatch.cpp | 2 +- shared/net/dhcp.c | 2 +- shared/net/udp.c | 11 ++++++----- shared/net/udp.h | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index 52d91304..e8af7b0a 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -131,7 +131,7 @@ void NetworkDispatch::send_packet(NetProtocol protocol, uint16_t port, network_c case UDP: packet_buffer = driver->allocate_packet(sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) + payload_len); context.port = port; - create_udp_packet(packet_buffer.ptr + driver->header_size, context, *destination, (uint8_t*)payload, payload_len); + create_udp_packet(packet_buffer.ptr + driver->header_size, context, *destination, (sizedptr){(uintptr_t)payload, payload_len}); break; case DHCP: packet_buffer = driver->allocate_packet(DHCP_SIZE); diff --git a/shared/net/dhcp.c b/shared/net/dhcp.c index b538ea8d..0245b152 100644 --- a/shared/net/dhcp.c +++ b/shared/net/dhcp.c @@ -50,7 +50,7 @@ void create_dhcp_packet(uintptr_t p, dhcp_request *payload){ packet.options[7] = 255; // END } - create_udp_packet(p, source, destination, (uint8_t*)&packet, sizeof(dhcp_packet)); + create_udp_packet(p, source, destination, (sizedptr){(uintptr_t)&packet, sizeof(dhcp_packet)}); } dhcp_packet* dhcp_parse_packet_payload(uintptr_t ptr){ diff --git a/shared/net/udp.c b/shared/net/udp.c index 51ec3002..9ab81d8e 100644 --- a/shared/net/udp.c +++ b/shared/net/udp.c @@ -5,22 +5,23 @@ #include "eth.h" #include "ipv4.h" -void create_udp_packet(uintptr_t p, network_connection_ctx source, network_connection_ctx destination, const uint8_t* payload, uint16_t payload_len) { +void create_udp_packet(uintptr_t p, network_connection_ctx source, network_connection_ctx destination, sizedptr payload){ p = create_eth_packet(p, source.mac, destination.mac, 0x800); - p = create_ipv4_packet(p, sizeof(udp_hdr_t) + payload_len, 0x11, source.ip, destination.ip); + p = create_ipv4_packet(p, sizeof(udp_hdr_t) + payload.size, 0x11, source.ip, destination.ip); udp_hdr_t* udp = (udp_hdr_t*)p; udp->src_port = __builtin_bswap16(source.port); udp->dst_port = __builtin_bswap16(destination.port); - udp->length = __builtin_bswap16(sizeof(udp_hdr_t) + payload_len); + udp->length = __builtin_bswap16(sizeof(udp_hdr_t) + payload.size); p += sizeof(udp_hdr_t); uint8_t* data = (uint8_t*)p; - for (int i = 0; i < payload_len; i++) data[i] = payload[i]; + uint8_t* payload_c = (uint8_t*)payload.ptr; + for (size_t i = 0; i < payload.size; i++) data[i] = payload_c[i]; - udp->checksum = __builtin_bswap16(checksum16_pipv4(source.ip,destination.ip,0x11,(uint8_t*)udp,sizeof(udp_hdr_t) + payload_len)); + udp->checksum = __builtin_bswap16(checksum16_pipv4(source.ip,destination.ip,0x11,(uint8_t*)udp,sizeof(udp_hdr_t) + payload.size)); } diff --git a/shared/net/udp.h b/shared/net/udp.h index 760af6d7..c14ab36a 100644 --- a/shared/net/udp.h +++ b/shared/net/udp.h @@ -14,7 +14,7 @@ typedef struct __attribute__((packed)) udp_hdr_t { uint16_t checksum; } udp_hdr_t; -void create_udp_packet(uintptr_t p, network_connection_ctx source, network_connection_ctx destination, const uint8_t* payload, uint16_t payload_len); +void create_udp_packet(uintptr_t p, network_connection_ctx source, network_connection_ctx destination, sizedptr payload); uint16_t udp_parse_packet(uintptr_t ptr); sizedptr udp_parse_packet_payload(uintptr_t ptr); From 8f0281266aa95d3157083fc675b02148bee161bd Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 24 Jun 2025 00:00:00 +0000 Subject: [PATCH 61/61] Format, comment, print and header location fixes --- .../drivers/virtio_net_pci/virtio_net_pci.cpp | 2 +- kernel/networking/network_dispatch.cpp | 2 +- kernel/networking/network_dispatch.hpp | 1 + kernel/networking/processes/net_proc.c | 8 +++---- shared/net/arp.c | 8 ++----- shared/net/checksums.c | 6 +++--- shared/net/eth.h | 6 ++++++ shared/net/http.c | 9 ++++++-- shared/net/ipv4.h | 14 +++++++++++++ shared/net/network_types.h | 21 +------------------ shared/net/tcp.c | 4 +--- shared/net/tcp.h | 1 + 12 files changed, 41 insertions(+), 41 deletions(-) diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index dac5244d..4011d439 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -179,7 +179,7 @@ void VirtioNetDriver::send_packet(sizedptr packet){ if (packet.ptr && packet.size) virtio_send_1d(&vnp_net_dev, packet.ptr, packet.size); - kprintf("Queued new packet"); + kprintfv("Queued new packet"); } void VirtioNetDriver::enable_verbose(){ diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index e8af7b0a..01066c65 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -62,7 +62,7 @@ void NetworkDispatch::handle_download_interrupt(){ arp_populate_response(&conn, arp); send_packet(ARP, 0, &conn, &req, 1); } - //Should also look for responses to our own queries + //TODO: Should also look for responses to our own queries } else if (ethtype == 0x800){//IPV4 ipv4_hdr_t *ipv4 = (ipv4_hdr_t*)ptr; uint8_t protocol = ipv4_get_protocol(ptr); diff --git a/kernel/networking/network_dispatch.hpp b/kernel/networking/network_dispatch.hpp index 6dd27463..55814b66 100644 --- a/kernel/networking/network_dispatch.hpp +++ b/kernel/networking/network_dispatch.hpp @@ -13,6 +13,7 @@ class NetworkDispatch { bool unbind_port(uint16_t port, uint16_t process); void handle_upload_interrupt(); void handle_download_interrupt(); + //TODO: use sizedptr void send_packet(NetProtocol protocol, uint16_t port, network_connection_ctx *destination, void* payload, uint16_t payload_len); bool read_packet(sizedptr *Packet, uint16_t process); diff --git a/kernel/networking/processes/net_proc.c b/kernel/networking/processes/net_proc.c index 3e11d9a0..38e1ac94 100644 --- a/kernel/networking/processes/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -59,13 +59,11 @@ void test_network(){ sizedptr http = request_http_data(GET, &server, 8888); - kprintf("Received payload? %x",(uintptr_t)&http); - if (http.ptr != 0){ kprintf("Parsing payload"); sizedptr payload = http_get_payload(http); string content = http_get_chunked_payload(payload); - printf("Received payload? %s",(uintptr_t)content.data); + printf("Received payload %s",(uintptr_t)content.data); } unbind_port(8888); @@ -87,7 +85,7 @@ uint32_t negotiate_dhcp(){ dhcp_packet *payload; for (int i = 5; i >= 0; i--){ - while (!read_packet(&ptr)); + while (!read_packet(&ptr));//TODO. Timeout. Opt kprintf("Received DHCP response"); payload = dhcp_parse_packet_payload(ptr.ptr); uint16_t opt_index = dhcp_parse_option(payload, 53); @@ -114,7 +112,7 @@ uint32_t negotiate_dhcp(){ for (int i = 5; i >= 0; i--){ while (!read_packet(&ptr)); - kprintf("Received DHCP response"); + kprintf("Received DHCP response");//TODO. Timeout. Opt payload = dhcp_parse_packet_payload(ptr.ptr); uint16_t opt_index = dhcp_parse_option(payload, 53); if (payload->options[opt_index + 2] == 5) diff --git a/shared/net/arp.c b/shared/net/arp.c index 97de0e10..403f226b 100644 --- a/shared/net/arp.c +++ b/shared/net/arp.c @@ -1,12 +1,9 @@ #include "arp.h" +#include "eth.h" #include "std/memfunctions.h" void create_arp_packet(uintptr_t p, uint8_t* src_mac, uint32_t src_ip, uint8_t* dst_mac, uint32_t dst_ip, bool is_request){ - eth_hdr_t* eth = (eth_hdr_t*)p; - for (int i = 0; i < 6; i++) eth->dst_mac[i] = is_request ? 0xFF : dst_mac[i]; - memcpy(eth->src_mac, src_mac, 6); - eth->ethertype = __builtin_bswap16(0x0806); - p += sizeof(eth_hdr_t); + p = create_eth_packet(p, src_mac, is_request ? (uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} : dst_mac, 0x806); arp_hdr_t* arp = (arp_hdr_t*)p; @@ -27,6 +24,5 @@ void arp_populate_response(network_connection_ctx *ctx, arp_hdr_t* arp){ } bool arp_should_handle(arp_hdr_t *arp, uint32_t ip){ - return __builtin_bswap32(arp->target_ip) == ip; } \ No newline at end of file diff --git a/shared/net/checksums.c b/shared/net/checksums.c index d5f45bb7..32b11ee0 100644 --- a/shared/net/checksums.c +++ b/shared/net/checksums.c @@ -11,7 +11,7 @@ uint16_t checksum16_pipv4( uint32_t src_ip, uint32_t dst_ip, uint8_t protocol, - const uint8_t* udp_header_and_payload, + const uint8_t* payload, uint16_t length ) { uint32_t sum = 0; @@ -24,10 +24,10 @@ uint16_t checksum16_pipv4( sum += length; for (uint16_t i = 0; i + 1 < length; i += 2) - sum += (udp_header_and_payload[i] << 8) | udp_header_and_payload[i + 1]; + sum += (payload[i] << 8) | payload[i + 1]; if (length & 1) - sum += udp_header_and_payload[length - 1] << 8; + sum += payload[length - 1] << 8; while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16); diff --git a/shared/net/eth.h b/shared/net/eth.h index 09600344..d5333391 100644 --- a/shared/net/eth.h +++ b/shared/net/eth.h @@ -7,6 +7,12 @@ extern "C" { #include "types.h" #include "net/network_types.h" +typedef struct __attribute__((packed)) eth_hdr_t { + uint8_t dst_mac[6]; + uint8_t src_mac[6]; + uint16_t ethertype; +} eth_hdr_t; + uint16_t eth_parse_packet_type(uintptr_t ptr); uintptr_t create_eth_packet(uintptr_t ptr, uint8_t src_mac[6], uint8_t dst_mac[6], uint16_t type); uintptr_t eth_get_source(uintptr_t ptr); diff --git a/shared/net/http.c b/shared/net/http.c index e002692d..cb27520f 100644 --- a/shared/net/http.c +++ b/shared/net/http.c @@ -63,6 +63,8 @@ sizedptr request_http_data(HTTPRequest request, network_connection_ctx *dest, ui .window = UINT16_MAX, }; + printf("TCP Handshake"); + if (!tcp_handskake(dest, 8888, &data, 0)){ printf("TCP Handshake Error"); return (sizedptr){0}; @@ -73,11 +75,13 @@ sizedptr request_http_data(HTTPRequest request, network_connection_ctx *dest, ui free(serverstr.data, serverstr.mem_length); - printf("Request"); + printf("HTTP Request"); + + //TODO: more chunked support sizedptr http_response = http_data_transfer(dest, (sizedptr){(uintptr_t)req.data, req.length}, port, &data, 0, data.sequence, data.ack); - printf("END"); + printf("TCP End"); free(req.data, req.mem_length); @@ -100,6 +104,7 @@ sizedptr http_get_payload(sizedptr header){ } string http_get_chunked_payload(sizedptr chunk){ + //TODO: allow finding 0 to know when we're done reading the payload if (chunk.ptr && chunk.size > 0){ int sizetrm = strindex((char*)chunk.ptr, "\r\n"); uint64_t chunk_size = parse_hex_u64((char*)chunk.ptr,sizetrm); diff --git a/shared/net/ipv4.h b/shared/net/ipv4.h index df196884..ff1d4182 100644 --- a/shared/net/ipv4.h +++ b/shared/net/ipv4.h @@ -7,6 +7,20 @@ extern "C" { #include "types.h" #include "net/network_types.h" #include "std/string.h" +#include "eth.h" + +typedef struct __attribute__((packed)) ipv4_hdr_t { + uint8_t version_ihl; + uint8_t dscp_ecn; + uint16_t total_length; + uint16_t identification; + uint16_t flags_frag_offset; + uint8_t ttl; + uint8_t protocol; + uint16_t header_checksum; + uint32_t src_ip; + uint32_t dst_ip; +} ipv4_hdr_t; uint8_t ipv4_get_protocol(uintptr_t ptr); uintptr_t create_ipv4_packet(uintptr_t p, uint32_t payload_len, uint8_t protocol, uint32_t source_ip, uint32_t destination_ip); diff --git a/shared/net/network_types.h b/shared/net/network_types.h index f37d2611..a3c54978 100644 --- a/shared/net/network_types.h +++ b/shared/net/network_types.h @@ -16,26 +16,7 @@ typedef enum NetProtocol { uint16_t checksum16(uint16_t *data, size_t len); -uint16_t checksum16_pipv4(uint32_t src_ip, uint32_t dst_ip, uint8_t protocol, const uint8_t* udp_header_and_payload, uint16_t length); - -typedef struct __attribute__((packed)) eth_hdr_t { - uint8_t dst_mac[6]; - uint8_t src_mac[6]; - uint16_t ethertype; -} eth_hdr_t; - -typedef struct __attribute__((packed)) ipv4_hdr_t { - uint8_t version_ihl; - uint8_t dscp_ecn; - uint16_t total_length; - uint16_t identification; - uint16_t flags_frag_offset; - uint8_t ttl; - uint8_t protocol; - uint16_t header_checksum; - uint32_t src_ip; - uint32_t dst_ip; -} ipv4_hdr_t; +uint16_t checksum16_pipv4(uint32_t src_ip, uint32_t dst_ip, uint8_t protocol, const uint8_t* payload, uint16_t length); typedef struct network_connection_ctx { uint16_t port; diff --git a/shared/net/tcp.c b/shared/net/tcp.c index d0f6962b..d244fa85 100644 --- a/shared/net/tcp.c +++ b/shared/net/tcp.c @@ -61,11 +61,9 @@ sizedptr tcp_parse_packet_payload(uintptr_t ptr){ void tcp_send(uint16_t port, network_connection_ctx *destination, tcp_data* data){ send_packet(TCP, port, destination, data, sizeof(tcp_data)); if ((data->flags & ~(1 << ACK_F)) != 0 || data->payload.size > 0){ - printf("The payload is %i size",data->payload.size); data->sequence += __builtin_bswap32(max(1,data->payload.size)); } data->expected_ack = __builtin_bswap32(data->sequence); - printf("Next seq %i", __builtin_bswap32(data->sequence)); } void tcp_reset(uint16_t port, network_connection_ctx *destination, tcp_data* data){ @@ -112,7 +110,7 @@ uint8_t tcp_check_response(tcp_data *data, sizedptr *out){ if (ack != data->expected_ack){ printf("Wrong ack %i vs %i. Resetting", ack, data->expected_ack); return TCP_RESET; - } else printf("Received ack %i", ack); + } if (response->flags != (data->flags | (1 << ACK_F))){ printf("Wrong flags %b vs %b. Resetting",response->flags, data->flags | (1 << ACK_F)); diff --git a/shared/net/tcp.h b/shared/net/tcp.h index 0d0cb9a6..fafa7fdd 100644 --- a/shared/net/tcp.h +++ b/shared/net/tcp.h @@ -16,6 +16,7 @@ extern "C" { #define ECE_F 6 #define CWR_F 7 +//TODO: more response types. Indicate why we reset or retry instead of just that #define TCP_RESET 2 #define TCP_RETRY 1 #define TCP_OK 0