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 2017/10/19 07:29:22 UTC

[trafficserver] branch quic-latest updated: Fix stream level flow control

This is an automated email from the ASF dual-hosted git repository.

maskit pushed a commit to branch quic-latest
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/quic-latest by this push:
     new d48631f  Fix stream level flow control
d48631f is described below

commit d48631f3d0c0bedf43655ab56b698341f931fb42
Author: Masakazu Kitajo <ma...@apache.org>
AuthorDate: Thu Oct 19 16:27:52 2017 +0900

    Fix stream level flow control
    
    It didn't use available credit if sending data don't fit in.
---
 iocore/net/quic/Mock.h                  |  11 ++++
 iocore/net/quic/QUICStream.cc           |   4 ++
 iocore/net/quic/test/test_QUICStream.cc | 102 ++++++++++++++++++++++++++++++++
 3 files changed, 117 insertions(+)

diff --git a/iocore/net/quic/Mock.h b/iocore/net/quic/Mock.h
index 65e9713..22ba21d 100644
--- a/iocore/net/quic/Mock.h
+++ b/iocore/net/quic/Mock.h
@@ -399,3 +399,14 @@ NetVConnection::send_OOB(Continuation *, char *, int)
 {
   return nullptr;
 }
+
+class MockContinuation : public Continuation
+{
+public:
+  MockContinuation(Ptr<ProxyMutex> m) : Continuation(m) { SET_HANDLER(&MockContinuation::event_handler); }
+  int
+  event_handler(int event, Event *data)
+  {
+    return EVENT_CONT;
+  }
+};
diff --git a/iocore/net/quic/QUICStream.cc b/iocore/net/quic/QUICStream.cc
index f0ec0ff..535b9f4 100644
--- a/iocore/net/quic/QUICStream.cc
+++ b/iocore/net/quic/QUICStream.cc
@@ -360,6 +360,10 @@ QUICStream::_send()
     int64_t len      = 0;
     bool fin         = false;
 
+    int64_t credit = this->_remote_flow_controller->current_limit() - this->_remote_flow_controller->current_offset();
+    if (credit != 0 && max_size > credit) {
+      max_size = credit;
+    }
     if (data_len > max_size) {
       len = max_size;
     } else {
diff --git a/iocore/net/quic/test/test_QUICStream.cc b/iocore/net/quic/test/test_QUICStream.cc
index ef523ab..5e63ade 100644
--- a/iocore/net/quic/test/test_QUICStream.cc
+++ b/iocore/net/quic/test/test_QUICStream.cc
@@ -146,4 +146,106 @@ TEST_CASE("QUICStream", "[quic]")
     CHECK(len == 16);
     CHECK(memcmp(buf, payload, len) == 0);
   }
