Compare commits

..

No commits in common. "2138eeb87f0c018826f60a014f177f9253197ae9" and "9213dd13bc4cdc705d2ba149d87cd3049548223a" have entirely different histories.

50 changed files with 577 additions and 2754 deletions

View File

@ -58,11 +58,6 @@ namespace BAN
template<integral T>
struct LittleEndian
{
constexpr LittleEndian(T value)
{
raw = host_to_little_endian(value);
}
constexpr operator T() const
{
return host_to_little_endian(raw);
@ -74,11 +69,6 @@ namespace BAN
template<integral T>
struct BigEndian
{
constexpr BigEndian(T value)
{
raw = host_to_big_endian(value);
}
constexpr operator T() const
{
return host_to_big_endian(raw);
@ -87,7 +77,4 @@ namespace BAN
T raw;
};
template<integral T>
using NetworkEndian = BigEndian<T>;
}

View File

@ -1,73 +0,0 @@
#pragma once
#include <BAN/Formatter.h>
#include <BAN/Hash.h>
namespace BAN
{
struct IPv4Address
{
constexpr IPv4Address(uint32_t u32_address)
{
address[0] = u32_address >> 24;
address[1] = u32_address >> 16;
address[2] = u32_address >> 8;
address[3] = u32_address >> 0;
}
constexpr uint32_t as_u32() const
{
return
((uint32_t)address[0] << 24) |
((uint32_t)address[1] << 16) |
((uint32_t)address[2] << 8) |
((uint32_t)address[3] << 0);
}
constexpr bool operator==(const IPv4Address& other) const
{
return
address[0] == other.address[0] &&
address[1] == other.address[1] &&
address[2] == other.address[2] &&
address[3] == other.address[3];
}
uint8_t address[4];
};
static_assert(sizeof(IPv4Address) == 4);
template<>
struct hash<IPv4Address>
{
constexpr hash_t operator()(IPv4Address ipv4) const
{
return hash<uint32_t>()(ipv4.as_u32());
}
};
}
namespace BAN::Formatter
{
template<typename F>
void print_argument(F putc, const IPv4Address& ipv4, const ValueFormat&)
{
ValueFormat format {
.base = 10,
.percision = 0,
.fill = 0,
.upper = false,
};
print_argument(putc, ipv4.address[0], format);
for (size_t i = 1; i < 4; i++)
{
putc('.');
print_argument(putc, ipv4.address[i], format);
}
}
}

View File

@ -42,8 +42,6 @@ namespace BAN
iterator remove(iterator);
void clear();
iterator move_element_to_other_linked_list(LinkedList& dest_list, iterator dest_iter, iterator src_iter);
iterator begin() { return iterator(m_data, empty()); }
const_iterator begin() const { return const_iterator(m_data, empty()); }
iterator end() { return iterator(m_last, true); }
@ -67,11 +65,7 @@ namespace BAN
Node* prev;
};
template<typename... Args>
ErrorOr<Node*> allocate_node(Args&&...) const;
Node* remove_node(iterator);
void insert_node(iterator, Node*);
ErrorOr<Node*> allocate_node() const;
Node* m_data = nullptr;
Node* m_last = nullptr;
@ -143,31 +137,6 @@ namespace BAN
return *this;
}
template<typename T>
LinkedList<T>::Node* LinkedList<T>::remove_node(iterator iter)
{
ASSERT(!empty() && iter);
Node* node = iter.m_current;
Node* prev = node->prev;
Node* next = node->next;
(prev ? prev->next : m_data) = next;
(next ? next->prev : m_last) = prev;
m_size--;
return node;
}
template<typename T>
void LinkedList<T>::insert_node(iterator iter, Node* node)
{
Node* next = iter.m_past_end ? nullptr : iter.m_current;
Node* prev = next ? next->prev : m_last;
node->next = next;
node->prev = prev;
(prev ? prev->next : m_data) = node;
(next ? next->prev : m_last) = node;
m_size++;
}
template<typename T>
ErrorOr<void> LinkedList<T>::push_back(const T& value)
{
@ -189,8 +158,15 @@ namespace BAN
template<typename T>
ErrorOr<void> LinkedList<T>::insert(iterator iter, T&& value)
{
Node* new_node = TRY(allocate_node(move(value)));
insert_node(iter, new_node);
Node* next = iter.m_past_end ? nullptr : iter.m_current;
Node* prev = next ? next->prev : m_last;
Node* new_node = TRY(allocate_node());
new (&new_node->value) T(move(value));
new_node->next = next;
new_node->prev = prev;
(prev ? prev->next : m_data) = new_node;
(next ? next->prev : m_last) = new_node;
m_size++;
return {};
}
@ -205,15 +181,21 @@ namespace BAN
template<typename... Args>
ErrorOr<void> LinkedList<T>::emplace(iterator iter, Args&&... args)
{
Node* new_node = TRY(allocate_node(forward<Args>(args)...));
insert_node(iter, new_node);
Node* next = iter.m_past_end ? nullptr : iter.m_current;
Node* prev = next ? next->prev : m_last;
Node* new_node = TRY(allocate_node());
new (&new_node->value) T(forward<Args>(args)...);
new_node->next = next;
new_node->prev = prev;
(prev ? prev->next : m_data) = new_node;
(next ? next->prev : m_last) = new_node;
m_size++;
return {};
}
template<typename T>
void LinkedList<T>::pop_back()
{
ASSERT(!empty());
remove(iterator(m_last, false));
}
@ -221,10 +203,14 @@ namespace BAN
LinkedList<T>::iterator LinkedList<T>::remove(iterator iter)
{
ASSERT(!empty() && iter);
Node* node = remove_node(iter);
Node* node = iter.m_current;
Node* prev = node->prev;
Node* next = node->next;
node->value.~T();
BAN::deallocator(node);
(prev ? prev->next : m_data) = next;
(next ? next->prev : m_last) = prev;
m_size--;
return next ? iterator(next, false) : iterator(m_last, true);
}
@ -244,16 +230,6 @@ namespace BAN
m_size = 0;
}
template<typename T>
LinkedList<T>::iterator LinkedList<T>::move_element_to_other_linked_list(LinkedList& dest_list, iterator dest_iter, iterator src_iter)
{
ASSERT(!empty() && src_iter);
Node* node = remove_node(src_iter);
iterator ret = node->next ? iterator(node->next, false) : iterator(m_last, true);
dest_list.insert_node(dest_iter, node);
return ret;
}
template<typename T>
const T& LinkedList<T>::back() const
{
@ -308,13 +284,11 @@ namespace BAN
}
template<typename T>
template<typename... Args>
ErrorOr<typename LinkedList<T>::Node*> LinkedList<T>::allocate_node(Args&&... args) const
ErrorOr<typename LinkedList<T>::Node*> LinkedList<T>::allocate_node() const
{
Node* node = (Node*)BAN::allocator(sizeof(Node));
if (node == nullptr)
return Error::from_errno(ENOMEM);
new (&node->value) T(forward<Args>(args)...);
return node;
}

View File

@ -1,36 +0,0 @@
#pragma once
#include <BAN/Formatter.h>
namespace BAN
{
struct MACAddress
{
uint8_t address[6];
};
}
namespace BAN::Formatter
{
template<typename F>
void print_argument(F putc, const MACAddress& mac, const ValueFormat&)
{
ValueFormat format {
.base = 16,
.percision = 0,
.fill = 2,
.upper = true,
};
print_argument(putc, mac.address[0], format);
for (size_t i = 1; i < 6; i++)
{
putc(':');
print_argument(putc, mac.address[i], format);
}
}
}

View File

@ -1,9 +1,8 @@
#pragma once
#include <BAN/Math.h>
#include <BAN/Swap.h>
#include <BAN/Traits.h>
#include <BAN/Vector.h>
#include <BAN/Math.h>
namespace BAN::sort
{
@ -176,61 +175,6 @@ namespace BAN::sort
detail::intro_sort_impl(begin, end, 2 * Math::ilog2(len), comp);
}
namespace detail
{
template<unsigned_integral T>
consteval T lsb_index(T value)
{
for (T result = 0;; result++)
if (value & (1 << result))
return result;
}
}
template<typename It, size_t radix = 256>
requires is_unsigned_v<typename It::value_type> && (radix > 0 && (radix & (radix - 1)) == 0)
BAN::ErrorOr<void> radix_sort(It begin, It end)
{
using value_type = typename It::value_type;
const size_t len = distance(begin, end);
if (len <= 1)
return {};
Vector<value_type> temp;
TRY(temp.resize(len));
Vector<size_t> counts;
TRY(counts.resize(radix));
constexpr size_t mask = radix - 1;
constexpr size_t shift = detail::lsb_index(radix);
for (size_t s = 0; s < sizeof(value_type) * 8; s += shift)
{
for (auto& cnt : counts)
cnt = 0;
for (It it = begin; it != end; ++it)
counts[(*it >> s) & mask]++;
for (size_t i = 0; i < radix - 1; i++)
counts[i + 1] += counts[i];
for (It it = end; it != begin;)
{
--it;
temp[--counts[(*it >> s) & mask]] = *it;
}
for (size_t j = 0; j < temp.size(); j++)
*next(begin, j) = temp[j];
}
return {};
}
template<typename It, typename Comp = less<typename It::value_type>>
void sort(It begin, It end, Comp comp = {})
{

View File

@ -49,14 +49,7 @@ set(KERNEL_SOURCES
kernel/Memory/MemoryRegion.cpp
kernel/Memory/PhysicalRange.cpp
kernel/Memory/VirtualRange.cpp
kernel/Networking/ARPTable.cpp
kernel/Networking/E1000/E1000.cpp
kernel/Networking/E1000/E1000E.cpp
kernel/Networking/IPv4.cpp
kernel/Networking/NetworkInterface.cpp
kernel/Networking/NetworkManager.cpp
kernel/Networking/NetworkSocket.cpp
kernel/Networking/UDPSocket.cpp
kernel/Networking/E1000.cpp
kernel/OpenFileDescriptorSet.cpp
kernel/Panic.cpp
kernel/PCI.cpp

View File

@ -11,7 +11,6 @@
#include <kernel/Credentials.h>
#include <kernel/SpinLock.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
@ -87,8 +86,6 @@ namespace Kernel
virtual bool is_pipe() const { return false; }
virtual bool is_tty() const { return false; }
void on_close();
// Directory API
BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode(BAN::StringView);
BAN::ErrorOr<void> list_next_inodes(off_t, DirectoryEntryList*, size_t);
@ -99,11 +96,6 @@ namespace Kernel
// Link API
BAN::ErrorOr<BAN::String> link_target();
// Socket API
BAN::ErrorOr<void> bind(const sockaddr* address, socklen_t address_len);
BAN::ErrorOr<ssize_t> sendto(const sys_sendto_t*);
BAN::ErrorOr<ssize_t> recvfrom(sys_recvfrom_t*);
// General API
BAN::ErrorOr<size_t> read(off_t, BAN::ByteSpan buffer);
BAN::ErrorOr<size_t> write(off_t, BAN::ConstByteSpan buffer);
@ -112,11 +104,7 @@ namespace Kernel
BAN::ErrorOr<void> chown(uid_t, gid_t);
bool has_data() const;
BAN::ErrorOr<long> ioctl(int request, void* arg);
protected:
virtual void on_close_impl() {}
// Directory API
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> list_next_inodes_impl(off_t, DirectoryEntryList*, size_t) { return BAN::Error::from_errno(ENOTSUP); }
@ -127,11 +115,6 @@ namespace Kernel
// Link API
virtual BAN::ErrorOr<BAN::String> link_target_impl() { return BAN::Error::from_errno(ENOTSUP); }
// Socket API
virtual BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<ssize_t> sendto_impl(const sys_sendto_t*) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<ssize_t> recvfrom_impl(sys_recvfrom_t*) { return BAN::Error::from_errno(ENOTSUP); }
// General API
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) { return BAN::Error::from_errno(ENOTSUP); }
@ -140,8 +123,6 @@ namespace Kernel
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual bool has_data_impl() const { dwarnln("nonblock not supported"); return true; }
virtual BAN::ErrorOr<long> ioctl_impl(int request, void* arg) { return BAN::Error::from_errno(ENOTSUP); }
protected:
mutable RecursivePrioritySpinLock m_lock;

View File

@ -1,43 +0,0 @@
#pragma once
#include <BAN/HashMap.h>
#include <BAN/UniqPtr.h>
#include <kernel/Networking/NetworkInterface.h>
namespace Kernel
{
class ARPTable
{
BAN_NON_COPYABLE(ARPTable);
BAN_NON_MOVABLE(ARPTable);
public:
static BAN::ErrorOr<BAN::UniqPtr<ARPTable>> create();
BAN::ErrorOr<BAN::MACAddress> get_mac_from_ipv4(NetworkInterface&, BAN::IPv4Address);
void handle_arp_packet(BAN::ConstByteSpan);
private:
ARPTable();
private:
struct ARPReply
{
BAN::IPv4Address ipv4_address { 0 };
BAN::MACAddress mac_address;
};
private:
SpinLock m_lock;
BAN::HashMap<BAN::IPv4Address, BAN::MACAddress> m_arp_table;
BAN::Atomic<bool> m_has_got_reply;
ARPReply m_reply;
friend class BAN::UniqPtr<ARPTable>;
};
}

View File

@ -0,0 +1,62 @@
#pragma once
#include <BAN/UniqPtr.h>
#include <kernel/InterruptController.h>
#include <kernel/Networking/NetworkDriver.h>
#include <kernel/PCI.h>
#define E1000_NUM_RX_DESC 32
#define E1000_NUM_TX_DESC 8
namespace Kernel
{
class E1000 final : public NetworkDriver, public Interruptable
{
public:
static bool probe(PCI::Device&);
static BAN::ErrorOr<BAN::UniqPtr<E1000>> create(PCI::Device&);
~E1000();
virtual uint8_t* get_mac_address() override { return m_mac_address; }
virtual BAN::ErrorOr<void> send_packet(const void* data, uint16_t len) override;
virtual bool link_up() override { return m_link_up; }
virtual int link_speed() override;
virtual void handle_irq() override { ASSERT_NOT_REACHED(); }
private:
E1000(PCI::Device& pci_device) : m_pci_device(pci_device) {}
BAN::ErrorOr<void> initialize();
static void interrupt_handler();
uint32_t read32(uint16_t reg);
void write32(uint16_t reg, uint32_t value);
void detect_eeprom();
uint32_t eeprom_read(uint8_t addr);
BAN::ErrorOr<void> read_mac_address();
void initialize_rx();
void initialize_tx();
void enable_link();
BAN::ErrorOr<void> enable_interrupts();
void handle_receive();
private:
PCI::Device& m_pci_device;
BAN::UniqPtr<PCI::BarRegion> m_bar_region;
bool m_has_eerprom { false };
uint8_t m_mac_address[6] {};
uint16_t m_rx_current {};
uint16_t m_tx_current {};
struct e1000_rx_desc* m_rx_descs[E1000_NUM_RX_DESC] {};
struct e1000_tx_desc* m_tx_descs[E1000_NUM_TX_DESC] {};
bool m_link_up { false };
};
}

View File

@ -1,202 +0,0 @@
#pragma once
#include <stdint.h>
namespace Kernel
{
enum E1000_REG : uint32_t
{
REG_CTRL = 0x0000,
REG_STATUS = 0x0008,
REG_EERD = 0x0014,
REG_ICR = 0x00C0,
REG_ITR = 0x00C4,
REG_IMS = 0x00D0,
REG_IMC = 0x00D8,
REG_IVAR = 0x00E4,
REG_EITR = 0x00E8,
REG_RCTL = 0x0100,
REG_TCTL = 0x0400,
REG_TIPG = 0x0410,
REG_RDBAL0 = 0x2800,
REG_RDBAH0 = 0x2804,
REG_RDLEN0 = 0x2808,
REG_RDH0 = 0x2810,
REG_RDT0 = 0x2818,
REG_TDBAL = 0x3800,
REG_TDBAH = 0x3804,
REG_TDLEN = 0x3808,
REG_TDH = 0x3810,
REG_TDT = 0x3818,
REG_MTA = 0x5200,
};
enum E1000_CTRL : uint32_t
{
CTRL_FD = 1u << 0,
CTRL_GIOMD = 1u << 2,
CTRL_ASDE = 1u << 5,
CTRL_SLU = 1u << 6,
CTRL_FRCSPD = 1u << 11,
CTRL_FCRDBLX = 1u << 12,
CTRL_ADVD3WUC = 1u << 20,
CTRL_RST = 1u << 26,
CTRL_RFCE = 1u << 27,
CTRL_TFCE = 1u << 28,
CTRL_VME = 1u << 30,
CTRL_PHY_RST = 1u << 31,
CTRL_SPEED_10MB = 0b00 << 8,
CTRL_SPEED_100MB = 0b01 << 8,
CTRL_SPEED_1000MB1 = 0b10 << 8,
CTRL_SPEED_1000MB2 = 0b11 << 8,
};
enum E1000_STATUS : uint32_t
{
STATUS_LU = 1 << 1,
STATUS_SPEED_MASK = 0b11 << 6,
STATUS_SPEED_10MB = 0b00 << 6,
STATUS_SPEED_100MB = 0b01 << 6,
STATUS_SPEED_1000MB1 = 0b10 << 6,
STATUS_SPEED_1000MB2 = 0b11 << 6,
};
enum E1000_ICR : uint32_t
{
ICR_TXDW = 1 << 0,
ICR_TXQE = 1 << 1,
ICR_LSC = 1 << 2,
ICR_RXDMT0 = 1 << 4,
ICR_RXO = 1 << 6,
ICR_RXT0 = 1 << 7,
ICR_MDAC = 1 << 9,
ICR_TXD_LOW = 1 << 15,
ICR_SRPD = 1 << 16,
ICR_ACK = 1 << 17,
ICR_MNG = 1 << 18,
ICR_RxQ0 = 1 << 20,
ICR_RxQ1 = 1 << 21,
ICR_TxQ0 = 1 << 22,
ICR_TxQ1 = 1 << 23,
ICR_Other = 1 << 24,
};
enum E1000_IMS : uint32_t
{
IMS_TXDW = 1 << 0,
IMS_TXQE = 1 << 1,
IMS_LSC = 1 << 2,
IMS_RXDMT0 = 1 << 4,
IMS_RXO = 1 << 6,
IMS_RXT0 = 1 << 7,
IMS_MDAC = 1 << 9,
IMS_TXD_LOW = 1 << 15,
IMS_SRPD = 1 << 16,
IMS_ACK = 1 << 17,
IMS_MNG = 1 << 18,
IMS_RxQ0 = 1 << 20,
IMS_RxQ1 = 1 << 21,
IMS_TxQ0 = 1 << 22,
IMS_TxQ1 = 1 << 23,
IMS_Other = 1 << 24,
};
enum E1000_IMC : uint32_t
{
IMC_TXDW = 1 << 0,
IMC_TXQE = 1 << 1,
IMC_LSC = 1 << 2,
IMC_RXDMT0 = 1 << 4,
IMC_RXO = 1 << 6,
IMC_RXT0 = 1 << 7,
IMC_MDAC = 1 << 9,
IMC_TXD_LOW = 1 << 15,
IMC_SRPD = 1 << 16,
IMC_ACK = 1 << 17,
IMC_MNG = 1 << 18,
IMC_RxQ0 = 1 << 20,
IMC_RxQ1 = 1 << 21,
IMC_TxQ0 = 1 << 22,
IMC_TxQ1 = 1 << 23,
IMC_Other = 1 << 24,
};
enum E1000_TCTL : uint32_t
{
TCTL_EN = 1 << 1,
TCTL_PSP = 1 << 3,
TCTL_CT_IEEE = 15 << 4,
TCTL_SWXOFF = 1 << 22,
TCTL_PBE = 1 << 23,
TCTL_RCTL = 1 << 24,
TCTL_UNORTX = 1 << 25,
TCTL_MULR = 1 << 28,
};
enum E1000_RCTL : uint32_t
{
RCTL_EN = 1 << 1,
RCTL_SBP = 1 << 2,
RCTL_UPE = 1 << 3,
RCTL_MPE = 1 << 4,
RCTL_BAM = 1 << 15,
RCTL_VFE = 1 << 18,
RCTL_CFIEN = 1 << 19,
RCTL_CFI = 1 << 20,
RCTL_DPF = 1 << 22,
RCTL_PMCF = 1 << 23,
RCTL_BSEX = 1 << 25,
RCTL_SECRC = 1 << 26,
RCTL_RDMTS_1_2 = 0b00 << 8,
RCTL_RDMTS_1_4 = 0b01 << 8,
RCTL_RDMTS_1_8 = 0b10 << 8,
RCTL_LBM_NORMAL = 0b00 << 6,
RCTL_LBM_MAC = 0b01 << 6,
RCTL_BSIZE_256 = (0b11 << 16),
RCTL_BSIZE_512 = (0b10 << 16),
RCTL_BSIZE_1024 = (0b01 << 16),
RCTL_BSIZE_2048 = (0b00 << 16),
RCTL_BSIZE_4096 = (0b11 << 16) | RCTL_BSEX,
RCTL_BSIZE_8192 = (0b10 << 16) | RCTL_BSEX,
RCTL_BSIZE_16384 = (0b01 << 16) | RCTL_BSEX,
};
enum E1000_CMD : uint8_t
{
CMD_EOP = 1 << 0,
CMD_IFCS = 1 << 1,
CMD_IC = 1 << 2,
CMD_RS = 1 << 3,
CMD_DEXT = 1 << 5,
CMD_VLE = 1 << 6,
CMD_IDE = 1 << 7,
};
struct e1000_rx_desc
{
uint64_t addr;
uint16_t length;
uint16_t checksum;
uint8_t status;
uint8_t errors;
uint16_t special;
} __attribute__((packed));
struct e1000_tx_desc
{
uint64_t addr;
uint16_t length;
uint8_t cso;
uint8_t cmd;
uint8_t status;
uint8_t css;
uint16_t special;
} __attribute__((packed));
}

View File

@ -1,75 +0,0 @@
#pragma once
#include <BAN/UniqPtr.h>
#include <kernel/InterruptController.h>
#include <kernel/Memory/DMARegion.h>
#include <kernel/Networking/E1000/Definitions.h>
#include <kernel/Networking/NetworkInterface.h>
#include <kernel/PCI.h>
#define E1000_RX_DESCRIPTOR_COUNT 256
#define E1000_TX_DESCRIPTOR_COUNT 256
#define E1000_RX_BUFFER_SIZE 8192
#define E1000_TX_BUFFER_SIZE 8192
namespace Kernel
{
class E1000 : public NetworkInterface, public Interruptable
{
public:
static bool probe(PCI::Device&);
static BAN::ErrorOr<BAN::RefPtr<E1000>> create(PCI::Device&);
~E1000();
virtual BAN::MACAddress get_mac_address() const override { return m_mac_address; }
virtual bool link_up() override { return m_link_up; }
virtual int link_speed() override;
virtual void handle_irq() final override;
protected:
E1000(PCI::Device& pci_device)
: m_pci_device(pci_device)
{ }
BAN::ErrorOr<void> initialize();
virtual void detect_eeprom();
virtual uint32_t eeprom_read(uint8_t addr);
uint32_t read32(uint16_t reg);
void write32(uint16_t reg, uint32_t value);
virtual BAN::ErrorOr<void> send_raw_bytes(BAN::ConstByteSpan) override;
private:
BAN::ErrorOr<void> read_mac_address();
BAN::ErrorOr<void> initialize_rx();
BAN::ErrorOr<void> initialize_tx();
void enable_link();
BAN::ErrorOr<void> enable_interrupt();
void handle_receive();
protected:
PCI::Device& m_pci_device;
BAN::UniqPtr<PCI::BarRegion> m_bar_region;
bool m_has_eerprom { false };
private:
BAN::UniqPtr<DMARegion> m_rx_buffer_region;
BAN::UniqPtr<DMARegion> m_tx_buffer_region;
BAN::UniqPtr<DMARegion> m_rx_descriptor_region;
BAN::UniqPtr<DMARegion> m_tx_descriptor_region;
BAN::MACAddress m_mac_address {};
bool m_link_up { false };
friend class BAN::RefPtr<E1000>;
};
}

View File

@ -1,27 +0,0 @@
#pragma once
#include <kernel/Networking/E1000/E1000.h>
namespace Kernel
{
class E1000E final : public E1000
{
public:
static bool probe(PCI::Device&);
static BAN::ErrorOr<BAN::RefPtr<E1000E>> create(PCI::Device&);
protected:
virtual void detect_eeprom() override;
virtual uint32_t eeprom_read(uint8_t addr) override;
private:
E1000E(PCI::Device& pci_device)
: E1000(pci_device)
{ }
private:
friend class BAN::RefPtr<E1000E>;
};
}

View File

@ -1,38 +0,0 @@
#pragma once
#include <BAN/ByteSpan.h>
#include <BAN/Endianness.h>
#include <BAN/IPv4.h>
#include <BAN/Vector.h>
namespace Kernel
{
struct IPv4Header
{
uint8_t version_IHL;
uint8_t DSCP_ECN;
BAN::NetworkEndian<uint16_t> total_length { 0 };
BAN::NetworkEndian<uint16_t> identification { 0 };
BAN::NetworkEndian<uint16_t> flags_frament { 0 };
uint8_t time_to_live;
uint8_t protocol;
BAN::NetworkEndian<uint16_t> checksum { 0 };
BAN::IPv4Address src_address;
BAN::IPv4Address dst_address;
constexpr uint16_t calculate_checksum() const
{
return 0xFFFF
- (((uint16_t)version_IHL << 8) | DSCP_ECN)
- total_length
- identification
- flags_frament
- (((uint16_t)time_to_live << 8) | protocol);
}
};
static_assert(sizeof(IPv4Header) == 20);
void add_ipv4_header(BAN::ByteSpan packet, BAN::IPv4Address src_ipv4, BAN::IPv4Address dst_ipv4, uint8_t protocol);
}

View File

@ -0,0 +1,20 @@
#pragma once
#include <BAN/Errors.h>
namespace Kernel
{
class NetworkDriver
{
public:
virtual ~NetworkDriver() {}
virtual uint8_t* get_mac_address() = 0;
virtual BAN::ErrorOr<void> send_packet(const void* data, uint16_t len) = 0;
virtual bool link_up() = 0;
virtual int link_speed() = 0;
};
}

View File

@ -1,70 +0,0 @@
#pragma once
#include <BAN/Errors.h>
#include <BAN/ByteSpan.h>
#include <BAN/MAC.h>
#include <kernel/Device/Device.h>
#include <kernel/Networking/IPv4.h>
namespace Kernel
{
struct EthernetHeader
{
BAN::MACAddress dst_mac;
BAN::MACAddress src_mac;
BAN::NetworkEndian<uint16_t> ether_type;
};
static_assert(sizeof(EthernetHeader) == 14);
enum EtherType : uint16_t
{
IPv4 = 0x0800,
ARP = 0x0806,
};
class NetworkInterface : public CharacterDevice
{
BAN_NON_COPYABLE(NetworkInterface);
BAN_NON_MOVABLE(NetworkInterface);
public:
enum class Type
{
Ethernet,
};
public:
NetworkInterface();
virtual ~NetworkInterface() {}
virtual BAN::MACAddress get_mac_address() const = 0;
BAN::IPv4Address get_ipv4_address() const { return m_ipv4_address; }
void set_ipv4_address(BAN::IPv4Address new_address) { m_ipv4_address = new_address; }
BAN::IPv4Address get_netmask() const { return m_netmask; }
void set_netmask(BAN::IPv4Address new_netmask) { m_netmask = new_netmask; }
virtual bool link_up() = 0;
virtual int link_speed() = 0;
size_t interface_header_size() const;
void add_interface_header(BAN::ByteSpan packet, BAN::MACAddress destination);
virtual dev_t rdev() const override { return m_rdev; }
virtual BAN::StringView name() const override { return m_name; }
virtual BAN::ErrorOr<void> send_raw_bytes(BAN::ConstByteSpan) = 0;
private:
const Type m_type;
const dev_t m_rdev;
char m_name[10];
BAN::IPv4Address m_ipv4_address { 0 };
BAN::IPv4Address m_netmask { 0 };
};
}

View File

@ -1,52 +0,0 @@
#pragma once
#include <BAN/Vector.h>
#include <kernel/FS/TmpFS/FileSystem.h>
#include <kernel/Networking/ARPTable.h>
#include <kernel/Networking/NetworkInterface.h>
#include <kernel/Networking/NetworkSocket.h>
#include <kernel/PCI.h>
#include <netinet/in.h>
namespace Kernel
{
class NetworkManager : public TmpFileSystem
{
BAN_NON_COPYABLE(NetworkManager);
BAN_NON_MOVABLE(NetworkManager);
public:
enum class SocketType
{
STREAM,
DGRAM,
SEQPACKET,
};
public:
static BAN::ErrorOr<void> initialize();
static NetworkManager& get();
ARPTable& arp_table() { return *m_arp_table; }
BAN::ErrorOr<void> add_interface(PCI::Device& pci_device);
void unbind_socket(uint16_t port, BAN::RefPtr<NetworkSocket>);
BAN::ErrorOr<void> bind_socket(uint16_t port, BAN::RefPtr<NetworkSocket>);
BAN::ErrorOr<BAN::RefPtr<NetworkSocket>> create_socket(SocketType, mode_t, uid_t, gid_t);
void on_receive(BAN::ConstByteSpan);
private:
NetworkManager();
private:
BAN::UniqPtr<ARPTable> m_arp_table;
BAN::Vector<BAN::RefPtr<NetworkInterface>> m_interfaces;
BAN::HashMap<int, BAN::WeakPtr<NetworkSocket>> m_bound_sockets;
};
}

View File

@ -1,53 +0,0 @@
#pragma once
#include <BAN/WeakPtr.h>
#include <kernel/FS/TmpFS/Inode.h>
#include <kernel/Networking/NetworkInterface.h>
#include <netinet/in.h>
namespace Kernel
{
enum NetworkProtocol : uint8_t
{
UDP = 0x11,
};
class NetworkSocket : public TmpInode, public BAN::Weakable<NetworkSocket>
{
BAN_NON_COPYABLE(NetworkSocket);
BAN_NON_MOVABLE(NetworkSocket);
public:
static constexpr uint16_t PORT_NONE = 0;
public:
void bind_interface_and_port(NetworkInterface*, uint16_t port);
~NetworkSocket();
virtual size_t protocol_header_size() const = 0;
virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t src_port, uint16_t dst_port) = 0;
virtual NetworkProtocol protocol() const = 0;
virtual void add_packet(BAN::ConstByteSpan, BAN::IPv4Address sender_address, uint16_t sender_port) = 0;
protected:
NetworkSocket(mode_t mode, uid_t uid, gid_t gid);
virtual BAN::ErrorOr<size_t> read_packet(BAN::ByteSpan, sockaddr_in* sender_address) = 0;
virtual void on_close_impl() override;
virtual BAN::ErrorOr<void> bind_impl(const sockaddr* address, socklen_t address_len) override;
virtual BAN::ErrorOr<ssize_t> sendto_impl(const sys_sendto_t*) override;
virtual BAN::ErrorOr<ssize_t> recvfrom_impl(sys_recvfrom_t*) override;
virtual BAN::ErrorOr<long> ioctl_impl(int request, void* arg) override;
protected:
NetworkInterface* m_interface = nullptr;
uint16_t m_port = PORT_NONE;
};
}

View File

@ -1,55 +0,0 @@
#pragma once
#include <BAN/CircularQueue.h>
#include <BAN/Endianness.h>
#include <kernel/Memory/VirtualRange.h>
#include <kernel/Networking/NetworkInterface.h>
#include <kernel/Networking/NetworkSocket.h>
#include <kernel/Semaphore.h>
namespace Kernel
{
struct UDPHeader
{
BAN::NetworkEndian<uint16_t> src_port;
BAN::NetworkEndian<uint16_t> dst_port;
BAN::NetworkEndian<uint16_t> length;
BAN::NetworkEndian<uint16_t> checksum;
};
static_assert(sizeof(UDPHeader) == 8);
class UDPSocket final : public NetworkSocket
{
public:
static BAN::ErrorOr<BAN::RefPtr<UDPSocket>> create(mode_t, uid_t, gid_t);
virtual size_t protocol_header_size() const override { return sizeof(UDPHeader); }
virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t src_port, uint16_t dst_port) override;
virtual NetworkProtocol protocol() const override { return NetworkProtocol::UDP; }
protected:
virtual void add_packet(BAN::ConstByteSpan, BAN::IPv4Address sender_addr, uint16_t sender_port) override;
virtual BAN::ErrorOr<size_t> read_packet(BAN::ByteSpan, sockaddr_in* sender_address) override;
private:
UDPSocket(mode_t, uid_t, gid_t);
struct PacketInfo
{
BAN::IPv4Address sender_addr;
uint16_t sender_port;
size_t packet_size;
};
private:
static constexpr size_t packet_buffer_size = 10 * PAGE_SIZE;
BAN::UniqPtr<VirtualRange> m_packet_buffer;
BAN::CircularQueue<PacketInfo, 128> m_packets;
size_t m_packet_total_size { 0 };
Semaphore m_semaphore;
friend class BAN::RefPtr<UDPSocket>;
};
}

View File

@ -23,8 +23,6 @@ namespace Kernel
BAN::ErrorOr<int> open(BAN::StringView absolute_path, int flags);
BAN::ErrorOr<int> socket(int domain, int type, int protocol);
BAN::ErrorOr<void> pipe(int fds[2]);
BAN::ErrorOr<int> dup(int);

View File

@ -16,7 +16,6 @@
#include <sys/banan-os.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <termios.h>
namespace LibELF { class LoadableELF; }
@ -112,13 +111,6 @@ namespace Kernel
BAN::ErrorOr<long> sys_chmod(const char*, mode_t);
BAN::ErrorOr<long> sys_chown(const char*, uid_t, gid_t);
BAN::ErrorOr<long> sys_socket(int domain, int type, int protocol);
BAN::ErrorOr<long> sys_bind(int socket, const sockaddr* address, socklen_t address_len);
BAN::ErrorOr<long> sys_sendto(const sys_sendto_t*);
BAN::ErrorOr<long> sys_recvfrom(sys_recvfrom_t*);
BAN::ErrorOr<long> sys_ioctl(int fildes, int request, void* arg);
BAN::ErrorOr<long> sys_pipe(int fildes[2]);
BAN::ErrorOr<long> sys_dup(int fildes);
BAN::ErrorOr<long> sys_dup2(int fildes, int fildes2);

View File

@ -44,26 +44,34 @@ namespace Kernel
BAN::ErrorOr<void> add_thread(Thread*);
private:
struct SchedulerThread
struct ActiveThread
{
SchedulerThread(Thread* thread)
: thread(thread)
{}
ActiveThread(Thread* thread) : thread(thread) {}
Thread* thread;
union
{
uint64_t wake_time;
Semaphore* semaphore;
};
uint64_t padding;
};
struct SleepingThread
{
SleepingThread(Thread* thread, uint64_t wake_time) : thread(thread), wake_time(wake_time) {}
Thread* thread;
uint64_t wake_time;
};
struct BlockingThread
{
BlockingThread(Thread* thread, Semaphore* semaphore) : thread(thread), semaphore(semaphore) {}
Thread* thread;
Semaphore* semaphore;
uint8_t padding[sizeof(uint64_t) - sizeof(Semaphore*)];
};
Thread* m_idle_thread { nullptr };
BAN::LinkedList<SchedulerThread> m_active_threads;
BAN::LinkedList<SchedulerThread> m_sleeping_threads;
BAN::LinkedList<SchedulerThread> m_blocking_threads;
BAN::LinkedList<ActiveThread> m_active_threads;
BAN::LinkedList<SleepingThread> m_sleeping_threads;
BAN::LinkedList<BlockingThread> m_blocking_threads;
BAN::LinkedList<SchedulerThread>::iterator m_current_thread;
BAN::LinkedList<ActiveThread>::iterator m_current_thread;
friend class Process;
};

View File

@ -56,12 +56,6 @@ namespace Kernel
return true;
}
void Inode::on_close()
{
LockGuard _(m_lock);
on_close_impl();
}
BAN::ErrorOr<BAN::RefPtr<Inode>> Inode::find_inode(BAN::StringView name)
{
LockGuard _(m_lock);
@ -116,30 +110,6 @@ namespace Kernel
return link_target_impl();
}
BAN::ErrorOr<void> Inode::bind(const sockaddr* address, socklen_t address_len)
{
LockGuard _(m_lock);
if (!mode().ifsock())
return BAN::Error::from_errno(ENOTSOCK);
return bind_impl(address, address_len);
}
BAN::ErrorOr<ssize_t> Inode::sendto(const sys_sendto_t* arguments)
{
LockGuard _(m_lock);
if (!mode().ifsock())
return BAN::Error::from_errno(ENOTSOCK);
return sendto_impl(arguments);
};
BAN::ErrorOr<ssize_t> Inode::recvfrom(sys_recvfrom_t* arguments)
{
LockGuard _(m_lock);
if (!mode().ifsock())
return BAN::Error::from_errno(ENOTSOCK);
return recvfrom_impl(arguments);
};
BAN::ErrorOr<size_t> Inode::read(off_t offset, BAN::ByteSpan buffer)
{
LockGuard _(m_lock);
@ -183,10 +153,4 @@ namespace Kernel
return has_data_impl();
}
BAN::ErrorOr<long> Inode::ioctl(int request, void* arg)
{
LockGuard _(m_lock);
return ioctl_impl(request, arg);
}
}

View File

@ -1,108 +0,0 @@
#include <kernel/LockGuard.h>
#include <kernel/Networking/ARPTable.h>
#include <kernel/Timer/Timer.h>
namespace Kernel
{
struct ARPPacket
{
BAN::NetworkEndian<uint16_t> htype;
BAN::NetworkEndian<uint16_t> ptype;
BAN::NetworkEndian<uint8_t> hlen;
BAN::NetworkEndian<uint8_t> plen;
BAN::NetworkEndian<uint16_t> oper;
BAN::MACAddress sha;
BAN::IPv4Address spa;
BAN::MACAddress tha;
BAN::IPv4Address tpa;
};
static_assert(sizeof(ARPPacket) == 28);
enum ARPOperation : uint16_t
{
Request = 1,
Reply = 2,
};
static constexpr BAN::IPv4Address s_broadcast_ipv4 { 0xFFFFFFFF };
static constexpr BAN::MACAddress s_broadcast_mac {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }};
BAN::ErrorOr<BAN::UniqPtr<ARPTable>> ARPTable::create()
{
return TRY(BAN::UniqPtr<ARPTable>::create());
}
ARPTable::ARPTable()
{
}
BAN::ErrorOr<BAN::MACAddress> ARPTable::get_mac_from_ipv4(NetworkInterface& interface, BAN::IPv4Address ipv4_address)
{
LockGuard _(m_lock);
if (ipv4_address == s_broadcast_ipv4)
return s_broadcast_mac;
if (m_arp_table.contains(ipv4_address))
return m_arp_table[ipv4_address];
BAN::Vector<uint8_t> full_packet_buffer;
TRY(full_packet_buffer.resize(sizeof(ARPPacket) + sizeof(EthernetHeader)));
auto full_packet = BAN::ByteSpan { full_packet_buffer.span() };
auto& ethernet_header = full_packet.as<EthernetHeader>();
ethernet_header.dst_mac = s_broadcast_mac;
ethernet_header.src_mac = interface.get_mac_address();
ethernet_header.ether_type = EtherType::ARP;
auto& arp_request = full_packet.slice(sizeof(EthernetHeader)).as<ARPPacket>();
arp_request.htype = 0x0001;
arp_request.ptype = EtherType::IPv4;
arp_request.hlen = 0x06;
arp_request.plen = 0x04;
arp_request.oper = ARPOperation::Request;
arp_request.sha = interface.get_mac_address();
arp_request.spa = interface.get_ipv4_address();
arp_request.tha = {{ 0, 0, 0, 0, 0, 0 }};
arp_request.tpa = ipv4_address;
TRY(interface.send_raw_bytes(full_packet));
uint64_t timeout = SystemTimer::get().ms_since_boot() + 5'000;
while (!m_has_got_reply)
if (SystemTimer::get().ms_since_boot() >= timeout)
return BAN::Error::from_errno(ETIMEDOUT);
ASSERT_EQ(m_reply.ipv4_address, ipv4_address);
BAN::MACAddress mac_address = m_reply.mac_address;
(void)m_arp_table.insert(ipv4_address, m_reply.mac_address);
m_has_got_reply = false;
dprintln("IPv4 {} resolved to MAC {}", ipv4_address, mac_address);
return mac_address;
}
void ARPTable::handle_arp_packet(BAN::ConstByteSpan buffer)
{
auto& arp_packet = buffer.as<const ARPPacket>();
if (arp_packet.oper != ARPOperation::Reply)
{
dprintln("Unhandled non-rely ARP packet (operation {2H})", (uint16_t)arp_packet.oper);
return;
}
if (arp_packet.ptype != EtherType::IPv4)
{
dprintln("Unhandled non-ipv4 ARP packet (ptype {2H})", (uint16_t)arp_packet.ptype);
return;
}
ASSERT(!m_has_got_reply);
m_has_got_reply = true;
m_reply.ipv4_address = arp_packet.spa;
m_reply.mac_address = arp_packet.sha;
}
}

View File

