++GITWEB_SITE_HTML_HEAD_STRING++

Jan 28, 2014 Warning: This GIT server is deprecated, we have moved to http://github.com/monkey

TCP: Add support for Linux TCP_FASTOPEN (aka TFO)
authorEduardo Silva <edsiper@gmail.com>
Sat, 16 Feb 2013 22:54:11 +0000 (16:54 -0600)
committerEduardo Silva <edsiper@gmail.com>
Sat, 16 Feb 2013 22:54:11 +0000 (16:54 -0600)
Recent Linux Kernels implements a new TCP feature
called TCP_FASTOPEN. This feature reduces the TCP
handshake roundtrip improving performance for new
connections. For more details refer to the following
articles:

 - http://lwn.net/Articles/508865/
 - http://kernelnewbies.org/Linux_3.7#head-cd32b65674184083465d349ad6d772c828fbbd8b

Requirements:

 - the client side must be running Kernel >= 3.6.
 - the server side must be running Kernel >= 3.7.
 - Besides the Kernel version, the client and the server
   must request to use TCP_FASTOPEN/MSG_FASTOPEN in their
   respective calls.
 - the tcp_fastopen flag must be enabled:

      # echo 1 > /proc/sys/net/ipv4/tcp_fastopen

The good thing of this feature is that no matters if
the client implements TFO or not, the server will work
anyways.

This patch enable TCP_FASTOPEN by default in Liana plugin
and also export a new function mk_socket_set_tcp_fastopen()
for generic purposes.

Signed-off-by: Eduardo Silva <edsiper@gmail.com>
plugins/liana/liana.c
src/include/mk_plugin.h
src/include/mk_socket.h
src/mk_plugin.c
src/mk_socket.c

index 7621822..0547ca1 100644 (file)
@@ -175,14 +175,29 @@ int _mkp_network_io_bind(int socket_fd, const struct sockaddr *addr, socklen_t a
     int ret;
 
     ret = bind(socket_fd, addr, addrlen);
-
     if( ret == -1 ) {
         mk_warn("Error binding socket");
         return ret;
     }
 
-    ret = listen(socket_fd, backlog);
+    /*
+     * Enable TCP_FASTOPEN by default: if for some reason this call fail,
+     * it will not affect the behavior of the server, in order to succeed,
+     * Monkey must be running in a Linux system with Kernel >= 3.7 and the
+     * tcp_fastopen flag enabled here:
+     *
+     *     # cat /proc/sys/net/ipv4/tcp_fastopen
+     *
+     * To enable this feature just do:
+     *
+     *     # echo 1 > /proc/sys/net/ipv4/tcp_fastopen
+     */
+    ret = mk_api->socket_set_tcp_fastopen(socket_fd);
+    if (ret != -1) {
+        mk_info("Linux TCP_FASTOPEN");
+    }
 
+    ret = listen(socket_fd, backlog);
     if(ret == -1 ) {
         mk_warn("Error setting up the listener");
         return -1;
index 70ce63a..0f8a41b 100644 (file)
@@ -236,6 +236,7 @@ struct plugin_api
     /* socket functions */
     int (*socket_cork_flag) (int, int);
     int (*socket_reset) (int);
+    int (*socket_set_tcp_fastopen) (int);
     int (*socket_set_tcp_nodelay) (int);
     int (*socket_connect) (char *, int);
     int (*socket_set_nonblocking) (int);
index 64a604f..b023bc3 100644 (file)
@@ -1,3 +1,5 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
 /*  Monkey HTTP Daemon
  *  ------------------
  *  Copyright (C) 2001-2012, Eduardo Silva P. <edsiper@gmail.com>
@@ -21,8 +23,8 @@
 #define MK_SOCKET_H
 
 #include <sys/uio.h>
-#include <netinet/in.h>
 #include <sys/socket.h>
+#include <netinet/in.h>
 
 #include "mk_iov.h"
 
 #define SOCK_NONBLOCK 04000
 #endif
 
+/*
+ * TCP_FASTOPEN: as this is a very new option in the Linux Kernel, the value is
+ * not yet exported and can be missing, lets make sure is available for all
+ * cases:
+ *
+ * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=1046716368979dee857a2b8a91c4a8833f21b9cb
+ */
+#ifndef TCP_FASTOPEN
+#define TCP_FASTOPEN  23
+#endif
+
 #define TCP_CORK_ON 1
 #define TCP_CORK_OFF 0
 
 int mk_socket_set_cork_flag(int fd, int state);
+int mk_socket_set_tcp_fastopen(int sockfd);
 int mk_socket_set_tcp_nodelay(int sockfd);
 int mk_socket_set_tcp_defer_accept(int sockfd);
 int mk_socket_set_nonblocking(int sockfd);
@@ -49,7 +63,7 @@ int mk_socket_accept(int server_fd);
 int mk_socket_sendv(int socket_fd, struct mk_iov *mk_io);
 int mk_socket_send(int socket_fd, const void *buf, size_t count);
 int mk_socket_read(int socket_fd, void *buf, int count);
-int mk_socket_send_file(int socket_fd, int file_fd, off_t *file_offset, 
+int mk_socket_send_file(int socket_fd, int file_fd, off_t *file_offset,
                         size_t file_count);
 int mk_socket_ip_str(int socket_fd, char **buf, int size, unsigned long *len);
 #endif
index 9a147a2..b55cb94 100644 (file)
@@ -377,6 +377,7 @@ void mk_plugin_init()
     api->socket_cork_flag = mk_socket_set_cork_flag;
     api->socket_connect = mk_socket_connect;
     api->socket_reset = mk_socket_reset;
+    api->socket_set_tcp_fastopen = mk_socket_set_tcp_fastopen;
     api->socket_set_tcp_nodelay = mk_socket_set_tcp_nodelay;
     api->socket_set_nonblocking = mk_socket_set_nonblocking;
     api->socket_create = mk_socket_create;
index 7b992d5..c0304fb 100644 (file)
@@ -71,6 +71,19 @@ int mk_socket_set_nonblocking(int sockfd)
     return 0;
 }
 
+/*
+ * Enable the TCP_FASTOPEN feature for server side implemented in Linux Kernel >= 3.7,
+ * for more details read here:
+ *
+ *  TCP Fast Open: expediting web services: http://lwn.net/Articles/508865/
+ */
+
+int mk_socket_set_tcp_fastopen(int sockfd)
+{
+    int qlen = 5;
+    return setsockopt(sockfd, SOL_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen));
+}
+
 int mk_socket_set_tcp_nodelay(int sockfd)
 {
     int on = 1;