mirror of
https://github.com/RGBCube/serenity
synced 2025-05-20 11:45:06 +00:00
Kernel: Add a NetworkTask and a received network packet queue.
It will be easier to deal with incoming packets in a separate task.
This commit is contained in:
parent
47b096feb4
commit
35098cbde1
10 changed files with 90 additions and 11 deletions
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
#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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Assertions.h>
|
||||
#include <AK/AKString.h>
|
||||
#include <AK/Types.h>
|
||||
#include <Kernel/StdLib.h>
|
||||
|
||||
|
@ -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];
|
||||
};
|
||||
|
|
|
@ -35,7 +35,8 @@ KERNEL_OBJS = \
|
|||
Socket.o \
|
||||
LocalSocket.o \
|
||||
NetworkAdapter.o \
|
||||
E1000NetworkAdapter.o
|
||||
E1000NetworkAdapter.o \
|
||||
NetworkTask.o
|
||||
|
||||
VFS_OBJS = \
|
||||
DiskDevice.o \
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/ByteBuffer.h>
|
||||
#include <AK/SinglyLinkedList.h>
|
||||
#include <AK/Types.h>
|
||||
#include <Kernel/MACAddress.h>
|
||||
#include <Kernel/ARPPacket.h>
|
||||
|
@ -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<ByteBuffer> m_packet_queue;
|
||||
};
|
||||
|
|
33
Kernel/NetworkTask.cpp
Normal file
33
Kernel/NetworkTask.cpp
Normal file
|
@ -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
Kernel/NetworkTask.h
Normal file
3
Kernel/NetworkTask.h
Normal file
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
void NetworkTask_main();
|
|
@ -24,6 +24,7 @@
|
|||
#include "DevPtsFS.h"
|
||||
#include "BXVGADevice.h"
|
||||
#include "E1000NetworkAdapter.h"
|
||||
#include <Kernel/NetworkTask.h>
|
||||
|
||||
#define SPAWN_LAUNCHER
|
||||
//#define SPAWN_GUITEST2
|
||||
|
@ -186,6 +187,7 @@ VFS* vfs;
|
|||
Scheduler::yield();
|
||||
}
|
||||
});
|
||||
Process::create_kernel_process("NetworkTask", NetworkTask_main);
|
||||
|
||||
Scheduler::pick_next();
|
||||
|
||||
|
|
10
Kernel/run
10
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
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue