Browse Source

Kernel+ifconfig: Add an MTU value to NetworkAdapter

This defaults to 1500 for all adapters, but LoopbackAdapter increases
it to 65536 on construction.

If an IPv4 packet is larger than the MTU, we'll need to break it into
smaller fragments before transmitting it. This part is a FIXME. :^)
Andreas Kling 5 years ago
parent
commit
75ed262fe5

+ 1 - 0
Kernel/FileSystem/ProcFS.cpp

@@ -345,6 +345,7 @@ Optional<KBuffer> procfs$net_adapters(InodeIdentifier)
         obj.add("packets_out", adapter.packets_out());
         obj.add("packets_out", adapter.packets_out());
         obj.add("bytes_out", adapter.bytes_out());
         obj.add("bytes_out", adapter.bytes_out());
         obj.add("link_up", adapter.link_up());
         obj.add("link_up", adapter.link_up());
+        obj.add("mtu", adapter.mtu());
     });
     });
     array.finish();
     array.finish();
     return builder.build();
     return builder.build();

+ 1 - 0
Kernel/Net/LoopbackAdapter.cpp

@@ -11,6 +11,7 @@ LoopbackAdapter& LoopbackAdapter::the()
 LoopbackAdapter::LoopbackAdapter()
 LoopbackAdapter::LoopbackAdapter()
 {
 {
     set_interface_name("loop");
     set_interface_name("loop");
+    set_mtu(65536);
 }
 }
 
 
 LoopbackAdapter::~LoopbackAdapter()
 LoopbackAdapter::~LoopbackAdapter()

+ 10 - 4
Kernel/Net/NetworkAdapter.cpp

@@ -70,8 +70,14 @@ void NetworkAdapter::send(const MACAddress& destination, const ARPPacket& packet
 
 
 void NetworkAdapter::send_ipv4(const MACAddress& destination_mac, const IPv4Address& destination_ipv4, IPv4Protocol protocol, const u8* payload, size_t payload_size, u8 ttl)
 void NetworkAdapter::send_ipv4(const MACAddress& destination_mac, const IPv4Address& destination_ipv4, IPv4Protocol protocol, const u8* payload, size_t payload_size, u8 ttl)
 {
 {
-    size_t size_in_bytes = sizeof(EthernetFrameHeader) + sizeof(IPv4Packet) + payload_size;
-    auto buffer = ByteBuffer::create_zeroed(size_in_bytes);
+    size_t ipv4_packet_size = sizeof(IPv4Packet) + payload_size;
+    if (ipv4_packet_size > mtu()) {
+        // FIXME: Implement IP fragmentation.
+        ASSERT_NOT_REACHED();
+    }
+
+    size_t ethernet_frame_size = sizeof(EthernetFrameHeader) + sizeof(IPv4Packet) + payload_size;
+    auto buffer = ByteBuffer::create_zeroed(ethernet_frame_size);
     auto& eth = *(EthernetFrameHeader*)buffer.data();
     auto& eth = *(EthernetFrameHeader*)buffer.data();
     eth.set_source(mac_address());
     eth.set_source(mac_address());
     eth.set_destination(destination_mac);
     eth.set_destination(destination_mac);
@@ -87,9 +93,9 @@ void NetworkAdapter::send_ipv4(const MACAddress& destination_mac, const IPv4Addr
     ipv4.set_ttl(ttl);
     ipv4.set_ttl(ttl);
     ipv4.set_checksum(ipv4.compute_checksum());
     ipv4.set_checksum(ipv4.compute_checksum());
     m_packets_out++;
     m_packets_out++;
-    m_bytes_out += size_in_bytes;
+    m_bytes_out += ethernet_frame_size;
     memcpy(ipv4.payload(), payload, payload_size);
     memcpy(ipv4.payload(), payload, payload_size);
-    send_raw((const u8*)&eth, size_in_bytes);
+    send_raw((const u8*)&eth, ethernet_frame_size);
 }
 }
 
 
 void NetworkAdapter::did_receive(const u8* data, int length)
 void NetworkAdapter::did_receive(const u8* data, int length)

+ 4 - 0
Kernel/Net/NetworkAdapter.h

@@ -41,6 +41,9 @@ public:
 
 
     bool has_queued_packets() const { return !m_packet_queue.is_empty(); }
     bool has_queued_packets() const { return !m_packet_queue.is_empty(); }
 
 
+    u32 mtu() const { return m_mtu; }
+    void set_mtu(u32 mtu) { m_mtu = mtu; }
+
     u32 packets_in() const { return m_packets_in; }
     u32 packets_in() const { return m_packets_in; }
     u32 bytes_in() const { return m_bytes_in; }
     u32 bytes_in() const { return m_bytes_in; }
     u32 packets_out() const { return m_packets_out; }
     u32 packets_out() const { return m_packets_out; }
@@ -66,4 +69,5 @@ private:
     u32 m_bytes_in { 0 };
     u32 m_bytes_in { 0 };
     u32 m_packets_out { 0 };
     u32 m_packets_out { 0 };
     u32 m_bytes_out { 0 };
     u32 m_bytes_out { 0 };
+    u32 m_mtu { 1500 };
 };
 };

+ 2 - 0
Userland/ifconfig.cpp

@@ -70,6 +70,7 @@ int main(int argc, char** argv)
         auto bytes_in = if_object.get("bytes_in").to_u32();
         auto bytes_in = if_object.get("bytes_in").to_u32();
         auto packets_out = if_object.get("packets_out").to_u32();
         auto packets_out = if_object.get("packets_out").to_u32();
         auto bytes_out = if_object.get("bytes_out").to_u32();
         auto bytes_out = if_object.get("bytes_out").to_u32();
+        auto mtu = if_object.get("mtu").to_u32();
 
 
         printf("%s:\n", name.characters());
         printf("%s:\n", name.characters());
         printf("     mac: %s\n", mac_address.characters());
         printf("     mac: %s\n", mac_address.characters());
@@ -77,6 +78,7 @@ int main(int argc, char** argv)
         printf("   class: %s\n", class_name.characters());
         printf("   class: %s\n", class_name.characters());
         printf("      RX: %u packets %u bytes (%s)\n", packets_in, bytes_in, si_bytes(bytes_in).characters());
         printf("      RX: %u packets %u bytes (%s)\n", packets_in, bytes_in, si_bytes(bytes_in).characters());
         printf("      TX: %u packets %u bytes (%s)\n", packets_out, bytes_out, si_bytes(bytes_out).characters());
         printf("      TX: %u packets %u bytes (%s)\n", packets_out, bytes_out, si_bytes(bytes_out).characters());
+        printf("     MTU: %u\n", mtu);
         printf("\n");
         printf("\n");
     });
     });