1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-24 23:17:44 +00:00

Kernel: Migrate ARP table locking to ProtectedValue

This commit is contained in:
Jean-Baptiste Boric 2021-07-18 10:30:27 +02:00 committed by Andreas Kling
parent 75260bff92
commit 738e604bfc
3 changed files with 27 additions and 20 deletions

View file

@ -76,12 +76,11 @@ private:
virtual bool output(KBufferBuilder& builder) override virtual bool output(KBufferBuilder& builder) override
{ {
JsonArraySerializer array { builder }; JsonArraySerializer array { builder };
MutexLocker locker(arp_table().lock(), Mutex::Mode::Shared); arp_table().for_each_shared([&](const auto& it) {
for (auto& it : arp_table().resource()) {
auto obj = array.add_object(); auto obj = array.add_object();
obj.add("mac_address", it.value.to_string()); obj.add("mac_address", it.value.to_string());
obj.add("ip_address", it.key.to_string()); obj.add("ip_address", it.key.to_string());
} });
array.finish(); array.finish();
return true; return true;
} }

View file

@ -7,6 +7,7 @@
#include <AK/HashMap.h> #include <AK/HashMap.h>
#include <AK/Singleton.h> #include <AK/Singleton.h>
#include <Kernel/Debug.h> #include <Kernel/Debug.h>
#include <Kernel/Locking/ProtectedValue.h>
#include <Kernel/Net/LoopbackAdapter.h> #include <Kernel/Net/LoopbackAdapter.h>
#include <Kernel/Net/NetworkTask.h> #include <Kernel/Net/NetworkTask.h>
#include <Kernel/Net/NetworkingManagement.h> #include <Kernel/Net/NetworkingManagement.h>
@ -15,7 +16,7 @@
namespace Kernel { namespace Kernel {
static AK::Singleton<Lockable<HashMap<IPv4Address, MACAddress>>> s_arp_table; static AK::Singleton<ProtectedValue<HashMap<IPv4Address, MACAddress>>> s_arp_table;
class ARPTableBlocker : public Thread::Blocker { class ARPTableBlocker : public Thread::Blocker {
public: public:
@ -70,7 +71,9 @@ protected:
{ {
VERIFY(b.blocker_type() == Thread::Blocker::Type::Routing); VERIFY(b.blocker_type() == Thread::Blocker::Type::Routing);
auto& blocker = static_cast<ARPTableBlocker&>(b); auto& blocker = static_cast<ARPTableBlocker&>(b);
auto val = s_arp_table->resource().get(blocker.ip_addr()); auto val = arp_table().with_shared([&](const auto& table) -> auto {
return table.get(blocker.ip_addr());
});
if (!val.has_value()) if (!val.has_value())
return true; return true;
return blocker.unblock(true, blocker.ip_addr(), val.value()); return blocker.unblock(true, blocker.ip_addr(), val.value());
@ -90,7 +93,9 @@ ARPTableBlocker::ARPTableBlocker(IPv4Address ip_addr, Optional<MACAddress>& addr
void ARPTableBlocker::not_blocking(bool timeout_in_past) void ARPTableBlocker::not_blocking(bool timeout_in_past)
{ {
VERIFY(timeout_in_past || !m_should_block); VERIFY(timeout_in_past || !m_should_block);
auto addr = s_arp_table->resource().get(ip_addr()); auto addr = arp_table().with_shared([&](const auto& table) -> auto {
return table.get(ip_addr());
});
ScopedSpinLock lock(m_lock); ScopedSpinLock lock(m_lock);
if (!m_did_unblock) { if (!m_did_unblock) {
@ -99,25 +104,27 @@ void ARPTableBlocker::not_blocking(bool timeout_in_past)
} }
} }
Lockable<HashMap<IPv4Address, MACAddress>>& arp_table() ProtectedValue<HashMap<IPv4Address, MACAddress>>& arp_table()
{ {
return *s_arp_table; return *s_arp_table;
} }
void update_arp_table(const IPv4Address& ip_addr, const MACAddress& addr, UpdateArp update) void update_arp_table(const IPv4Address& ip_addr, const MACAddress& addr, UpdateArp update)
{ {
MutexLocker locker(arp_table().lock()); arp_table().with_exclusive([&](auto& table) {
if (update == UpdateArp::Set) if (update == UpdateArp::Set)
arp_table().resource().set(ip_addr, addr); table.set(ip_addr, addr);
if (update == UpdateArp::Delete) if (update == UpdateArp::Delete)
arp_table().resource().remove(ip_addr); table.remove(ip_addr);
});
s_arp_table_block_condition->unblock(ip_addr, addr); s_arp_table_block_condition->unblock(ip_addr, addr);
if constexpr (ROUTING_DEBUG) { if constexpr (ROUTING_DEBUG) {
dmesgln("ARP table ({} entries):", arp_table().resource().size()); arp_table().with_shared([&](const auto& table) {
for (auto& it : arp_table().resource()) { dmesgln("ARP table ({} entries):", table.size());
dmesgln("{} :: {}", it.value.to_string(), it.key.to_string()); for (auto& it : table)
} dmesgln("{} :: {}", it.value.to_string(), it.key.to_string());
});
} }
} }
@ -224,8 +231,9 @@ RoutingDecision route_to(const IPv4Address& target, const IPv4Address& source, c
return { adapter, multicast_ethernet_address(target) }; return { adapter, multicast_ethernet_address(target) };
{ {
MutexLocker locker(arp_table().lock()); auto addr = arp_table().with_shared([&](const auto& table) -> auto {
auto addr = arp_table().resource().get(next_hop_ip); return table.get(next_hop_ip);
});
if (addr.has_value()) { if (addr.has_value()) {
dbgln_if(ROUTING_DEBUG, "Routing: Using cached ARP entry for {} ({})", next_hop_ip, addr.value().to_string()); dbgln_if(ROUTING_DEBUG, "Routing: Using cached ARP entry for {} ({})", next_hop_ip, addr.value().to_string());
return { adapter, addr.value() }; return { adapter, addr.value() };

View file

@ -6,7 +6,7 @@
#pragma once #pragma once
#include <Kernel/Locking/Lockable.h> #include <Kernel/Locking/ProtectedValue.h>
#include <Kernel/Net/NetworkAdapter.h> #include <Kernel/Net/NetworkAdapter.h>
#include <Kernel/Thread.h> #include <Kernel/Thread.h>
@ -27,6 +27,6 @@ enum class UpdateArp {
void update_arp_table(const IPv4Address&, const MACAddress&, UpdateArp update); void update_arp_table(const IPv4Address&, const MACAddress&, UpdateArp update);
RoutingDecision route_to(const IPv4Address& target, const IPv4Address& source, const RefPtr<NetworkAdapter> through = nullptr); RoutingDecision route_to(const IPv4Address& target, const IPv4Address& source, const RefPtr<NetworkAdapter> through = nullptr);
Lockable<HashMap<IPv4Address, MACAddress>>& arp_table(); ProtectedValue<HashMap<IPv4Address, MACAddress>>& arp_table();
} }