Parcourir la source

Kernel: Add a way to look up NetworkAdapters by IPv4 address.

Andreas Kling il y a 6 ans
Parent
commit
8e667747f0
3 fichiers modifiés avec 36 ajouts et 13 suppressions
  1. 26 0
      Kernel/NetworkAdapter.cpp
  2. 1 0
      Kernel/NetworkAdapter.h
  3. 9 13
      Kernel/NetworkTask.cpp

+ 26 - 0
Kernel/NetworkAdapter.cpp

@@ -3,13 +3,39 @@
 #include <Kernel/EthernetFrameHeader.h>
 #include <Kernel/kmalloc.h>
 #include <Kernel/EtherType.h>
+#include <AK/HashTable.h>
+#include <AK/Lock.h>
+
+static Lockable<HashTable<NetworkAdapter*>>& all_adapters()
+{
+    static Lockable<HashTable<NetworkAdapter*>>* table;
+    if (!table)
+        table = new Lockable<HashTable<NetworkAdapter*>>;
+    return *table;
+}
+
+NetworkAdapter* NetworkAdapter::from_ipv4_address(const IPv4Address& address)
+{
+    LOCKER(all_adapters().lock());
+    for (auto* adapter : all_adapters().resource()) {
+        if (adapter->ipv4_address() == address)
+            return adapter;
+    }
+    return nullptr;
+}
 
 NetworkAdapter::NetworkAdapter()
 {
+    // FIXME: I wanna lock :(
+    ASSERT_INTERRUPTS_DISABLED();
+    all_adapters().resource().set(this);
 }
 
 NetworkAdapter::~NetworkAdapter()
 {
+    // FIXME: I wanna lock :(
+    ASSERT_INTERRUPTS_DISABLED();
+    all_adapters().resource().remove(this);
 }
 
 void NetworkAdapter::send(const MACAddress& destination, const ARPPacket& packet)

+ 1 - 0
Kernel/NetworkAdapter.h

@@ -10,6 +10,7 @@
 
 class NetworkAdapter {
 public:
+    static NetworkAdapter* from_ipv4_address(const IPv4Address&);
     virtual ~NetworkAdapter();
 
     virtual const char* class_name() const = 0;

+ 9 - 13
Kernel/NetworkTask.cpp

@@ -33,7 +33,7 @@ void NetworkTask_main()
     for (;;) {
         auto packet = e1000.dequeue_packet();
         if (packet.is_null()) {
-            sleep(1);
+            sleep(100);
             continue;
         }
         if (packet.size() < (int)(sizeof(EthernetFrameHeader))) {
@@ -94,23 +94,20 @@ void handle_arp(const EthernetFrameHeader& eth, int frame_size)
     );
 #endif
 
-    // FIXME: Get the adapter through some kind of lookup by IPv4 address.
-    auto& e1000 = *E1000NetworkAdapter::the();
-
     if (packet.operation() == ARPOperation::Request) {
         // Who has this IP address?
-        if (e1000.ipv4_address() == packet.target_protocol_address()) {
+        if (auto* adapter = NetworkAdapter::from_ipv4_address(packet.target_protocol_address())) {
             // We do!
             kprintf("handle_arp: Responding to ARP request for my IPv4 address (%s)\n",
-                    e1000.ipv4_address().to_string().characters());
+                    adapter->ipv4_address().to_string().characters());
             ARPPacket response;
             response.set_operation(ARPOperation::Response);
             response.set_target_hardware_address(packet.sender_hardware_address());
             response.set_target_protocol_address(packet.sender_protocol_address());
-            response.set_sender_hardware_address(e1000.mac_address());
-            response.set_sender_protocol_address(e1000.ipv4_address());
+            response.set_sender_hardware_address(adapter->mac_address());
+            response.set_sender_protocol_address(adapter->ipv4_address());
 
-            e1000.send(packet.sender_hardware_address(), response);
+            adapter->send(packet.sender_hardware_address(), response);
         }
         return;
     }
@@ -168,9 +165,8 @@ void handle_icmp(const EthernetFrameHeader& eth, int frame_size)
     );
 #endif
 
-    // FIXME: Get adapater via lookup.
-    auto& adapter = *E1000NetworkAdapter::the();
-    if (ipv4_packet.destination() != adapter.ipv4_address())
+    auto* adapter = NetworkAdapter::from_ipv4_address(ipv4_packet.destination());
+    if (!adapter)
         return;
 
     if (icmp_header.type() == ICMPType::EchoRequest) {
@@ -190,6 +186,6 @@ void handle_icmp(const EthernetFrameHeader& eth, int frame_size)
         if (size_t icmp_payload_size = icmp_packet_size - sizeof(ICMPEchoPacket))
             memcpy(response.payload(), request.payload(), icmp_payload_size);
         response.header.set_checksum(internet_checksum(&response, icmp_packet_size));
-        adapter.send_ipv4(eth.source(), ipv4_packet.source(), IPv4Protocol::ICMP, move(buffer));
+        adapter->send_ipv4(eth.source(), ipv4_packet.source(), IPv4Protocol::ICMP, move(buffer));
     }
 }