Forráskód Böngészése

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.
Gunnar Beutner 4 éve
szülő
commit
c6299d1e5d
2 módosított fájl, 10 hozzáadás és 4 törlés
  1. 9 3
      Kernel/Net/TCPSocket.cpp
  2. 1 1
      Kernel/Net/TCPSocket.h

+ 9 - 3
Kernel/Net/TCPSocket.cpp

@@ -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;
 

+ 1 - 1
Kernel/Net/TCPSocket.h

@@ -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;