Kernel: Move Ethernet header prepending from NIC to helper
This commit is contained in:
@@ -45,7 +45,7 @@ namespace Kernel
|
|||||||
uint32_t read32(uint16_t reg);
|
uint32_t read32(uint16_t reg);
|
||||||
void write32(uint16_t reg, uint32_t value);
|
void write32(uint16_t reg, uint32_t value);
|
||||||
|
|
||||||
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) override;
|
BAN::ErrorOr<void> send_raw_bytes(BAN::Span<const BAN::ConstByteSpan> buffers) override;
|
||||||
|
|
||||||
bool can_read_impl() const override { return false; }
|
bool can_read_impl() const override { return false; }
|
||||||
bool can_write_impl() const override { return false; }
|
bool can_write_impl() const override { return false; }
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ namespace Kernel
|
|||||||
virtual BAN::ErrorOr<void> bind_socket_to_address(BAN::RefPtr<NetworkSocket>, const sockaddr* address, socklen_t address_len) override;
|
virtual BAN::ErrorOr<void> bind_socket_to_address(BAN::RefPtr<NetworkSocket>, const sockaddr* address, socklen_t address_len) override;
|
||||||
virtual BAN::ErrorOr<void> get_socket_address(BAN::RefPtr<NetworkSocket>, sockaddr* address, socklen_t* address_len) override;
|
virtual BAN::ErrorOr<void> get_socket_address(BAN::RefPtr<NetworkSocket>, sockaddr* address, socklen_t* address_len) override;
|
||||||
|
|
||||||
virtual BAN::ErrorOr<size_t> sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) override;
|
virtual BAN::ErrorOr<void> sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) override;
|
||||||
|
|
||||||
virtual Socket::Domain domain() const override { return Socket::Domain::INET ;}
|
virtual Socket::Domain domain() const override { return Socket::Domain::INET ;}
|
||||||
virtual size_t header_size() const override { return sizeof(IPv4Header); }
|
virtual size_t header_size() const override { return sizeof(IPv4Header); }
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Kernel
|
|||||||
{}
|
{}
|
||||||
~LoopbackInterface();
|
~LoopbackInterface();
|
||||||
|
|
||||||
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) override;
|
BAN::ErrorOr<void> send_raw_bytes(BAN::Span<const BAN::ConstByteSpan> buffers) override;
|
||||||
|
|
||||||
bool can_read_impl() const override { return false; }
|
bool can_read_impl() const override { return false; }
|
||||||
bool can_write_impl() const override { return false; }
|
bool can_write_impl() const override { return false; }
|
||||||
|
|||||||
@@ -59,11 +59,30 @@ namespace Kernel
|
|||||||
|
|
||||||
virtual BAN::StringView name() const override { return m_name; }
|
virtual BAN::StringView name() const override { return m_name; }
|
||||||
|
|
||||||
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan payload)
|
BAN::ErrorOr<void> send_with_ethernet_header(BAN::MACAddress dst_mac, EtherType ether_type, BAN::ConstByteSpan buffer)
|
||||||
{
|
{
|
||||||
return send_bytes(destination, protocol, { &payload, 1 });
|
BAN::ConstByteSpan buffer_array[1] { buffer };
|
||||||
|
return send_with_ethernet_header(dst_mac, ether_type, buffer_array);
|
||||||
}
|
}
|
||||||
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) = 0;
|
|
||||||
|
template<size_t SIZE>
|
||||||
|
BAN::ErrorOr<void> send_with_ethernet_header(BAN::MACAddress dst_mac, EtherType ether_type, const BAN::ConstByteSpan (&buffer_array)[SIZE])
|
||||||
|
{
|
||||||
|
const auto ethernet_header = EthernetHeader {
|
||||||
|
.dst_mac = dst_mac,
|
||||||
|
.src_mac = get_mac_address(),
|
||||||
|
.ether_type = ether_type,
|
||||||
|
};
|
||||||
|
|
||||||
|
BAN::ConstByteSpan new_buffer_array[SIZE + 1];
|
||||||
|
new_buffer_array[0] = BAN::ConstByteSpan::from(ethernet_header);
|
||||||
|
for (size_t i = 0; i < SIZE; i++)
|
||||||
|
new_buffer_array[i + 1] = buffer_array[i];
|
||||||
|
|
||||||
|
return send_raw_bytes({ new_buffer_array, SIZE + 1 });
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual BAN::ErrorOr<void> send_raw_bytes(BAN::Span<const BAN::ConstByteSpan> buffers) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Kernel
|
|||||||
virtual BAN::ErrorOr<void> bind_socket_to_address(BAN::RefPtr<NetworkSocket>, const sockaddr* address, socklen_t address_len) = 0;
|
virtual BAN::ErrorOr<void> bind_socket_to_address(BAN::RefPtr<NetworkSocket>, const sockaddr* address, socklen_t address_len) = 0;
|
||||||
virtual BAN::ErrorOr<void> get_socket_address(BAN::RefPtr<NetworkSocket>, sockaddr* address, socklen_t* address_len) = 0;
|
virtual BAN::ErrorOr<void> get_socket_address(BAN::RefPtr<NetworkSocket>, sockaddr* address, socklen_t* address_len) = 0;
|
||||||
|
|
||||||
virtual BAN::ErrorOr<size_t> sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) = 0;
|
virtual BAN::ErrorOr<void> sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) = 0;
|
||||||
|
|
||||||
virtual Socket::Domain domain() const = 0;
|
virtual Socket::Domain domain() const = 0;
|
||||||
virtual size_t header_size() const = 0;
|
virtual size_t header_size() const = 0;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace Kernel
|
|||||||
virtual bool link_up() override { return m_link_up; }
|
virtual bool link_up() override { return m_link_up; }
|
||||||
virtual int link_speed() override;
|
virtual int link_speed() override;
|
||||||
|
|
||||||
virtual size_t payload_mtu() const override { return 7436 - sizeof(EthernetHeader); }
|
virtual size_t payload_mtu() const override { return 0x1FF8 - sizeof(EthernetHeader); }
|
||||||
|
|
||||||
virtual void handle_irq() override;
|
virtual void handle_irq() override;
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> initialize();
|
BAN::ErrorOr<void> initialize();
|
||||||
|
|
||||||
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan>) override;
|
virtual BAN::ErrorOr<void> send_raw_bytes(BAN::Span<const BAN::ConstByteSpan> buffers) override;
|
||||||
|
|
||||||
virtual bool can_read_impl() const override { return false; }
|
virtual bool can_read_impl() const override { return false; }
|
||||||
virtual bool can_write_impl() const override { return false; }
|
virtual bool can_write_impl() const override { return false; }
|
||||||
|
|||||||
@@ -50,18 +50,19 @@ namespace Kernel
|
|||||||
return it->value;
|
return it->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ARPPacket arp_request;
|
const auto arp_request = ARPPacket {
|
||||||
arp_request.htype = 0x0001;
|
.htype = 0x0001,
|
||||||
arp_request.ptype = EtherType::IPv4;
|
.ptype = EtherType::IPv4,
|
||||||
arp_request.hlen = 0x06;
|
.hlen = 0x06,
|
||||||
arp_request.plen = 0x04;
|
.plen = 0x04,
|
||||||
arp_request.oper = ARPOperation::Request;
|
.oper = ARPOperation::Request,
|
||||||
arp_request.sha = interface.get_mac_address();
|
.sha = interface.get_mac_address(),
|
||||||
arp_request.spa = interface.get_ipv4_address();
|
.spa = interface.get_ipv4_address(),
|
||||||
arp_request.tha = {{ 0, 0, 0, 0, 0, 0 }};
|
.tha = {{ 0, 0, 0, 0, 0, 0 }},
|
||||||
arp_request.tpa = ipv4_address;
|
.tpa = ipv4_address,
|
||||||
|
};
|
||||||
|
|
||||||
TRY(interface.send_bytes(s_broadcast_mac, EtherType::ARP, BAN::ConstByteSpan::from(arp_request)));
|
TRY(interface.send_with_ethernet_header(s_broadcast_mac, EtherType::ARP, BAN::ConstByteSpan::from(arp_request)));
|
||||||
|
|
||||||
uint64_t timeout = SystemTimer::get().ms_since_boot() + 1'000;
|
uint64_t timeout = SystemTimer::get().ms_since_boot() + 1'000;
|
||||||
while (SystemTimer::get().ms_since_boot() < timeout)
|
while (SystemTimer::get().ms_since_boot() < timeout)
|
||||||
@@ -100,7 +101,7 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
if (packet.tpa == interface.get_ipv4_address())
|
if (packet.tpa == interface.get_ipv4_address())
|
||||||
{
|
{
|
||||||
const ARPPacket arp_reply {
|
const auto arp_reply = ARPPacket {
|
||||||
.htype = 0x0001,
|
.htype = 0x0001,
|
||||||
.ptype = EtherType::IPv4,
|
.ptype = EtherType::IPv4,
|
||||||
.hlen = 0x06,
|
.hlen = 0x06,
|
||||||
@@ -111,7 +112,7 @@ namespace Kernel
|
|||||||
.tha = packet.sha,
|
.tha = packet.sha,
|
||||||
.tpa = packet.spa,
|
.tpa = packet.spa,
|
||||||
};
|
};
|
||||||
TRY(interface.send_bytes(packet.sha, EtherType::ARP, BAN::ConstByteSpan::from(arp_reply)));
|
TRY(interface.send_with_ethernet_header(packet.sha, EtherType::ARP, BAN::ConstByteSpan::from(arp_reply)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ namespace Kernel
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> E1000::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload)
|
BAN::ErrorOr<void> E1000::send_raw_bytes(BAN::Span<const BAN::ConstByteSpan> buffers)
|
||||||
{
|
{
|
||||||
const auto interrupt_state = Processor::get_interrupt_state();
|
const auto interrupt_state = Processor::get_interrupt_state();
|
||||||
Processor::set_interrupt_state(InterruptState::Disabled);
|
Processor::set_interrupt_state(InterruptState::Disabled);
|
||||||
@@ -293,15 +293,10 @@ namespace Kernel
|
|||||||
|
|
||||||
auto* tx_buffer = reinterpret_cast<uint8_t*>(m_tx_buffer_region->vaddr() + E1000_TX_BUFFER_SIZE * tx_current);
|
auto* tx_buffer = reinterpret_cast<uint8_t*>(m_tx_buffer_region->vaddr() + E1000_TX_BUFFER_SIZE * tx_current);
|
||||||
|
|
||||||
auto& ethernet_header = *reinterpret_cast<EthernetHeader*>(tx_buffer);
|
size_t packet_size = 0;
|
||||||
ethernet_header.dst_mac = destination;
|
for (const auto& buffer : buffers)
|
||||||
ethernet_header.src_mac = get_mac_address();
|
|
||||||
ethernet_header.ether_type = protocol;
|
|
||||||
|
|
||||||
size_t packet_size = sizeof(EthernetHeader);
|
|
||||||
for (const auto& buffer : payload)
|
|
||||||
{
|
{
|
||||||
ASSERT(packet_size + buffer.size() < E1000_TX_BUFFER_SIZE);
|
ASSERT(packet_size + buffer.size() <= E1000_TX_BUFFER_SIZE);
|
||||||
memcpy(tx_buffer + packet_size, buffer.data(), buffer.size());
|
memcpy(tx_buffer + packet_size, buffer.data(), buffer.size());
|
||||||
packet_size += buffer.size();
|
packet_size += buffer.size();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ namespace Kernel
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> IPv4Layer::sendto(NetworkSocket& socket, BAN::ConstByteSpan payload, const sockaddr* address, socklen_t address_len)
|
BAN::ErrorOr<void> IPv4Layer::sendto(NetworkSocket& socket, BAN::ConstByteSpan payload, const sockaddr* address, socklen_t address_len)
|
||||||
{
|
{
|
||||||
if (address->sa_family != AF_INET)
|
if (address->sa_family != AF_INET)
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
@@ -224,20 +224,18 @@ namespace Kernel
|
|||||||
};
|
};
|
||||||
|
|
||||||
uint8_t protocol_header_buffer[32];
|
uint8_t protocol_header_buffer[32];
|
||||||
ASSERT(socket.protocol_header_size() < sizeof(protocol_header_buffer));
|
|
||||||
|
|
||||||
auto protocol_header = BAN::ByteSpan::from(protocol_header_buffer).slice(0, socket.protocol_header_size());
|
auto protocol_header = BAN::ByteSpan::from(protocol_header_buffer).slice(0, socket.protocol_header_size());
|
||||||
socket.get_protocol_header(protocol_header, payload, dst_port, pseudo_header);
|
socket.get_protocol_header(protocol_header, payload, dst_port, pseudo_header);
|
||||||
|
|
||||||
BAN::ConstByteSpan buffers[] {
|
const BAN::ConstByteSpan buffers[] {
|
||||||
BAN::ConstByteSpan::from(ipv4_header),
|
BAN::ConstByteSpan::from(ipv4_header),
|
||||||
protocol_header,
|
protocol_header,
|
||||||
payload,
|
payload,
|
||||||
};
|
};
|
||||||
|
|
||||||
TRY(interface->send_bytes(dst_mac, EtherType::IPv4, { buffers, sizeof(buffers) / sizeof(*buffers) }));
|
TRY(interface->send_with_ethernet_header(dst_mac, EtherType::IPv4, buffers));
|
||||||
|
|
||||||
return payload.size();
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> IPv4Layer::handle_ipv4_packet(NetworkInterface& interface, BAN::ConstByteSpan packet)
|
BAN::ErrorOr<void> IPv4Layer::handle_ipv4_packet(NetworkInterface& interface, BAN::ConstByteSpan packet)
|
||||||
@@ -284,34 +282,33 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
case ICMPType::EchoRequest:
|
case ICMPType::EchoRequest:
|
||||||
{
|
{
|
||||||
auto dst_mac = TRY(m_arp_table->get_mac_from_ipv4(interface, src_ipv4));
|
const auto dst_mac = TRY(m_arp_table->get_mac_from_ipv4(interface, src_ipv4));
|
||||||
|
|
||||||
auto send_ipv4_header = get_ipv4_header(
|
const auto send_ipv4_header = get_ipv4_header(
|
||||||
ipv4_data.size(),
|
ipv4_data.size(),
|
||||||
interface.get_ipv4_address(),
|
interface.get_ipv4_address(),
|
||||||
src_ipv4,
|
src_ipv4,
|
||||||
NetworkProtocol::ICMP
|
NetworkProtocol::ICMP
|
||||||
);
|
);
|
||||||
|
|
||||||
ICMPHeader send_icmp_header {
|
auto send_icmp_header = ICMPHeader {
|
||||||
.type = ICMPType::EchoReply,
|
.type = ICMPType::EchoReply,
|
||||||
.code = icmp_header.code,
|
.code = icmp_header.code,
|
||||||
.checksum = 0,
|
.checksum = 0,
|
||||||
.rest = icmp_header.rest,
|
.rest = icmp_header.rest,
|
||||||
};
|
};
|
||||||
|
|
||||||
auto send_payload = ipv4_data.slice(sizeof(ICMPHeader));
|
|
||||||
|
|
||||||
const BAN::ConstByteSpan send_buffers[] {
|
const BAN::ConstByteSpan send_buffers[] {
|
||||||
BAN::ConstByteSpan::from(send_ipv4_header),
|
BAN::ConstByteSpan::from(send_ipv4_header),
|
||||||
BAN::ConstByteSpan::from(send_icmp_header),
|
BAN::ConstByteSpan::from(send_icmp_header),
|
||||||
send_payload
|
ipv4_data.slice(sizeof(ICMPHeader))
|
||||||
};
|
};
|
||||||
auto send_buffers_span = BAN::Span { send_buffers, sizeof(send_buffers) / sizeof(*send_buffers) };
|
|
||||||
|
|
||||||
send_icmp_header.checksum = calculate_internet_checksum(send_buffers_span.slice(1));
|
send_icmp_header.checksum = calculate_internet_checksum({
|
||||||
|
send_buffers + 1, sizeof(send_buffers) / sizeof(*send_buffers) - 1
|
||||||
|
});
|
||||||
|
|
||||||
TRY(interface.send_bytes(dst_mac, EtherType::IPv4, send_buffers_span));
|
TRY(interface.send_with_ethernet_header(dst_mac, EtherType::IPv4, send_buffers));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ namespace Kernel
|
|||||||
Processor::yield();
|
Processor::yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> LoopbackInterface::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload)
|
BAN::ErrorOr<void> LoopbackInterface::send_raw_bytes(BAN::Span<const BAN::ConstByteSpan> buffers)
|
||||||
{
|
{
|
||||||
auto& descriptor =
|
auto& descriptor =
|
||||||
[&]() -> Descriptor&
|
[&]() -> Descriptor&
|
||||||
@@ -73,13 +73,8 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
auto& ethernet_header = *reinterpret_cast<EthernetHeader*>(descriptor.addr);
|
size_t packet_size = 0;
|
||||||
ethernet_header.dst_mac = destination;
|
for (const auto& buffer : buffers)
|
||||||
ethernet_header.src_mac = get_mac_address();
|
|
||||||
ethernet_header.ether_type = protocol;
|
|
||||||
|
|
||||||
size_t packet_size = sizeof(EthernetHeader);
|
|
||||||
for (const auto& buffer : payload)
|
|
||||||
{
|
{
|
||||||
ASSERT(packet_size + buffer.size() <= buffer_size);
|
ASSERT(packet_size + buffer.size() <= buffer_size);
|
||||||
memcpy(descriptor.addr + packet_size, buffer.data(), buffer.size());
|
memcpy(descriptor.addr + packet_size, buffer.data(), buffer.size());
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ namespace Kernel
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> RTL8169::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload)
|
BAN::ErrorOr<void> RTL8169::send_raw_bytes(BAN::Span<const BAN::ConstByteSpan> buffers)
|
||||||
{
|
{
|
||||||
if (!link_up())
|
if (!link_up())
|
||||||
return BAN::Error::from_errno(EADDRNOTAVAIL);
|
return BAN::Error::from_errno(EADDRNOTAVAIL);
|
||||||
@@ -222,14 +222,10 @@ namespace Kernel
|
|||||||
auto* tx_buffer = reinterpret_cast<uint8_t*>(m_tx_buffer_region->vaddr() + tx_current * s_buffer_size);
|
auto* tx_buffer = reinterpret_cast<uint8_t*>(m_tx_buffer_region->vaddr() + tx_current * s_buffer_size);
|
||||||
|
|
||||||
// write packet
|
// write packet
|
||||||
auto& ethernet_header = *reinterpret_cast<EthernetHeader*>(tx_buffer);
|
size_t packet_size = 0;
|
||||||
ethernet_header.dst_mac = destination;
|
for (const auto& buffer : buffers)
|
||||||
ethernet_header.src_mac = get_mac_address();
|
|
||||||
ethernet_header.ether_type = protocol;
|
|
||||||
|
|
||||||
size_t packet_size = sizeof(EthernetHeader);
|
|
||||||
for (const auto& buffer : payload)
|
|
||||||
{
|
{
|
||||||
|
ASSERT(packet_size + buffer.size() <= s_buffer_size);
|
||||||
memcpy(tx_buffer + packet_size, buffer.data(), buffer.size());
|
memcpy(tx_buffer + packet_size, buffer.data(), buffer.size());
|
||||||
packet_size += buffer.size();
|
packet_size += buffer.size();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -224,7 +224,9 @@ namespace Kernel
|
|||||||
address_len = message.msg_namelen;
|
address_len = message.msg_namelen;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRY(m_network_layer.sendto(*this, buffer.span(), address, address_len));
|
TRY(m_network_layer.sendto(*this, buffer.span(), address, address_len));
|
||||||
|
|
||||||
|
return buffer.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> UDPSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len)
|
BAN::ErrorOr<void> UDPSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len)
|
||||||
|
|||||||
Reference in New Issue
Block a user