Explorar el Código

Kernel: Add a NetworkTask and a received network packet queue.

It will be easier to deal with incoming packets in a separate task.
Andreas Kling hace 6 años
padre
commit
35098cbde1

+ 12 - 2
AK/SinglyLinkedList.h

@@ -1,6 +1,6 @@
 #pragma once
 #pragma once
 
 
-#include <utility>
+#include "StdLibExtras.h"
 
 
 namespace AK {
 namespace AK {
 
 
@@ -35,9 +35,19 @@ public:
     T& last() { ASSERT(head()); return tail()->value; }
     T& last() { ASSERT(head()); return tail()->value; }
     const T& last() const { 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)
     void append(T&& value)
     {
     {
-        auto* node = new Node(std::move(value));
+        auto* node = new Node(move(value));
         if (!m_head) {
         if (!m_head) {
             m_head = node;
             m_head = node;
             m_tail = node;
             m_tail = node;

+ 4 - 6
Kernel/E1000NetworkAdapter.cpp

@@ -148,7 +148,6 @@ E1000NetworkAdapter::~E1000NetworkAdapter()
 
 
 void E1000NetworkAdapter::handle_irq()
 void E1000NetworkAdapter::handle_irq()
 {
 {
-    kprintf("E1000: IRQ!\n");
     out32(REG_IMASK, 0x1);
     out32(REG_IMASK, 0x1);
 
 
     dword status = in32(0xc0);
     dword status = in32(0xc0);
@@ -157,10 +156,9 @@ void E1000NetworkAdapter::handle_irq()
         out32(REG_CTRL, flags | ECTRL_SLU);
         out32(REG_CTRL, flags | ECTRL_SLU);
     }
     }
     if (status & 0x10) {
     if (status & 0x10) {
-        kprintf("E1000: threshold\n");
+        // Threshold OK?
     }
     }
     if (status & 0x80) {
     if (status & 0x80) {
-        kprintf("E1000: receive...\n");
         receive();
         receive();
     }
     }
 }
 }
@@ -318,8 +316,8 @@ void E1000NetworkAdapter::send_raw(const byte* data, int length)
     auto& descriptor = m_tx_descriptors[m_tx_current];
     auto& descriptor = m_tx_descriptors[m_tx_current];
     descriptor.addr = (uint64_t)data;
     descriptor.addr = (uint64_t)data;
     descriptor.length = length;
     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);
     out32(REG_TXDESCTAIL, m_tx_current);
     while (!(descriptor.status & 0xff))
     while (!(descriptor.status & 0xff))
         ;
         ;
@@ -333,7 +331,7 @@ void E1000NetworkAdapter::receive()
         word length = m_rx_descriptors[m_rx_current].length;
         word length = m_rx_descriptors[m_rx_current].length;
 
 
         kprintf("E1000: Received 1 packet @ %p (%u) bytes!\n", buffer, length);
         kprintf("E1000: Received 1 packet @ %p (%u) bytes!\n", buffer, length);
-
+        did_receive(buffer, length);
         m_rx_descriptors[m_rx_current].status = 0;
         m_rx_descriptors[m_rx_current].status = 0;
         auto old_current = m_rx_current;
         auto old_current = m_rx_current;
         m_rx_current = (m_rx_current + 1) % number_of_rx_descriptors;
         m_rx_current = (m_rx_current + 1) % number_of_rx_descriptors;

+ 6 - 0
Kernel/MACAddress.h

@@ -1,6 +1,7 @@
 #pragma once
 #pragma once
 
 
 #include <AK/Assertions.h>
 #include <AK/Assertions.h>
+#include <AK/AKString.h>
 #include <AK/Types.h>
 #include <AK/Types.h>
 #include <Kernel/StdLib.h>
 #include <Kernel/StdLib.h>
 
 
@@ -19,6 +20,11 @@ public:
         return m_data[i];
         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:
 private:
     byte m_data[6];
     byte m_data[6];
 };
 };

+ 2 - 1
Kernel/Makefile

@@ -35,7 +35,8 @@ KERNEL_OBJS = \
        Socket.o \
        Socket.o \
        LocalSocket.o \
        LocalSocket.o \
        NetworkAdapter.o \
        NetworkAdapter.o \
-       E1000NetworkAdapter.o
+       E1000NetworkAdapter.o \
+       NetworkTask.o
 
 
 VFS_OBJS = \
 VFS_OBJS = \
     DiskDevice.o \
     DiskDevice.o \

+ 14 - 0
Kernel/NetworkAdapter.cpp

@@ -21,3 +21,17 @@ void NetworkAdapter::send(const MACAddress& destination, const ARPPacket& packet
     send_raw((byte*)eth, size_in_bytes);
     send_raw((byte*)eth, size_in_bytes);
     kfree(eth);
     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();
+}

+ 6 - 0
Kernel/NetworkAdapter.h

@@ -1,5 +1,7 @@
 #pragma once
 #pragma once
 
 
+#include <AK/ByteBuffer.h>
+#include <AK/SinglyLinkedList.h>
 #include <AK/Types.h>
 #include <AK/Types.h>
 #include <Kernel/MACAddress.h>
 #include <Kernel/MACAddress.h>
 #include <Kernel/ARPPacket.h>
 #include <Kernel/ARPPacket.h>
@@ -13,11 +15,15 @@ public:
 
 
     void send(const MACAddress&, const ARPPacket&);
     void send(const MACAddress&, const ARPPacket&);
 
 
+    ByteBuffer dequeue_packet();
+
 protected:
 protected:
     NetworkAdapter();
     NetworkAdapter();
     void set_mac_address(const MACAddress& mac_address) { m_mac_address = mac_address; }
     void set_mac_address(const MACAddress& mac_address) { m_mac_address = mac_address; }
     virtual void send_raw(const byte*, int) = 0;
     virtual void send_raw(const byte*, int) = 0;
+    void did_receive(const byte*, int);
 
 
 private:
 private:
     MACAddress m_mac_address;
     MACAddress m_mac_address;
+    SinglyLinkedList<ByteBuffer> m_packet_queue;
 };
 };

+ 33 - 0
Kernel/NetworkTask.cpp

@@ -0,0 +1,33 @@
+#include <Kernel/E1000NetworkAdapter.h>
+#include <Kernel/EthernetFrameHeader.h>
+#include <Kernel/ARPPacket.h>
+#include <Kernel/Process.h>
+
+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());
+    }
+}

+ 3 - 0
Kernel/NetworkTask.h

@@ -0,0 +1,3 @@
+#pragma once
+
+void NetworkTask_main();

+ 2 - 0
Kernel/init.cpp

@@ -24,6 +24,7 @@
 #include "DevPtsFS.h"
 #include "DevPtsFS.h"
 #include "BXVGADevice.h"
 #include "BXVGADevice.h"
 #include "E1000NetworkAdapter.h"
 #include "E1000NetworkAdapter.h"
+#include <Kernel/NetworkTask.h>
 
 
 #define SPAWN_LAUNCHER
 #define SPAWN_LAUNCHER
 //#define SPAWN_GUITEST2
 //#define SPAWN_GUITEST2
@@ -186,6 +187,7 @@ VFS* vfs;
             Scheduler::yield();
             Scheduler::yield();
         }
         }
     });
     });
+    Process::create_kernel_process("NetworkTask", NetworkTask_main);
 
 
     Scheduler::pick_next();
     Scheduler::pick_next();
 
 

+ 8 - 2
Kernel/run

@@ -1,8 +1,14 @@
 #!/bin/sh
 #!/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 #$@
     qemu-system-i386 -s -m 32 -device e1000 -drive format=raw,file=.floppy-image,if=floppy -drive format=raw,file=_fs_contents #$@
 else
 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
 fi