Serenity Operating System
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}