mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-23 18:02:05 -05: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/Devices/RandomDevice.h>
|
||||
#include <Kernel/FileSystem/FileDescription.h>
|
||||
#include <Kernel/Net/EthernetFrameHeader.h>
|
||||
#include <Kernel/Net/IPv4.h>
|
||||
#include <Kernel/Net/NetworkAdapter.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)
|
||||
{
|
||||
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)
|
||||
return KResult((ErrnoCode)-err);
|
||||
return data_length;
|
||||
|
@ -180,7 +186,7 @@ KResult TCPSocket::send_ack(bool allow_duplicate)
|
|||
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 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;
|
||||
}
|
||||
|
||||
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())
|
||||
return EHOSTUNREACH;
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ public:
|
|||
u32 duplicate_acks() const { return m_duplicate_acks; }
|
||||
|
||||
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);
|
||||
|
||||
bool should_delay_next_ack() const;
|
||||
|
|
Loading…
Add table
Reference in a new issue