From 35098cbde155b387a478bccb354c9ddfd2b5dc2c Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 11 Mar 2019 12:43:45 +0100 Subject: [PATCH] Kernel: Add a NetworkTask and a received network packet queue. It will be easier to deal with incoming packets in a separate task. --- AK/SinglyLinkedList.h | 14 ++++++++++++-- Kernel/E1000NetworkAdapter.cpp | 10 ++++------ Kernel/MACAddress.h | 6 ++++++ Kernel/Makefile | 3 ++- Kernel/NetworkAdapter.cpp | 14 ++++++++++++++ Kernel/NetworkAdapter.h | 6 ++++++ Kernel/NetworkTask.cpp | 33 +++++++++++++++++++++++++++++++++ Kernel/NetworkTask.h | 3 +++ Kernel/init.cpp | 2 ++ Kernel/run | 10 ++++++++-- 10 files changed, 90 insertions(+), 11 deletions(-) create mode 100644 Kernel/NetworkTask.cpp create mode 100644 Kernel/NetworkTask.h diff --git a/AK/SinglyLinkedList.h b/AK/SinglyLinkedList.h index e7bd1cfd3b..34281f2175 100644 --- a/AK/SinglyLinkedList.h +++ b/AK/SinglyLinkedList.h @@ -1,6 +1,6 @@ #pragma once -#include +#include "StdLibExtras.h" namespace AK { @@ -35,9 +35,19 @@ public: T& last() { ASSERT(head()); return tail()->value; } const T& last() const { ASSERT(head()); return tail()->value; } + T take_first() + { + ASSERT(head()); + T value = first(); + if (m_tail == m_head) + m_tail = nullptr; + m_head = m_head->next; + return value; + } + void append(T&& value) { - auto* node = new Node(std::move(value)); + auto* node = new Node(move(value)); if (!m_head) { m_head = node; m_tail = node; diff --git a/Kernel/E1000NetworkAdapter.cpp b/Kernel/E1000NetworkAdapter.cpp index ede54a650f..b70bf79a0d 100644 --- a/Kernel/E1000NetworkAdapter.cpp +++ b/Kernel/E1000NetworkAdapter.cpp @@ -148,7 +148,6 @@ E1000NetworkAdapter::~E1000NetworkAdapter() void E1000NetworkAdapter::handle_irq() { - kprintf("E1000: IRQ!\n"); out32(REG_IMASK, 0x1); dword status = in32(0xc0); @@ -157,10 +156,9 @@ void E1000NetworkAdapter::handle_irq() out32(REG_CTRL, flags | ECTRL_SLU); } if (status & 0x10) { - kprintf("E1000: threshold\n"); + // Threshold OK? } if (status & 0x80) { - kprintf("E1000: receive...\n"); receive(); } } @@ -318,8 +316,8 @@ void E1000NetworkAdapter::send_raw(const byte* data, int length) auto& descriptor = m_tx_descriptors[m_tx_current]; descriptor.addr = (uint64_t)data; descriptor.length = length; - descriptor.cmd = (1 << 3) | 3; - m_tx_current = m_tx_current + 1 % number_of_tx_descriptors; + descriptor.cmd = CMD_EOP | CMD_IFCS | CMD_RS; + m_tx_current = (m_tx_current + 1) % number_of_tx_descriptors; out32(REG_TXDESCTAIL, m_tx_current); while (!(descriptor.status & 0xff)) ; @@ -333,7 +331,7 @@ void E1000NetworkAdapter::receive() word length = m_rx_descriptors[m_rx_current].length; kprintf("E1000: Received 1 packet @ %p (%u) bytes!\n", buffer, length); - + did_receive(buffer, length); m_rx_descriptors[m_rx_current].status = 0; auto old_current = m_rx_current; m_rx_current = (m_rx_current + 1) % number_of_rx_descriptors; diff --git a/Kernel/MACAddress.h b/Kernel/MACAddress.h index 788b0f2525..d8619beaaf 100644 --- a/Kernel/MACAddress.h +++ b/Kernel/MACAddress.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -19,6 +20,11 @@ public: return m_data[i]; } + String to_string() const + { + return String::format("%b:%b:%b:%b:%b:%b", m_data[0], m_data[1], m_data[2], m_data[3], m_data[4], m_data[5]); + } + private: byte m_data[6]; }; diff --git a/Kernel/Makefile b/Kernel/Makefile index 3e69a806ca..16fba0effc 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -35,7 +35,8 @@ KERNEL_OBJS = \ Socket.o \ LocalSocket.o \ NetworkAdapter.o \ - E1000NetworkAdapter.o + E1000NetworkAdapter.o \ + NetworkTask.o VFS_OBJS = \ DiskDevice.o \ diff --git a/Kernel/NetworkAdapter.cpp b/Kernel/NetworkAdapter.cpp index 8fef2f89db..6d46c5c660 100644 --- a/Kernel/NetworkAdapter.cpp +++ b/Kernel/NetworkAdapter.cpp @@ -21,3 +21,17 @@ void NetworkAdapter::send(const MACAddress& destination, const ARPPacket& packet send_raw((byte*)eth, size_in_bytes); kfree(eth); } + +void NetworkAdapter::did_receive(const byte* data, int length) +{ + InterruptDisabler disabler; + m_packet_queue.append(ByteBuffer::copy(data, length)); +} + +ByteBuffer NetworkAdapter::dequeue_packet() +{ + InterruptDisabler disabler; + if (m_packet_queue.is_empty()) + return { }; + return m_packet_queue.take_first(); +} diff --git a/Kernel/NetworkAdapter.h b/Kernel/NetworkAdapter.h index 2bc80329f9..38ccb8ce10 100644 --- a/Kernel/NetworkAdapter.h +++ b/Kernel/NetworkAdapter.h @@ -1,5 +1,7 @@ #pragma once +#include +#include #include #include #include @@ -13,11 +15,15 @@ public: void send(const MACAddress&, const ARPPacket&); + ByteBuffer dequeue_packet(); + protected: NetworkAdapter(); void set_mac_address(const MACAddress& mac_address) { m_mac_address = mac_address; } virtual void send_raw(const byte*, int) = 0; + void did_receive(const byte*, int); private: MACAddress m_mac_address; + SinglyLinkedList m_packet_queue; }; diff --git a/Kernel/NetworkTask.cpp b/Kernel/NetworkTask.cpp new file mode 100644 index 0000000000..763331cc5f --- /dev/null +++ b/Kernel/NetworkTask.cpp @@ -0,0 +1,33 @@ +#include +#include +#include +#include + +void NetworkTask_main() +{ + auto* e1000_ptr = E1000NetworkAdapter::the(); + ASSERT(e1000_ptr); + auto& e1000 = *e1000_ptr; + ARPPacket arp; + arp.hardware_type = 1; // Ethernet + arp.hardware_address_length = 6; // MAC length + arp.protocol_type = 0x0800; // IPv4 + arp.protocol_address_length = 4; // IP length + arp.operation = 1; // 1 (request) + e1000.send(MACAddress(), arp); + + kprintf("NetworkTask: Enter main loop.\n"); + for (;;) { + auto packet = e1000.dequeue_packet(); + if (packet.is_null()) { + sleep(100); + continue; + } + if (packet.size() < sizeof(EthernetFrameHeader) + 4) { + kprintf("NetworkTask: Packet is too small to be an Ethernet packet! (%d)\n", packet.size()); + continue; + } + auto* eth = (const EthernetFrameHeader*)packet.pointer(); + kprintf("NetworkTask: Handle packet from %s to %s\n", eth->source().to_string().characters(), eth->destination().to_string().characters()); + } +} diff --git a/Kernel/NetworkTask.h b/Kernel/NetworkTask.h new file mode 100644 index 0000000000..16d8817309 --- /dev/null +++ b/Kernel/NetworkTask.h @@ -0,0 +1,3 @@ +#pragma once + +void NetworkTask_main(); diff --git a/Kernel/init.cpp b/Kernel/init.cpp index ee002a38bd..a957b112d7 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -24,6 +24,7 @@ #include "DevPtsFS.h" #include "BXVGADevice.h" #include "E1000NetworkAdapter.h" +#include #define SPAWN_LAUNCHER //#define SPAWN_GUITEST2 @@ -186,6 +187,7 @@ VFS* vfs; Scheduler::yield(); } }); + Process::create_kernel_process("NetworkTask", NetworkTask_main); Scheduler::pick_next(); diff --git a/Kernel/run b/Kernel/run index ac7127d7d6..d4a8ed41b6 100755 --- a/Kernel/run +++ b/Kernel/run @@ -1,8 +1,14 @@ #!/bin/sh -if [ "$1" = "q" ]; then +if [ "$1" = "b" ]; then + # ./run b: bochs + bochs -q -f .bochsrc +elif [ "$1" = "qn" ]; then + # ./run qn: qemu without network qemu-system-i386 -s -m 32 -device e1000 -drive format=raw,file=.floppy-image,if=floppy -drive format=raw,file=_fs_contents #$@ else - bochs -q -f .bochsrc + echo run with net + # ./run: qemu with network + sudo qemu-system-i386 -s -m 32 -netdev tap,id=br0 -device e1000,netdev=br0 -drive format=raw,file=.floppy-image,if=floppy -drive format=raw,file=_fs_contents #$ fi