Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: net/socket/tcp_socket_posix.cc

Issue 1376473003: Notify NQE of TCP RTT values (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added throttle on TCP socket notifications (with tests) Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/socket/tcp_socket.h" 5 #include "net/socket/tcp_socket.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <netinet/tcp.h> 8 #include <netinet/tcp.h>
9 #include <sys/socket.h> 9 #include <sys/socket.h>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/files/file_path.h" 12 #include "base/files/file_path.h"
13 #include "base/files/file_util.h" 13 #include "base/files/file_util.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/metrics/histogram_macros.h" 15 #include "base/metrics/histogram_macros.h"
16 #include "base/posix/eintr_wrapper.h" 16 #include "base/posix/eintr_wrapper.h"
17 #include "base/profiler/scoped_tracker.h"
17 #include "base/task_runner_util.h" 18 #include "base/task_runner_util.h"
18 #include "base/threading/worker_pool.h" 19 #include "base/threading/worker_pool.h"
20 #include "base/time/default_tick_clock.h"
19 #include "net/base/address_list.h" 21 #include "net/base/address_list.h"
20 #include "net/base/connection_type_histograms.h" 22 #include "net/base/connection_type_histograms.h"
21 #include "net/base/io_buffer.h" 23 #include "net/base/io_buffer.h"
22 #include "net/base/ip_endpoint.h" 24 #include "net/base/ip_endpoint.h"
23 #include "net/base/net_errors.h" 25 #include "net/base/net_errors.h"
24 #include "net/base/network_activity_monitor.h" 26 #include "net/base/network_activity_monitor.h"
25 #include "net/base/network_change_notifier.h" 27 #include "net/base/network_change_notifier.h"
26 #include "net/base/sockaddr_storage.h" 28 #include "net/base/sockaddr_storage.h"
27 #include "net/socket/socket_net_log_params.h" 29 #include "net/socket/socket_net_log_params.h"
28 #include "net/socket/socket_posix.h" 30 #include "net/socket/socket_posix.h"
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 void CheckSupportAndMaybeEnableTCPFastOpen(bool user_enabled) { 131 void CheckSupportAndMaybeEnableTCPFastOpen(bool user_enabled) {
130 #if defined(OS_LINUX) || defined(OS_ANDROID) 132 #if defined(OS_LINUX) || defined(OS_ANDROID)
131 base::PostTaskAndReplyWithResult( 133 base::PostTaskAndReplyWithResult(
132 base::WorkerPool::GetTaskRunner(/*task_is_slow=*/false).get(), 134 base::WorkerPool::GetTaskRunner(/*task_is_slow=*/false).get(),
133 FROM_HERE, 135 FROM_HERE,
134 base::Bind(SystemSupportsTCPFastOpen), 136 base::Bind(SystemSupportsTCPFastOpen),
135 base::Bind(RegisterTCPFastOpenIntentAndSupport, user_enabled)); 137 base::Bind(RegisterTCPFastOpenIntentAndSupport, user_enabled));
136 #endif 138 #endif
137 } 139 }
138 140
139 TCPSocketPosix::TCPSocketPosix(NetLog* net_log, const NetLog::Source& source) 141 TCPSocketPosix::TCPSocketPosix(
140 : use_tcp_fastopen_(false), 142 scoped_ptr<SocketPerformanceWatcher> socket_performance_watcher,
143 NetLog* net_log,
144 const NetLog::Source& source)
145 : rtt_notifications_minimum_interval_(base::TimeDelta::FromSeconds(1)),
146 socket_performance_watcher_(std::move(socket_performance_watcher)),
147 tick_clock_(new base::DefaultTickClock()),
148 use_tcp_fastopen_(false),
141 tcp_fastopen_write_attempted_(false), 149 tcp_fastopen_write_attempted_(false),
142 tcp_fastopen_connected_(false), 150 tcp_fastopen_connected_(false),
143 tcp_fastopen_status_(TCP_FASTOPEN_STATUS_UNKNOWN), 151 tcp_fastopen_status_(TCP_FASTOPEN_STATUS_UNKNOWN),
144 logging_multiple_connect_attempts_(false), 152 logging_multiple_connect_attempts_(false),
145 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { 153 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {
146 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, 154 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE,
147 source.ToEventParametersCallback()); 155 source.ToEventParametersCallback());
148 } 156 }
149 157
150 TCPSocketPosix::~TCPSocketPosix() { 158 TCPSocketPosix::~TCPSocketPosix() {
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 475
468 void TCPSocketPosix::EndLoggingMultipleConnectAttempts(int net_error) { 476 void TCPSocketPosix::EndLoggingMultipleConnectAttempts(int net_error) {
469 if (logging_multiple_connect_attempts_) { 477 if (logging_multiple_connect_attempts_) {
470 LogConnectEnd(net_error); 478 LogConnectEnd(net_error);
471 logging_multiple_connect_attempts_ = false; 479 logging_multiple_connect_attempts_ = false;
472 } else { 480 } else {
473 NOTREACHED(); 481 NOTREACHED();
474 } 482 }
475 } 483 }
476 484
485 void TCPSocketPosix::SetTickClockForTesting(
486 scoped_ptr<base::TickClock> tick_clock) {
487 tick_clock_.swap(tick_clock);
Ryan Sleevi 2016/04/11 22:06:56 I believe this should be tick_clock_.swap(std::mo
tbansal1 2016/04/12 16:14:33 This gave compilation error: error: non-const lval
488 }
489
477 void TCPSocketPosix::AcceptCompleted(scoped_ptr<TCPSocketPosix>* tcp_socket, 490 void TCPSocketPosix::AcceptCompleted(scoped_ptr<TCPSocketPosix>* tcp_socket,
478 IPEndPoint* address, 491 IPEndPoint* address,
479 const CompletionCallback& callback, 492 const CompletionCallback& callback,
480 int rv) { 493 int rv) {
481 DCHECK_NE(ERR_IO_PENDING, rv); 494 DCHECK_NE(ERR_IO_PENDING, rv);
482 callback.Run(HandleAcceptCompleted(tcp_socket, address, rv)); 495 callback.Run(HandleAcceptCompleted(tcp_socket, address, rv));
483 } 496 }
484 497
485 int TCPSocketPosix::HandleAcceptCompleted( 498 int TCPSocketPosix::HandleAcceptCompleted(
486 scoped_ptr<TCPSocketPosix>* tcp_socket, 499 scoped_ptr<TCPSocketPosix>* tcp_socket,
(...skipping 16 matching lines...) Expand all
503 IPEndPoint* address) { 516 IPEndPoint* address) {
504 DCHECK(accept_socket_); 517 DCHECK(accept_socket_);
505 518
506 SockaddrStorage storage; 519 SockaddrStorage storage;
507 if (accept_socket_->GetPeerAddress(&storage) != OK || 520 if (accept_socket_->GetPeerAddress(&storage) != OK ||
508 !address->FromSockAddr(storage.addr, storage.addr_len)) { 521 !address->FromSockAddr(storage.addr, storage.addr_len)) {
509 accept_socket_.reset(); 522 accept_socket_.reset();
510 return ERR_ADDRESS_INVALID; 523 return ERR_ADDRESS_INVALID;
511 } 524 }
512 525
513 tcp_socket->reset(new TCPSocketPosix(net_log_.net_log(), net_log_.source())); 526 tcp_socket->reset(
527 new TCPSocketPosix(nullptr, net_log_.net_log(), net_log_.source()));
514 (*tcp_socket)->socket_.reset(accept_socket_.release()); 528 (*tcp_socket)->socket_.reset(accept_socket_.release());
515 return OK; 529 return OK;
516 } 530 }
517 531
518 void TCPSocketPosix::ConnectCompleted(const CompletionCallback& callback, 532 void TCPSocketPosix::ConnectCompleted(const CompletionCallback& callback,
519 int rv) const { 533 int rv) {
520 DCHECK_NE(ERR_IO_PENDING, rv); 534 DCHECK_NE(ERR_IO_PENDING, rv);
521 callback.Run(HandleConnectCompleted(rv)); 535 callback.Run(HandleConnectCompleted(rv));
522 } 536 }
523 537
524 int TCPSocketPosix::HandleConnectCompleted(int rv) const { 538 int TCPSocketPosix::HandleConnectCompleted(int rv) {
525 // Log the end of this attempt (and any OS error it threw). 539 // Log the end of this attempt (and any OS error it threw).
526 if (rv != OK) { 540 if (rv != OK) {
527 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, 541 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT,
528 NetLog::IntCallback("os_error", errno)); 542 NetLog::IntCallback("os_error", errno));
529 } else { 543 } else {
530 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT); 544 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT);
545 NotifySocketPerformanceWatcher();
531 } 546 }
532 547
533 // Give a more specific error when the user is offline. 548 // Give a more specific error when the user is offline.
534 if (rv == ERR_ADDRESS_UNREACHABLE && NetworkChangeNotifier::IsOffline()) 549 if (rv == ERR_ADDRESS_UNREACHABLE && NetworkChangeNotifier::IsOffline())
535 rv = ERR_INTERNET_DISCONNECTED; 550 rv = ERR_INTERNET_DISCONNECTED;
536 551
537 if (!logging_multiple_connect_attempts_) 552 if (!logging_multiple_connect_attempts_)
538 LogConnectEnd(rv); 553 LogConnectEnd(rv);
539 554
540 return rv; 555 return rv;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 else 605 else
591 g_tcp_fastopen_has_failed = true; 606 g_tcp_fastopen_has_failed = true;
592 UpdateTCPFastOpenStatusAfterRead(); 607 UpdateTCPFastOpenStatusAfterRead();
593 } 608 }
594 609
595 if (rv < 0) { 610 if (rv < 0) {
596 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR, 611 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR,
597 CreateNetLogSocketErrorCallback(rv, errno)); 612 CreateNetLogSocketErrorCallback(rv, errno));
598 return rv; 613 return rv;
599 } 614 }
615 NotifySocketPerformanceWatcher();
616
600 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, rv, 617 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, rv,
601 buf->data()); 618 buf->data());
602 NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(rv); 619 NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(rv);
603 620
604 return rv; 621 return rv;
605 } 622 }
606 623
607 void TCPSocketPosix::WriteCompleted(const scoped_refptr<IOBuffer>& buf, 624 void TCPSocketPosix::WriteCompleted(const scoped_refptr<IOBuffer>& buf,
608 const CompletionCallback& callback, 625 const CompletionCallback& callback,
609 int rv) { 626 int rv) {
(...skipping 11 matching lines...) Expand all
621 // FastOpen is turned off on _any_ error. Implement optimizations, 638 // FastOpen is turned off on _any_ error. Implement optimizations,
622 // such as turning off TCP FastOpen on more specific errors, and 639 // such as turning off TCP FastOpen on more specific errors, and
623 // re-attempting TCP FastOpen after a certain amount of time has passed. 640 // re-attempting TCP FastOpen after a certain amount of time has passed.
624 tcp_fastopen_status_ = TCP_FASTOPEN_ERROR; 641 tcp_fastopen_status_ = TCP_FASTOPEN_ERROR;
625 g_tcp_fastopen_has_failed = true; 642 g_tcp_fastopen_has_failed = true;
626 } 643 }
627 net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR, 644 net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR,
628 CreateNetLogSocketErrorCallback(rv, errno)); 645 CreateNetLogSocketErrorCallback(rv, errno));
629 return rv; 646 return rv;
630 } 647 }
648 NotifySocketPerformanceWatcher();
649
631 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, rv, 650 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, rv,
632 buf->data()); 651 buf->data());
633 NetworkActivityMonitor::GetInstance()->IncrementBytesSent(rv); 652 NetworkActivityMonitor::GetInstance()->IncrementBytesSent(rv);
634 return rv; 653 return rv;
635 } 654 }
636 655
637 int TCPSocketPosix::TcpFastOpenWrite(IOBuffer* buf, 656 int TCPSocketPosix::TcpFastOpenWrite(IOBuffer* buf,
638 int buf_len, 657 int buf_len,
639 const CompletionCallback& callback) { 658 const CompletionCallback& callback) {
640 SockaddrStorage storage; 659 SockaddrStorage storage;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
688 // turning off TCP FastOpen on more specific errors. 707 // turning off TCP FastOpen on more specific errors.
689 tcp_fastopen_status_ = TCP_FASTOPEN_ERROR; 708 tcp_fastopen_status_ = TCP_FASTOPEN_ERROR;
690 g_tcp_fastopen_has_failed = true; 709 g_tcp_fastopen_has_failed = true;
691 return rv; 710 return rv;
692 } 711 }
693 712
694 tcp_fastopen_status_ = TCP_FASTOPEN_SLOW_CONNECT_RETURN; 713 tcp_fastopen_status_ = TCP_FASTOPEN_SLOW_CONNECT_RETURN;
695 return socket_->WaitForWrite(buf, buf_len, callback); 714 return socket_->WaitForWrite(buf, buf_len, callback);
696 } 715 }
697 716
717 void TCPSocketPosix::NotifySocketPerformanceWatcher() {
718 #if defined(TCP_INFO)
719 // TODO(tbansal): Remove ScopedTracker once crbug.com/590254 is fixed.
720 tracked_objects::ScopedTracker tracking_profile(
721 FROM_HERE_WITH_EXPLICIT_FUNCTION(
722 "590254 TCPSocketPosix::NotifySocketPerformanceWatcher"));
723
724 const base::TimeTicks now_ticks = tick_clock_->NowTicks();
725 // Do not notify |socket_performance_watcher_| if the last notification was
726 // recent than |rtt_notifications_minimum_interval_| ago. This helps in
727 // reducing the overall overhead of the tcp_info syscalls.
728 if (now_ticks - last_rtt_notification_ < rtt_notifications_minimum_interval_)
729 return;
730
731 // Check if |socket_performance_watcher_| is interested in receiving a RTT
732 // update notification.
733 if (!socket_performance_watcher_ ||
734 !socket_performance_watcher_->ShouldNotifyUpdatedRTT()) {
735 return;
736 }
737
738 tcp_info info;
739 if (!GetTcpInfo(socket_->socket_fd(), &info))
740 return;
741
742 // Only notify the |socket_performance_watcher_| if the RTT in |tcp_info|
743 // struct was populated. A value of 0 may be valid in certain cases
744 // (on very fast networks), but it is discarded. This means that
745 // some of the RTT values may be missed, but the values that are kept are
746 // guaranteed to be correct.
747 if (info.tcpi_rtt == 0 && info.tcpi_rttvar == 0)
748 return;
749
750 socket_performance_watcher_->OnUpdatedRTTAvailable(
751 base::TimeDelta::FromMicroseconds(info.tcpi_rtt));
752 last_rtt_notification_ = now_ticks;
753 #endif // defined(TCP_INFO)
754 }
755
698 void TCPSocketPosix::UpdateTCPFastOpenStatusAfterRead() { 756 void TCPSocketPosix::UpdateTCPFastOpenStatusAfterRead() {
699 DCHECK(tcp_fastopen_status_ == TCP_FASTOPEN_FAST_CONNECT_RETURN || 757 DCHECK(tcp_fastopen_status_ == TCP_FASTOPEN_FAST_CONNECT_RETURN ||
700 tcp_fastopen_status_ == TCP_FASTOPEN_SLOW_CONNECT_RETURN); 758 tcp_fastopen_status_ == TCP_FASTOPEN_SLOW_CONNECT_RETURN);
701 759
702 if (tcp_fastopen_write_attempted_ && !tcp_fastopen_connected_) { 760 if (tcp_fastopen_write_attempted_ && !tcp_fastopen_connected_) {
703 // TCP FastOpen connect-with-write was attempted, and failed. 761 // TCP FastOpen connect-with-write was attempted, and failed.
704 tcp_fastopen_status_ = 762 tcp_fastopen_status_ =
705 (tcp_fastopen_status_ == TCP_FASTOPEN_FAST_CONNECT_RETURN ? 763 (tcp_fastopen_status_ == TCP_FASTOPEN_FAST_CONNECT_RETURN ?
706 TCP_FASTOPEN_FAST_CONNECT_READ_FAILED : 764 TCP_FASTOPEN_FAST_CONNECT_READ_FAILED :
707 TCP_FASTOPEN_SLOW_CONNECT_READ_FAILED); 765 TCP_FASTOPEN_SLOW_CONNECT_READ_FAILED);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 if (info.tcpi_rtt > 0) { 807 if (info.tcpi_rtt > 0) {
750 *out_rtt = base::TimeDelta::FromMicroseconds(info.tcpi_rtt); 808 *out_rtt = base::TimeDelta::FromMicroseconds(info.tcpi_rtt);
751 return true; 809 return true;
752 } 810 }
753 } 811 }
754 #endif // defined(TCP_INFO) 812 #endif // defined(TCP_INFO)
755 return false; 813 return false;
756 } 814 }
757 815
758 } // namespace net 816 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698