mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-28 21:54:40 +03:00
Kernel: Introduce the NetworkingManagement singleton
Instead of initializing network adapters in init.cpp, let's move that logic into a separate class to handle this. Also, it seems like a good idea to shift responsiblity on enumeration of network adapters after the boot process, so this singleton will take care of finding the appropriate network adapter when asked to with an IPv4 address or interface name. With this change being merged, we simplify the creation logic of NetworkAdapter derived classes, so we enumerate the PCI bus only once, searching for driver candidates when doing so, and we let each driver to test if it is resposible for the specified PCI device.
This commit is contained in:
parent
8b1d4d1b8e
commit
1c94b5e8eb
Notes:
sideshowbarker
2024-07-18 12:32:39 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/1c94b5e8eb9 Pull-request: https://github.com/SerenityOS/serenity/pull/7762 Reviewed-by: https://github.com/alimpfard ✅
@ -121,6 +121,7 @@ set(KERNEL_SOURCES
|
||||
Net/LoopbackAdapter.cpp
|
||||
Net/NE2000NetworkAdapter.cpp
|
||||
Net/NetworkAdapter.cpp
|
||||
Net/NetworkingManagement.cpp
|
||||
Net/NetworkTask.cpp
|
||||
Net/RTL8139NetworkAdapter.cpp
|
||||
Net/Routing.cpp
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <Kernel/Module.h>
|
||||
#include <Kernel/Net/LocalSocket.h>
|
||||
#include <Kernel/Net/NetworkAdapter.h>
|
||||
#include <Kernel/Net/NetworkingManagement.h>
|
||||
#include <Kernel/Net/Routing.h>
|
||||
#include <Kernel/Net/TCPSocket.h>
|
||||
#include <Kernel/Net/UDPSocket.h>
|
||||
@ -477,7 +478,7 @@ static bool procfs$pid_perf_events(InodeIdentifier identifier, KBufferBuilder& b
|
||||
static bool procfs$net_adapters(InodeIdentifier, KBufferBuilder& builder)
|
||||
{
|
||||
JsonArraySerializer array { builder };
|
||||
NetworkAdapter::for_each([&array](auto& adapter) {
|
||||
NetworkingManagement::the().for_each([&array](auto& adapter) {
|
||||
auto obj = array.add_object();
|
||||
obj.add("name", adapter.name());
|
||||
obj.add("class_name", adapter.class_name());
|
||||
|
@ -156,18 +156,15 @@ UNMAP_AFTER_INIT static bool is_valid_device_id(u16 device_id)
|
||||
}
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT void E1000NetworkAdapter::detect()
|
||||
UNMAP_AFTER_INIT RefPtr<E1000NetworkAdapter> E1000NetworkAdapter::try_to_initialize(PCI::Address address)
|
||||
{
|
||||
PCI::enumerate([&](const PCI::Address& address, PCI::ID id) {
|
||||
if (address.is_null())
|
||||
return;
|
||||
if (id.vendor_id != (u16)PCIVendorID::Intel)
|
||||
return;
|
||||
if (!is_valid_device_id(id.device_id))
|
||||
return;
|
||||
u8 irq = PCI::get_interrupt_line(address);
|
||||
[[maybe_unused]] auto& unused = adopt_ref(*new E1000NetworkAdapter(address, irq)).leak_ref();
|
||||
});
|
||||
auto id = PCI::get_id(address);
|
||||
if (id.vendor_id != (u16)PCIVendorID::Intel)
|
||||
return {};
|
||||
if (!is_valid_device_id(id.device_id))
|
||||
return {};
|
||||
u8 irq = PCI::get_interrupt_line(address);
|
||||
return adopt_ref_if_nonnull(new E1000NetworkAdapter(address, irq));
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT E1000NetworkAdapter::E1000NetworkAdapter(PCI::Address address, u8 irq)
|
||||
|
@ -20,9 +20,8 @@ namespace Kernel {
|
||||
class E1000NetworkAdapter final : public NetworkAdapter
|
||||
, public PCI::Device {
|
||||
public:
|
||||
static void detect();
|
||||
static RefPtr<E1000NetworkAdapter> try_to_initialize(PCI::Address);
|
||||
|
||||
E1000NetworkAdapter(PCI::Address, u8 irq);
|
||||
virtual ~E1000NetworkAdapter() override;
|
||||
|
||||
virtual void send_raw(ReadonlyBytes) override;
|
||||
@ -31,6 +30,7 @@ public:
|
||||
virtual const char* purpose() const override { return class_name(); }
|
||||
|
||||
private:
|
||||
E1000NetworkAdapter(PCI::Address, u8 irq);
|
||||
virtual void handle_irq(const RegisterState&) override;
|
||||
virtual const char* class_name() const override { return "E1000NetworkAdapter"; }
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <Kernel/Net/IPv4.h>
|
||||
#include <Kernel/Net/IPv4Socket.h>
|
||||
#include <Kernel/Net/NetworkAdapter.h>
|
||||
#include <Kernel/Net/NetworkingManagement.h>
|
||||
#include <Kernel/Net/Routing.h>
|
||||
#include <Kernel/Net/TCP.h>
|
||||
#include <Kernel/Net/TCPSocket.h>
|
||||
@ -582,7 +583,7 @@ int IPv4Socket::ioctl(FileDescription&, unsigned request, FlatPtr arg)
|
||||
if (copied_ifname.is_null())
|
||||
return -EFAULT;
|
||||
|
||||
auto adapter = NetworkAdapter::lookup_by_name(copied_ifname);
|
||||
auto adapter = NetworkingManagement::the().lookup_by_name(copied_ifname);
|
||||
if (!adapter)
|
||||
return -ENODEV;
|
||||
|
||||
@ -615,7 +616,7 @@ int IPv4Socket::ioctl(FileDescription&, unsigned request, FlatPtr arg)
|
||||
memcpy(namebuf, ifr.ifr_name, IFNAMSIZ);
|
||||
namebuf[sizeof(namebuf) - 1] = '\0';
|
||||
|
||||
auto adapter = NetworkAdapter::lookup_by_name(namebuf);
|
||||
auto adapter = NetworkingManagement::the().lookup_by_name(namebuf);
|
||||
if (!adapter)
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -9,15 +9,17 @@
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
static AK::Singleton<LoopbackAdapter> s_loopback;
|
||||
static bool s_loopback_initialized = false;
|
||||
|
||||
LoopbackAdapter& LoopbackAdapter::the()
|
||||
NonnullRefPtr<LoopbackAdapter> LoopbackAdapter::create()
|
||||
{
|
||||
return *s_loopback;
|
||||
return adopt_ref(*new LoopbackAdapter());
|
||||
}
|
||||
|
||||
LoopbackAdapter::LoopbackAdapter()
|
||||
{
|
||||
VERIFY(!s_loopback_initialized);
|
||||
s_loopback_initialized = true;
|
||||
set_loopback_name();
|
||||
set_mtu(65536);
|
||||
set_mac_address({ 19, 85, 2, 9, 0x55, 0xaa });
|
||||
|
@ -12,10 +12,12 @@ namespace Kernel {
|
||||
|
||||
class LoopbackAdapter final : public NetworkAdapter {
|
||||
AK_MAKE_ETERNAL
|
||||
public:
|
||||
LoopbackAdapter();
|
||||
static LoopbackAdapter& the();
|
||||
|
||||
private:
|
||||
LoopbackAdapter();
|
||||
|
||||
public:
|
||||
static NonnullRefPtr<LoopbackAdapter> create();
|
||||
virtual ~LoopbackAdapter() override;
|
||||
|
||||
virtual void send_raw(ReadonlyBytes) override;
|
||||
|
@ -135,7 +135,7 @@ struct [[gnu::packed]] received_packet_header {
|
||||
u16 length;
|
||||
};
|
||||
|
||||
UNMAP_AFTER_INIT void NE2000NetworkAdapter::detect()
|
||||
UNMAP_AFTER_INIT RefPtr<NE2000NetworkAdapter> NE2000NetworkAdapter::try_to_initialize(PCI::Address address)
|
||||
{
|
||||
constexpr auto ne2k_ids = Array {
|
||||
PCI::ID { 0x10EC, 0x8029 }, // RealTek RTL-8029(AS)
|
||||
@ -152,14 +152,11 @@ UNMAP_AFTER_INIT void NE2000NetworkAdapter::detect()
|
||||
PCI::ID { 0x12c3, 0x5598 }, // Holtek HT80229
|
||||
PCI::ID { 0x8c4a, 0x1980 }, // Winbond W89C940 (misprogrammed)
|
||||
};
|
||||
PCI::enumerate([&](const PCI::Address& address, PCI::ID id) {
|
||||
if (address.is_null())
|
||||
return;
|
||||
if (!ne2k_ids.span().contains_slow(id))
|
||||
return;
|
||||
u8 irq = PCI::get_interrupt_line(address);
|
||||
[[maybe_unused]] auto& unused = adopt_ref(*new NE2000NetworkAdapter(address, irq)).leak_ref();
|
||||
});
|
||||
auto id = PCI::get_id(address);
|
||||
if (!ne2k_ids.span().contains_slow(id))
|
||||
return {};
|
||||
u8 irq = PCI::get_interrupt_line(address);
|
||||
return adopt_ref_if_nonnull(new NE2000NetworkAdapter(address, irq));
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT NE2000NetworkAdapter::NE2000NetworkAdapter(PCI::Address address, u8 irq)
|
||||
|
@ -18,9 +18,8 @@ namespace Kernel {
|
||||
class NE2000NetworkAdapter final : public NetworkAdapter
|
||||
, public PCI::Device {
|
||||
public:
|
||||
static void detect();
|
||||
static RefPtr<NE2000NetworkAdapter> try_to_initialize(PCI::Address);
|
||||
|
||||
NE2000NetworkAdapter(PCI::Address, u8 irq);
|
||||
virtual ~NE2000NetworkAdapter() override;
|
||||
|
||||
virtual void send_raw(ReadonlyBytes) override;
|
||||
@ -29,6 +28,7 @@ public:
|
||||
virtual const char* purpose() const override { return class_name(); }
|
||||
|
||||
private:
|
||||
NE2000NetworkAdapter(PCI::Address, u8 irq);
|
||||
virtual void handle_irq(const RegisterState&) override;
|
||||
virtual const char* class_name() const override { return "NE2000NetworkAdapter"; }
|
||||
|
||||
|
@ -12,53 +12,19 @@
|
||||
#include <Kernel/Net/EtherType.h>
|
||||
#include <Kernel/Net/LoopbackAdapter.h>
|
||||
#include <Kernel/Net/NetworkAdapter.h>
|
||||
#include <Kernel/Net/NetworkingManagement.h>
|
||||
#include <Kernel/Process.h>
|
||||
#include <Kernel/Random.h>
|
||||
#include <Kernel/StdLib.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
static AK::Singleton<Lockable<HashTable<NetworkAdapter*>>> s_table;
|
||||
|
||||
Lockable<HashTable<NetworkAdapter*>>& NetworkAdapter::all_adapters()
|
||||
{
|
||||
return *s_table;
|
||||
}
|
||||
|
||||
RefPtr<NetworkAdapter> NetworkAdapter::from_ipv4_address(const IPv4Address& address)
|
||||
{
|
||||
Locker locker(all_adapters().lock());
|
||||
for (auto* adapter : all_adapters().resource()) {
|
||||
if (adapter->ipv4_address() == address || adapter->ipv4_broadcast() == address)
|
||||
return adapter;
|
||||
}
|
||||
if (address[0] == 0 && address[1] == 0 && address[2] == 0 && address[3] == 0)
|
||||
return LoopbackAdapter::the();
|
||||
if (address[0] == 127)
|
||||
return LoopbackAdapter::the();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<NetworkAdapter> NetworkAdapter::lookup_by_name(const StringView& name)
|
||||
{
|
||||
NetworkAdapter* found_adapter = nullptr;
|
||||
for_each([&](auto& adapter) {
|
||||
if (adapter.name() == name)
|
||||
found_adapter = &adapter;
|
||||
});
|
||||
return found_adapter;
|
||||
}
|
||||
|
||||
NetworkAdapter::NetworkAdapter()
|
||||
{
|
||||
// FIXME: I wanna lock :(
|
||||
all_adapters().resource().set(this);
|
||||
}
|
||||
|
||||
NetworkAdapter::~NetworkAdapter()
|
||||
{
|
||||
// FIXME: I wanna lock :(
|
||||
all_adapters().resource().remove(this);
|
||||
}
|
||||
|
||||
void NetworkAdapter::send_packet(ReadonlyBytes packet)
|
||||
@ -199,14 +165,14 @@ void NetworkAdapter::set_interface_name(const PCI::Address& pci_address)
|
||||
{
|
||||
// Note: This stands for e - "Ethernet", p - "Port" as for PCI bus, "s" for slot as for PCI slot
|
||||
auto name = String::formatted("ep{}s{}", pci_address.bus(), pci_address.device());
|
||||
VERIFY(!lookup_by_name(name));
|
||||
VERIFY(!NetworkingManagement::the().lookup_by_name(name));
|
||||
m_name = move(name);
|
||||
}
|
||||
|
||||
void NetworkAdapter::set_loopback_name()
|
||||
{
|
||||
auto name = String("loop");
|
||||
VERIFY(!lookup_by_name(name));
|
||||
VERIFY(!NetworkingManagement::the().lookup_by_name(name));
|
||||
m_name = move(name);
|
||||
}
|
||||
}
|
||||
|
@ -42,16 +42,6 @@ struct PacketWithTimestamp : public RefCounted<PacketWithTimestamp> {
|
||||
class NetworkAdapter : public RefCounted<NetworkAdapter>
|
||||
, public Weakable<NetworkAdapter> {
|
||||
public:
|
||||
template<typename Callback>
|
||||
static inline void for_each(Callback callback)
|
||||
{
|
||||
Locker locker(all_adapters().lock());
|
||||
for (auto& it : all_adapters().resource())
|
||||
callback(*it);
|
||||
}
|
||||
|
||||
static RefPtr<NetworkAdapter> from_ipv4_address(const IPv4Address&);
|
||||
static RefPtr<NetworkAdapter> lookup_by_name(const StringView&);
|
||||
virtual ~NetworkAdapter();
|
||||
|
||||
virtual const char* class_name() const = 0;
|
||||
@ -103,8 +93,6 @@ protected:
|
||||
void set_loopback_name();
|
||||
|
||||
private:
|
||||
static Lockable<HashTable<NetworkAdapter*>>& all_adapters();
|
||||
|
||||
MACAddress m_mac_address;
|
||||
IPv4Address m_ipv4_address;
|
||||
IPv4Address m_ipv4_netmask;
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <Kernel/Net/IPv4Socket.h>
|
||||
#include <Kernel/Net/LoopbackAdapter.h>
|
||||
#include <Kernel/Net/NetworkTask.h>
|
||||
#include <Kernel/Net/NetworkingManagement.h>
|
||||
#include <Kernel/Net/Routing.h>
|
||||
#include <Kernel/Net/TCP.h>
|
||||
#include <Kernel/Net/TCPSocket.h>
|
||||
@ -55,7 +56,7 @@ void NetworkTask_main(void*)
|
||||
|
||||
WaitQueue packet_wait_queue;
|
||||
int pending_packets = 0;
|
||||
NetworkAdapter::for_each([&](auto& adapter) {
|
||||
NetworkingManagement::the().for_each([&](auto& adapter) {
|
||||
dmesgln("NetworkTask: {} network adapter found: hw={}", adapter.class_name(), adapter.mac_address().to_string());
|
||||
|
||||
if (String(adapter.class_name()) == "LoopbackAdapter") {
|
||||
@ -74,7 +75,7 @@ void NetworkTask_main(void*)
|
||||
if (pending_packets == 0)
|
||||
return 0;
|
||||
size_t packet_size = 0;
|
||||
NetworkAdapter::for_each([&](auto& adapter) {
|
||||
NetworkingManagement::the().for_each([&](auto& adapter) {
|
||||
if (packet_size || !adapter.has_queued_packets())
|
||||
return;
|
||||
packet_size = adapter.dequeue_packet(buffer, buffer_size, packet_timestamp);
|
||||
@ -155,7 +156,7 @@ void handle_arp(const EthernetFrameHeader& eth, size_t frame_size)
|
||||
|
||||
if (packet.operation() == ARPOperation::Request) {
|
||||
// Who has this IP address?
|
||||
if (auto adapter = NetworkAdapter::from_ipv4_address(packet.target_protocol_address())) {
|
||||
if (auto adapter = NetworkingManagement::the().from_ipv4_address(packet.target_protocol_address())) {
|
||||
// We do!
|
||||
dbgln("handle_arp: Responding to ARP request for my IPv4 address ({})", adapter->ipv4_address());
|
||||
ARPPacket response;
|
||||
@ -193,7 +194,7 @@ void handle_ipv4(const EthernetFrameHeader& eth, size_t frame_size, const Time&
|
||||
|
||||
dbgln_if(IPV4_DEBUG, "handle_ipv4: source={}, destination={}", packet.source(), packet.destination());
|
||||
|
||||
NetworkAdapter::for_each([&](auto& adapter) {
|
||||
NetworkingManagement::the().for_each([&](auto& adapter) {
|
||||
if (adapter.link_up()) {
|
||||
auto my_net = adapter.ipv4_address().to_u32() & adapter.ipv4_netmask().to_u32();
|
||||
auto their_net = packet.source().to_u32() & adapter.ipv4_netmask().to_u32();
|
||||
@ -234,7 +235,7 @@ void handle_icmp(const EthernetFrameHeader& eth, const IPv4Packet& ipv4_packet,
|
||||
socket.did_receive(ipv4_packet.source(), 0, { &ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size() }, packet_timestamp);
|
||||
}
|
||||
|
||||
auto adapter = NetworkAdapter::from_ipv4_address(ipv4_packet.destination());
|
||||
auto adapter = NetworkingManagement::the().from_ipv4_address(ipv4_packet.destination());
|
||||
if (!adapter)
|
||||
return;
|
||||
|
||||
@ -292,7 +293,7 @@ void handle_udp(const IPv4Packet& ipv4_packet, const Time& packet_timestamp)
|
||||
|
||||
auto& destination = ipv4_packet.destination();
|
||||
|
||||
if (destination == IPv4Address(255, 255, 255, 255) || NetworkAdapter::from_ipv4_address(destination) || socket->multicast_memberships().contains_slow(destination))
|
||||
if (destination == IPv4Address(255, 255, 255, 255) || NetworkingManagement::the().from_ipv4_address(destination) || socket->multicast_memberships().contains_slow(destination))
|
||||
socket->did_receive(ipv4_packet.source(), udp_packet.source_port(), { &ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size() }, packet_timestamp);
|
||||
}
|
||||
|
||||
@ -365,7 +366,7 @@ void handle_tcp(const IPv4Packet& ipv4_packet, const Time& packet_timestamp)
|
||||
tcp_packet.window_size(),
|
||||
payload_size);
|
||||
|
||||
auto adapter = NetworkAdapter::from_ipv4_address(ipv4_packet.destination());
|
||||
auto adapter = NetworkingManagement::the().from_ipv4_address(ipv4_packet.destination());
|
||||
if (!adapter) {
|
||||
dbgln("handle_tcp: this packet is not for me, it's for {}", ipv4_packet.destination());
|
||||
return;
|
||||
|
101
Kernel/Net/NetworkingManagement.cpp
Normal file
101
Kernel/Net/NetworkingManagement.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/Checked.h>
|
||||
#include <AK/Singleton.h>
|
||||
#include <Kernel/CommandLine.h>
|
||||
#include <Kernel/Debug.h>
|
||||
#include <Kernel/IO.h>
|
||||
#include <Kernel/Multiboot.h>
|
||||
#include <Kernel/Net/E1000NetworkAdapter.h>
|
||||
#include <Kernel/Net/LoopbackAdapter.h>
|
||||
#include <Kernel/Net/NE2000NetworkAdapter.h>
|
||||
#include <Kernel/Net/NetworkingManagement.h>
|
||||
#include <Kernel/Net/RTL8139NetworkAdapter.h>
|
||||
#include <Kernel/Panic.h>
|
||||
#include <Kernel/VM/AnonymousVMObject.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
static AK::Singleton<NetworkingManagement> s_the;
|
||||
|
||||
NetworkingManagement& NetworkingManagement::the()
|
||||
{
|
||||
return *s_the;
|
||||
}
|
||||
|
||||
bool NetworkingManagement::is_initialized()
|
||||
{
|
||||
return s_the.is_initialized();
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT NetworkingManagement::NetworkingManagement()
|
||||
{
|
||||
}
|
||||
|
||||
NonnullRefPtr<NetworkAdapter> NetworkingManagement::loopback_adapter() const
|
||||
{
|
||||
return *m_loopback_adapter;
|
||||
}
|
||||
|
||||
void NetworkingManagement::for_each(Function<void(NetworkAdapter&)> callback)
|
||||
{
|
||||
Locker locker(m_lock);
|
||||
for (auto& it : m_adapters)
|
||||
callback(it);
|
||||
}
|
||||
|
||||
RefPtr<NetworkAdapter> NetworkingManagement::from_ipv4_address(const IPv4Address& address) const
|
||||
{
|
||||
Locker locker(m_lock);
|
||||
for (auto& adapter : m_adapters) {
|
||||
if (adapter.ipv4_address() == address || adapter.ipv4_broadcast() == address)
|
||||
return adapter;
|
||||
}
|
||||
if (address[0] == 0 && address[1] == 0 && address[2] == 0 && address[3] == 0)
|
||||
return m_loopback_adapter;
|
||||
if (address[0] == 127)
|
||||
return m_loopback_adapter;
|
||||
return {};
|
||||
}
|
||||
RefPtr<NetworkAdapter> NetworkingManagement::lookup_by_name(const StringView& name) const
|
||||
{
|
||||
Locker locker(m_lock);
|
||||
RefPtr<NetworkAdapter> found_adapter;
|
||||
for (auto& it : m_adapters) {
|
||||
if (it.name() == name)
|
||||
found_adapter = it;
|
||||
}
|
||||
return found_adapter;
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT RefPtr<NetworkAdapter> NetworkingManagement::determine_network_device(PCI::Address address) const
|
||||
{
|
||||
if (auto candidate = E1000NetworkAdapter::try_to_initialize(address); !candidate.is_null())
|
||||
return candidate;
|
||||
if (auto candidate = RTL8139NetworkAdapter::try_to_initialize(address); !candidate.is_null())
|
||||
return candidate;
|
||||
if (auto candidate = NE2000NetworkAdapter::try_to_initialize(address); !candidate.is_null())
|
||||
return candidate;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool NetworkingManagement::initialize()
|
||||
{
|
||||
PCI::enumerate([&](const PCI::Address& address, PCI::ID) {
|
||||
// Note: PCI class 2 is the class of Network devices
|
||||
if (PCI::get_class(address) != 0x02)
|
||||
return;
|
||||
if (auto adapter = determine_network_device(address); !adapter.is_null())
|
||||
m_adapters.append(adapter.release_nonnull());
|
||||
});
|
||||
auto loopback = LoopbackAdapter::create();
|
||||
m_adapters.append(loopback);
|
||||
m_loopback_adapter = loopback;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
46
Kernel/Net/NetworkingManagement.h
Normal file
46
Kernel/Net/NetworkingManagement.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Function.h>
|
||||
#include <AK/NonnullOwnPtr.h>
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <AK/NonnullRefPtrVector.h>
|
||||
#include <AK/Types.h>
|
||||
#include <Kernel/PCI/Definitions.h>
|
||||
#include <Kernel/VM/Region.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class NetworkAdapter;
|
||||
class NetworkingManagement {
|
||||
friend class NetworkAdapter;
|
||||
AK_MAKE_ETERNAL
|
||||
|
||||
public:
|
||||
static NetworkingManagement& the();
|
||||
static bool is_initialized();
|
||||
bool initialize();
|
||||
|
||||
NetworkingManagement();
|
||||
|
||||
void for_each(Function<void(NetworkAdapter&)>);
|
||||
|
||||
RefPtr<NetworkAdapter> from_ipv4_address(const IPv4Address&) const;
|
||||
RefPtr<NetworkAdapter> lookup_by_name(const StringView&) const;
|
||||
|
||||
NonnullRefPtr<NetworkAdapter> loopback_adapter() const;
|
||||
|
||||
private:
|
||||
RefPtr<NetworkAdapter> determine_network_device(PCI::Address address) const;
|
||||
|
||||
NonnullRefPtrVector<NetworkAdapter> m_adapters;
|
||||
RefPtr<NetworkAdapter> m_loopback_adapter;
|
||||
mutable Lock m_lock { "Networking" };
|
||||
};
|
||||
|
||||
}
|
@ -105,17 +105,14 @@ namespace Kernel {
|
||||
#define RX_BUFFER_SIZE 32768
|
||||
#define TX_BUFFER_SIZE PACKET_SIZE_MAX
|
||||
|
||||
UNMAP_AFTER_INIT void RTL8139NetworkAdapter::detect()
|
||||
UNMAP_AFTER_INIT RefPtr<RTL8139NetworkAdapter> RTL8139NetworkAdapter::try_to_initialize(PCI::Address address)
|
||||
{
|
||||
constexpr PCI::ID rtl8139_id = { 0x10EC, 0x8139 };
|
||||
PCI::enumerate([&](const PCI::Address& address, PCI::ID id) {
|
||||
if (address.is_null())
|
||||
return;
|
||||
if (id != rtl8139_id)
|
||||
return;
|
||||
u8 irq = PCI::get_interrupt_line(address);
|
||||
[[maybe_unused]] auto& unused = adopt_ref(*new RTL8139NetworkAdapter(address, irq)).leak_ref();
|
||||
});
|
||||
auto id = PCI::get_id(address);
|
||||
if (id != rtl8139_id)
|
||||
return {};
|
||||
u8 irq = PCI::get_interrupt_line(address);
|
||||
return adopt_ref_if_nonnull(new RTL8139NetworkAdapter(address, irq));
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT RTL8139NetworkAdapter::RTL8139NetworkAdapter(PCI::Address address, u8 irq)
|
||||
|
@ -20,9 +20,8 @@ namespace Kernel {
|
||||
class RTL8139NetworkAdapter final : public NetworkAdapter
|
||||
, public PCI::Device {
|
||||
public:
|
||||
static void detect();
|
||||
static RefPtr<RTL8139NetworkAdapter> try_to_initialize(PCI::Address);
|
||||
|
||||
RTL8139NetworkAdapter(PCI::Address, u8 irq);
|
||||
virtual ~RTL8139NetworkAdapter() override;
|
||||
|
||||
virtual void send_raw(ReadonlyBytes) override;
|
||||
@ -31,6 +30,7 @@ public:
|
||||
virtual const char* purpose() const override { return class_name(); }
|
||||
|
||||
private:
|
||||
RTL8139NetworkAdapter(PCI::Address, u8 irq);
|
||||
virtual void handle_irq(const RegisterState&) override;
|
||||
virtual const char* class_name() const override { return "RTL8139NetworkAdapter"; }
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <Kernel/Debug.h>
|
||||
#include <Kernel/Net/LoopbackAdapter.h>
|
||||
#include <Kernel/Net/NetworkTask.h>
|
||||
#include <Kernel/Net/NetworkingManagement.h>
|
||||
#include <Kernel/Net/Routing.h>
|
||||
#include <Kernel/Thread.h>
|
||||
|
||||
@ -142,9 +143,9 @@ RoutingDecision route_to(const IPv4Address& target, const IPv4Address& source, c
|
||||
};
|
||||
|
||||
if (target[0] == 0 && target[1] == 0 && target[2] == 0 && target[3] == 0)
|
||||
return if_matches(LoopbackAdapter::the(), LoopbackAdapter::the().mac_address());
|
||||
return if_matches(*NetworkingManagement::the().loopback_adapter(), NetworkingManagement::the().loopback_adapter()->mac_address());
|
||||
if (target[0] == 127)
|
||||
return if_matches(LoopbackAdapter::the(), LoopbackAdapter::the().mac_address());
|
||||
return if_matches(*NetworkingManagement::the().loopback_adapter(), NetworkingManagement::the().loopback_adapter()->mac_address());
|
||||
|
||||
auto target_addr = target.to_u32();
|
||||
auto source_addr = source.to_u32();
|
||||
@ -152,12 +153,12 @@ RoutingDecision route_to(const IPv4Address& target, const IPv4Address& source, c
|
||||
RefPtr<NetworkAdapter> local_adapter = nullptr;
|
||||
RefPtr<NetworkAdapter> gateway_adapter = nullptr;
|
||||
|
||||
NetworkAdapter::for_each([source_addr, &target_addr, &local_adapter, &gateway_adapter, &matches, &through](auto& adapter) {
|
||||
NetworkingManagement::the().for_each([source_addr, &target_addr, &local_adapter, &gateway_adapter, &matches, &through](NetworkAdapter& adapter) {
|
||||
auto adapter_addr = adapter.ipv4_address().to_u32();
|
||||
auto adapter_mask = adapter.ipv4_netmask().to_u32();
|
||||
|
||||
if (target_addr == adapter_addr) {
|
||||
local_adapter = LoopbackAdapter::the();
|
||||
local_adapter = NetworkingManagement::the().loopback_adapter();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -213,7 +214,7 @@ RoutingDecision route_to(const IPv4Address& target, const IPv4Address& source, c
|
||||
if (target_addr == 0xffffffff && matches(adapter))
|
||||
return { adapter, { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
|
||||
|
||||
if (adapter == LoopbackAdapter::the())
|
||||
if (adapter == NetworkingManagement::the().loopback_adapter())
|
||||
return { adapter, adapter->mac_address() };
|
||||
|
||||
if ((target_addr & IPv4Address { 240, 0, 0, 0 }.to_u32()) == IPv4Address { 224, 0, 0, 0 }.to_u32())
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <Kernel/FileSystem/FileDescription.h>
|
||||
#include <Kernel/Net/IPv4Socket.h>
|
||||
#include <Kernel/Net/LocalSocket.h>
|
||||
#include <Kernel/Net/NetworkingManagement.h>
|
||||
#include <Kernel/Net/Socket.h>
|
||||
#include <Kernel/Process.h>
|
||||
#include <Kernel/UnixTypes.h>
|
||||
@ -111,7 +112,7 @@ KResult Socket::setsockopt(int level, int option, Userspace<const void*> user_va
|
||||
auto ifname = copy_string_from_user(user_string, user_value_size);
|
||||
if (ifname.is_null())
|
||||
return EFAULT;
|
||||
auto device = NetworkAdapter::lookup_by_name(ifname);
|
||||
auto device = NetworkingManagement::the().lookup_by_name(ifname);
|
||||
if (!device)
|
||||
return ENODEV;
|
||||
m_bound_interface = device;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <Kernel/Net/EthernetFrameHeader.h>
|
||||
#include <Kernel/Net/IPv4.h>
|
||||
#include <Kernel/Net/NetworkAdapter.h>
|
||||
#include <Kernel/Net/NetworkingManagement.h>
|
||||
#include <Kernel/Net/Routing.h>
|
||||
#include <Kernel/Net/TCP.h>
|
||||
#include <Kernel/Net/TCPSocket.h>
|
||||
@ -357,7 +358,7 @@ NetworkOrdered<u16> TCPSocket::compute_tcp_checksum(const IPv4Address& source, c
|
||||
KResult TCPSocket::protocol_bind()
|
||||
{
|
||||
if (has_specific_local_address() && !m_adapter) {
|
||||
m_adapter = NetworkAdapter::from_ipv4_address(local_address());
|
||||
m_adapter = NetworkingManagement::the().from_ipv4_address(local_address());
|
||||
if (!m_adapter)
|
||||
return EADDRNOTAVAIL;
|
||||
}
|
||||
|
@ -33,11 +33,8 @@
|
||||
#include <Kernel/Interrupts/PIC.h>
|
||||
#include <Kernel/KSyms.h>
|
||||
#include <Kernel/Multiboot.h>
|
||||
#include <Kernel/Net/E1000NetworkAdapter.h>
|
||||
#include <Kernel/Net/LoopbackAdapter.h>
|
||||
#include <Kernel/Net/NE2000NetworkAdapter.h>
|
||||
#include <Kernel/Net/NetworkTask.h>
|
||||
#include <Kernel/Net/RTL8139NetworkAdapter.h>
|
||||
#include <Kernel/Net/NetworkingManagement.h>
|
||||
#include <Kernel/PCI/Access.h>
|
||||
#include <Kernel/PCI/Initializer.h>
|
||||
#include <Kernel/Panic.h>
|
||||
@ -243,12 +240,7 @@ void init_stage2(void*)
|
||||
|
||||
VirtIO::detect();
|
||||
|
||||
E1000NetworkAdapter::detect();
|
||||
NE2000NetworkAdapter::detect();
|
||||
RTL8139NetworkAdapter::detect();
|
||||
|
||||
LoopbackAdapter::the();
|
||||
|
||||
NetworkingManagement::the().initialize();
|
||||
Syscall::initialize();
|
||||
|
||||
new MemoryDevice;
|
||||
|
Loading…
Reference in New Issue
Block a user