Serenity Operating System
at master 131 lines 4.1 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9#include <AK/AtomicRefCounted.h> 10#include <AK/ByteBuffer.h> 11#include <AK/Function.h> 12#include <AK/IntrusiveList.h> 13#include <AK/MACAddress.h> 14#include <AK/Types.h> 15#include <Kernel/Bus/PCI/Definitions.h> 16#include <Kernel/KBuffer.h> 17#include <Kernel/Library/LockWeakPtr.h> 18#include <Kernel/Library/LockWeakable.h> 19#include <Kernel/Net/ARP.h> 20#include <Kernel/Net/EthernetFrameHeader.h> 21#include <Kernel/Net/ICMP.h> 22#include <Kernel/Net/IPv4.h> 23#include <Kernel/UserOrKernelBuffer.h> 24 25namespace Kernel { 26 27class NetworkAdapter; 28 29using NetworkByteBuffer = AK::Detail::ByteBuffer<1500>; 30 31struct PacketWithTimestamp final : public AtomicRefCounted<PacketWithTimestamp> { 32 PacketWithTimestamp(NonnullOwnPtr<KBuffer> buffer, Time timestamp) 33 : buffer(move(buffer)) 34 , timestamp(timestamp) 35 { 36 } 37 38 ReadonlyBytes bytes() { return buffer->bytes(); } 39 40 NonnullOwnPtr<KBuffer> buffer; 41 Time timestamp; 42 IntrusiveListNode<PacketWithTimestamp, LockRefPtr<PacketWithTimestamp>> packet_node; 43}; 44 45class NetworkingManagement; 46class NetworkAdapter 47 : public AtomicRefCounted<NetworkAdapter> 48 , public LockWeakable<NetworkAdapter> { 49public: 50 enum class Type { 51 Loopback, 52 Ethernet 53 }; 54 55 static constexpr i32 LINKSPEED_INVALID = -1; 56 57 virtual ~NetworkAdapter(); 58 59 virtual StringView class_name() const = 0; 60 virtual Type adapter_type() const = 0; 61 virtual ErrorOr<void> initialize(Badge<NetworkingManagement>) = 0; 62 63 StringView name() const { return m_name->view(); } 64 MACAddress mac_address() { return m_mac_address; } 65 IPv4Address ipv4_address() const { return m_ipv4_address; } 66 IPv4Address ipv4_netmask() const { return m_ipv4_netmask; } 67 IPv4Address ipv4_broadcast() const { return IPv4Address { (m_ipv4_address.to_u32() & m_ipv4_netmask.to_u32()) | ~m_ipv4_netmask.to_u32() }; } 68 virtual bool link_up() { return false; } 69 virtual i32 link_speed() 70 { 71 // In Mbit/sec. 72 return LINKSPEED_INVALID; 73 } 74 virtual bool link_full_duplex() { return false; } 75 76 void set_ipv4_address(IPv4Address const&); 77 void set_ipv4_netmask(IPv4Address const&); 78 79 void send(MACAddress const&, ARPPacket const&); 80 void fill_in_ipv4_header(PacketWithTimestamp&, IPv4Address const&, MACAddress const&, IPv4Address const&, IPv4Protocol, size_t, u8 type_of_service, u8 ttl); 81 82 size_t dequeue_packet(u8* buffer, size_t buffer_size, Time& packet_timestamp); 83 84 bool has_queued_packets() const { return !m_packet_queue.is_empty(); } 85 86 u32 mtu() const { return m_mtu; } 87 void set_mtu(u32 mtu) { m_mtu = mtu; } 88 89 u32 packets_in() const { return m_packets_in; } 90 u32 bytes_in() const { return m_bytes_in; } 91 u32 packets_out() const { return m_packets_out; } 92 u32 bytes_out() const { return m_bytes_out; } 93 94 LockRefPtr<PacketWithTimestamp> acquire_packet_buffer(size_t); 95 void release_packet_buffer(PacketWithTimestamp&); 96 97 constexpr size_t layer3_payload_offset() const { return sizeof(EthernetFrameHeader); } 98 constexpr size_t ipv4_payload_offset() const { return layer3_payload_offset() + sizeof(IPv4Packet); } 99 100 Function<void()> on_receive; 101 102 void send_packet(ReadonlyBytes); 103 104protected: 105 NetworkAdapter(NonnullOwnPtr<KString>); 106 void set_mac_address(MACAddress const& mac_address) { m_mac_address = mac_address; } 107 void did_receive(ReadonlyBytes); 108 virtual void send_raw(ReadonlyBytes) = 0; 109 110private: 111 MACAddress m_mac_address; 112 IPv4Address m_ipv4_address; 113 IPv4Address m_ipv4_netmask; 114 115 // FIXME: Make this configurable 116 static constexpr size_t max_packet_buffers = 1024; 117 118 using PacketList = IntrusiveList<&PacketWithTimestamp::packet_node>; 119 120 PacketList m_packet_queue; 121 size_t m_packet_queue_size { 0 }; 122 SpinlockProtected<PacketList, LockRank::None> m_unused_packets {}; 123 NonnullOwnPtr<KString> m_name; 124 u32 m_packets_in { 0 }; 125 u32 m_bytes_in { 0 }; 126 u32 m_packets_out { 0 }; 127 u32 m_bytes_out { 0 }; 128 u32 m_mtu { 1500 }; 129}; 130 131}