@ -0,0 +1,374 @@
#include <kernel/IDT.h>
#include <kernel/InterruptController.h>
#include <kernel/IO.h>
#include <kernel/Memory/PageTable.h>
#include <kernel/MMIO.h>
#include <kernel/Networking/E1000.h>
#define DEBUG_E1000 1
#define E1000_REG_CTRL 0x0000
#define E1000_REG_STATUS 0x0008
#define E1000_REG_EEPROM 0x0014
#define E1000_REG_INT_CAUSE_READ 0x00C0
#define E1000_REG_INT_RATE 0x00C4
#define E1000_REG_INT_MASK_SET 0x00D0
#define E1000_REG_INT_MASK_CLEAR 0x00D8
#define E1000_REG_RCTRL 0x0100
#define E1000_REG_RXDESCLO 0x2800
#define E1000_REG_RXDESCHI 0x2804
#define E1000_REG_RXDESCLEN 0x2808
#define E1000_REG_RXDESCHEAD 0x2810
#define E1000_REG_RXDESCTAIL 0x2818
#define E1000_REG_TXDESCLO 0x3800
#define E1000_REG_TXDESCHI 0x3804
#define E1000_REG_TXDESCLEN 0x3808
#define E1000_REG_TXDESCHEAD 0x3810
#define E1000_REG_TXDESCTAIL 0x3818
#define E1000_REG_TCTRL 0x0400
#define E1000_REG_TIPG 0x0410
#define E1000_STATUS_LINK_UP 0x02
#define E1000_STATUS_SPEED_MASK 0xC0
#define E1000_STATUS_SPEED_10MB 0x00
#define E1000_STATUS_SPEED_100MB 0x40
#define E1000_STATUS_SPEED_1000MB1 0x80
#define E1000_STATUS_SPEED_1000MB2 0xC0
#define E1000_CTRL_SET_LINK_UP 0x40
#define E1000_INT_TXDW (1 << 0)
#define E1000_INT_TXQE (1 << 1)
#define E1000_INT_LSC (1 << 2)
#define E1000_INT_RXSEQ (1 << 3)
#define E1000_INT_RXDMT0 (1 << 4)
#define E1000_INT_RXO (1 << 6)
#define E1000_INT_RXT0 (1 << 7)
#define E1000_INT_MDAC (1 << 9)
#define E1000_INT_RXCFG (1 << 10)
#define E1000_INT_PHYINT (1 << 12)
#define E1000_INT_TXD_LOW (1 << 15)
#define E1000_INT_SRPD (1 << 16)
#define E1000_TCTL_EN (1 << 1)
#define E1000_TCTL_PSP (1 << 3)
#define E1000_TCTL_CT_SHIFT 4
#define E1000_TCTL_COLD_SHIFT 12
#define E1000_TCTL_SWXOFF (1 << 22)
#define E1000_TCTL_RTLC (1 << 24)
#define E1000_RCTL_EN (1 << 1)
#define E1000_RCTL_SBP (1 << 2)
#define E1000_RCTL_UPE (1 << 3)
#define E1000_RCTL_MPE (1 << 4)
#define E1000_RCTL_LPE (1 << 5)
#define E1000_RCTL_LBM_NONE (0 << 6)
#define E1000_RCTL_LBM_PHY (3 << 6)
#define E1000_RTCL_RDMTS_HALF (0 << 8)
#define E1000_RTCL_RDMTS_QUARTER (1 << 8)
#define E1000_RTCL_RDMTS_EIGHTH (2 << 8)
#define E1000_RCTL_MO_36 (0 << 12)
#define E1000_RCTL_MO_35 (1 << 12)
#define E1000_RCTL_MO_34 (2 << 12)
#define E1000_RCTL_MO_32 (3 << 12)
#define E1000_RCTL_BAM (1 << 15)
#define E1000_RCTL_VFE (1 << 18)
#define E1000_RCTL_CFIEN (1 << 19)
#define E1000_RCTL_CFI (1 << 20)
#define E1000_RCTL_DPF (1 << 22)
#define E1000_RCTL_PMCF (1 << 23)
#define E1000_RCTL_SECRC (1 << 26)
#define E1000_RCTL_BSIZE_256 (3 << 16)
#define E1000_RCTL_BSIZE_512 (2 << 16)
#define E1000_RCTL_BSIZE_1024 (1 << 16)
#define E1000_RCTL_BSIZE_2048 (0 << 16)
#define E1000_RCTL_BSIZE_4096 ((3 << 16) | (1 << 25))
#define E1000_RCTL_BSIZE_8192 ((2 << 16) | (1 << 25))
#define E1000_RCTL_BSIZE_16384 ((1 << 16) | (1 << 25))
namespace Kernel
{
struct e1000_rx_desc
{
volatile uint64_t addr;
volatile uint16_t length;
volatile uint16_t checksum;
volatile uint8_t status;
volatile uint8_t errors;
volatile uint16_t special;
} __attribute__((packed));
struct e1000_tx_desc
{
volatile uint64_t addr;
volatile uint16_t length;
volatile uint8_t cso;
volatile uint8_t cmd;
volatile uint8_t status;
volatile uint8_t css;
volatile uint16_t special;
} __attribute__((packed));
// https://www.intel.com/content/dam/doc/manual/pci-pci-x-family-gbe-controllers-software-dev-manual.pdf (section 5.2)
bool E1000::probe(PCI::Device& pci_device)
{
// Intel device
if (pci_device.vendor_id() != 0x8086)
return false;
switch (pci_device.device_id())
{
case 0x1019:
case 0x101A:
case 0x1010:
case 0x1012:
case 0x101D:
case 0x1079:
case 0x107A:
case 0x107B:
case 0x100F:
case 0x1011:
case 0x1026:
case 0x1027:
case 0x1028:
case 0x1107:
case 0x1112:
case 0x1013:
case 0x1018:
case 0x1076:
case 0x1077:
case 0x1078:
case 0x1017:
case 0x1016:
case 0x100e:
case 0x1015:
return true;
default:
return false;
}
}
BAN::ErrorOr<BAN::UniqPtr<E1000>> E1000::create(PCI::Device& pci_device)
{
E1000* e1000 = new E1000();
ASSERT(e1000);
if (auto ret = e1000->initialize(pci_device); ret.is_error())
{
delete e1000;
return ret.release_error();
}
return BAN::UniqPtr<E1000>::adopt(e1000);
}
E1000::~E1000()
{
}
BAN::ErrorOr<void> E1000::initialize(PCI::Device& pci_device)
{
m_bar_region = TRY(pci_device.allocate_bar_region(0));
pci_device.enable_bus_mastering();
detect_eeprom();
TRY(read_mac_address());
initialize_rx();
initialize_tx();
enable_link();
enable_interrupts();
#if DEBUG_E1000
dprintln("E1000 at PCI {}:{}.{}", pci_device.bus(), pci_device.dev(), pci_device.func());
dprintln(" MAC: {2H}:{2H}:{2H}:{2H}:{2H}:{2H}",
m_mac_address[0],
m_mac_address[1],
m_mac_address[2],
m_mac_address[3],
m_mac_address[4],
m_mac_address[5]
);
dprintln(" link up: {}", link_up());
if (link_up())
dprintln(" link speed: {} Mbps", link_speed());
#endif
return {};
}
void E1000::write32(uint16_t reg, uint32_t value)
{
m_bar_region->write32(reg, value);
}
uint32_t E1000::read32(uint16_t reg)
{
return m_bar_region->read32(reg);
}
void E1000::detect_eeprom()
{
m_has_eerprom = false;
write32(E1000_REG_EEPROM, 0x01);
for (int i = 0; i < 1000 && !m_has_eerprom; i++)
if (read32(E1000_REG_EEPROM) & 0x10)
m_has_eerprom = true;
}
uint32_t E1000::eeprom_read(uint8_t address)
{
uint32_t tmp = 0;
if (m_has_eerprom)
{
write32(E1000_REG_EEPROM, ((uint32_t)address << 8) | 1);
while (!((tmp = read32(E1000_REG_EEPROM)) & (1 << 4)))
continue;
}
else
{
write32(E1000_REG_EEPROM, ((uint32_t)address << 2) | 1);
while (!((tmp = read32(E1000_REG_EEPROM)) & (1 << 1)))
continue;
}
return (tmp >> 16) & 0xFFFF;
}
BAN::ErrorOr<void> E1000::read_mac_address()
{
if (m_has_eerprom)
{
uint32_t temp = eeprom_read(0);
m_mac_address[0] = temp;
m_mac_address[1] = temp >> 8;
temp = eeprom_read(1);
m_mac_address[2] = temp;
m_mac_address[3] = temp >> 8;
temp = eeprom_read(2);
m_mac_address[4] = temp;
m_mac_address[5] = temp >> 8;
return {};
}
if (read32(0x5400) == 0)
{
dwarnln("no mac address");
return BAN::Error::from_errno(EINVAL);
}
for (int i = 0; i < 6; i++)
m_mac_address[i] = (uint8_t)read32(0x5400 + i * 8);
return {};
}
void E1000::initialize_rx()
{
uint8_t* ptr = (uint8_t*)kmalloc(sizeof(e1000_rx_desc) * E1000_NUM_RX_DESC + 16, 16, true);
ASSERT(ptr);
e1000_rx_desc* descs = (e1000_rx_desc*)ptr;
for (int i = 0; i < E1000_NUM_RX_DESC; i++)
{
// FIXME
m_rx_descs[i] = &descs[i];
m_rx_descs[i]->addr = 0;
m_rx_descs[i]->status = 0;
}
write32(E1000_REG_RXDESCLO, (uintptr_t)ptr >> 32);
write32(E1000_REG_RXDESCHI, (uintptr_t)ptr & 0xFFFFFFFF);
write32(E1000_REG_RXDESCLEN, E1000_NUM_RX_DESC * sizeof(e1000_rx_desc));
write32(E1000_REG_RXDESCHEAD, 0);
write32(E1000_REG_RXDESCTAIL, E1000_NUM_RX_DESC - 1);
m_rx_current = 0;
uint32_t rctrl = 0;
rctrl |= E1000_RCTL_EN;
rctrl |= E1000_RCTL_SBP;
rctrl |= E1000_RCTL_UPE;
rctrl |= E1000_RCTL_MPE;
rctrl |= E1000_RCTL_LBM_NONE;
rctrl |= E1000_RTCL_RDMTS_HALF;
rctrl |= E1000_RCTL_BAM;
rctrl |= E1000_RCTL_SECRC;
rctrl |= E1000_RCTL_BSIZE_8192;
write32(E1000_REG_RCTRL, rctrl);
}
void E1000::initialize_tx()
{
auto* ptr = (uint8_t*)kmalloc(sizeof(e1000_tx_desc) * E1000_NUM_TX_DESC + 16, 16, true);
ASSERT(ptr);
auto* descs = (e1000_tx_desc*)ptr;
for(int i = 0; i < E1000_NUM_TX_DESC; i++)
{
// FIXME
m_tx_descs[i] = &descs[i];
m_tx_descs[i]->addr = 0;
m_tx_descs[i]->cmd = 0;
}
write32(E1000_REG_TXDESCHI, (uintptr_t)ptr >> 32);
write32(E1000_REG_TXDESCLO, (uintptr_t)ptr & 0xFFFFFFFF);
write32(E1000_REG_TXDESCLEN, E1000_NUM_TX_DESC * sizeof(e1000_tx_desc));
write32(E1000_REG_TXDESCHEAD, 0);
write32(E1000_REG_TXDESCTAIL, 0);
m_tx_current = 0;
write32(E1000_REG_TCTRL, read32(E1000_REG_TCTRL) | E1000_TCTL_EN | E1000_TCTL_PSP);
write32(E1000_REG_TIPG, 0x0060200A);
}
void E1000::enable_link()
{
write32(E1000_REG_CTRL, read32(E1000_REG_CTRL) | E1000_CTRL_SET_LINK_UP);
m_link_up = !!(read32(E1000_REG_STATUS) & E1000_STATUS_LINK_UP);
}
int E1000::link_speed()
{
if (!link_up())
return 0;
uint32_t speed = read32(E1000_REG_STATUS) & E1000_STATUS_SPEED_MASK;
if (speed == E1000_STATUS_SPEED_10MB)
return 10;
if (speed == E1000_STATUS_SPEED_100MB)
return 100;
if (speed == E1000_STATUS_SPEED_1000MB1)
return 1000;
if (speed == E1000_STATUS_SPEED_1000MB2)
return 1000;
return 0;
}
void E1000::enable_interrupts()
{
write32(E1000_REG_INT_RATE, 6000);
write32(E1000_REG_INT_MASK_SET, E1000_INT_LSC | E1000_INT_RXT0 | E1000_INT_RXO);
read32(E1000_REG_INT_CAUSE_READ);
// FIXME: implement PCI interrupt allocation
//IDT::register_irq_handler(irq, E1000::interrupt_handler);
//InterruptController::enable_irq(irq);
}
BAN::ErrorOr<void> E1000::send_packet(const void* data, uint16_t len)
{
(void)data;
(void)len;
return BAN::Error::from_errno(ENOTSUP);
}
}

View File

