You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by ma...@apache.org on 2018/08/24 07:02:21 UTC
[trafficserver] 02/02: Send BLOCKED frame
This is an automated email from the ASF dual-hosted git repository.
masaori pushed a commit to branch quic-latest
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit 7a195464eca6c51c491dfb14d6343e06f863ac46
Author: Masaori Koshiba <ma...@apache.org>
AuthorDate: Thu Aug 23 16:05:16 2018 +0900
Send BLOCKED frame
QUICRemoteFlowController::update() create BLOCKED(_STREAM) frame. It will be sent when STREAMs have anything to send.
---
iocore/net/QUICNetVConnection.cc | 22 +++++++++----
iocore/net/quic/QUICFlowController.cc | 6 ++--
iocore/net/quic/QUICStream.cc | 17 ++++++++--
iocore/net/quic/test/test_QUICFlowController.cc | 43 ++++++++++++++++++++++---
4 files changed, 73 insertions(+), 15 deletions(-)
diff --git a/iocore/net/QUICNetVConnection.cc b/iocore/net/QUICNetVConnection.cc
index 03fde79..a019f9b 100644
--- a/iocore/net/QUICNetVConnection.cc
+++ b/iocore/net/QUICNetVConnection.cc
@@ -1214,7 +1214,8 @@ QUICNetVConnection::_packetize_frames(QUICEncryptionLevel level, uint64_t max_pa
bool ack_only = true;
if (this->_connection_error || this->_packet_retransmitter.will_generate_frame(level) ||
this->_handshake_handler->will_generate_frame(level) || this->_stream_manager->will_generate_frame(level) ||
- this->_path_validator->will_generate_frame(level)) {
+ this->_path_validator->will_generate_frame(level) || this->_local_flow_controller->will_generate_frame(level) ||
+ (this->_stream_manager->will_generate_frame(level) && this->_remote_flow_controller->will_generate_frame(level))) {
ack_only = false;
}
@@ -1241,7 +1242,7 @@ QUICNetVConnection::_packetize_frames(QUICEncryptionLevel level, uint64_t max_pa
}
// PATH_CHALLENGE, PATH_RESPOSNE
- frame = this->_path_validator->generate_frame(level, this->_remote_flow_controller->credit(), max_frame_size);
+ frame = this->_path_validator->generate_frame(level, UINT16_MAX, max_frame_size);
if (frame) {
++frame_count;
this->_store_frame(buf, len, max_frame_size, std::move(frame));
@@ -1249,22 +1250,31 @@ QUICNetVConnection::_packetize_frames(QUICEncryptionLevel level, uint64_t max_pa
// NEW_CONNECTION_ID
if (this->_alt_con_manager) {
- frame = this->_alt_con_manager->generate_frame(level, this->_remote_flow_controller->credit(), max_frame_size);
+ frame = this->_alt_con_manager->generate_frame(level, UINT16_MAX, max_frame_size);
while (frame) {
++frame_count;
this->_store_frame(buf, len, max_frame_size, std::move(frame));
- frame = this->_alt_con_manager->generate_frame(level, this->_remote_flow_controller->credit(), max_frame_size);
+ frame = this->_alt_con_manager->generate_frame(level, UINT16_MAX, max_frame_size);
}
}
// Lost frames
- frame = this->_packet_retransmitter.generate_frame(level, this->_remote_flow_controller->credit(), max_frame_size);
+ frame = this->_packet_retransmitter.generate_frame(level, UINT16_MAX, max_frame_size);
while (frame) {
++frame_count;
this->_store_frame(buf, len, max_frame_size, std::move(frame));
- frame = this->_packet_retransmitter.generate_frame(level, this->_remote_flow_controller->credit(), max_frame_size);
+ frame = this->_packet_retransmitter.generate_frame(level, UINT16_MAX, max_frame_size);
+ }
+
+ // BLOCKED
+ if (this->_remote_flow_controller->credit() == 0 && this->_stream_manager->will_generate_frame(level)) {
+ frame = this->_remote_flow_controller->generate_frame(level, UINT16_MAX, max_frame_size);
+ if (frame) {
+ ++frame_count;
+ this->_store_frame(buf, len, max_frame_size, std::move(frame));
+ }
}
// STREAM, MAX_STREAM_DATA, STREAM_BLOCKED
diff --git a/iocore/net/quic/QUICFlowController.cc b/iocore/net/quic/QUICFlowController.cc
index 57357f1..70ff181 100644
--- a/iocore/net/quic/QUICFlowController.cc
+++ b/iocore/net/quic/QUICFlowController.cc
@@ -100,6 +100,7 @@ QUICFlowController::set_limit(QUICOffset limit)
this->_limit = limit;
}
+// For RemoteFlowController, caller of this function should also check QUICStreamManager::will_generate_frame()
bool
QUICFlowController::will_generate_frame(QUICEncryptionLevel level)
{
@@ -142,8 +143,9 @@ QUICRemoteFlowController::update(QUICOffset offset)
{
int ret = QUICFlowController::update(offset);
- // Send BLOCKED(_STREAM) frame
- if (!this->_blocked && offset > this->_limit) {
+ // Create BLOCKED(_STREAM) frame
+ // The frame will be sent if stream has something to send.
+ if (!this->_blocked && offset >= this->_limit) {
this->_frame = this->_create_frame();
this->_blocked = true;
}
diff --git a/iocore/net/quic/QUICStream.cc b/iocore/net/quic/QUICStream.cc
index ff38147..d2a5a3f 100644
--- a/iocore/net/quic/QUICStream.cc
+++ b/iocore/net/quic/QUICStream.cc
@@ -403,6 +403,10 @@ QUICStream::generate_frame(QUICEncryptionLevel level, uint64_t connection_credit
return frame;
}
+ if (connection_credit == 0) {
+ return frame;
+ }
+
if (maximum_frame_size <= MAX_STREAM_FRAME_OVERHEAD) {
return frame;
}
@@ -413,13 +417,20 @@ QUICStream::generate_frame(QUICEncryptionLevel level, uint64_t connection_credit
return frame;
}
+ // STREAM_BLOCKED
+ uint64_t stream_credit = this->_remote_flow_controller.credit();
+ // The `bytes_avail` should be also checked before calling QUICRemoteFlowController::generate_frame(), but we don't need it.
+ // Because it's already checked in above.
+ if (stream_credit == 0) {
+ frame = this->_remote_flow_controller.generate_frame(level, connection_credit, maximum_frame_size);
+ }
+
int64_t data_len = reader->block_read_avail();
int64_t len = 0;
bool fin = false;
- len = std::min(data_len, static_cast<int64_t>(
- std::min(static_cast<uint64_t>(maximum_frame_size - MAX_STREAM_FRAME_OVERHEAD),
- std::min(this->_remote_flow_controller.credit(), static_cast<uint64_t>(connection_credit)))));
+ len = std::min(data_len, static_cast<int64_t>(std::min(static_cast<uint64_t>(maximum_frame_size - MAX_STREAM_FRAME_OVERHEAD),
+ std::min(stream_credit, static_cast<uint64_t>(connection_credit)))));
if (this->_write_vio.nbytes == static_cast<int64_t>(this->_send_offset + len)) {
fin = true;
diff --git a/iocore/net/quic/test/test_QUICFlowController.cc b/iocore/net/quic/test/test_QUICFlowController.cc
index 0d8749c..951a0e5 100644
--- a/iocore/net/quic/test/test_QUICFlowController.cc
+++ b/iocore/net/quic/test/test_QUICFlowController.cc
@@ -132,20 +132,20 @@ TEST_CASE("QUICFlowController_Remote_Connection", "[quic]")
CHECK(fc.current_limit() == 1024);
CHECK(ret == 0);
- ret = fc.update(1024);
- CHECK(fc.current_offset() == 1024);
+ ret = fc.update(1000);
+ CHECK(fc.current_offset() == 1000);
CHECK(fc.current_limit() == 1024);
CHECK(ret == 0);
// Delay
ret = fc.update(512);
- CHECK(fc.current_offset() == 1024);
+ CHECK(fc.current_offset() == 1000);
CHECK(fc.current_limit() == 1024);
CHECK(ret == 0);
// Exceed limit
ret = fc.update(1280);
- CHECK(fc.current_offset() == 1024);
+ CHECK(fc.current_offset() == 1000);
CHECK(fc.current_limit() == 1024);
CHECK(ret != 0);
QUICFrameUPtr frame = fc.generate_frame(QUICEncryptionLevel::ONE_RTT, 0, 1024);
@@ -154,6 +154,38 @@ TEST_CASE("QUICFlowController_Remote_Connection", "[quic]")
// MAX_STREAM_DATA
fc.forward_limit(2048);
+ CHECK(fc.current_offset() == 1000);
+ CHECK(fc.current_limit() == 2048);
+
+ ret = fc.update(1280);
+ CHECK(fc.current_offset() == 1280);
+ CHECK(fc.current_limit() == 2048);
+ CHECK(ret == 0);
+}
+
+TEST_CASE("QUICFlowController_Remote_Connection_ZERO_Credit", "[quic]")
+{
+ int ret = 0;
+ QUICRemoteConnectionFlowController fc(1024);
+
+ // Check initial state
+ CHECK(fc.current_offset() == 0);
+ CHECK(fc.current_limit() == 1024);
+
+ // Zero credit
+ ret = fc.update(1024);
+ CHECK(fc.current_offset() == 1024);
+ CHECK(fc.current_limit() == 1024);
+ CHECK(ret == 0);
+
+ CHECK(fc.will_generate_frame(QUICEncryptionLevel::ONE_RTT));
+ // if there're anything to send
+ QUICFrameUPtr frame = fc.generate_frame(QUICEncryptionLevel::ONE_RTT, 0, 1024);
+ CHECK(frame);
+ CHECK(frame->type() == QUICFrameType::BLOCKED);
+
+ // MAX_STREAM_DATA
+ fc.forward_limit(2048);
CHECK(fc.current_offset() == 1024);
CHECK(fc.current_limit() == 2048);
@@ -251,6 +283,9 @@ TEST_CASE("QUICFlowController_Remote_Stream", "[quic]")
CHECK(fc.current_limit() == 1024);
CHECK(ret == 0);
+ CHECK(fc.credit() == 0);
+ CHECK(fc.will_generate_frame(QUICEncryptionLevel::ONE_RTT));
+
// Delay
ret = fc.update(512);
CHECK(fc.current_offset() == 1024);