diff options
author | rdsmith@chromium.org <rdsmith@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-12 16:25:31 +0000 |
---|---|---|
committer | rdsmith@chromium.org <rdsmith@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-12 16:25:31 +0000 |
commit | 314a69b0434608976f13c936b7dc630b5467413c (patch) | |
tree | d4e36bd6e1a4992a328c79c552f624fedafaded5 | |
parent | 761eeca283a00ac9a45c67a5efec1ec0bbf2ef13 (diff) | |
download | chromium_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.cc | 55 | ||||
-rw-r--r-- | net/socket/tcp_client_socket_libevent.h | 51 |
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); }; |