[haiku-bugs] Re: [Haiku] #13681: tcp: 2018: implementing TCP SACK option

  • From: "Haiku" <trac@xxxxxxxxxxxx>
  • To: undisclosed-recipients: ;
  • Date: Fri, 15 Oct 2021 23:46:25 -0000

#13681: tcp: 2018: implementing TCP SACK option
-------------------------------------+----------------------------
  Reporter:  a-star                  |      Owner:  axeld
      Type:  enhancement             |     Status:  closed
  Priority:  normal                  |  Milestone:  R1/beta3
 Component:  Network & Internet/TCP  |    Version:  R1/Development
Resolution:  fixed                   |   Keywords:  tcp, sack
Blocked By:                          |   Blocking:
  Platform:  All                     |
-------------------------------------+----------------------------
Comment (by Skik):

 TCP functionality breaks with TCP SACK option due to my company firewall
 (SonicWall) thinking its an invalid Option #4 and dropping the packet.
 Looking at reference packet captures
 https://packetlife.net/media/captures/TCP_SACK.cap and local Linux packet
 captures. The SACK option is sent before the TCP Timestamp option and used
 as padding instead of the two NOP Options.

 I reordered the operations and also added padding when there is no
 SACK_PERMITTED. And TCP works now with my company firewall. This is
 attached as a reference. I am sure there is a better way to handle it.

 {{{
 diff --git a/src/add-ons/kernel/network/protocols/tcp/tcp.cpp b/src/add-
 ons/kernel/network/protocols/tcp/tcp.cpp
 index 5ad4014dfc..5449a35b2e 100644
 --- a/src/add-ons/kernel/network/protocols/tcp/tcp.cpp
 +++ b/src/add-ons/kernel/network/protocols/tcp/tcp.cpp
 @@ -106,13 +106,25 @@ add_options(tcp_segment_header &segment, uint8
 *buffer, size_t bufferSize)
                 bump_option(option, length);
         }

 +       if ((segment.options & TCP_SACK_PERMITTED) != 0
 +               && length + 2 <= bufferSize) {
 +               option->kind = TCP_OPTION_SACK_PERMITTED;
 +               option->length = 2;
 +               bump_option(option, length);
 +       }
 +
         if ((segment.options & TCP_HAS_TIMESTAMPS) != 0
 -               && length + 12 <= bufferSize) {
 -               // two NOPs so the timestamps get aligned to a 4 byte
 boundary
 +               && (segment.options & TCP_SACK_PERMITTED) == 0
 +               && length + 2 <= bufferSize) {
 +               // two NOPs so the timestamps get aligned to a 4 byte
 boundary when no SACK
                 option->kind = TCP_OPTION_NOP;
                 bump_option(option, length);
                 option->kind = TCP_OPTION_NOP;
                 bump_option(option, length);
 +       }
 +
 +       if ((segment.options & TCP_HAS_TIMESTAMPS) != 0
 +               && length + 10 <= bufferSize) {
                 option->kind = TCP_OPTION_TIMESTAMP;
                 option->length = 10;
                 option->timestamp.value = htonl(segment.timestamp_value);
 @@ -132,13 +144,6 @@ add_options(tcp_segment_header &segment, uint8
 *buffer, size_t bufferSize)
                 bump_option(option, length);
         }

 -       if ((segment.options & TCP_SACK_PERMITTED) != 0
 -               && length + 2 <= bufferSize) {
 -               option->kind = TCP_OPTION_SACK_PERMITTED;
 -               option->length = 2;
 -               bump_option(option, length);
 -       }
 -
         if (segment.sackCount > 0) {
                 int sackCount = ((int)(bufferSize - length) - 4) /
 sizeof(tcp_sack);
                 if (sackCount > segment.sackCount)
 @@ -435,15 +440,15 @@ tcp_options_length(tcp_segment_header& segment)
         if (segment.max_segment_size > 0)
                 length += 4;

 +       if (segment.options & TCP_SACK_PERMITTED)
 +               length += 2;
 +
         if (segment.options & TCP_HAS_TIMESTAMPS)
 -               length += 12;
 +               length += (segment.options & TCP_SACK_PERMITTED) ? 10 :
 12;

         if (segment.options & TCP_HAS_WINDOW_SCALE)
                 length += 4;

 -       if (segment.options & TCP_SACK_PERMITTED)
 -               length += 2;
 -
         if (segment.sackCount > 0) {
                 int sackCount = min_c((int)((kMaxOptionSize - length - 4)
                         / sizeof(tcp_sack)), segment.sackCount);

 }}}
-- 
Ticket URL: <https://dev.haiku-os.org/ticket/13681#comment:11>
Haiku <https://dev.haiku-os.org>
The Haiku operating system.

Other related posts: