diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp index 768eaaea76..7302c6b37a 100644 --- a/Kernel/FileSystem/ProcFS.cpp +++ b/Kernel/FileSystem/ProcFS.cpp @@ -269,15 +269,20 @@ Optional procfs$cmdline(InodeIdentifier) Optional procfs$netadapters(InodeIdentifier) { - KBufferBuilder builder; - NetworkAdapter::for_each([&builder](auto& adapter) { - builder.appendf("%s,%s,%s,%s\n", - adapter.name().characters(), - adapter.class_name(), - adapter.mac_address().to_string().characters(), - adapter.ipv4_address().to_string().characters()); + JsonArray json; + NetworkAdapter::for_each([&json](auto& adapter) { + JsonObject obj; + obj.set("name", adapter.name()); + obj.set("class_name", adapter.class_name()); + obj.set("mac_address", adapter.mac_address().to_string()); + obj.set("ipv4_address", adapter.ipv4_address().to_string()); + obj.set("packets_in", adapter.packets_in()); + obj.set("bytes_in", adapter.bytes_in()); + obj.set("packets_out", adapter.packets_out()); + obj.set("bytes_out", adapter.bytes_out()); + json.append(obj); }); - return builder.build(); + return json.serialized(); } Optional procfs$net_tcp(InodeIdentifier) @@ -292,6 +297,10 @@ Optional procfs$net_tcp(InodeIdentifier) obj.set("state", TCPSocket::to_string(socket->state())); obj.set("ack_number", socket->ack_number()); obj.set("sequence_number", socket->sequence_number()); + obj.set("packets_in", socket->packets_in()); + obj.set("bytes_in", socket->bytes_in()); + obj.set("packets_out", socket->packets_out()); + obj.set("bytes_out", socket->bytes_out()); json.append(obj); }); return json.serialized(); diff --git a/Kernel/Net/NetworkAdapter.cpp b/Kernel/Net/NetworkAdapter.cpp index 62e023014c..f77804a914 100644 --- a/Kernel/Net/NetworkAdapter.cpp +++ b/Kernel/Net/NetworkAdapter.cpp @@ -52,6 +52,8 @@ void NetworkAdapter::send(const MACAddress& destination, const ARPPacket& packet eth->set_source(mac_address()); eth->set_destination(destination); eth->set_ether_type(EtherType::ARP); + m_packets_out++; + m_bytes_out += size_in_bytes; memcpy(eth->payload(), &packet, sizeof(ARPPacket)); send_raw((u8*)eth, size_in_bytes); } @@ -74,6 +76,8 @@ void NetworkAdapter::send_ipv4(const MACAddress& destination_mac, const IPv4Addr ipv4.set_ident(1); ipv4.set_ttl(64); ipv4.set_checksum(ipv4.compute_checksum()); + m_packets_out++; + m_bytes_out += size_in_bytes; memcpy(ipv4.payload(), payload, payload_size); send_raw((const u8*)ð, size_in_bytes); } @@ -81,6 +85,8 @@ void NetworkAdapter::send_ipv4(const MACAddress& destination_mac, const IPv4Addr void NetworkAdapter::did_receive(const u8* data, int length) { InterruptDisabler disabler; + m_packets_in++; + m_bytes_in += length; m_packet_queue.append(KBuffer::copy(data, length)); } diff --git a/Kernel/Net/NetworkAdapter.h b/Kernel/Net/NetworkAdapter.h index 46782dd8fd..c1d99b3f9e 100644 --- a/Kernel/Net/NetworkAdapter.h +++ b/Kernel/Net/NetworkAdapter.h @@ -33,6 +33,11 @@ public: bool has_queued_packets() const { return !m_packet_queue.is_empty(); } + u32 packets_in() const { return m_packets_in; } + u32 bytes_in() const { return m_bytes_in; } + u32 packets_out() const { return m_packets_out; } + u32 bytes_out() const { return m_bytes_out; } + protected: NetworkAdapter(); void set_interface_name(const StringView& basename); @@ -45,4 +50,8 @@ private: IPv4Address m_ipv4_address; SinglyLinkedList m_packet_queue; String m_name; + u32 m_packets_in { 0 }; + u32 m_bytes_in { 0 }; + u32 m_packets_out { 0 }; + u32 m_bytes_out { 0 }; }; diff --git a/Kernel/Net/NetworkTask.cpp b/Kernel/Net/NetworkTask.cpp index d18ea32a5c..c57562b1aa 100644 --- a/Kernel/Net/NetworkTask.cpp +++ b/Kernel/Net/NetworkTask.cpp @@ -334,6 +334,8 @@ void handle_tcp(const EthernetFrameHeader& eth, int frame_size) return; } + socket->record_incoming_data(ipv4_packet.payload_size()); + #ifdef TCP_DEBUG kprintf("handle_tcp: state=%s\n", TCPSocket::to_string(socket->state())); #endif diff --git a/Kernel/Net/TCPSocket.cpp b/Kernel/Net/TCPSocket.cpp index 557cbcb4d0..b6c1b726af 100644 --- a/Kernel/Net/TCPSocket.cpp +++ b/Kernel/Net/TCPSocket.cpp @@ -117,6 +117,15 @@ void TCPSocket::send_tcp_packet(u16 flags, const void* payload, int payload_size tcp_packet.ack_number()); #endif m_adapter->send_ipv4(MACAddress(), peer_address(), IPv4Protocol::TCP, buffer.data(), buffer.size()); + + m_packets_out++; + m_bytes_out += buffer.size(); +} + +void TCPSocket::record_incoming_data(int size) +{ + m_packets_in++; + m_bytes_in += size; } NetworkOrdered TCPSocket::compute_tcp_checksum(const IPv4Address& source, const IPv4Address& destination, const TCPPacket& packet, u16 payload_size) diff --git a/Kernel/Net/TCPSocket.h b/Kernel/Net/TCPSocket.h index f310fbb01e..c6450e850b 100644 --- a/Kernel/Net/TCPSocket.h +++ b/Kernel/Net/TCPSocket.h @@ -60,8 +60,13 @@ public: void set_sequence_number(u32 n) { m_sequence_number = n; } u32 ack_number() const { return m_ack_number; } u32 sequence_number() const { return m_sequence_number; } + u32 packets_in() const { return m_packets_in; } + u32 bytes_in() const { return m_bytes_in; } + u32 packets_out() const { return m_packets_out; } + u32 bytes_out() const { return m_bytes_out; } void send_tcp_packet(u16 flags, const void* = nullptr, int = 0); + void record_incoming_data(int); static Lockable>& sockets_by_tuple(); static TCPSocketHandle from_tuple(const IPv4SocketTuple& tuple); @@ -85,6 +90,10 @@ private: u32 m_sequence_number { 0 }; u32 m_ack_number { 0 }; State m_state { State::Closed }; + u32 m_packets_in { 0 }; + u32 m_bytes_in { 0 }; + u32 m_packets_out { 0 }; + u32 m_bytes_out { 0 }; }; class TCPSocketHandle : public SocketHandle { diff --git a/Userland/ifconfig.cpp b/Userland/ifconfig.cpp index fbde9341a5..d32e62f133 100644 --- a/Userland/ifconfig.cpp +++ b/Userland/ifconfig.cpp @@ -1,6 +1,21 @@ +#include +#include +#include +#include #include #include +String si_bytes(unsigned bytes) +{ + if (bytes >= GB) + return String::format("%fGiB", (double)bytes / (double)GB); + if (bytes >= MB) + return String::format("%fMiB", (double)bytes / (double)MB); + if (bytes >= KB) + return String::format("%fKiB", (double)bytes / (double)KB); + return String::format("%dB", bytes); +} + int main(int argc, char** argv) { UNUSED_PARAM(argc); @@ -12,19 +27,28 @@ int main(int argc, char** argv) return 1; } - for (;;) { - auto line = file.read_line(1024); - if (line.is_null()) - break; - auto parts = String::copy(line, Chomp).split(','); - if (parts.size() < 4) - continue; - printf("%s:\n", parts[0].characters()); - printf(" mac: %s\n", parts[2].characters()); - printf(" ipv4: %s\n", parts[3].characters()); - printf(" class: %s\n", parts[1].characters()); + auto file_contents = file.read_all(); + auto json = JsonValue::from_string(file_contents).as_array(); + json.for_each([](auto& value) { + auto if_object = value.as_object(); + + auto name = if_object.get("name").to_string(); + auto class_name = if_object.get("class_name").to_string(); + auto mac_address = if_object.get("mac_address").to_string(); + auto ipv4_address = if_object.get("ipv4_address").to_string(); + auto packets_in = if_object.get("packets_in").to_u32(); + auto bytes_in = if_object.get("bytes_in").to_u32(); + auto packets_out = if_object.get("packets_out").to_u32(); + auto bytes_out = if_object.get("bytes_out").to_u32(); + + printf("%s:\n", name.characters()); + printf(" mac: %s\n", mac_address.characters()); + printf(" ipv4: %s\n", ipv4_address.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(" TX: %u packets %u bytes (%s)\n", packets_out, bytes_out, si_bytes(bytes_out).characters()); printf("\n"); - } + }); return 0; }