+
+  SECTION("QUICStream_flow_control_local", "[quic]")
+  {
+    std::unique_ptr<QUICError> error = nullptr;
+
+    MIOBuffer *read_buffer = new_MIOBuffer(BUFFER_SIZE_INDEX_4K);
+    IOBufferReader *reader = read_buffer->alloc_reader();
+    MockQUICFrameTransmitter tx;
+
+    std::unique_ptr<QUICStream> stream(new QUICStream());
+    stream->init(&tx, 0, stream_id);
+    stream->init_flow_control_params(4096, 4096);
+    stream->do_io_read(nullptr, 0, read_buffer);
+
+    // Start with 1024 but not 0 so received frames won't be processed
+    error = stream->recv(std::make_shared<QUICStreamFrame>(ats_unique_malloc(1024), 1024, stream_id, 1024));
+    CHECK(error->cls == QUICErrorClass::NONE);
+    // duplicate
+    error = stream->recv(std::make_shared<QUICStreamFrame>(ats_unique_malloc(1024), 1024, stream_id, 1024));
+    CHECK(error->cls == QUICErrorClass::NONE);
+    error = stream->recv(std::make_shared<QUICStreamFrame>(ats_unique_malloc(1024), 1024, stream_id, 3072));
+    CHECK(error->cls == QUICErrorClass::NONE);
+    // delay
+    error = stream->recv(std::make_shared<QUICStreamFrame>(ats_unique_malloc(1024), 1024, stream_id, 2048));
+    CHECK(error->cls == QUICErrorClass::NONE);
+    // all frames should be processed
+    error = stream->recv(std::make_shared<QUICStreamFrame>(ats_unique_malloc(1024), 1024, stream_id, 0));
+    CHECK(error->cls == QUICErrorClass::NONE);
+    // start again without the first block
+    error = stream->recv(std::make_shared<QUICStreamFrame>(ats_unique_malloc(1024), 1024, stream_id, 5120));
+    CHECK(error->cls == QUICErrorClass::NONE);
+    // this should exceed the limit
+    error = stream->recv(std::make_shared<QUICStreamFrame>(ats_unique_malloc(1024), 1024, stream_id, 8192));
+    CHECK(error->code == QUICErrorCode::FLOW_CONTROL_ERROR);
+  }
+
+  SECTION("QUICStream_flow_control_remote", "[quic]")
+  {
+    std::unique_ptr<QUICError> error = nullptr;
+
+    MIOBuffer *read_buffer              = new_MIOBuffer(BUFFER_SIZE_INDEX_4K);
+    MIOBuffer *write_buffer             = new_MIOBuffer(BUFFER_SIZE_INDEX_4K);
+    IOBufferReader *read_buffer_reader  = read_buffer->alloc_reader();
+    IOBufferReader *write_buffer_reader = write_buffer->alloc_reader();
+    MockQUICFrameTransmitter tx;
+
+    std::unique_ptr<QUICStream> stream(new QUICStream());
+    stream->init(&tx, 0, stream_id);
+    stream->init_flow_control_params(4096, 4096);
+    MockContinuation mock_cont(stream->mutex);
+    stream->do_io_read(nullptr, 0, read_buffer);
+    stream->do_io_write(&mock_cont, 0, write_buffer_reader);
+
+    // Check the initial state
+    CHECK(tx.frameCount[static_cast<int>(QUICFrameType::STREAM)] == 0);
+
+    const char data[1024] = {0};
+    write_buffer->write(data, 1024);
+    stream->main_event_handler(VC_EVENT_WRITE_READY, nullptr);
+    CHECK(tx.frameCount[static_cast<int>(QUICFrameType::STREAM)] == 1);
+
+    write_buffer->write(data, 1024);
+    stream->main_event_handler(VC_EVENT_WRITE_READY, nullptr);
+    CHECK(tx.frameCount[static_cast<int>(QUICFrameType::STREAM)] == 2);
+
+    write_buffer->write(data, 1024);
+    stream->main_event_handler(VC_EVENT_WRITE_READY, nullptr);
+    CHECK(tx.frameCount[static_cast<int>(QUICFrameType::STREAM)] == 3);
+
+    write_buffer->write(data, 1024);
+    stream->main_event_handler(VC_EVENT_WRITE_READY, nullptr);
+    CHECK(tx.frameCount[static_cast<int>(QUICFrameType::STREAM)] == 4);
+
+    // This should not send a frame because of flow control
+    write_buffer->write(data, 1024);
+    stream->main_event_handler(VC_EVENT_WRITE_READY, nullptr);
+    CHECK(tx.frameCount[static_cast<int>(QUICFrameType::STREAM)] == 4);
+
+    // Update window
+    stream->recv(std::make_shared<QUICMaxStreamDataFrame>(stream_id, 5120));
+
+    // This should send a frame
+    stream->main_event_handler(VC_EVENT_WRITE_READY, nullptr);
+    CHECK(tx.frameCount[static_cast<int>(QUICFrameType::STREAM)] == 5);
+
+    // Update window
+    stream->recv(std::make_shared<QUICMaxStreamDataFrame>(stream_id, 5632));
+
+    // This should send a frame
+    write_buffer->write(data, 1024);
+    stream->main_event_handler(VC_EVENT_WRITE_READY, nullptr);
+    CHECK(tx.frameCount[static_cast<int>(QUICFrameType::STREAM)] == 6);
+
+    stream->main_event_handler(VC_EVENT_WRITE_READY, nullptr);
+    CHECK(tx.frameCount[static_cast<int>(QUICFrameType::STREAM)] == 6);
+
+    // Update window
+    stream->recv(std::make_shared<QUICMaxStreamDataFrame>(stream_id, 6144));
+
+    stream->main_event_handler(VC_EVENT_WRITE_READY, nullptr);
+    CHECK(tx.frameCount[static_cast<int>(QUICFrameType::STREAM)] == 7);
+  }
 }

-- 
To stop receiving notification emails like this one, please contact
['"commits@trafficserver.apache.org" <co...@trafficserver.apache.org>'].