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

Side by Side Diff: net/quic/core/quic_buffered_packet_store.cc

Issue 2310543002: Limits only 16 new QUIC connections can be opened per epoll event. (Closed)
Patch Set: Limits only 16 new QUIC connections can be opened per epoll event. Created 4 years, 3 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 (c) 2016 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2016 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/quic/core/quic_buffered_packet_store.h" 5 #include "net/quic/core/quic_buffered_packet_store.h"
6 6
7 #include <list> 7 #include <list>
8 8
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 #include "net/quic/core/quic_bug_tracker.h"
10 11
11 using std::list; 12 using std::list;
12 13
13 namespace net { 14 namespace net {
14 15
15 typedef QuicBufferedPacketStore::BufferedPacket BufferedPacket; 16 typedef QuicBufferedPacketStore::BufferedPacket BufferedPacket;
16 typedef QuicBufferedPacketStore::EnqueuePacketResult EnqueuePacketResult; 17 typedef QuicBufferedPacketStore::EnqueuePacketResult EnqueuePacketResult;
17 typedef QuicBufferedPacketStore::BufferedPacketList BufferedPacketList; 18 typedef QuicBufferedPacketStore::BufferedPacketList BufferedPacketList;
18 19
19 // Max number of connections this store can keep track. 20 // Max number of connections this store can keep track.
20 static const size_t kDefaultMaxConnectionsInStore = 100; 21 static const size_t kDefaultMaxConnectionsInStore = 100;
22 // Up to half of the capacity can be used for storing non-CHLO packets.
23 static const size_t kMaxConnectionsWithoutCHLO =
24 kDefaultMaxConnectionsInStore / 2;
21 25
22 namespace { 26 namespace {
23 27
24 // This alarm removes expired entries in map each time this alarm fires. 28 // This alarm removes expired entries in map each time this alarm fires.
25 class ConnectionExpireAlarm : public QuicAlarm::Delegate { 29 class ConnectionExpireAlarm : public QuicAlarm::Delegate {
26 public: 30 public:
27 explicit ConnectionExpireAlarm(QuicBufferedPacketStore* store) 31 explicit ConnectionExpireAlarm(QuicBufferedPacketStore* store)
28 : connection_store_(store) {} 32 : connection_store_(store) {}
29 33
30 void OnAlarm() override { connection_store_->OnExpirationTimeout(); } 34 void OnAlarm() override { connection_store_->OnExpirationTimeout(); }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 clock_(clock), 75 clock_(clock),
72 expiration_alarm_( 76 expiration_alarm_(
73 alarm_factory->CreateAlarm(new ConnectionExpireAlarm(this))) {} 77 alarm_factory->CreateAlarm(new ConnectionExpireAlarm(this))) {}
74 78
75 QuicBufferedPacketStore::~QuicBufferedPacketStore() {} 79 QuicBufferedPacketStore::~QuicBufferedPacketStore() {}
76 80
77 EnqueuePacketResult QuicBufferedPacketStore::EnqueuePacket( 81 EnqueuePacketResult QuicBufferedPacketStore::EnqueuePacket(
78 QuicConnectionId connection_id, 82 QuicConnectionId connection_id,
79 const QuicReceivedPacket& packet, 83 const QuicReceivedPacket& packet,
80 IPEndPoint server_address, 84 IPEndPoint server_address,
81 IPEndPoint client_address) { 85 IPEndPoint client_address,
82 if (!base::ContainsKey(undecryptable_packets_, connection_id) && IsFull()) { 86 bool is_chlo) {
83 // Drop the packet if store can't keep track of more connections. 87 QUIC_BUG_IF(is_chlo &&
88 base::ContainsKey(connections_with_chlo_, connection_id))
89 << "Shouldn't buffer duplicated CHLO on connection " << connection_id;
90
91 if (!base::ContainsKey(undecryptable_packets_, connection_id) &&
92 ShouldBufferPacket(is_chlo)) {
93 // Drop the packet if the upper limit of undecryptable packets has been
94 // reached or the whole capacity of the store has been reached.
84 return TOO_MANY_CONNECTIONS; 95 return TOO_MANY_CONNECTIONS;
85 } else if (!base::ContainsKey(undecryptable_packets_, connection_id)) { 96 } else if (!base::ContainsKey(undecryptable_packets_, connection_id)) {
86 undecryptable_packets_.emplace( 97 undecryptable_packets_.emplace(
87 std::make_pair(connection_id, BufferedPacketList())); 98 std::make_pair(connection_id, BufferedPacketList()));
88 } 99 }
89 CHECK(base::ContainsKey(undecryptable_packets_, connection_id)); 100 CHECK(base::ContainsKey(undecryptable_packets_, connection_id));
90 BufferedPacketList& queue = 101 BufferedPacketList& queue =
91 undecryptable_packets_.find(connection_id)->second; 102 undecryptable_packets_.find(connection_id)->second;
92 103
93 if (queue.buffered_packets.size() >= kDefaultMaxUndecryptablePackets) { 104 if (!is_chlo) {
94 // If there are kMaxBufferedPacketsPerConnection packets buffered up for 105 // If current packet is not CHLO, it might not be buffered because store
95 // this connection, drop the current packet. 106 // only buffers certain number of undecryptable packets per connection.
96 return TOO_MANY_PACKETS; 107 size_t num_non_chlo_packets =
108 base::ContainsKey(connections_with_chlo_, connection_id)
109 ? (queue.buffered_packets.size() - 1)
110 : queue.buffered_packets.size();
111 if (num_non_chlo_packets >= kDefaultMaxUndecryptablePackets) {
112 // If there are kMaxBufferedPacketsPerConnection packets buffered up for
113 // this connection, drop the current packet.
114 return TOO_MANY_PACKETS;
115 }
97 } 116 }
98 117
99 if (queue.buffered_packets.empty()) { 118 if (queue.buffered_packets.empty()) {
100 // If this is the first packet arrived on a new connection, initialize the 119 // If this is the first packet arrived on a new connection, initialize the
101 // creation time. 120 // creation time.
102 queue.creation_time = clock_->ApproximateNow(); 121 queue.creation_time = clock_->ApproximateNow();
103 } 122 }
104 123
105 BufferedPacket new_entry(std::unique_ptr<QuicReceivedPacket>(packet.Clone()), 124 BufferedPacket new_entry(std::unique_ptr<QuicReceivedPacket>(packet.Clone()),
106 server_address, client_address); 125 server_address, client_address);
107 126 if (is_chlo) {
108 queue.buffered_packets.push_back(std::move(new_entry)); 127 // Add CHLO to the beginning of buffered packets so that it can be delivered
109 128 // first later.
129 queue.buffered_packets.push_front(std::move(new_entry));
130 connections_with_chlo_[connection_id] = false; // Dummy value.
131 } else {
132 // Buffer non-CHLO packets in arrival order.
133 queue.buffered_packets.push_back(std::move(new_entry));
134 }
110 MaybeSetExpirationAlarm(); 135 MaybeSetExpirationAlarm();
111 return SUCCESS; 136 return SUCCESS;
112 } 137 }
113 138
114 bool QuicBufferedPacketStore::HasBufferedPackets( 139 bool QuicBufferedPacketStore::HasBufferedPackets(
115 QuicConnectionId connection_id) const { 140 QuicConnectionId connection_id) const {
116 return base::ContainsKey(undecryptable_packets_, connection_id); 141 return base::ContainsKey(undecryptable_packets_, connection_id);
117 } 142 }
118 143
144 bool QuicBufferedPacketStore::HasChlosBuffered() const {
145 return !connections_with_chlo_.empty();
146 }
147
119 list<BufferedPacket> QuicBufferedPacketStore::DeliverPackets( 148 list<BufferedPacket> QuicBufferedPacketStore::DeliverPackets(
120 QuicConnectionId connection_id) { 149 QuicConnectionId connection_id) {
121 list<BufferedPacket> packets_to_deliver; 150 list<BufferedPacket> packets_to_deliver;
122 auto it = undecryptable_packets_.find(connection_id); 151 auto it = undecryptable_packets_.find(connection_id);
123 if (it != undecryptable_packets_.end()) { 152 if (it != undecryptable_packets_.end()) {
124 packets_to_deliver = std::move(it->second.buffered_packets); 153 packets_to_deliver = std::move(it->second.buffered_packets);
125 undecryptable_packets_.erase(connection_id); 154 undecryptable_packets_.erase(connection_id);
126 } 155 }
127 return packets_to_deliver; 156 return packets_to_deliver;
128 } 157 }
129 158
130 void QuicBufferedPacketStore::OnExpirationTimeout() { 159 void QuicBufferedPacketStore::OnExpirationTimeout() {
131 QuicTime expiration_time = clock_->ApproximateNow() - connection_life_span_; 160 QuicTime expiration_time = clock_->ApproximateNow() - connection_life_span_;
132 while (!undecryptable_packets_.empty()) { 161 while (!undecryptable_packets_.empty()) {
133 auto& entry = undecryptable_packets_.front(); 162 auto& entry = undecryptable_packets_.front();
134 if (entry.second.creation_time > expiration_time) { 163 if (entry.second.creation_time > expiration_time) {
135 break; 164 break;
136 } 165 }
137 visitor_->OnExpiredPackets(entry.first, std::move(entry.second)); 166 QuicConnectionId connection_id = entry.first;
167 visitor_->OnExpiredPackets(connection_id, std::move(entry.second));
138 undecryptable_packets_.erase(undecryptable_packets_.begin()); 168 undecryptable_packets_.erase(undecryptable_packets_.begin());
169 connections_with_chlo_.erase(connection_id);
139 } 170 }
140 if (!undecryptable_packets_.empty()) { 171 if (!undecryptable_packets_.empty()) {
141 expiration_alarm_->Set(clock_->ApproximateNow() + connection_life_span_); 172 expiration_alarm_->Set(clock_->ApproximateNow() + connection_life_span_);
142 } 173 }
143 } 174 }
144 175
145 void QuicBufferedPacketStore::MaybeSetExpirationAlarm() { 176 void QuicBufferedPacketStore::MaybeSetExpirationAlarm() {
146 if (!expiration_alarm_->IsSet()) { 177 if (!expiration_alarm_->IsSet()) {
147 expiration_alarm_->Set(clock_->ApproximateNow() + connection_life_span_); 178 expiration_alarm_->Set(clock_->ApproximateNow() + connection_life_span_);
148 } 179 }
149 } 180 }
150 181
151 bool QuicBufferedPacketStore::IsFull() { 182 bool QuicBufferedPacketStore::ShouldBufferPacket(bool is_chlo) {
152 return undecryptable_packets_.size() >= kDefaultMaxConnectionsInStore; 183 bool is_store_full =
184 undecryptable_packets_.size() >= kDefaultMaxConnectionsInStore;
185
186 if (is_chlo) {
187 return is_store_full;
188 }
189
190 size_t num_connections_without_chlo =
191 undecryptable_packets_.size() - connections_with_chlo_.size();
192 bool reach_non_chlo_limit =
193 FLAGS_quic_limit_num_new_sessions_per_epoll_loop &&
194 num_connections_without_chlo >= kMaxConnectionsWithoutCHLO;
195
196 return is_store_full || reach_non_chlo_limit;
197 }
198
199 list<BufferedPacket> QuicBufferedPacketStore::DeliverPacketsForNextConnection(
200 QuicConnectionId* connection_id) {
201 if (connections_with_chlo_.empty()) {
202 // Returns empty list if no CHLO has been buffered.
203 return list<BufferedPacket>();
204 }
205 *connection_id = connections_with_chlo_.front().first;
206 connections_with_chlo_.erase(connections_with_chlo_.begin());
207
208 list<BufferedPacket> packets = DeliverPackets(*connection_id);
209 DCHECK(!packets.empty()) << "Try to deliver connectons without CHLO";
210 return packets;
211 }
212
213 bool QuicBufferedPacketStore::HasChloForConnection(
214 QuicConnectionId connection_id) {
215 return base::ContainsKey(connections_with_chlo_, connection_id);
153 } 216 }
154 217
155 } // namespace net 218 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/core/quic_buffered_packet_store.h ('k') | net/quic/core/quic_buffered_packet_store_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698