mirror of
https://github.com/RGBCube/serenity
synced 2025-07-23 19:37:34 +00:00
Kernel: Don't try to send TCP packets larger than the MSS
Previously TCPSocket::send_tcp_packet() would try to send TCP packets which matched whatever size the userspace program specified. We'd try to break those packets up into smaller fragments, however a much better approach is to limit TCP packets to the maximum segment size and avoid fragmentation altogether.
This commit is contained in:
parent
dce97678ae
commit
c6299d1e5d
2 changed files with 10 additions and 4 deletions
|
@ -9,6 +9,7 @@
|
||||||
#include <Kernel/Debug.h>
|
#include <Kernel/Debug.h>
|
||||||
#include <Kernel/Devices/RandomDevice.h>
|
#include <Kernel/Devices/RandomDevice.h>
|
||||||
#include <Kernel/FileSystem/FileDescription.h>
|
#include <Kernel/FileSystem/FileDescription.h>
|
||||||
|
#include <Kernel/Net/EthernetFrameHeader.h>
|
||||||
#include <Kernel/Net/IPv4.h>
|
#include <Kernel/Net/IPv4.h>
|
||||||
#include <Kernel/Net/NetworkAdapter.h>
|
#include <Kernel/Net/NetworkAdapter.h>
|
||||||
#include <Kernel/Net/Routing.h>
|
#include <Kernel/Net/Routing.h>
|
||||||
|
@ -167,7 +168,12 @@ KResultOr<size_t> TCPSocket::protocol_receive(ReadonlyBytes raw_ipv4_packet, Use
|
||||||
|
|
||||||
KResultOr<size_t> TCPSocket::protocol_send(const UserOrKernelBuffer& data, size_t data_length)
|
KResultOr<size_t> TCPSocket::protocol_send(const UserOrKernelBuffer& data, size_t data_length)
|
||||||
{
|
{
|
||||||
int err = send_tcp_packet(TCPFlags::PUSH | TCPFlags::ACK, &data, data_length);
|
RoutingDecision routing_decision = route_to(peer_address(), local_address(), bound_interface());
|
||||||
|
if (routing_decision.is_zero())
|
||||||
|
return EHOSTUNREACH;
|
||||||
|
size_t mss = routing_decision.adapter->mtu() - sizeof(IPv4Packet) - sizeof(TCPPacket);
|
||||||
|
data_length = min(data_length, mss);
|
||||||
|
int err = send_tcp_packet(TCPFlags::PUSH | TCPFlags::ACK, &data, data_length, &routing_decision);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return KResult((ErrnoCode)-err);
|
return KResult((ErrnoCode)-err);
|
||||||
return data_length;
|
return data_length;
|
||||||
|
@ -180,7 +186,7 @@ KResult TCPSocket::send_ack(bool allow_duplicate)
|
||||||
return send_tcp_packet(TCPFlags::ACK);
|
return send_tcp_packet(TCPFlags::ACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
KResult TCPSocket::send_tcp_packet(u16 flags, const UserOrKernelBuffer* payload, size_t payload_size)
|
KResult TCPSocket::send_tcp_packet(u16 flags, const UserOrKernelBuffer* payload, size_t payload_size, RoutingDecision* user_routing_decision)
|
||||||
{
|
{
|
||||||
const bool has_mss_option = flags == TCPFlags::SYN;
|
const bool has_mss_option = flags == TCPFlags::SYN;
|
||||||
const size_t options_size = has_mss_option ? sizeof(TCPOptionMSS) : 0;
|
const size_t options_size = has_mss_option ? sizeof(TCPOptionMSS) : 0;
|
||||||
|
@ -211,7 +217,7 @@ KResult TCPSocket::send_tcp_packet(u16 flags, const UserOrKernelBuffer* payload,
|
||||||
m_sequence_number += payload_size;
|
m_sequence_number += payload_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto routing_decision = route_to(peer_address(), local_address(), bound_interface());
|
RoutingDecision routing_decision = user_routing_decision ? *user_routing_decision : route_to(peer_address(), local_address(), bound_interface());
|
||||||
if (routing_decision.is_zero())
|
if (routing_decision.is_zero())
|
||||||
return EHOSTUNREACH;
|
return EHOSTUNREACH;
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,7 @@ public:
|
||||||
u32 duplicate_acks() const { return m_duplicate_acks; }
|
u32 duplicate_acks() const { return m_duplicate_acks; }
|
||||||
|
|
||||||
KResult send_ack(bool allow_duplicate = false);
|
KResult send_ack(bool allow_duplicate = false);
|
||||||
KResult send_tcp_packet(u16 flags, const UserOrKernelBuffer* = nullptr, size_t = 0);
|
KResult send_tcp_packet(u16 flags, const UserOrKernelBuffer* = nullptr, size_t = 0, RoutingDecision* = nullptr);
|
||||||
void receive_tcp_packet(const TCPPacket&, u16 size);
|
void receive_tcp_packet(const TCPPacket&, u16 size);
|
||||||
|
|
||||||
bool should_delay_next_ack() const;
|
bool should_delay_next_ack() const;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue