mirror of
https://github.com/fergalmoran/ladybird.git
synced 2026-02-25 09:04:53 +00:00
Kernel: Avoid allocations when sending IP packets
Previously we'd allocate buffers when sending packets. This patch avoids these allocations by using the NetworkAdapter's packet queue. At the same time this also avoids copying partially constructed packets in order to prepend Ethernet and/or IPv4 headers. It also properly truncates UDP and raw IP packets.
This commit is contained in:
committed by
Andreas Kling
parent
f8310b7796
commit
b436dd138b
@@ -78,19 +78,23 @@ KResultOr<size_t> UDPSocket::protocol_send(const UserOrKernelBuffer& data, size_
|
||||
auto routing_decision = route_to(peer_address(), local_address(), bound_interface());
|
||||
if (routing_decision.is_zero())
|
||||
return EHOSTUNREACH;
|
||||
const size_t buffer_size = sizeof(UDPPacket) + data_length;
|
||||
auto buffer = ByteBuffer::create_zeroed(buffer_size);
|
||||
auto& udp_packet = *reinterpret_cast<UDPPacket*>(buffer.data());
|
||||
auto ipv4_payload_offset = routing_decision.adapter->ipv4_payload_offset();
|
||||
data_length = min(data_length, routing_decision.adapter->mtu() - ipv4_payload_offset - sizeof(UDPPacket));
|
||||
const size_t udp_buffer_size = sizeof(UDPPacket) + data_length;
|
||||
auto packet = routing_decision.adapter->acquire_packet_buffer(ipv4_payload_offset + udp_buffer_size);
|
||||
if (!packet)
|
||||
return ENOMEM;
|
||||
memset(packet->buffer.data() + ipv4_payload_offset, 0, sizeof(UDPPacket));
|
||||
auto& udp_packet = *reinterpret_cast<UDPPacket*>(packet->buffer.data() + ipv4_payload_offset);
|
||||
udp_packet.set_source_port(local_port());
|
||||
udp_packet.set_destination_port(peer_port());
|
||||
udp_packet.set_length(buffer_size);
|
||||
udp_packet.set_length(udp_buffer_size);
|
||||
if (!data.read(udp_packet.payload(), data_length))
|
||||
return EFAULT;
|
||||
|
||||
auto result = routing_decision.adapter->send_ipv4(local_address(), routing_decision.next_hop,
|
||||
peer_address(), IPv4Protocol::UDP, UserOrKernelBuffer::for_kernel_buffer(buffer.data()), buffer_size, ttl());
|
||||
if (result.is_error())
|
||||
return result;
|
||||
routing_decision.adapter->fill_in_ipv4_header(*packet, local_address(), routing_decision.next_hop,
|
||||
peer_address(), IPv4Protocol::UDP, udp_buffer_size, ttl());
|
||||
routing_decision.adapter->send_raw({ packet->buffer.data(), packet->buffer.size() });
|
||||
return data_length;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user