diff options
-rw-r--r-- | Kernel/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Kernel/FileSystem/ProcFS.cpp | 3 | ||||
-rw-r--r-- | Kernel/Net/E1000NetworkAdapter.cpp | 19 | ||||
-rw-r--r-- | Kernel/Net/E1000NetworkAdapter.h | 4 | ||||
-rw-r--r-- | Kernel/Net/IPv4Socket.cpp | 5 | ||||
-rw-r--r-- | Kernel/Net/LoopbackAdapter.cpp | 8 | ||||
-rw-r--r-- | Kernel/Net/LoopbackAdapter.h | 6 | ||||
-rw-r--r-- | Kernel/Net/NE2000NetworkAdapter.cpp | 15 | ||||
-rw-r--r-- | Kernel/Net/NE2000NetworkAdapter.h | 4 | ||||
-rw-r--r-- | Kernel/Net/NetworkAdapter.cpp | 40 | ||||
-rw-r--r-- | Kernel/Net/NetworkAdapter.h | 12 | ||||
-rw-r--r-- | Kernel/Net/NetworkTask.cpp | 15 | ||||
-rw-r--r-- | Kernel/Net/NetworkingManagement.cpp | 101 | ||||
-rw-r--r-- | Kernel/Net/NetworkingManagement.h | 46 | ||||
-rw-r--r-- | Kernel/Net/RTL8139NetworkAdapter.cpp | 15 | ||||
-rw-r--r-- | Kernel/Net/RTL8139NetworkAdapter.h | 4 | ||||
-rw-r--r-- | Kernel/Net/Routing.cpp | 11 | ||||
-rw-r--r-- | Kernel/Net/Socket.cpp | 3 | ||||
-rw-r--r-- | Kernel/Net/TCPSocket.cpp | 3 | ||||
-rw-r--r-- | Kernel/init.cpp | 12 |
20 files changed, 211 insertions, 116 deletions
diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 023ab811fe..93f0fd58ee 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -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 diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp index 434ba03257..10adb72459 100644 --- a/Kernel/FileSystem/ProcFS.cpp +++ b/Kernel/FileSystem/ProcFS.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()); diff --git a/Kernel/Net/E1000NetworkAdapter.cpp b/Kernel/Net/E1000NetworkAdapter.cpp index 69cb0fa588..03d1fce700 100644 --- a/Kernel/Net/E1000NetworkAdapter.cpp +++ b/Kernel/Net/E1000NetworkAdapter.cpp @@ -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) diff --git a/Kernel/Net/E1000NetworkAdapter.h b/Kernel/Net/E1000NetworkAdapter.h index e7fa10ad70..6458ae9d45 100644 --- a/Kernel/Net/E1000NetworkAdapter.h +++ b/Kernel/Net/E1000NetworkAdapter.h @@ -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"; } diff --git a/Kernel/Net/IPv4Socket.cpp b/Kernel/Net/IPv4Socket.cpp index 260c878e22..c1c1d5bb1d 100644 --- a/Kernel/Net/IPv4Socket.cpp +++ b/Kernel/Net/IPv4Socket.cpp @@ -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; diff --git a/Kernel/Net/LoopbackAdapter.cpp b/Kernel/Net/LoopbackAdapter.cpp index 2fd4fb7a50..647c168550 100644 --- a/Kernel/Net/LoopbackAdapter.cpp +++ b/Kernel/Net/LoopbackAdapter.cpp @@ -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 }); diff --git a/Kernel/Net/LoopbackAdapter.h b/Kernel/Net/LoopbackAdapter.h index ab5c3906f1..b7949793db 100644 --- a/Kernel/Net/LoopbackAdapter.h +++ b/Kernel/Net/LoopbackAdapter.h @@ -12,10 +12,12 @@ namespace Kernel { class LoopbackAdapter final : public NetworkAdapter { AK_MAKE_ETERNAL -public: + +private: LoopbackAdapter(); - static LoopbackAdapter& the(); +public: + static NonnullRefPtr<LoopbackAdapter> create(); virtual ~LoopbackAdapter() override; virtual void send_raw(ReadonlyBytes) override; diff --git a/Kernel/Net/NE2000NetworkAdapter.cpp b/Kernel/Net/NE2000NetworkAdapter.cpp index 31b962d961..9c542579e7 100644 --- a/Kernel/Net/NE2000NetworkAdapter.cpp +++ b/Kernel/Net/NE2000NetworkAdapter.cpp @@ -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) diff --git a/Kernel/Net/NE2000NetworkAdapter.h b/Kernel/Net/NE2000NetworkAdapter.h index e70ea93ba4..2bab3cc0ed 100644 --- a/Kernel/Net/NE2000NetworkAdapter.h +++ b/Kernel/Net/NE2000NetworkAdapter.h @@ -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"; } diff --git a/Kernel/Net/NetworkAdapter.cpp b/Kernel/Net/NetworkAdapter.cpp index c61fb5872d..c386b7362c 100644 --- a/Kernel/Net/NetworkAdapter.cpp +++ b/Kernel/Net/NetworkAdapter.cpp @@ -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); } } diff --git a/Kernel/Net/NetworkAdapter.h b/Kernel/Net/NetworkAdapter.h index a454ee7592..4ddee225e6 100644 --- a/Kernel/Net/NetworkAdapter.h +++ b/Kernel/Net/NetworkAdapter.h @@ -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; diff --git a/Kernel/Net/NetworkTask.cpp b/Kernel/Net/NetworkTask.cpp index 99c5f7bc2c..f65d846b4e 100644 --- a/Kernel/Net/NetworkTask.cpp +++ b/Kernel/Net/NetworkTask.cpp @@ -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; diff --git a/Kernel/Net/NetworkingManagement.cpp b/Kernel/Net/NetworkingManagement.cpp new file mode 100644 index 0000000000..c2bb229b14 --- /dev/null +++ b/Kernel/Net/NetworkingManagement.cpp @@ -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; +} + +} diff --git a/Kernel/Net/NetworkingManagement.h b/Kernel/Net/NetworkingManagement.h new file mode 100644 index 0000000000..f8be65a6c8 --- /dev/null +++ b/Kernel/Net/NetworkingManagement.h @@ -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" }; +}; + +} diff --git a/Kernel/Net/RTL8139NetworkAdapter.cpp b/Kernel/Net/RTL8139NetworkAdapter.cpp index 4ff9431856..e78bd93180 100644 --- a/Kernel/Net/RTL8139NetworkAdapter.cpp +++ b/Kernel/Net/RTL8139NetworkAdapter.cpp @@ -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) diff --git a/Kernel/Net/RTL8139NetworkAdapter.h b/Kernel/Net/RTL8139NetworkAdapter.h index 9d1ebe2f1a..b04ec65d1f 100644 --- a/Kernel/Net/RTL8139NetworkAdapter.h +++ b/Kernel/Net/RTL8139NetworkAdapter.h @@ -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"; } diff --git a/Kernel/Net/Routing.cpp b/Kernel/Net/Routing.cpp index 41f7e94587..90d7d268fe 100644 --- a/Kernel/Net/Routing.cpp +++ b/Kernel/Net/Routing.cpp @@ -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()) diff --git a/Kernel/Net/Socket.cpp b/Kernel/Net/Socket.cpp index 2ff8c6ce69..1484ff260f 100644 --- a/Kernel/Net/Socket.cpp +++ b/Kernel/Net/Socket.cpp @@ -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; diff --git a/Kernel/Net/TCPSocket.cpp b/Kernel/Net/TCPSocket.cpp index bb42064366..0fdb838355 100644 --- a/Kernel/Net/TCPSocket.cpp +++ b/Kernel/Net/TCPSocket.cpp @@ -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; } diff --git a/Kernel/init.cpp b/Kernel/init.cpp index df56ae26e7..3711ec7ed6 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -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; |