summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrdsmith@chromium.org <rdsmith@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-12 16:25:31 +0000
committerrdsmith@chromium.org <rdsmith@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-12 16:25:31 +0000
commit314a69b0434608976f13c936b7dc630b5467413c (patch)
treed4e36bd6e1a4992a328c79c552f624fedafaded5
parent761eeca283a00ac9a45c67a5efec1ec0bbf2ef13 (diff)
downloadchromium_src-314a69b0434608976f13c936b7dc630b5467413c.zip
chromium_src-314a69b0434608976f13c936b7dc630b5467413c.tar.gz
chromium_src-314a69b0434608976f13c936b7dc630b5467413c.tar.bz2
Initial attempt at fast open UMA.
BUG=175623 R=rch@chromium.org R=ycheng@google.com Review URL: https://chromiumcodereview.appspot.com/13730013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@193949 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--net/socket/tcp_client_socket_libevent.cc55
-rw-r--r--net/socket/tcp_client_socket_libevent.h51
2 files changed, 102 insertions, 4 deletions
diff --git a/net/socket/tcp_client_socket_libevent.cc b/net/socket/tcp_client_socket_libevent.cc
index e045e89..f98ca37 100644
--- a/net/socket/tcp_client_socket_libevent.cc
+++ b/net/socket/tcp_client_socket_libevent.cc
@@ -15,6 +15,7 @@
#include "base/logging.h"
#include "base/message_loop.h"
+#include "base/metrics/histogram.h"
#include "base/metrics/stats_counters.h"
#include "base/posix/eintr_wrapper.h"
#include "base/string_util.h"
@@ -27,6 +28,11 @@
#include "net/base/network_change_notifier.h"
#include "net/socket/socket_net_log_params.h"
+// If we don't have a definition for TCPI_OPT_SYN_DATA, create one.
+#ifndef TCPI_OPT_SYN_DATA
+#define TCPI_OPT_SYN_DATA 32
+#endif
+
namespace net {
namespace {
@@ -137,7 +143,8 @@ TCPClientSocketLibevent::TCPClientSocketLibevent(
net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)),
previously_disconnected_(false),
use_tcp_fastopen_(IsTCPFastOpenEnabled()),
- tcp_fastopen_connected_(false) {
+ tcp_fastopen_connected_(false),
+ fast_open_status_(FAST_OPEN_STATUS_UNKNOWN) {
net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE,
source.ToEventParametersCallback());
}
@@ -145,6 +152,10 @@ TCPClientSocketLibevent::TCPClientSocketLibevent(
TCPClientSocketLibevent::~TCPClientSocketLibevent() {
Disconnect();
net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE);
+ if (tcp_fastopen_connected_) {
+ UMA_HISTOGRAM_ENUMERATION("Net.TcpFastOpenSocketConnection",
+ fast_open_status_, FAST_OPEN_MAX_VALUE);
+ }
}
int TCPClientSocketLibevent::AdoptSocket(int socket) {
@@ -432,6 +443,37 @@ int TCPClientSocketLibevent::Read(IOBuffer* buf,
DCHECK(!callback.is_null());
DCHECK_GT(buf_len, 0);
+ if (use_tcp_fastopen_ &&
+ (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN ||
+ fast_open_status_ == FAST_OPEN_SLOW_CONNECT_RETURN)) {
+ DCHECK_NE(FAST_OPEN_STATUS_UNKNOWN, fast_open_status_);
+ bool getsockopt_success(false);
+ bool server_acked_data(false);
+#if defined(TCP_INFO)
+ // Probe to see the if the socket used TCP Fast Open.
+ tcp_info info;
+ socklen_t info_len = sizeof(tcp_info);
+ getsockopt_success =
+ getsockopt(socket_, IPPROTO_TCP, TCP_INFO, &info, &info_len) == 0 &&
+ info_len == sizeof(tcp_info);
+ server_acked_data = getsockopt_success &&
+ (info.tcpi_options & TCPI_OPT_SYN_DATA);
+#endif
+ if (getsockopt_success) {
+ if (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN) {
+ fast_open_status_ = (server_acked_data ? FAST_OPEN_SYN_DATA_ACK :
+ FAST_OPEN_SYN_DATA_NACK);
+ } else {
+ fast_open_status_ = (server_acked_data ? FAST_OPEN_NO_SYN_DATA_ACK :
+ FAST_OPEN_NO_SYN_DATA_NACK);
+ }
+ } else {
+ fast_open_status_ = (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN ?
+ FAST_OPEN_SYN_DATA_FAILED :
+ FAST_OPEN_NO_SYN_DATA_FAILED);
+ }
+ }
+
int nread = HANDLE_EINTR(read(socket_, buf->data(), buf_len));
if (nread >= 0) {
base::StatsCounter read_bytes("tcp.read_bytes");
@@ -537,9 +579,14 @@ int TCPClientSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) {
// Remap EINPROGRESS to EAGAIN so we treat this the same as our other
// asynchronous cases. Note that the user buffer has not been copied to
// kernel space.
- if (errno == EINPROGRESS)
- errno = EAGAIN;
-
+ if (errno == EINPROGRESS) {
+ errno = EAGAIN;
+ fast_open_status_ = FAST_OPEN_SLOW_CONNECT_RETURN;
+ } else {
+ fast_open_status_ = FAST_OPEN_ERROR;
+ }
+ } else {
+ fast_open_status_ = FAST_OPEN_FAST_CONNECT_RETURN;
}
} else {
nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len));
diff --git a/net/socket/tcp_client_socket_libevent.h b/net/socket/tcp_client_socket_libevent.h
index 2ac1d6d..2533300 100644
--- a/net/socket/tcp_client_socket_libevent.h
+++ b/net/socket/tcp_client_socket_libevent.h
@@ -80,6 +80,55 @@ class NET_EXPORT_PRIVATE TCPClientSocketLibevent : public StreamSocket,
CONNECT_STATE_NONE,
};
+ // States that a fast open socket attempt can result in.
+ enum FastOpenStatus {
+ FAST_OPEN_STATUS_UNKNOWN,
+
+ // The initial fast open connect attempted returned synchronously,
+ // indicating that we had and sent a cookie along with the initial data.
+ FAST_OPEN_FAST_CONNECT_RETURN,
+
+ // The initial fast open connect attempted returned asynchronously,
+ // indicating that we did not have a cookie for the server.
+ FAST_OPEN_SLOW_CONNECT_RETURN,
+
+ // Some other error occurred on connection, so we couldn't tell if
+ // fast open would have worked.
+ FAST_OPEN_ERROR,
+
+ // An attempt to do a fast open succeeded immediately
+ // (FAST_OPEN_FAST_CONNECT_RETURN) and we later confirmed that the server
+ // had acked the data we sent.
+ FAST_OPEN_SYN_DATA_ACK,
+
+ // An attempt to do a fast open succeeded immediately
+ // (FAST_OPEN_FAST_CONNECT_RETURN) and we later confirmed that the server
+ // had nacked the data we sent.
+ FAST_OPEN_SYN_DATA_NACK,
+
+ // An attempt to do a fast open succeeded immediately
+ // (FAST_OPEN_FAST_CONNECT_RETURN) and our probe to determine if the
+ // socket was using fast open failed.
+ FAST_OPEN_SYN_DATA_FAILED,
+
+ // An attempt to do a fast open failed (FAST_OPEN_SLOW_CONNECT_RETURN)
+ // and we later confirmed that the server had acked initial data. This
+ // should never happen (we didn't send data, so it shouldn't have
+ // been acked).
+ FAST_OPEN_NO_SYN_DATA_ACK,
+
+ // An attempt to do a fast open failed (FAST_OPEN_SLOW_CONNECT_RETURN)
+ // and we later discovered that the server had nacked initial data. This
+ // is the expected case results for FAST_OPEN_SLOW_CONNECT_RETURN.
+ FAST_OPEN_NO_SYN_DATA_NACK,
+
+ // An attempt to do a fast open failed (FAST_OPEN_SLOW_CONNECT_RETURN)
+ // and our later probe for ack/nack state failed.
+ FAST_OPEN_NO_SYN_DATA_FAILED,
+
+ FAST_OPEN_MAX_VALUE
+ };
+
class ReadWatcher : public MessageLoopForIO::Watcher {
public:
explicit ReadWatcher(TCPClientSocketLibevent* socket) : socket_(socket) {}
@@ -194,6 +243,8 @@ class NET_EXPORT_PRIVATE TCPClientSocketLibevent : public StreamSocket,
// True when TCP FastOpen is in use and we have done the connect.
bool tcp_fastopen_connected_;
+ enum FastOpenStatus fast_open_status_;
+
DISALLOW_COPY_AND_ASSIGN(TCPClientSocketLibevent);
};