[newlib-cygwin] Cygwin: tcp: Support TCP_QUICKACK

Corinna Vinschen corinna@sourceware.org
Wed Jul 1 19:28:05 GMT 2020


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=ee2292413792f0360d357bc200c5e947eae516e6

commit ee2292413792f0360d357bc200c5e947eae516e6
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Wed Jul 1 21:26:59 2020 +0200

    Cygwin: tcp: Support TCP_QUICKACK
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/fhandler.h              |  1 +
 winsup/cygwin/fhandler_socket_inet.cc | 45 +++++++++++++++++++++++++++++++++++
 winsup/cygwin/include/netinet/tcp.h   |  3 +++
 3 files changed, 49 insertions(+)

diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 24184dacc..7a28adc16 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -719,6 +719,7 @@ class fhandler_socket_inet: public fhandler_socket_wsock
 {
  private:
   bool oobinline;	/* True if option SO_OOBINLINE is set */
+  bool tcp_quickack;	/* True if quickack is enabled */
   bool tcp_fastopen;	/* True if TCP_FASTOPEN is set on older systems */
   int  tcp_keepidle;	/* TCP_KEEPIDLE value in secs on older systems */
   int  tcp_keepcnt;	/* TCP_KEEPCNT value on older systems */
diff --git a/winsup/cygwin/fhandler_socket_inet.cc b/winsup/cygwin/fhandler_socket_inet.cc
index 6b6b63d83..74c415d60 100644
--- a/winsup/cygwin/fhandler_socket_inet.cc
+++ b/winsup/cygwin/fhandler_socket_inet.cc
@@ -693,6 +693,7 @@ fhandler_socket_wsock::set_socket_handle (SOCKET sock, int af, int type,
 fhandler_socket_inet::fhandler_socket_inet () :
   fhandler_socket_wsock (),
   oobinline (false),
+  tcp_quickack (false),
   tcp_fastopen (false),
   tcp_keepidle (7200),	/* WinSock default */
   tcp_keepcnt (10),	/* WinSock default */
@@ -1579,6 +1580,10 @@ fhandler_socket_wsock::writev (const struct iovec *const iov, const int iovcnt,
 #define TCP_MAXRT	      5	/* Older systems don't support TCP_MAXRTMS
 				   TCP_MAXRT takes secs, not msecs. */
 
+#ifndef SIO_TCP_SET_ACK_FREQUENCY
+#define SIO_TCP_SET_ACK_FREQUENCY	_WSAIOW(IOC_VENDOR,23)
+#endif
+
 #define MAX_TCP_KEEPIDLE  32767
 #define MAX_TCP_KEEPCNT     255
 #define MAX_TCP_KEEPINTVL 32767
@@ -1767,6 +1772,41 @@ fhandler_socket_inet::setsockopt (int level, int optname, const void *optval,
 	  ignore = true;
 	  break;
 
+	case TCP_QUICKACK:
+	  /* Various sources on the net claim that TCP_QUICKACK is supported
+	     by Windows, even using the same optname value of 12.  However,
+	     the ws2ipdef.h header calls this option TCP_CONGESTION_ALGORITHM
+	     and there's no official statement, nor official documentation
+	     confirming or denying this option is equivalent to Linux'
+	     TCP_QUICKACK.  Also, weirdly, this option takes values from 0..7.
+
+	     There is another undocumented option to WSAIoctl called
+	     SIO_TCP_SET_ACK_FREQUENCY which is already used by some
+	     projects, so we're going to use it here, too, for now.
+
+	     There's an open issue in the dotnet github,
+	     https://github.com/dotnet/runtime/issues/798
+	     Hopefully this clarifies the situation in the not too distant
+	     future... */
+	  {
+	    DWORD dummy;
+	    /* https://stackoverflow.com/questions/55034112/c-disable-delayed-ack-on-windows
+	       claims that valid values for SIO_TCP_SET_ACK_FREQUENCY are
+	       1..255.  In contrast to that, my own testing shows that
+	       valid values are 0 and 1 exclusively. */
+	    int freq = !!*(int *) optval;
+	    if (WSAIoctl (get_socket (), SIO_TCP_SET_ACK_FREQUENCY, &freq,
+			  sizeof freq, NULL, 0, &dummy, NULL, NULL)
+		== SOCKET_ERROR)
+	      {
+		set_winsock_errno ();
+		return -1;
+	      }
+	    ignore = true;
+	    tcp_quickack = freq ? true : false;
+	  }
+	  break;
+
 	case TCP_MAXRT:
 	  /* Don't let this option slip through from user space. */
 	  set_errno (EOPNOTSUPP);
@@ -1983,6 +2023,11 @@ fhandler_socket_inet::getsockopt (int level, int optname, const void *optval,
 
       switch (optname)
 	{
+	case TCP_QUICKACK:
+	  *(int *) optval = tcp_quickack ? 1 : 0;
+	  *optlen = sizeof (int);
+	  return 0;
+
 	case TCP_MAXRT:
 	  /* Don't let this option slip through from user space. */
 	  set_errno (EOPNOTSUPP);
diff --git a/winsup/cygwin/include/netinet/tcp.h b/winsup/cygwin/include/netinet/tcp.h
index 8ccb0dfaa..7e4f5bbd6 100644
--- a/winsup/cygwin/include/netinet/tcp.h
+++ b/winsup/cygwin/include/netinet/tcp.h
@@ -126,6 +126,9 @@ struct tcphdr {
 #define TCP_NODELAY      0x01   /* don't delay send to coalesce packets */
 #define TCP_KEEPIDLE     0x03   /* start keepalives after this period */
 #define TCP_MAXSEG       0x04   /* get maximum segment size (r/o on windows) */
+#define TCP_QUICKACK     0x0c   /* block/reenable quick acks
+				   (TCP_CONGESTION_ALGORITHM in ws2ipdef.h,
+				    valid vals 0 - 7, unclear if equivalent) */
 #define TCP_USER_TIMEOUT 0x0e   /* how long for loss retry before timeout,
 				   like WinSock TCP_MAXRTMS/TCP_MAXRT */
 #define TCP_FASTOPEN     0x0f   /* enable FastOpen on listeners */


More information about the Cygwin-cvs mailing list