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

Unified Diff: net/quic/core/quic_buffered_packet_store_test.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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/quic/core/quic_buffered_packet_store.cc ('k') | net/quic/core/quic_flags_list.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/quic/core/quic_buffered_packet_store_test.cc
diff --git a/net/quic/core/quic_buffered_packet_store_test.cc b/net/quic/core/quic_buffered_packet_store_test.cc
index 53cbe0c132d78e9209c05c784ed7510129303f4d..9bce74c45f0d52a190653c41147f3a55eaac04db 100644
--- a/net/quic/core/quic_buffered_packet_store_test.cc
+++ b/net/quic/core/quic_buffered_packet_store_test.cc
@@ -23,6 +23,8 @@ typedef QuicBufferedPacketStore::BufferedPacket BufferedPacket;
typedef QuicBufferedPacketStore::EnqueuePacketResult EnqueuePacketResult;
static const size_t kDefaultMaxConnectionsInStore = 100;
+static const size_t kMaxConnectionsWithoutCHLO =
+ kDefaultMaxConnectionsInStore / 2;
namespace test {
namespace {
@@ -70,8 +72,8 @@ class QuicBufferedPacketStoreTest : public ::testing::Test {
TEST_F(QuicBufferedPacketStoreTest, SimpleEnqueueAndDeliverPacket) {
QuicConnectionId connection_id = 1;
- store_.EnqueuePacket(connection_id, packet_, server_address_,
- client_address_);
+ store_.EnqueuePacket(connection_id, packet_, server_address_, client_address_,
+ false);
EXPECT_TRUE(store_.HasBufferedPackets(connection_id));
list<BufferedPacket> queue = store_.DeliverPackets(connection_id);
ASSERT_EQ(1u, queue.size());
@@ -88,10 +90,10 @@ TEST_F(QuicBufferedPacketStoreTest, SimpleEnqueueAndDeliverPacket) {
TEST_F(QuicBufferedPacketStoreTest, DifferentPacketAddressOnOneConnection) {
IPEndPoint addr_with_new_port(Loopback4(), 256);
QuicConnectionId connection_id = 1;
+ store_.EnqueuePacket(connection_id, packet_, server_address_, client_address_,
+ false);
store_.EnqueuePacket(connection_id, packet_, server_address_,
- client_address_);
- store_.EnqueuePacket(connection_id, packet_, server_address_,
- addr_with_new_port);
+ addr_with_new_port, false);
list<BufferedPacket> queue = store_.DeliverPackets(connection_id);
ASSERT_EQ(2u, queue.size());
// The address migration path should be preserved.
@@ -105,9 +107,9 @@ TEST_F(QuicBufferedPacketStoreTest,
for (QuicConnectionId connection_id = 1; connection_id <= num_connections;
++connection_id) {
store_.EnqueuePacket(connection_id, packet_, server_address_,
- client_address_);
+ client_address_, false);
store_.EnqueuePacket(connection_id, packet_, server_address_,
- client_address_);
+ client_address_, false);
}
// Deliver packets in reversed order.
@@ -124,10 +126,17 @@ TEST_F(QuicBufferedPacketStoreTest,
// buffered.
size_t num_packets = kDefaultMaxUndecryptablePackets + 1;
QuicConnectionId connection_id = 1;
+ if (FLAGS_quic_limit_num_new_sessions_per_epoll_loop) {
+ // Arrived CHLO packet shouldn't affect how many non-CHLO pacekts store can
+ // keep.
+ EXPECT_EQ(QuicBufferedPacketStore::SUCCESS,
+ store_.EnqueuePacket(connection_id, packet_, server_address_,
+ client_address_, true));
+ }
for (size_t i = 1; i <= num_packets; ++i) {
// Only first |kDefaultMaxUndecryptablePackets packets| will be buffered.
EnqueuePacketResult result = store_.EnqueuePacket(
- connection_id, packet_, server_address_, client_address_);
+ connection_id, packet_, server_address_, client_address_, false);
if (i <= kDefaultMaxUndecryptablePackets) {
EXPECT_EQ(EnqueuePacketResult::SUCCESS, result);
} else {
@@ -135,32 +144,40 @@ TEST_F(QuicBufferedPacketStoreTest,
}
}
- // Only first |kDefaultMaxUndecryptablePackets| packets are kept in the store
- // and can be delivered.
- EXPECT_EQ(kDefaultMaxUndecryptablePackets,
+ // Only first |kDefaultMaxUndecryptablePackets| non-CHLO packets and CHLO are
+ // buffered.
+ EXPECT_EQ(kDefaultMaxUndecryptablePackets +
+ (FLAGS_quic_limit_num_new_sessions_per_epoll_loop ? 1 : 0),
store_.DeliverPackets(connection_id).size());
}
-TEST_F(QuicBufferedPacketStoreTest, FailToBufferPacketsForTooManyConnections) {
+TEST_F(QuicBufferedPacketStoreTest, ReachNonChloConnectionUpperLimit) {
// Tests that store can only keep early arrived packets for limited number of
// connections.
- size_t num_connections = kDefaultMaxConnectionsInStore + 1;
- for (size_t connection_id = 1; connection_id <= num_connections;
+ const size_t kNumConnections =
+ (FLAGS_quic_limit_num_new_sessions_per_epoll_loop
+ ? kMaxConnectionsWithoutCHLO
+ : kDefaultMaxConnectionsInStore) +
+ 1;
+ for (size_t connection_id = 1; connection_id <= kNumConnections;
++connection_id) {
EnqueuePacketResult result = store_.EnqueuePacket(
- connection_id, packet_, server_address_, client_address_);
- if (connection_id <= kDefaultMaxConnectionsInStore) {
+ connection_id, packet_, server_address_, client_address_, false);
+ if (connection_id <= (FLAGS_quic_limit_num_new_sessions_per_epoll_loop
+ ? kMaxConnectionsWithoutCHLO
+ : kDefaultMaxConnectionsInStore)) {
EXPECT_EQ(EnqueuePacketResult::SUCCESS, result);
} else {
EXPECT_EQ(EnqueuePacketResult::TOO_MANY_CONNECTIONS, result);
}
}
- // Store only keeps early arrived packets upto |kDefaultMaxConnectionsInStore|
- // connections.
- for (size_t connection_id = 1; connection_id <= num_connections;
+ // Store only keeps early arrived packets upto |kNumConnections| connections.
+ for (size_t connection_id = 1; connection_id <= kNumConnections;
++connection_id) {
list<BufferedPacket> queue = store_.DeliverPackets(connection_id);
- if (connection_id <= kDefaultMaxConnectionsInStore) {
+ if (connection_id <= (FLAGS_quic_limit_num_new_sessions_per_epoll_loop
+ ? kMaxConnectionsWithoutCHLO
+ : kDefaultMaxConnectionsInStore)) {
EXPECT_EQ(1u, queue.size());
} else {
EXPECT_EQ(0u, queue.size());
@@ -168,10 +185,91 @@ TEST_F(QuicBufferedPacketStoreTest, FailToBufferPacketsForTooManyConnections) {
}
}
-TEST_F(QuicBufferedPacketStoreTest, PacketQueueExpiredBeforeDelivery) {
+TEST_F(QuicBufferedPacketStoreTest,
+ FullStoreFailToBufferDataPacketOnNewConnection) {
+ FLAGS_quic_limit_num_new_sessions_per_epoll_loop = true;
+ // Send enough CHLOs so that store gets full before number of connections
+ // without CHLO reaches its upper limit.
+ size_t num_chlos =
+ kDefaultMaxConnectionsInStore - kMaxConnectionsWithoutCHLO + 1;
+ for (size_t connection_id = 1; connection_id <= num_chlos; ++connection_id) {
+ EXPECT_EQ(EnqueuePacketResult::SUCCESS,
+ store_.EnqueuePacket(connection_id, packet_, server_address_,
+ client_address_, true));
+ }
+
+ // Send data packets on another |kMaxConnectionsWithoutCHLO| connections.
+ // Store should only be able to buffer till it's full.
+ for (size_t conn_id = num_chlos + 1;
+ conn_id <= (kDefaultMaxConnectionsInStore + 1); ++conn_id) {
+ EnqueuePacketResult result = store_.EnqueuePacket(
+ conn_id, packet_, server_address_, client_address_, true);
+ if (conn_id <= kDefaultMaxConnectionsInStore) {
+ EXPECT_EQ(EnqueuePacketResult::SUCCESS, result);
+ } else {
+ EXPECT_EQ(EnqueuePacketResult::TOO_MANY_CONNECTIONS, result);
+ }
+ }
+}
+
+TEST_F(QuicBufferedPacketStoreTest, EnqueueChloOnTooManyDifferentConnections) {
+ FLAGS_quic_limit_num_new_sessions_per_epoll_loop = true;
+ // Buffer data packets on different connections upto limit.
+ for (QuicConnectionId conn_id = 1; conn_id <= kMaxConnectionsWithoutCHLO;
+ ++conn_id) {
+ EXPECT_EQ(EnqueuePacketResult::SUCCESS,
+ store_.EnqueuePacket(conn_id, packet_, server_address_,
+ client_address_, false));
+ }
+
+ // Buffer CHLOs on other connections till store is full.
+ for (size_t i = kMaxConnectionsWithoutCHLO + 1;
+ i <= kDefaultMaxConnectionsInStore + 1; ++i) {
+ EnqueuePacketResult rs = store_.EnqueuePacket(
+ /*connection_id=*/i, packet_, server_address_, client_address_, true);
+ if (i <= kDefaultMaxConnectionsInStore) {
+ EXPECT_EQ(EnqueuePacketResult::SUCCESS, rs);
+ EXPECT_TRUE(store_.HasChloForConnection(/*connection_id=*/i));
+ } else {
+ // Last CHLO can't be buffered because store is full.
+ EXPECT_EQ(EnqueuePacketResult::TOO_MANY_CONNECTIONS, rs);
+ EXPECT_FALSE(store_.HasChloForConnection(/*connection_id=*/i));
+ }
+ }
+
+ // But buffering a CHLO belonging to a connection already has data packet
+ // buffered in the store should success. This is the connection should be
+ // delivered at last.
+ EXPECT_EQ(EnqueuePacketResult::SUCCESS,
+ store_.EnqueuePacket(/*connection_id=*/1, packet_, server_address_,
+ client_address_, true));
+ EXPECT_TRUE(store_.HasChloForConnection(/*connection_id=*/1));
+
+ QuicConnectionId delivered_conn_id;
+ for (size_t i = 0;
+ i < kDefaultMaxConnectionsInStore - kMaxConnectionsWithoutCHLO + 1;
+ ++i) {
+ if (i < kDefaultMaxConnectionsInStore - kMaxConnectionsWithoutCHLO) {
+ // Only CHLO is buffered.
+ EXPECT_EQ(
+ 1u,
+ store_.DeliverPacketsForNextConnection(&delivered_conn_id).size());
+ EXPECT_EQ(i + kMaxConnectionsWithoutCHLO + 1, delivered_conn_id);
+ } else {
+ EXPECT_EQ(
+ 2u,
+ store_.DeliverPacketsForNextConnection(&delivered_conn_id).size());
+ EXPECT_EQ(1u, delivered_conn_id);
+ }
+ }
+ EXPECT_FALSE(store_.HasChlosBuffered());
+}
+
+TEST_F(QuicBufferedPacketStoreTest, PacketQueueExpiredBeforeDelivery1) {
+ FLAGS_quic_limit_num_new_sessions_per_epoll_loop = false;
QuicConnectionId connection_id = 1;
- store_.EnqueuePacket(connection_id, packet_, server_address_,
- client_address_);
+ store_.EnqueuePacket(connection_id, packet_, server_address_, client_address_,
+ false);
// Packet for another connection arrive 1ms later.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
QuicConnectionId connection_id2 = 2;
@@ -179,7 +277,7 @@ TEST_F(QuicBufferedPacketStoreTest, PacketQueueExpiredBeforeDelivery) {
// connections.
IPEndPoint another_client_address(Loopback4(), 255);
store_.EnqueuePacket(connection_id2, packet_, server_address_,
- another_client_address);
+ another_client_address, false);
// Advance clock to the time when connection 1 expires.
clock_.AdvanceTime(
QuicBufferedPacketStorePeer::expiration_alarm(&store_)->deadline() -
@@ -205,9 +303,76 @@ TEST_F(QuicBufferedPacketStoreTest, PacketQueueExpiredBeforeDelivery) {
// for them to expire.
QuicConnectionId connection_id3 = 3;
store_.EnqueuePacket(connection_id3, packet_, server_address_,
- client_address_);
+ client_address_, false);
store_.EnqueuePacket(connection_id3, packet_, server_address_,
- client_address_);
+ client_address_, false);
+ clock_.AdvanceTime(
+ QuicBufferedPacketStorePeer::expiration_alarm(&store_)->deadline() -
+ clock_.ApproximateNow());
+ alarm_factory_.FireAlarm(
+ QuicBufferedPacketStorePeer::expiration_alarm(&store_));
+ // |last_expired_packet_queue_| should be updated.
+ EXPECT_EQ(2u, visitor_.last_expired_packet_queue_.buffered_packets.size());
+}
+
+// Tests that store expires long-staying connections appropriately for
+// connections both with and without CHLOs.
+TEST_F(QuicBufferedPacketStoreTest, PacketQueueExpiredBeforeDelivery2) {
+ FLAGS_quic_limit_num_new_sessions_per_epoll_loop = true;
+ QuicConnectionId connection_id = 1;
+ store_.EnqueuePacket(connection_id, packet_, server_address_, client_address_,
+ false);
+ if (FLAGS_quic_limit_num_new_sessions_per_epoll_loop) {
+ EXPECT_EQ(EnqueuePacketResult::SUCCESS,
+ store_.EnqueuePacket(connection_id, packet_, server_address_,
+ client_address_, true));
+ }
+ QuicConnectionId connection_id2 = 2;
+ EXPECT_EQ(EnqueuePacketResult::SUCCESS,
+ store_.EnqueuePacket(connection_id2, packet_, server_address_,
+ client_address_, false));
+
+ // CHLO on connection 3 arrives 1ms later.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
+ QuicConnectionId connection_id3 = 3;
+ // Use different client address to differetiate packets from different
+ // connections.
+ IPEndPoint another_client_address(Any4(), 255);
+ store_.EnqueuePacket(connection_id3, packet_, server_address_,
+ another_client_address, true);
+
+ // Advance clock to the time when connection 1 and 2 expires.
+ clock_.AdvanceTime(
+ QuicBufferedPacketStorePeer::expiration_alarm(&store_)->deadline() -
+ clock_.ApproximateNow());
+ ASSERT_GE(clock_.ApproximateNow(),
+ QuicBufferedPacketStorePeer::expiration_alarm(&store_)->deadline());
+ // Fire alarm to remove long-staying connection 1 and 2 packets.
+ alarm_factory_.FireAlarm(
+ QuicBufferedPacketStorePeer::expiration_alarm(&store_));
+ EXPECT_EQ(1u, visitor_.last_expired_packet_queue_.buffered_packets.size());
+ EXPECT_FALSE(store_.HasBufferedPackets(connection_id));
+ EXPECT_FALSE(store_.HasBufferedPackets(connection_id2));
+
+ // Try to deliver packets, but packet queue has been removed so no
+ // packets can be returned.
+ ASSERT_EQ(0u, store_.DeliverPackets(connection_id).size());
+ ASSERT_EQ(0u, store_.DeliverPackets(connection_id2).size());
+ QuicConnectionId delivered_conn_id;
+ auto queue = store_.DeliverPacketsForNextConnection(&delivered_conn_id);
+ // Connection 3 is the next to be delivered as connection 1 already expired.
+ EXPECT_EQ(connection_id3, delivered_conn_id);
+ ASSERT_EQ(1u, queue.size());
+ // Packets in connection 3 should use another client address.
+ EXPECT_EQ(another_client_address, queue.front().client_address);
+
+ // Test the alarm is reset by enqueueing 2 packets for 4th connection and wait
+ // for them to expire.
+ QuicConnectionId connection_id4 = 4;
+ store_.EnqueuePacket(connection_id4, packet_, server_address_,
+ client_address_, false);
+ store_.EnqueuePacket(connection_id4, packet_, server_address_,
+ client_address_, false);
clock_.AdvanceTime(
QuicBufferedPacketStorePeer::expiration_alarm(&store_)->deadline() -
clock_.ApproximateNow());
« no previous file with comments | « net/quic/core/quic_buffered_packet_store.cc ('k') | net/quic/core/quic_flags_list.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698