@ -1,305 +0,0 @@
#include <kernel/IDT.h>
#include <kernel/InterruptController.h>
#include <kernel/IO.h>
#include <kernel/Memory/PageTable.h>
#include <kernel/MMIO.h>
#include <kernel/Networking/E1000/E1000.h>
#include <kernel/Networking/NetworkManager.h>
#define DEBUG_E1000 1
namespace Kernel
{
// https://www.intel.com/content/dam/doc/manual/pci-pci-x-family-gbe-controllers-software-dev-manual.pdf (section 5.2)
bool E1000::probe(PCI::Device& pci_device)
{
// Intel device
if (pci_device.vendor_id() != 0x8086)
return false;
switch (pci_device.device_id())
{
case 0x1019:
case 0x101A:
case 0x1010:
case 0x1012:
case 0x101D:
case 0x1079:
case 0x107A:
case 0x107B:
case 0x100F:
case 0x1011:
case 0x1026:
case 0x1027:
case 0x1028:
case 0x1107:
case 0x1112:
case 0x1013:
case 0x1018:
case 0x1076:
case 0x1077:
case 0x1078:
case 0x1017:
case 0x1016:
case 0x100e:
case 0x1015:
return true;
default:
return false;
}
}
BAN::ErrorOr<BAN::RefPtr<E1000>> E1000::create(PCI::Device& pci_device)
{
auto e1000 = TRY(BAN::RefPtr<E1000>::create(pci_device));
TRY(e1000->initialize());
return e1000;
}
E1000::~E1000()
{
}
BAN::ErrorOr<void> E1000::initialize()
{
m_bar_region = TRY(m_pci_device.allocate_bar_region(0));
m_pci_device.enable_bus_mastering();
detect_eeprom();
TRY(read_mac_address());
#if DEBUG_E1000
dprintln("E1000 at PCI {}:{}.{}", m_pci_device.bus(), m_pci_device.dev(), m_pci_device.func());
dprintln(" MAC: {}", m_mac_address);
#endif
TRY(initialize_rx());
TRY(initialize_tx());
enable_link();
TRY(enable_interrupt());
m_link_up = !!(read32(REG_STATUS) & STATUS_LU);
#if DEBUG_E1000
dprintln(" link up: {}", link_up());
if (link_up())
{
int speed = link_speed();
dprintln(" link speed: {} Mbps", speed);
}
#endif
return {};
}
void E1000::write32(uint16_t reg, uint32_t value)
{
m_bar_region->write32(reg, value);
}
uint32_t E1000::read32(uint16_t reg)
{
return m_bar_region->read32(reg);
}
void E1000::detect_eeprom()
{
m_has_eerprom = false;
write32(REG_EERD, 0x01);
for (int i = 0; i < 1000 && !m_has_eerprom; i++)
if (read32(REG_EERD) & 0x10)
m_has_eerprom = true;
}
uint32_t E1000::eeprom_read(uint8_t address)
{
uint32_t tmp = 0;
if (m_has_eerprom)
{
write32(REG_EERD, ((uint32_t)address << 8) | 1);
while (!((tmp = read32(REG_EERD)) & (1 << 4)))
continue;
}
else
{
write32(REG_EERD, ((uint32_t)address << 2) | 1);
while (!((tmp = read32(REG_EERD)) & (1 << 1)))
continue;
}
return (tmp >> 16) & 0xFFFF;
}
BAN::ErrorOr<void> E1000::read_mac_address()
{
if (m_has_eerprom)
{
uint32_t temp = eeprom_read(0);
m_mac_address.address[0] = temp;
m_mac_address.address[1] = temp >> 8;
temp = eeprom_read(1);
m_mac_address.address[2] = temp;
m_mac_address.address[3] = temp >> 8;
temp = eeprom_read(2);
m_mac_address.address[4] = temp;
m_mac_address.address[5] = temp >> 8;
return {};
}
if (read32(0x5400) == 0)
{
dwarnln("no mac address");
return BAN::Error::from_errno(EINVAL);
}
for (int i = 0; i < 6; i++)
m_mac_address.address[i] = (uint8_t)read32(0x5400 + i * 8);
return {};
}
BAN::ErrorOr<void> E1000::initialize_rx()
{
m_rx_buffer_region = TRY(DMARegion::create(E1000_RX_BUFFER_SIZE * E1000_RX_DESCRIPTOR_COUNT));
m_rx_descriptor_region = TRY(DMARegion::create(sizeof(e1000_rx_desc) * E1000_RX_DESCRIPTOR_COUNT));
auto* rx_descriptors = reinterpret_cast<volatile e1000_rx_desc*>(m_rx_descriptor_region->vaddr());
for (size_t i = 0; i < E1000_RX_DESCRIPTOR_COUNT; i++)
{
rx_descriptors[i].addr = m_rx_buffer_region->paddr() + E1000_RX_BUFFER_SIZE * i;
rx_descriptors[i].status = 0;
}
write32(REG_RDBAL0, m_rx_descriptor_region->paddr() & 0xFFFFFFFF);
write32(REG_RDBAH0, m_rx_descriptor_region->paddr() >> 32);
write32(REG_RDLEN0, E1000_RX_DESCRIPTOR_COUNT * sizeof(e1000_rx_desc));
write32(REG_RDH0, 0);
write32(REG_RDT0, E1000_RX_DESCRIPTOR_COUNT - 1);
uint32_t rctrl = 0;
rctrl |= RCTL_EN;
rctrl |= RCTL_SBP;
rctrl |= RCTL_UPE;
rctrl |= RCTL_MPE;
rctrl |= RCTL_LBM_NORMAL;
rctrl |= RCTL_RDMTS_1_2;
rctrl |= RCTL_BAM;
rctrl |= RCTL_SECRC;
rctrl |= RCTL_BSIZE_8192;
write32(REG_RCTL, rctrl);
return {};
}
BAN::ErrorOr<void> E1000::initialize_tx()
{
m_tx_buffer_region = TRY(DMARegion::create(E1000_TX_BUFFER_SIZE * E1000_TX_DESCRIPTOR_COUNT));
m_tx_descriptor_region = TRY(DMARegion::create(sizeof(e1000_tx_desc) * E1000_TX_DESCRIPTOR_COUNT));
auto* tx_descriptors = reinterpret_cast<volatile e1000_tx_desc*>(m_tx_descriptor_region->vaddr());
for (size_t i = 0; i < E1000_TX_DESCRIPTOR_COUNT; i++)
{
tx_descriptors[i].addr = m_tx_buffer_region->paddr() + E1000_TX_BUFFER_SIZE * i;
tx_descriptors[i].cmd = 0;
}
write32(REG_TDBAL, m_tx_descriptor_region->paddr() & 0xFFFFFFFF);
write32(REG_TDBAH, m_tx_descriptor_region->paddr() >> 32);
write32(REG_TDLEN, E1000_TX_DESCRIPTOR_COUNT * sizeof(e1000_tx_desc));
write32(REG_TDH, 0);
write32(REG_TDT, 0);
write32(REG_TCTL, TCTL_EN | TCTL_PSP);
write32(REG_TIPG, 0x0060200A);
return {};
}
void E1000::enable_link()
{
write32(REG_CTRL, read32(REG_CTRL) | CTRL_SLU);
}
int E1000::link_speed()
{
if (!link_up())
return 0;
uint32_t speed = read32(REG_STATUS) & STATUS_SPEED_MASK;
if (speed == STATUS_SPEED_10MB)
return 10;
if (speed == STATUS_SPEED_100MB)
return 100;
if (speed == STATUS_SPEED_1000MB1)
return 1000;
if (speed == STATUS_SPEED_1000MB2)
return 1000;
return 0;
}
BAN::ErrorOr<void> E1000::enable_interrupt()
{
write32(REG_ITR, 0x1000);
write32(REG_IVAR, 1 << 3);
write32(REG_EITR, 0x1000);
write32(REG_IMS, IMC_RxQ0);
read32(REG_ICR);
TRY(m_pci_device.reserve_irqs(1));
set_irq(m_pci_device.get_irq(0));
Interruptable::enable_interrupt();
return {};
}
BAN::ErrorOr<void> E1000::send_raw_bytes(BAN::ConstByteSpan buffer)
{
ASSERT_LTE(buffer.size(), E1000_TX_BUFFER_SIZE);
CriticalScope _;
size_t tx_current = read32(REG_TDT) % E1000_TX_DESCRIPTOR_COUNT;
auto* tx_buffer = reinterpret_cast<void*>(m_tx_buffer_region->vaddr() + E1000_TX_BUFFER_SIZE * tx_current);
memcpy(tx_buffer, buffer.data(), buffer.size());
auto& descriptor = reinterpret_cast<volatile e1000_tx_desc*>(m_tx_descriptor_region->vaddr())[tx_current];
descriptor.length = buffer.size();
descriptor.status = 0;
descriptor.cmd = CMD_EOP | CMD_IFCS | CMD_RS;
write32(REG_TDT, (tx_current + 1) % E1000_TX_DESCRIPTOR_COUNT);
while (descriptor.status == 0)
continue;
return {};
}
void E1000::handle_irq()
{
if (read32(REG_ICR) & ICR_RxQ0)
return;
for (;;) {
uint32_t rx_current = (read32(REG_RDT0) + 1) % E1000_RX_DESCRIPTOR_COUNT;
auto& descriptor = reinterpret_cast<volatile e1000_rx_desc*>(m_rx_descriptor_region->vaddr())[rx_current];
if (!(descriptor.status & 1))
break;
ASSERT_LTE((uint16_t)descriptor.length, E1000_RX_BUFFER_SIZE);
NetworkManager::get().on_receive(BAN::ConstByteSpan {
reinterpret_cast<const uint8_t*>(m_rx_buffer_region->vaddr() + rx_current * E1000_RX_BUFFER_SIZE),
descriptor.length
});
descriptor.status = 0;
write32(REG_RDT0, rx_current);
}
}
}

View File

@ -1,43 +0,0 @@
#include <kernel/Networking/E1000/E1000E.h>
#include <kernel/Timer/Timer.h>
#define E1000E_VENDOR_INTEL 0x8086
#define E1000E_DEVICE_82574 0x10D3
namespace Kernel
{
bool E1000E::probe(PCI::Device& pci_device)
{
if (pci_device.vendor_id() != E1000E_VENDOR_INTEL)
return false;
switch (pci_device.device_id())
{
case E1000E_DEVICE_82574:
return true;
}
return false;
}
BAN::ErrorOr<BAN::RefPtr<E1000E>> E1000E::create(PCI::Device& pci_device)
{
auto e1000e = TRY(BAN::RefPtr<E1000E>::create(pci_device));
TRY(e1000e->initialize());
return e1000e;
}
void E1000E::detect_eeprom()
{
m_has_eerprom = true;
}
uint32_t E1000E::eeprom_read(uint8_t addr)
{
uint32_t tmp;
write32(REG_EERD, ((uint32_t)addr << 2) | 1);
while (!((tmp = read32(REG_EERD)) & (1 << 1)))
continue;
return tmp >> 16;
}
}

View File

@ -1,22 +0,0 @@
#include <BAN/Endianness.h>
#include <kernel/Networking/IPv4.h>
namespace Kernel
{
void add_ipv4_header(BAN::ByteSpan packet, BAN::IPv4Address src_ipv4, BAN::IPv4Address dst_ipv4, uint8_t protocol)
{
auto& header = packet.as<IPv4Header>();
header.version_IHL = 0x45;
header.DSCP_ECN = 0x10;
header.total_length = packet.size();
header.identification = 1;
header.flags_frament = 0x00;
header.time_to_live = 0x40;
header.protocol = protocol;
header.checksum = header.calculate_checksum();
header.src_address = src_ipv4;
header.dst_address = dst_ipv4;
}
}

View File

@ -1,50 +0,0 @@
#include <BAN/Endianness.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/Networking/NetworkInterface.h>
#include <sys/sysmacros.h>
#include <string.h>
namespace Kernel
{
static dev_t get_network_rdev_major()
{
static dev_t major = DevFileSystem::get().get_next_dev();
return major;
}
static dev_t get_network_rdev_minor()
{
static dev_t minor = 0;
return minor++;
}
NetworkInterface::NetworkInterface()
: CharacterDevice(0400, 0, 0)
, m_type(Type::Ethernet)
, m_rdev(makedev(get_network_rdev_major(), get_network_rdev_minor()))
{
ASSERT(minor(m_rdev) < 10);
ASSERT(m_type == Type::Ethernet);
strcpy(m_name, "ethx");
m_name[3] = minor(m_rdev) + '0';
}
size_t NetworkInterface::interface_header_size() const
{
ASSERT(m_type == Type::Ethernet);
return sizeof(EthernetHeader);
}
void NetworkInterface::add_interface_header(BAN::ByteSpan packet, BAN::MACAddress destination)
{
ASSERT(m_type == Type::Ethernet);
auto& header = packet.as<EthernetHeader>();
header.dst_mac = destination;
header.src_mac = get_mac_address();
header.ether_type = 0x0800;
}
}

View File

@ -1,159 +0,0 @@
#include <BAN/Endianness.h>
#include <BAN/UniqPtr.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/Networking/E1000/E1000.h>
#include <kernel/Networking/E1000/E1000E.h>
#include <kernel/Networking/IPv4.h>
#include <kernel/Networking/NetworkManager.h>
#include <kernel/Networking/UDPSocket.h>
namespace Kernel
{
static BAN::UniqPtr<NetworkManager> s_instance;
BAN::ErrorOr<void> NetworkManager::initialize()
{
ASSERT(!s_instance);
NetworkManager* manager_ptr = new NetworkManager();
if (manager_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
auto manager = BAN::UniqPtr<NetworkManager>::adopt(manager_ptr);
manager->m_arp_table = TRY(ARPTable::create());
TRY(manager->TmpFileSystem::initialize(0777, 0, 0));
s_instance = BAN::move(manager);
return {};
}
NetworkManager& NetworkManager::get()
{
ASSERT(s_instance);
return *s_instance;
}
NetworkManager::NetworkManager()
: TmpFileSystem(128)
{ }
BAN::ErrorOr<void> NetworkManager::add_interface(PCI::Device& pci_device)
{
BAN::RefPtr<NetworkInterface> interface;
switch (pci_device.subclass())
{
case 0x00:
if (E1000::probe(pci_device))
{
interface = TRY(E1000::create(pci_device));
break;
}
if (E1000E::probe(pci_device))
{
interface = TRY(E1000E::create(pci_device));
break;
}
// fall through
default:
dprintln("unsupported network controller (pci {2H}.{2H}.{2H})", pci_device.class_code(), pci_device.subclass(), pci_device.prog_if());
dprintln(" vendor id: {4H}", pci_device.vendor_id());
dprintln(" device id: {4H}", pci_device.device_id());
return BAN::Error::from_errno(ENOTSUP);
}
ASSERT(interface);
TRY(m_interfaces.push_back(interface));
DevFileSystem::get().add_device(interface);
return {};
}
BAN::ErrorOr<BAN::RefPtr<NetworkSocket>> NetworkManager::create_socket(SocketType type, mode_t mode, uid_t uid, gid_t gid)
{
ASSERT((mode & Inode::Mode::TYPE_MASK) == 0);
if (type != SocketType::DGRAM)
return BAN::Error::from_errno(EPROTOTYPE);
auto udp_socket = TRY(UDPSocket::create(mode | Inode::Mode::IFSOCK, uid, gid));
return BAN::RefPtr<NetworkSocket>(udp_socket);
}
void NetworkManager::unbind_socket(uint16_t port, BAN::RefPtr<NetworkSocket> socket)
{
if (m_bound_sockets.contains(port))
{
ASSERT(m_bound_sockets[port].valid());
ASSERT(m_bound_sockets[port].lock() == socket);
m_bound_sockets.remove(port);
}
NetworkManager::get().remove_from_cache(socket);
}
BAN::ErrorOr<void> NetworkManager::bind_socket(uint16_t port, BAN::RefPtr<NetworkSocket> socket)
{
if (m_interfaces.empty())
return BAN::Error::from_errno(EADDRNOTAVAIL);
if (port != NetworkSocket::PORT_NONE)
{
if (m_bound_sockets.contains(port))
return BAN::Error::from_errno(EADDRINUSE);
TRY(m_bound_sockets.insert(port, socket));
}
// FIXME: actually determine proper interface
auto interface = m_interfaces.front();
socket->bind_interface_and_port(interface.ptr(), port);
return {};
}
void NetworkManager::on_receive(BAN::ConstByteSpan packet)
{
auto ethernet_header = packet.as<const EthernetHeader>();
switch (ethernet_header.ether_type)
{
case EtherType::ARP:
{
m_arp_table->handle_arp_packet(packet.slice(sizeof(EthernetHeader)));
break;
}
case EtherType::IPv4:
{
auto ipv4 = packet.slice(sizeof(EthernetHeader));
auto& ipv4_header = ipv4.as<const IPv4Header>();
auto src_ipv4 = ipv4_header.src_address;
switch (ipv4_header.protocol)
{
case NetworkProtocol::UDP:
{
auto udp = ipv4.slice(sizeof(IPv4Header));
auto& udp_header = udp.as<const UDPHeader>();
uint16_t src_port = udp_header.src_port;
uint16_t dst_port = udp_header.dst_port;
if (!m_bound_sockets.contains(dst_port))
{
dprintln("no one is listening on port {}", dst_port);
return;
}
auto raw = udp.slice(8);
m_bound_sockets[dst_port].lock()->add_packet(raw, src_ipv4, src_port);
break;
}
default:
dprintln("Unknown network protocol 0x{2H}", ipv4_header.protocol);
break;
}
break;
}
default:
dprintln("Unknown EtherType 0x{4H}", (uint16_t)ethernet_header.ether_type);
break;
}
}
}

View File

@ -1,185 +0,0 @@
#include <kernel/Networking/IPv4.h>
#include <kernel/Networking/NetworkManager.h>
#include <kernel/Networking/NetworkSocket.h>
#include <net/if.h>
namespace Kernel
{
NetworkSocket::NetworkSocket(mode_t mode, uid_t uid, gid_t gid)
// FIXME: what the fuck is this
: TmpInode(
NetworkManager::get(),
MUST(NetworkManager::get().allocate_inode(create_inode_info(mode, uid, gid))),
create_inode_info(mode, uid, gid)
)
{ }
NetworkSocket::~NetworkSocket()
{
}
void NetworkSocket::on_close_impl()
{
if (m_interface)
NetworkManager::get().unbind_socket(m_port, this);
}
void NetworkSocket::bind_interface_and_port(NetworkInterface* interface, uint16_t port)
{
ASSERT(!m_interface);
ASSERT(interface);
m_interface = interface;
m_port = port;
}
BAN::ErrorOr<void> NetworkSocket::bind_impl(const sockaddr* address, socklen_t address_len)
{
if (address_len != sizeof(sockaddr_in))
return BAN::Error::from_errno(EINVAL);
auto* addr_in = reinterpret_cast<const sockaddr_in*>(address);
return NetworkManager::get().bind_socket(addr_in->sin_port, this);
}
BAN::ErrorOr<ssize_t> NetworkSocket::sendto_impl(const sys_sendto_t* arguments)
{
if (arguments->dest_len != sizeof(sockaddr_in))
return BAN::Error::from_errno(EINVAL);
if (arguments->flags)
{
dprintln("flags not supported");
return BAN::Error::from_errno(ENOTSUP);
}
if (!m_interface)
TRY(NetworkManager::get().bind_socket(PORT_NONE, this));
auto* destination = reinterpret_cast<const sockaddr_in*>(arguments->dest_addr);
auto message = BAN::ConstByteSpan((const uint8_t*)arguments->message, arguments->length);
uint16_t dst_port = destination->sin_port;
if (dst_port == PORT_NONE)
return BAN::Error::from_errno(EINVAL);
auto dst_addr = BAN::IPv4Address(destination->sin_addr.s_addr);
auto dst_mac = TRY(NetworkManager::get().arp_table().get_mac_from_ipv4(*m_interface, dst_addr));
const size_t interface_header_offset = 0;
const size_t interface_header_size = m_interface->interface_header_size();
const size_t ipv4_header_offset = interface_header_offset + interface_header_size;
const size_t ipv4_header_size = sizeof(IPv4Header);
const size_t protocol_header_offset = ipv4_header_offset + ipv4_header_size;
const size_t protocol_header_size = this->protocol_header_size();
const size_t payload_offset = protocol_header_offset + protocol_header_size;
const size_t payload_size = message.size();
BAN::Vector<uint8_t> full_packet;
TRY(full_packet.resize(payload_offset + payload_size));
BAN::ByteSpan packet_bytespan { full_packet.span() };
memcpy(full_packet.data() + payload_offset, message.data(), payload_size);
add_protocol_header(packet_bytespan.slice(protocol_header_offset), m_port, dst_port);
add_ipv4_header(packet_bytespan.slice(ipv4_header_offset), m_interface->get_ipv4_address(), dst_addr, protocol());
m_interface->add_interface_header(packet_bytespan.slice(interface_header_offset), dst_mac);
TRY(m_interface->send_raw_bytes(packet_bytespan));
return arguments->length;
}
BAN::ErrorOr<ssize_t> NetworkSocket::recvfrom_impl(sys_recvfrom_t* arguments)
{
sockaddr_in* sender_addr = nullptr;
if (arguments->address)
{
ASSERT(arguments->address_len);
if (*arguments->address_len < (socklen_t)sizeof(sockaddr_in))
*arguments->address_len = 0;
else
{
sender_addr = reinterpret_cast<sockaddr_in*>(arguments->address);
*arguments->address_len = sizeof(sockaddr_in);
}
}
if (!m_interface)
{
dprintln("No interface bound");
return BAN::Error::from_errno(EINVAL);
}
if (m_port == PORT_NONE)
{
dprintln("No port bound");
return BAN::Error::from_errno(EINVAL);
}
return TRY(read_packet(BAN::ByteSpan { reinterpret_cast<uint8_t*>(arguments->buffer), arguments->length }, sender_addr));
}
BAN::ErrorOr<long> NetworkSocket::ioctl_impl(int request, void* arg)
{
if (!arg)
{
dprintln("No argument provided");
return BAN::Error::from_errno(EINVAL);
}
if (m_interface == nullptr)
{
dprintln("No interface bound");
return BAN::Error::from_errno(EADDRNOTAVAIL);
}
auto* ifreq = reinterpret_cast<struct ifreq*>(arg);
switch (request)
{
case SIOCGIFADDR:
{
auto ipv4_address = m_interface->get_ipv4_address();
ifreq->ifr_ifru.ifru_addr.sa_family = AF_INET;
memcpy(ifreq->ifr_ifru.ifru_addr.sa_data, &ipv4_address, sizeof(ipv4_address));
return 0;
}
case SIOCSIFADDR:
{
if (ifreq->ifr_ifru.ifru_addr.sa_family != AF_INET)
return BAN::Error::from_errno(EADDRNOTAVAIL);
BAN::IPv4Address ipv4_address { *reinterpret_cast<uint32_t*>(ifreq->ifr_ifru.ifru_addr.sa_data) };
m_interface->set_ipv4_address(ipv4_address);
dprintln("IPv4 address set to {}", m_interface->get_ipv4_address());
return 0;
}
case SIOCGIFNETMASK:
{
auto netmask_address = m_interface->get_netmask();
ifreq->ifr_ifru.ifru_netmask.sa_family = AF_INET;
memcpy(ifreq->ifr_ifru.ifru_netmask.sa_data, &netmask_address, sizeof(netmask_address));
return 0;
}
case SIOCSIFNETMASK:
{
if (ifreq->ifr_ifru.ifru_netmask.sa_family != AF_INET)
return BAN::Error::from_errno(EADDRNOTAVAIL);
BAN::IPv4Address netmask { *reinterpret_cast<uint32_t*>(ifreq->ifr_ifru.ifru_netmask.sa_data) };
m_interface->set_netmask(netmask);
dprintln("Netmask set to {}", m_interface->get_netmask());
return 0;
}
case SIOCGIFHWADDR:
{
auto mac_address = m_interface->get_mac_address();
ifreq->ifr_ifru.ifru_hwaddr.sa_family = AF_INET;
memcpy(ifreq->ifr_ifru.ifru_hwaddr.sa_data, &mac_address, sizeof(mac_address));
return 0;
}
default:
return BAN::Error::from_errno(EINVAL);
}
}
}

View File

@ -1,101 +0,0 @@
#include <kernel/Memory/Heap.h>
#include <kernel/Networking/UDPSocket.h>
#include <kernel/Thread.h>
namespace Kernel
{
BAN::ErrorOr<BAN::RefPtr<UDPSocket>> UDPSocket::create(mode_t mode, uid_t uid, gid_t gid)
{
auto socket = TRY(BAN::RefPtr<UDPSocket>::create(mode, uid, gid));
socket->m_packet_buffer = TRY(VirtualRange::create_to_vaddr_range(
PageTable::kernel(),
KERNEL_OFFSET,
~(uintptr_t)0,
packet_buffer_size,
PageTable::Flags::ReadWrite | PageTable::Flags::Present,
true
));
return socket;
}
UDPSocket::UDPSocket(mode_t mode, uid_t uid, gid_t gid)
: NetworkSocket(mode, uid, gid)
{ }
void UDPSocket::add_protocol_header(BAN::ByteSpan packet, uint16_t src_port, uint16_t dst_port)
{
auto& header = packet.as<UDPHeader>();
header.src_port = src_port;
header.dst_port = dst_port;
header.length = packet.size();
header.checksum = 0;
}
void UDPSocket::add_packet(BAN::ConstByteSpan packet, BAN::IPv4Address sender_addr, uint16_t sender_port)
{
CriticalScope _;
if (m_packets.full())
{
dprintln("Packet buffer full, dropping packet");
return;
}
if (!m_packets.empty() && m_packet_total_size > m_packet_buffer->size())
{
dprintln("Packet buffer full, dropping packet");
return;
}
void* buffer = reinterpret_cast<void*>(m_packet_buffer->vaddr() + m_packet_total_size);
memcpy(buffer, packet.data(), packet.size());
m_packets.push(PacketInfo {
.sender_addr = sender_addr,
.sender_port = sender_port,
.packet_size = packet.size()
});
m_packet_total_size += packet.size();
m_semaphore.unblock();
}
BAN::ErrorOr<size_t> UDPSocket::read_packet(BAN::ByteSpan buffer, sockaddr_in* sender_addr)
{
while (m_packets.empty())
TRY(Thread::current().block_or_eintr(m_semaphore));
CriticalScope _;
if (m_packets.empty())
return read_packet(buffer, sender_addr);
auto packet_info = m_packets.front();
m_packets.pop();
size_t nread = BAN::Math::min<size_t>(packet_info.packet_size, buffer.size());
memcpy(
buffer.data(),
(const void*)m_packet_buffer->vaddr(),
nread
);
memmove(
(void*)m_packet_buffer->vaddr(),
(void*)(m_packet_buffer->vaddr() + packet_info.packet_size),
m_packet_total_size - packet_info.packet_size
);
m_packet_total_size -= packet_info.packet_size;
if (sender_addr)
{
sender_addr->sin_family = AF_INET;
sender_addr->sin_port = packet_info.sender_port;
sender_addr->sin_addr.s_addr = packet_info.sender_addr.as_u32();
}
return nread;
}
}

View File

@ -1,10 +1,8 @@
#include <kernel/FS/Pipe.h>
#include <kernel/FS/VirtualFileSystem.h>
#include <kernel/Networking/NetworkManager.h>
#include <kernel/OpenFileDescriptorSet.h>
#include <fcntl.h>
#include <sys/socket.h>
namespace Kernel
{
@ -78,38 +76,6 @@ namespace Kernel
return fd;
}
BAN::ErrorOr<int> OpenFileDescriptorSet::socket(int domain, int type, int protocol)
{
using SocketType = NetworkManager::SocketType;
if (domain != AF_INET)
return BAN::Error::from_errno(EAFNOSUPPORT);
if (protocol != 0)
return BAN::Error::from_errno(EPROTONOSUPPORT);
SocketType sock_type;
switch (type)
{
case SOCK_STREAM:
sock_type = SocketType::STREAM;
break;
case SOCK_DGRAM:
sock_type = SocketType::DGRAM;
break;
case SOCK_SEQPACKET:
sock_type = SocketType::SEQPACKET;
break;
default:
return BAN::Error::from_errno(EPROTOTYPE);
}
auto socket = TRY(NetworkManager::get().create_socket(sock_type, 0777, m_credentials.euid(), m_credentials.egid()));
int fd = TRY(get_free_fd());
m_open_files[fd] = TRY(BAN::RefPtr<OpenFileDescription>::create(socket, "no-path"sv, 0, O_RDWR));
return fd;
}
BAN::ErrorOr<void> OpenFileDescriptorSet::pipe(int fds[2])
{
TRY(get_free_fd_pair(fds));
@ -276,8 +242,6 @@ namespace Kernel
if (m_open_files[fd]->flags & O_WRONLY && m_open_files[fd]->inode->is_pipe())
((Pipe*)m_open_files[fd]->inode.ptr())->close_writing();
m_open_files[fd]->inode->on_close();
m_open_files[fd].clear();
return {};

View File

@ -2,7 +2,7 @@
#include <kernel/IO.h>
#include <kernel/Memory/PageTable.h>
#include <kernel/MMIO.h>
#include <kernel/Networking/NetworkManager.h>
#include <kernel/Networking/E1000.h>
#include <kernel/PCI.h>
#include <kernel/Storage/ATA/AHCI/Controller.h>
#include <kernel/Storage/ATA/ATAController.h>
@ -183,8 +183,17 @@ namespace Kernel::PCI
}
case 0x02:
{
if (auto res = NetworkManager::get().add_interface(pci_device); res.is_error())
dprintln("{}", res.error());
switch (pci_device.subclass())
{
case 0x00:
if (E1000::probe(pci_device))
if (auto res = E1000::create(pci_device); res.is_error())
dprintln("E1000: {}", res.error());
break;
default:
dprintln("unsupported ethernet device (pci {2H}.{2H}.{2H})", pci_device.class_code(), pci_device.subclass(), pci_device.prog_if());
break;
}
break;
}
default:
@ -250,7 +259,7 @@ namespace Kernel::PCI
device.write_word(PCI_REG_COMMAND, command);
#if DEBUG_PCI
dprintln("created BAR region for PCI {2H}:{2H}.{2H}",
dprintln("created BAR region for PCI {}:{}.{}",
device.bus(),
device.dev(),
device.func()
@ -484,12 +493,12 @@ namespace Kernel::PCI
return {};
}
static constexpr uint64_t msi_message_address()
static uint64_t msi_message_address()
{
return 0xFEE00000;
}
static constexpr uint32_t msi_message_data(uint8_t irq)
static uint32_t msi_message_data(uint8_t irq)
{
return (IRQ_VECTOR_BASE + irq) & 0xFF;
}

View File

@ -895,70 +895,6 @@ namespace Kernel
return 0;
}
BAN::ErrorOr<long> Process::sys_socket(int domain, int type, int protocol)
{
LockGuard _(m_lock);
return TRY(m_open_file_descriptors.socket(domain, type, protocol));
}
BAN::ErrorOr<long> Process::sys_bind(int socket, const sockaddr* address, socklen_t address_len)
{
LockGuard _(m_lock);
TRY(validate_pointer_access(address, address_len));
auto inode = TRY(m_open_file_descriptors.inode_of(socket));
if (!inode->mode().ifsock())
return BAN::Error::from_errno(ENOTSOCK);
TRY(inode->bind(address, address_len));
return 0;
}
BAN::ErrorOr<long> Process::sys_sendto(const sys_sendto_t* arguments)
{
LockGuard _(m_lock);
TRY(validate_pointer_access(arguments, sizeof(sys_sendto_t)));
TRY(validate_pointer_access(arguments->message, arguments->length));
TRY(validate_pointer_access(arguments->dest_addr, arguments->dest_len));
auto inode = TRY(m_open_file_descriptors.inode_of(arguments->socket));
if (!inode->mode().ifsock())
return BAN::Error::from_errno(ENOTSOCK);
return TRY(inode->sendto(arguments));
}
BAN::ErrorOr<long> Process::sys_recvfrom(sys_recvfrom_t* arguments)
{
if (arguments->address && !arguments->address_len)
return BAN::Error::from_errno(EINVAL);
if (!arguments->address && arguments->address_len)
return BAN::Error::from_errno(EINVAL);
LockGuard _(m_lock);
TRY(validate_pointer_access(arguments, sizeof(sys_recvfrom_t)));
TRY(validate_pointer_access(arguments->buffer, arguments->length));
if (arguments->address)
{
TRY(validate_pointer_access(arguments->address_len, sizeof(*arguments->address_len)));
TRY(validate_pointer_access(arguments->address, *arguments->address_len));
}
auto inode = TRY(m_open_file_descriptors.inode_of(arguments->socket));
if (!inode->mode().ifsock())
return BAN::Error::from_errno(ENOTSOCK);
return TRY(inode->recvfrom(arguments));
}
BAN::ErrorOr<long> Process::sys_ioctl(int fildes, int request, void* arg)
{
LockGuard _(m_lock);
auto inode = TRY(m_open_file_descriptors.inode_of(fildes));
return TRY(inode->ioctl(request, arg));
}
BAN::ErrorOr<long> Process::sys_pipe(int fildes[2])
{
LockGuard _(m_lock);

View File

@ -5,7 +5,7 @@
#include <kernel/InterruptController.h>
#include <kernel/Process.h>
#include <kernel/Scheduler.h>
#include <kernel/Timer/Timer.h>
#include <kernel/Timer/PIT.h>
#define SCHEDULER_VERIFY_STACK 1
#define SCHEDULER_VERIFY_INTERRUPT_STATE 1
@ -116,11 +116,12 @@ namespace Kernel
uint64_t current_time = SystemTimer::get().ms_since_boot();
while (!m_sleeping_threads.empty() && m_sleeping_threads.front().wake_time <= current_time)
{
m_sleeping_threads.move_element_to_other_linked_list(
m_active_threads,
m_active_threads.end(),
m_sleeping_threads.begin()
);
Thread* thread = m_sleeping_threads.front().thread;
m_sleeping_threads.remove(m_sleeping_threads.begin());
// This should work as we released enough memory from sleeping thread
static_assert(sizeof(ActiveThread) == sizeof(SleepingThread));
MUST(m_active_threads.emplace_back(thread));
}
}
@ -285,26 +286,23 @@ namespace Kernel
ASSERT(m_current_thread);
Thread* sleeping = m_current_thread->thread;
if (save_current_thread())
{
ENABLE_INTERRUPTS();
return;
}
remove_and_advance_current_thread();
auto it = m_sleeping_threads.begin();
for (; it != m_sleeping_threads.end(); it++)
if (wake_time <= it->wake_time)
break;
m_current_thread->wake_time = wake_time;
m_active_threads.move_element_to_other_linked_list(
m_sleeping_threads,
it,
m_current_thread
);
m_current_thread = {};
advance_current_thread();
// This should work as we released enough memory from active thread
static_assert(sizeof(ActiveThread) == sizeof(SleepingThread));
MUST(m_sleeping_threads.emplace(it, sleeping, wake_time));
execute_current_thread();
ASSERT_NOT_REACHED();
@ -317,21 +315,18 @@ namespace Kernel
ASSERT(m_current_thread);
Thread* blocking = m_current_thread->thread;
if (save_current_thread())
{
ENABLE_INTERRUPTS();
return;
}
remove_and_advance_current_thread();
m_current_thread->semaphore = semaphore;
m_active_threads.move_element_to_other_linked_list(
m_blocking_threads,
m_blocking_threads.end(),
m_current_thread
);
m_current_thread = {};
advance_current_thread();
// This should work as we released enough memory from active thread
static_assert(sizeof(ActiveThread) == sizeof(BlockingThread));
MUST(m_blocking_threads.emplace_back(blocking, semaphore));
execute_current_thread();
ASSERT_NOT_REACHED();
@ -345,11 +340,12 @@ namespace Kernel
{
if (it->semaphore == semaphore)
{
it = m_blocking_threads.move_element_to_other_linked_list(
m_active_threads,
m_active_threads.end(),
it
);
auto thread = it->thread;
it = m_blocking_threads.remove(it);
// This should work as we released enough memory from active thread
static_assert(sizeof(ActiveThread) == sizeof(BlockingThread));
MUST(m_active_threads.emplace_back(thread));
}
else
{
@ -366,11 +362,13 @@ namespace Kernel
{
if (it->thread->tid() == tid)
{
m_blocking_threads.move_element_to_other_linked_list(
m_active_threads,
m_active_threads.end(),
it
);
Thread* thread = it->thread;
m_blocking_threads.remove(it);
// This should work as we released enough memory from active thread
static_assert(sizeof(ActiveThread) == sizeof(BlockingThread));
MUST(m_active_threads.emplace_back(thread));
return;
}
}
@ -379,11 +377,13 @@ namespace Kernel
{
if (it->thread->tid() == tid)
{
m_sleeping_threads.move_element_to_other_linked_list(
m_active_threads,
m_active_threads.end(),
it
);
Thread* thread = it->thread;
m_sleeping_threads.remove(it);
// This should work as we released enough memory from active thread
static_assert(sizeof(ActiveThread) == sizeof(BlockingThread));
MUST(m_active_threads.emplace_back(thread));
return;
}
}

View File

@ -213,21 +213,6 @@ namespace Kernel
case SYS_LOAD_KEYMAP:
ret = Process::current().sys_load_keymap((const char*)arg1);
break;
case SYS_SOCKET:
ret = Process::current().sys_socket((int)arg1, (int)arg2, (int)arg3);
break;
case SYS_BIND:
ret = Process::current().sys_bind((int)arg1, (const sockaddr*)arg2, (socklen_t)arg3);
break;
case SYS_SENDTO:
ret = Process::current().sys_sendto((const sys_sendto_t*)arg1);
break;
case SYS_RECVFROM:
ret = Process::current().sys_recvfrom((sys_recvfrom_t*)arg1);
break;
case SYS_IOCTL:
ret = Process::current().sys_ioctl((int)arg1, (int)arg2, (void*)arg3);
break;
default:
dwarnln("Unknown syscall {}", syscall);
break;

View File

@ -15,7 +15,6 @@
#include <kernel/Memory/Heap.h>
#include <kernel/Memory/kmalloc.h>
#include <kernel/Memory/PageTable.h>
#include <kernel/Networking/NetworkManager.h>
#include <kernel/PCI.h>
#include <kernel/PIC.h>
#include <kernel/Process.h>
@ -188,8 +187,6 @@ static void init2(void*)
if (auto res = PS2Controller::initialize(); res.is_error())
dprintln("{}", res.error());
MUST(NetworkManager::initialize());
// NOTE: PCI devices are the last ones to be initialized
// so other devices can reserve predefined interrupts
PCI::PCIManager::initialize();

View File

@ -17,10 +17,8 @@ set(LIBC_SOURCES
stdlib.cpp
string.cpp
strings.cpp
stropts.cpp
sys/banan-os.cpp
sys/mman.cpp
sys/socket.cpp
sys/stat.cpp
sys/wait.cpp
termios.cpp

View File

@ -5,8 +5,6 @@
#include <sys/cdefs.h>
#include <sys/socket.h>
#define IF_NAMESIZE 16
__BEGIN_DECLS
@ -17,22 +15,6 @@ struct if_nameindex
char* if_name; /* Null-terminated name of the interface. */
};
struct ifreq
{
union {
struct sockaddr ifru_addr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
unsigned char __min_storage[sizeof(sockaddr) + 6];
} ifr_ifru;
};
#define SIOCGIFADDR 1 /* Get interface address */
#define SIOCSIFADDR 2 /* Set interface address */
#define SIOCGIFNETMASK 3 /* Get network mask */
#define SIOCSIFNETMASK 4 /* Set network mask */
#define SIOCGIFHWADDR 5 /* Get hardware address */
void if_freenameindex(struct if_nameindex* ptr);
char* if_indextoname(unsigned ifindex, char* ifname);
struct if_nameindex* if_nameindex(void);

View File

@ -1,153 +0,0 @@
#ifndef _STROPTS_H
#define _STROPTS_H 1
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stropts.h.html
#include <sys/cdefs.h>
__BEGIN_DECLS
#define __need_uid_t
#define __need_gid_t
#include <sys/types.h>
typedef __UINT32_TYPE__ t_uscalar_t;
typedef __INT32_TYPE__ t_scalar_t;
struct bandinfo
{
int bi_flag; /* Flushing type. */
unsigned char bi_pri; /* Priority band. */
};
struct strbuf
{
char* buf; /* Pointer to buffer. */
int len; /* Length of data. */
int maxlen; /* Maximum buffer length. */
};
struct strpeek
{
struct strbuf ctlbuf; /* The control portion of the message. */
struct strbuf databuf; /* The data portion of the message. */
t_uscalar_t flags; /* RS_HIPRI or 0. */
};
struct strfdinsert
{
struct strbuf ctlbuf; /* The control portion of the message. */
struct strbuf databuf; /* The data portion of the message. */
int fildes; /* File descriptor of the other STREAM. */
t_uscalar_t flags; /* RS_HIPRI or 0. */
int offset; /* Relative location of the stored value. */
};
struct strioctl
{
int ic_cmd; /* ioctl() command. */
char* ic_dp; /* Pointer to buffer. */
int ic_len; /* Length of data. */
int ic_timout; /* Timeout for response. */
};
struct strrecvfd
{
int fd; /* Received file descriptor. */
gid_t gid; /* GID of sender. */
uid_t uid; /* UID of sender. */
};
#define FMNAMESZ 128
struct str_mlist
{
char l_name[FMNAMESZ+1]; /* A STREAMS module name. */
};
struct str_list
{
struct str_mlist* sl_modlist; /* STREAMS module names. */
int sl_nmods; /* Number of STREAMS module names. */
};
#define I_ATMARK 1
#define I_CANPUT 2
#define I_CKBAND 3
#define I_FDINSERT 4
#define I_FIND 5
#define I_FLUSH 6
#define I_FLUSHBAND 7
#define I_GETBAND 8
#define I_GETCLTIME 9
#define I_GETSIG 10
#define I_GRDOPT 11
#define I_GWROPT 12
#define I_LINK 13
#define I_LIST 14
#define I_LOOK 15
#define I_NREAD 16
#define I_PEEK 17
#define I_PLINK 18
#define I_POP 19
#define I_PUNLINK 20
#define I_PUSH 21
#define I_RECVFD 22
#define I_SENDFD 23
#define I_SETCLTIME 24
#define I_SETSIG 25
#define I_SRDOPT 26
#define I_STR 27
#define I_SWROPT 28
#define I_UNLINK 29
#define FLUSHR 1
#define FLUSHRW 2
#define FLUSHW 3
#define S_BANDURG 1
#define S_ERROR 2
#define S_HANGUP 3
#define S_HIPRI 4
#define S_INPUT 5
#define S_MSG 6
#define S_OUTPUT 7
#define S_RDBAND 8
#define S_RDNORM 9
#define S_WRBAND 10
#define S_WRNORM 11
#define RS_HIPRI 1
#define RMSGD 1
#define RMSGN 2
#define RNORM 3
#define RPROTDAT 4
#define RPROTDIS 5
#define RPROTNORM 6
#define SNDZERO 1
#define ANYMARK 1
#define LASTMARK 2
#define MUXID_ALL 1
#define MORECTL 1
#define MOREDATA 2
#define MSG_ANY 3
#define MSG_BAND 4
#define MSG_HIPRI 5
int fattach(int, const char*);
int fdetach(const char*);
int getmsg(int, struct strbuf* __restrict, struct strbuf* __restrict, int* __restrict);
int getpmsg(int, struct strbuf* __restrict, struct strbuf* __restrict, int* __restrict, int* __restrict);
int ioctl(int, int, ...);
int isastream(int);
int putmsg(int, const struct strbuf*, const struct strbuf*, int);
int putpmsg(int, const struct strbuf*, const struct strbuf*, int, int);
__END_DECLS
#endif

View File

@ -105,26 +105,6 @@ struct linger
#define SHUT_WR 0x02
#define SHUT_RDWR (SHUT_RD | SHUT_WR)
struct sys_sendto_t
{
int socket;
const void* message;
size_t length;
int flags;
const struct sockaddr* dest_addr;
socklen_t dest_len;
};
struct sys_recvfrom_t
{
int socket;
void* buffer;
size_t length;
int flags;
struct sockaddr* address;
socklen_t* address_len;
};
int accept(int socket, struct sockaddr* __restrict address, socklen_t* __restrict address_len);
int bind(int socket, const struct sockaddr* address, socklen_t address_len);
int connect(int socket, const struct sockaddr* address, socklen_t address_len);

View File

@ -63,11 +63,6 @@ __BEGIN_DECLS
#define SYS_PREAD 62
#define SYS_CHOWN 63
#define SYS_LOAD_KEYMAP 64
#define SYS_SOCKET 65
#define SYS_BIND 66
#define SYS_SENDTO 67
#define SYS_RECVFROM 68
#define SYS_IOCTL 69
__END_DECLS

View File

@ -1,14 +0,0 @@
#include <stdarg.h>
#include <stropts.h>
#include <sys/syscall.h>
#include <unistd.h>
int ioctl(int fildes, int request, ...)
{
va_list args;
va_start(args, request);
void* extra = va_arg(args, void*);
va_end(args);
return syscall(SYS_IOCTL, fildes, request, extra);
}

View File

@ -1,40 +0,0 @@
#include <sys/socket.h>
#include <sys/syscall.h>
#include <unistd.h>
int bind(int socket, const struct sockaddr* address, socklen_t address_len)
{
return syscall(SYS_BIND, socket, address, address_len);
}
ssize_t recvfrom(int socket, void* __restrict buffer, size_t length, int flags, struct sockaddr* __restrict address, socklen_t* __restrict address_len)
{
sys_recvfrom_t arguments {
.socket = socket,
.buffer = buffer,
.length = length,
.flags = flags,
.address = address,
.address_len = address_len
};
return syscall(SYS_RECVFROM, &arguments);
}
ssize_t sendto(int socket, const void* message, size_t length, int flags, const struct sockaddr* dest_addr, socklen_t dest_len)
{
sys_sendto_t arguments {
.socket = socket,
.message = message,
.length = length,
.flags = flags,
.dest_addr = dest_addr,
.dest_len = dest_len
};
return syscall(SYS_SENDTO, &arguments);
}
int socket(int domain, int type, int protocol)
{
return syscall(SYS_SOCKET, domain, type, protocol);
}

View File

@ -20,11 +20,9 @@ else
fi
qemu-system-$BANAN_ARCH \
-m 1G \
-m 128 \
-smp 2 \
$BIOS_ARGS \
-drive format=raw,id=disk,file=${BANAN_DISK_IMAGE_PATH},if=none \
-device e1000e,netdev=net \
-netdev user,id=net \
$DISK_ARGS \
$@ \

View File

@ -8,7 +8,6 @@ set(USERSPACE_PROJECTS
chmod
cp
dd
dhcp-client
echo
id
init

View File

@ -1,16 +0,0 @@
cmake_minimum_required(VERSION 3.26)
project(dhcp-client CXX)
set(SOURCES
main.cpp
)
add_executable(dhcp-client ${SOURCES})
target_compile_options(dhcp-client PUBLIC -O2 -g)
target_link_libraries(dhcp-client PUBLIC libc)
add_custom_target(dhcp-client-install
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/dhcp-client ${BANAN_BIN}/
DEPENDS dhcp-client
)

View File

@ -1,380 +0,0 @@
#include <BAN/Endianness.h>
#include <BAN/IPv4.h>
#include <BAN/MAC.h>
#include <BAN/Vector.h>
#include <fcntl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stropts.h>
#include <sys/socket.h>
#define DEBUG_DHCP 0
struct DHCPPacket
{
uint8_t op;
uint8_t htype { 0x01 };
uint8_t hlen { 0x06 };
uint8_t hops { 0x00 };
BAN::NetworkEndian<uint32_t> xid { 0x3903F326 };
BAN::NetworkEndian<uint16_t> secs { 0x0000 };
BAN::NetworkEndian<uint16_t> flags { 0x0000 };
BAN::NetworkEndian<uint32_t> ciaddr { 0 };
BAN::NetworkEndian<uint32_t> yiaddr { 0 };
BAN::NetworkEndian<uint32_t> siaddr { 0 };
BAN::NetworkEndian<uint32_t> giaddr { 0 };
BAN::MACAddress chaddr;
uint8_t padding[10] {};
uint8_t legacy[192] {};
BAN::NetworkEndian<uint32_t> magic_cookie { 0x63825363 };
uint8_t options[0x100];
};
static_assert(offsetof(DHCPPacket, options) == 240);
enum DHCPType
{
SubnetMask = 1,
Router = 3,
DomainNameServer = 6,
RequestedIPv4Address= 50,
DHCPMessageType = 53,
ServerIdentifier = 54,
ParameterRequestList = 55,
End = 255,
};
enum DHCPMessageType
{
INVALID = 0,
DHCPDISCOVER = 1,
DHCPOFFER = 2,
DHCPREQUEST = 3,
DHCPDECLINE = 4,
DHCPACK = 5,
};
BAN::MACAddress get_mac_address(int socket)
{
ifreq ifreq;
if (ioctl(socket, SIOCGIFHWADDR, &ifreq) == -1)
{
perror("ioctl");
exit(1);
}
BAN::MACAddress mac_address;
memcpy(&mac_address, ifreq.ifr_ifru.ifru_hwaddr.sa_data, sizeof(mac_address));
return mac_address;
}
void update_ipv4_info(int socket, BAN::IPv4Address address, BAN::IPv4Address subnet)
{
{
ifreq ifreq;
ifreq.ifr_ifru.ifru_addr.sa_family = AF_INET;
*(uint32_t*)ifreq.ifr_ifru.ifru_addr.sa_data = address.as_u32();
if (ioctl(socket, SIOCSIFADDR, &ifreq) == -1)
{
perror("ioctl");
exit(1);
}
}
{
ifreq ifreq;
ifreq.ifr_ifru.ifru_netmask.sa_family = AF_INET;
*(uint32_t*)ifreq.ifr_ifru.ifru_netmask.sa_data = subnet.as_u32();
if (ioctl(socket, SIOCSIFNETMASK, &ifreq) == -1)
{
perror("ioctl");
exit(1);
}
}
}
void send_dhcp_packet(int socket, const DHCPPacket& dhcp_packet, BAN::IPv4Address server_ipv4)
{
sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = 67;
server_addr.sin_addr.s_addr = server_ipv4.as_u32();;
if (sendto(socket, &dhcp_packet, sizeof(DHCPPacket), 0, (sockaddr*)&server_addr, sizeof(server_addr)) == -1)
{
perror("sendto");
exit(1);
}
}
void send_dhcp_discover(int socket, BAN::MACAddress mac_address)
{
DHCPPacket dhcp_packet;
dhcp_packet.op = 0x01;
dhcp_packet.chaddr = mac_address;
size_t idx = 0;
dhcp_packet.options[idx++] = DHCPMessageType;
dhcp_packet.options[idx++] = 0x01;
dhcp_packet.options[idx++] = DHCPDISCOVER;
dhcp_packet.options[idx++] = ParameterRequestList;
dhcp_packet.options[idx++] = 0x03;
dhcp_packet.options[idx++] = DomainNameServer;
dhcp_packet.options[idx++] = SubnetMask;
dhcp_packet.options[idx++] = Router;
dhcp_packet.options[idx++] = 0xFF;
send_dhcp_packet(socket, dhcp_packet, BAN::IPv4Address { 0xFFFFFFFF });
}
void send_dhcp_request(int socket, BAN::MACAddress mac_address, BAN::IPv4Address offered_ipv4, BAN::IPv4Address server_ipv4)
{
DHCPPacket dhcp_packet;
dhcp_packet.op = 0x01;
dhcp_packet.siaddr = server_ipv4.as_u32();
dhcp_packet.chaddr = mac_address;
size_t idx = 0;
dhcp_packet.options[idx++] = DHCPMessageType;
dhcp_packet.options[idx++] = 0x01;
dhcp_packet.options[idx++] = DHCPREQUEST;
dhcp_packet.options[idx++] = RequestedIPv4Address;
dhcp_packet.options[idx++] = 0x04;
dhcp_packet.options[idx++] = offered_ipv4.address[0];
dhcp_packet.options[idx++] = offered_ipv4.address[1];
dhcp_packet.options[idx++] = offered_ipv4.address[2];
dhcp_packet.options[idx++] = offered_ipv4.address[3];
dhcp_packet.options[idx++] = 0xFF;
send_dhcp_packet(socket, dhcp_packet, BAN::IPv4Address { 0xFFFFFFFF });
}
struct DHCPPacketInfo
{
enum DHCPMessageType message_type { INVALID };
BAN::IPv4Address address { 0 };
BAN::IPv4Address subnet { 0 };
BAN::IPv4Address server { 0 };
BAN::Vector<BAN::IPv4Address> routers;
BAN::Vector<BAN::IPv4Address> dns;
};
DHCPPacketInfo parse_dhcp_packet(const DHCPPacket& packet)
{
DHCPPacketInfo packet_info;
packet_info.address = BAN::IPv4Address(packet.yiaddr);
const uint8_t* options = packet.options;
while (*options != End)
{
uint8_t type = *options++;
uint8_t length = *options++;
switch (type)
{
case SubnetMask:
{
if (length != 4)
{
fprintf(stderr, "Subnet mask with invalid length %hhu\n", length);
break;
}
uint32_t raw = *reinterpret_cast<const BAN::NetworkEndian<uint32_t>*>(options);
packet_info.subnet = BAN::IPv4Address(raw);
break;
}
case Router:
{
if (length % 4 != 0)
{
fprintf(stderr, "Router with invalid length %hhu\n", length);
break;
}
for (int i = 0; i < length; i += 4)
{
uint32_t raw = *reinterpret_cast<const BAN::NetworkEndian<uint32_t>*>(options + i);
MUST(packet_info.routers.emplace_back(raw));
}
break;
}
case DomainNameServer:
{
if (length % 4 != 0)
{
fprintf(stderr, "DNS with invalid length %hhu\n", length);
break;
}
for (int i = 0; i < length; i += 4)
{
uint32_t raw = *reinterpret_cast<const BAN::NetworkEndian<uint32_t>*>(options + i);
MUST(packet_info.dns.emplace_back(raw));
}
break;
}
case DHCPMessageType:
{
if (length != 1)
{
fprintf(stderr, "DHCP Message Type with invalid length %hhu\n", length);
break;
}
switch (*options)
{
case DHCPDISCOVER: packet_info.message_type = DHCPDISCOVER; break;
case DHCPOFFER: packet_info.message_type = DHCPOFFER; break;
case DHCPREQUEST: packet_info.message_type = DHCPREQUEST; break;
case DHCPDECLINE: packet_info.message_type = DHCPDECLINE; break;
case DHCPACK: packet_info.message_type = DHCPACK; break;
}
break;
}
case ServerIdentifier:
{
if (length != 4)
{
fprintf(stderr, "Server identifier with invalid length %hhu\n", length);
break;
}
uint32_t raw = *reinterpret_cast<const BAN::NetworkEndian<uint32_t>*>(options);
packet_info.server = BAN::IPv4Address(raw);
break;
}
}
options += length;
}
return packet_info;
}
BAN::Optional<DHCPPacketInfo> read_dhcp_packet(int socket)
{
DHCPPacket dhcp_packet;
ssize_t nrecv = recvfrom(socket, &dhcp_packet, sizeof(dhcp_packet), 0, nullptr, nullptr);
if (nrecv == -1)
{
perror("revcfrom");
return {};
}
if (nrecv <= (ssize_t)offsetof(DHCPPacket, options))
{
fprintf(stderr, "invalid DHCP offer\n");
return {};
}
if (dhcp_packet.magic_cookie != 0x63825363)
{
fprintf(stderr, "invalid DHCP offer\n");
return {};
}
return parse_dhcp_packet(dhcp_packet);
}
int main()
{
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
if (socket == -1)
{
perror("socket");
return 1;
}
sockaddr_in client_addr;
client_addr.sin_family = AF_INET;
client_addr.sin_port = 68;
client_addr.sin_addr.s_addr = 0x00000000;
if (bind(socket, (sockaddr*)&client_addr, sizeof(client_addr)) == -1)
{
perror("bind");
return 1;
}
auto mac_address = get_mac_address(socket);
#if DEBUG_DHCP
BAN::Formatter::println(putchar, "MAC: {}", mac_address);
#endif
send_dhcp_discover(socket, mac_address);
#if DEBUG_DHCP
printf("DHCPDISCOVER sent\n");
#endif
auto dhcp_offer = read_dhcp_packet(socket);
if (!dhcp_offer.has_value())
return 1;
if (dhcp_offer->message_type != DHCPOFFER)
{
fprintf(stderr, "DHCP server did not respond with DHCPOFFER\n");
return 1;
}
#if DEBUG_DHCP
BAN::Formatter::println(putchar, "DHCPOFFER");
BAN::Formatter::println(putchar, " IP {}", dhcp_offer->address);
BAN::Formatter::println(putchar, " SUBNET {}", dhcp_offer->subnet);
BAN::Formatter::println(putchar, " SERVER {}", dhcp_offer->server);
#endif
send_dhcp_request(socket, mac_address, dhcp_offer->address, dhcp_offer->server);
#if DEBUG_DHCP
printf("DHCPREQUEST sent\n");
#endif
auto dhcp_ack = read_dhcp_packet(socket);
if (!dhcp_ack.has_value())
return 1;
if (dhcp_ack->message_type != DHCPACK)
{
fprintf(stderr, "DHCP server did not respond with DHCPACK\n");
return 1;
}
#if DEBUG_DHCP
BAN::Formatter::println(putchar, "DHCPACK");
BAN::Formatter::println(putchar, " IP {}", dhcp_ack->address);
BAN::Formatter::println(putchar, " SUBNET {}", dhcp_ack->subnet);
BAN::Formatter::println(putchar, " SERVER {}", dhcp_ack->server);
#endif
if (dhcp_offer->address != dhcp_ack->address)
{
fprintf(stderr, "DHCP server OFFER and ACK ips don't match\n");
return 1;
}
update_ipv4_info(socket, dhcp_ack->address, dhcp_ack->subnet);
if (true)
{
uint32_t packet = 0x12345678;
sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = 67;
server_addr.sin_addr.s_addr = dhcp_ack->routers.front().as_u32();
server_addr.sin_addr.s_addr = (192 << 24) | (168 << 16) | (1 << 8) | 203;
if (sendto(socket, &packet, sizeof(packet), 0, (sockaddr*)&server_addr, sizeof(server_addr)) == -1)
{
perror("sendto");
exit(1);
}
}
close(socket);
return 0;
}

View File

@ -29,12 +29,6 @@ int main()
if (load_keymap("/usr/share/keymaps/fi.keymap") == -1)
perror("load_keymap");
if (fork() == 0)
{
execl("/bin/dhcp-client", "dhcp-client", NULL);
exit(1);
}
bool first = true;
termios termios;

View File

@ -16,37 +16,26 @@ bool is_sorted(BAN::Vector<T>& vec)
#define CURRENT_NS() ({ timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); ts.tv_sec * 1'000'000'000 + ts.tv_nsec; })
#define TEST_ALGORITHM(ms, function) do { \
uint64_t duration_us = 0; \
printf(#function "\n"); \
for (size_t size = 100; duration_us < ms * 1000; size *= 10) { \
BAN::Vector<unsigned> data(size, 0); \
for (auto& val : data) \
val = rand() % 100; \
uint64_t start_ns = CURRENT_NS(); \
(void)function(data.begin(), data.end()); \
uint64_t stop_ns = CURRENT_NS(); \
if (!is_sorted(data)) { \
printf(" \e[31mFAILED!\e[m\n"); \
break; \
} \
duration_us = (stop_ns - start_ns) / 1'000; \
printf(" %5d.%03d ms (%zu)\n", \
(int)(duration_us / 1000), \
(int)(duration_us % 1000), \
size \
); \
} \
#define TEST(name, function, count) do { \
BAN::Vector<int> ivec(count, 0); \
for (int& i : ivec) \
i = rand() % 100; \
uint64_t start_ns = CURRENT_NS(); \
function(ivec.begin(), ivec.end()); \
uint64_t end_ns = CURRENT_NS(); \
uint64_t dur_us = (end_ns - start_ns) / 1000; \
printf(name " (" #count "): %s\n", is_sorted(ivec) ? "success" : "fail"); \
printf(" took %" PRIu64 ".%03" PRIu64 " ms\n", dur_us / 1000, dur_us % 1000); \
} while (0)
int main()
{
srand(time(0));
TEST_ALGORITHM(100, BAN::sort::exchange_sort);
TEST_ALGORITHM(100, BAN::sort::quick_sort);
TEST_ALGORITHM(100, BAN::sort::insertion_sort);
TEST_ALGORITHM(100, BAN::sort::heap_sort);
TEST_ALGORITHM(100, BAN::sort::intro_sort);
TEST_ALGORITHM(1000, BAN::sort::sort);
TEST_ALGORITHM(1000, BAN::sort::radix_sort);
TEST("exchange sort", BAN::sort::exchange_sort, 100);
TEST("exchange sort", BAN::sort::exchange_sort, 1000);
TEST("exchange sort", BAN::sort::exchange_sort, 10000);
TEST("quick sort", BAN::sort::quick_sort, 100);
TEST("quick sort", BAN::sort::quick_sort, 1000);
TEST("quick sort", BAN::sort::quick_sort, 10000);
}