Skip to content

Commit

Permalink
Update Loss Detection logic to draft-29
Browse files Browse the repository at this point in the history
  • Loading branch information
maskit committed Jul 22, 2020
1 parent e8109c0 commit 42c4054
Show file tree
Hide file tree
Showing 24 changed files with 698 additions and 541 deletions.
10 changes: 8 additions & 2 deletions iocore/net/P_QUICNetVConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@ class QUICNetVConnection : public UnixNetVConnection,
QUICVersion negotiated_version() const override;
std::string_view negotiated_application_name() const override;
bool is_closed() const override;
bool is_at_anti_amplification_limit() const override;
bool is_address_validation_completed() const override;
bool is_handshake_completed() const override;
bool has_keys_for(QUICPacketNumberSpace space) const override;

// QUICConnection (QUICFrameHandler)
std::vector<QUICFrameType> interests() override;
Expand Down Expand Up @@ -311,9 +315,9 @@ class QUICNetVConnection : public UnixNetVConnection,
uint64_t _maximum_stream_frame_data_size();

Ptr<IOBufferBlock> _store_frame(Ptr<IOBufferBlock> parent_block, size_t &size_added, uint64_t &max_frame_size, QUICFrame &frame,
std::vector<QUICFrameInfo> &frames);
std::vector<QUICSentPacketInfo::FrameInfo> &frames);
QUICPacketUPtr _packetize_frames(uint8_t *packet_buf, QUICEncryptionLevel level, uint64_t max_packet_size,
std::vector<QUICFrameInfo> &frames);
std::vector<QUICSentPacketInfo::FrameInfo> &frames);
void _packetize_closing_frame();
QUICPacketUPtr _build_packet(uint8_t *packet_buf, QUICEncryptionLevel level, Ptr<IOBufferBlock> parent_block,
bool retransmittable, bool probing, bool crypto);
Expand Down Expand Up @@ -344,7 +348,9 @@ class QUICNetVConnection : public UnixNetVConnection,
QUICPacketUPtr _dequeue_recv_packet(uint8_t *packet_buf, QUICPacketCreationResult &result);
void _validate_new_path(const QUICPath &path);

bool _handshake_completed = false;
int _complete_handshake_if_possible();

void _switch_to_handshake_state();
void _switch_to_established_state();
void _switch_to_closing_state(QUICConnectionErrorUPtr error);
Expand Down
82 changes: 62 additions & 20 deletions iocore/net/QUICNetVConnection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
#include "QUICMultiCertConfigLoader.h"
#include "QUICTLS.h"

#include "QUICNewRenoCongestionController.h"

#include "QUICStats.h"
#include "QUICGlobals.h"
#include "QUICDebugNames.h"
Expand Down Expand Up @@ -285,6 +287,15 @@ QUICNetVConnection::init(QUICVersion version, QUICConnectionId peer_cid, QUICCon
if (is_debug_tag_set(QUIC_DEBUG_TAG.data())) {
QUICConDebug("dcid=%s scid=%s", this->_peer_quic_connection_id.hex().c_str(), this->_quic_connection_id.hex().c_str());
}

this->_pinger = new QUICPinger();
this->_padder = new QUICPadder(this->netvc_context);
this->_path_manager = new QUICPathManagerImpl(*this, *this->_path_validator);
this->_context = std::make_unique<QUICContext>(&this->_rtt_measure, this, &this->_pp_key_info, this->_path_manager);
this->_congestion_controller = new QUICNewRenoCongestionController(*_context);
this->_rtt_measure.init(this->_context->ld_config());
this->_loss_detector =
new QUICLossDetector(*_context, this->_congestion_controller, &this->_rtt_measure, this->_pinger, this->_padder);
}

bool
Expand Down Expand Up @@ -393,8 +404,6 @@ QUICNetVConnection::start()
this->ping();
}
});
this->_path_manager = new QUICPathManagerImpl(*this, *this->_path_validator);
this->_context = std::make_unique<QUICContext>(&this->_rtt_measure, this, &this->_pp_key_info, this->_path_manager);
this->_five_tuple.update(this->local_addr, this->remote_addr, SOCK_DGRAM);
QUICPath trusted_path = {{}, {}};
// Version 0x00000001 uses stream 0 for cryptographic handshake with TLS 1.3, but newer version may not
Expand Down Expand Up @@ -431,12 +440,6 @@ QUICNetVConnection::start()
this->_frame_dispatcher = new QUICFrameDispatcher(this);

// Create frame handlers
this->_pinger = new QUICPinger();
this->_padder = new QUICPadder(this->netvc_context);
this->_rtt_measure.init(this->_context->ld_config());
this->_congestion_controller = new QUICNewRenoCongestionController(*_context);
this->_loss_detector =
new QUICLossDetector(*_context, this->_congestion_controller, &this->_rtt_measure, this->_pinger, this->_padder);
this->_frame_dispatcher->add_handler(this->_loss_detector);

this->_remote_flow_controller = new QUICRemoteConnectionFlowController(UINT64_MAX);
Expand Down Expand Up @@ -688,6 +691,7 @@ void
QUICNetVConnection::handle_received_packet(UDPPacket *packet)
{
this->_packet_recv_queue.enqueue(packet);
this->_loss_detector->on_datagram_received();
}

void
Expand Down Expand Up @@ -1080,6 +1084,44 @@ QUICNetVConnection::is_closed() const
return this->handler == reinterpret_cast<NetVConnHandler>(&QUICNetVConnection::state_connection_closed);
}

bool
QUICNetVConnection::is_at_anti_amplification_limit() const
{
return !this->_verified_state.is_verified() || this->_verified_state.windows() == 0;
}

bool
QUICNetVConnection::is_address_validation_completed() const
{
return this->_verified_state.is_verified();
}

bool
QUICNetVConnection::is_handshake_completed() const
{
return this->_handshake_completed;
}

bool
QUICNetVConnection::has_keys_for(QUICPacketNumberSpace space) const
{
switch (space) {
case QUICPacketNumberSpace::INITIAL:
return this->_pp_key_info.is_decryption_key_available(QUICKeyPhase::INITIAL) &&
this->_pp_key_info.is_encryption_key_available(QUICKeyPhase::INITIAL);
case QUICPacketNumberSpace::HANDSHAKE:
return this->_pp_key_info.is_decryption_key_available(QUICKeyPhase::HANDSHAKE) &&
this->_pp_key_info.is_encryption_key_available(QUICKeyPhase::HANDSHAKE);
case QUICPacketNumberSpace::APPLICATION_DATA:
return (this->_pp_key_info.is_decryption_key_available(QUICKeyPhase::PHASE_0) &&
this->_pp_key_info.is_encryption_key_available(QUICKeyPhase::PHASE_0)) ||
(this->_pp_key_info.is_decryption_key_available(QUICKeyPhase::PHASE_1) &&
this->_pp_key_info.is_encryption_key_available(QUICKeyPhase::PHASE_1));
default:
return false;
}
}

QUICPacketNumber
QUICNetVConnection::_largest_acked_packet_number(QUICEncryptionLevel level) const
{
Expand Down Expand Up @@ -1459,8 +1501,8 @@ QUICNetVConnection::_state_common_send_packet()
max_packet_size = std::min(max_packet_size, this->_verified_state.windows());
}

QUICPacketInfoUPtr packet_info = std::make_unique<QUICPacketInfo>();
QUICPacketUPtr packet = this->_packetize_frames(packet_buf, level, max_packet_size, packet_info->frames);
QUICSentPacketInfoUPtr packet_info = std::make_unique<QUICSentPacketInfo>();
QUICPacketUPtr packet = this->_packetize_frames(packet_buf, level, max_packet_size, packet_info->frames);

if (packet) {
// trigger callback
Expand All @@ -1469,12 +1511,7 @@ QUICNetVConnection::_state_common_send_packet()
packet_info->packet_number = packet->packet_number();
packet_info->time_sent = Thread::get_hrtime();
packet_info->ack_eliciting = packet->is_ack_eliciting();
if (packet->type() == QUICPacketType::PROTECTED) {
packet_info->is_crypto_packet = false;
} else {
packet_info->is_crypto_packet = static_cast<QUICLongHeaderPacket &>(*packet).is_crypto_packet();
}
packet_info->in_flight = true;
packet_info->in_flight = true;
if (packet_info->ack_eliciting) {
packet_info->sent_bytes = packet->size();
} else {
Expand Down Expand Up @@ -1554,7 +1591,7 @@ QUICNetVConnection::_state_closing_send_packet()

Ptr<IOBufferBlock>
QUICNetVConnection::_store_frame(Ptr<IOBufferBlock> parent_block, size_t &size_added, uint64_t &max_frame_size, QUICFrame &frame,
std::vector<QUICFrameInfo> &frames)
std::vector<QUICSentPacketInfo::FrameInfo> &frames)
{
Ptr<IOBufferBlock> new_block = frame.to_io_buffer_block(max_frame_size);

Expand Down Expand Up @@ -1590,7 +1627,7 @@ QUICNetVConnection::_store_frame(Ptr<IOBufferBlock> parent_block, size_t &size_a

QUICPacketUPtr
QUICNetVConnection::_packetize_frames(uint8_t *packet_buf, QUICEncryptionLevel level, uint64_t max_packet_size,
std::vector<QUICFrameInfo> &frames)
std::vector<QUICSentPacketInfo::FrameInfo> &frames)
{
QUICPacketUPtr packet = QUICPacketFactory::create_null_packet();
if (max_packet_size <= MAX_PACKET_OVERHEAD) {
Expand Down Expand Up @@ -1702,7 +1739,7 @@ QUICNetVConnection::_packetize_closing_frame()

size_t size_added = 0;
uint64_t max_frame_size = static_cast<uint64_t>(max_size);
std::vector<QUICFrameInfo> frames;
std::vector<QUICSentPacketInfo::FrameInfo> frames;
Ptr<IOBufferBlock> first_block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
Ptr<IOBufferBlock> last_block = first_block;
first_block->alloc(iobuffer_size_to_index(0, BUFFER_SIZE_INDEX_32K));
Expand Down Expand Up @@ -2034,11 +2071,14 @@ QUICNetVConnection::_complete_handshake_if_possible()
this->_init_flow_control_params(this->_handshake_handler->local_transport_parameters(),
this->_handshake_handler->remote_transport_parameters());

// PN space doesn't matter but seems like this is the way to pick the LossDetector for 0-RTT and Short packet
uint64_t ack_delay_exponent =
this->_handshake_handler->remote_transport_parameters()->getAsUInt(QUICTransportParameterId::ACK_DELAY_EXPONENT);
this->_loss_detector->update_ack_delay_exponent(ack_delay_exponent);

uint64_t max_ack_delay =
this->_handshake_handler->remote_transport_parameters()->getAsUInt(QUICTransportParameterId::MAX_ACK_DELAY);
this->_rtt_measure.set_max_ack_delay(max_ack_delay);

const uint8_t *reset_token;
uint16_t reset_token_len;
reset_token = this->_handshake_handler->remote_transport_parameters()->getAsBytes(QUICTransportParameterId::STATELESS_RESET_TOKEN,
Expand All @@ -2049,6 +2089,8 @@ QUICNetVConnection::_complete_handshake_if_possible()

this->_start_application();

this->_handshake_completed = true;

return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion iocore/net/quic/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ TESTS = $(check_PROGRAMS)

test_CPPFLAGS = \
$(AM_CPPFLAGS) \
-I$(abs_top_srcdir)/tests/include
-I$(abs_top_srcdir)/tests/include -O0

test_LDADD = \
libquic.a \
Expand Down
59 changes: 56 additions & 3 deletions iocore/net/quic/Mock.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,30 @@ class MockQUICConnectionInfoProvider : public QUICConnectionInfoProvider
return false;
}

bool
is_at_anti_amplification_limit() const override
{
return false;
}

bool
is_address_validation_completed() const override
{
return true;
}

bool
is_handshake_completed() const override
{
return true;
}

bool
has_keys_for(QUICPacketNumberSpace space) const override
{
return true;
}

QUICVersion
negotiated_version() const override
{
Expand Down Expand Up @@ -442,6 +466,30 @@ class MockQUICConnection : public QUICConnection
return false;
}

bool
is_at_anti_amplification_limit() const override
{
return false;
}

bool
is_address_validation_completed() const override
{
return true;
}

bool
is_handshake_completed() const override
{
return true;
}

bool
has_keys_for(QUICPacketNumberSpace space) const override
{
return true;
}

void
handle_received_packet(UDPPacket *) override
{
Expand Down Expand Up @@ -486,8 +534,13 @@ class MockQUICCongestionController : public QUICCongestionController
public:
MockQUICCongestionController() {}
// Override
void
on_packets_acked(const std::vector<QUICSentPacketInfoUPtr> &packets) override
{
}

virtual void
on_packets_lost(const std::map<QUICPacketNumber, QUICPacketInfo *> &packets) override
on_packets_lost(const std::map<QUICPacketNumber, QUICSentPacketInfoUPtr> &packets) override
{
for (auto &p : packets) {
lost_packets.insert(p.first);
Expand All @@ -499,11 +552,11 @@ class MockQUICCongestionController : public QUICCongestionController
{
}
virtual void
on_packet_acked(const QUICPacketInfo &acked_packet) override
on_packet_acked(const QUICSentPacketInfo &acked_packet) override
{
}
virtual void
process_ecn(const QUICPacketInfo &acked_largest_packet, const QUICAckFrame::EcnSection *ecn_section) override
process_ecn(const QUICAckFrame &ack_frame, QUICPacketNumberSpace pn_space, ink_hrtime largest_acked_time_sent) override
{
}
virtual void
Expand Down
8 changes: 4 additions & 4 deletions iocore/net/quic/QUICAckFrameCreator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

QUICAckFrameManager::QUICAckFrameManager()
{
for (auto i = 0; i < kPacketNumberSpace; i++) {
for (auto i = 0; i < QUIC_N_PACKET_SPACES; i++) {
this->_ack_creator[i] = std::make_unique<QUICAckFrameCreator>(static_cast<QUICPacketNumberSpace>(i), this);
}
}
Expand Down Expand Up @@ -132,7 +132,7 @@ QUICAckFrameManager::ack_delay_exponent() const
void
QUICAckFrameManager::set_max_ack_delay(uint16_t delay)
{
for (auto i = 0; i < kPacketNumberSpace; i++) {
for (auto i = 0; i < QUIC_N_PACKET_SPACES; i++) {
this->_ack_creator[i]->set_max_ack_delay(delay);
}
}
Expand Down Expand Up @@ -193,7 +193,7 @@ QUICAckFrameManager::QUICAckFrameCreator::push_back(QUICPacketNumber packet_numb
}

// can not delay handshake packet
if ((this->_pn_space == QUICPacketNumberSpace::Initial || this->_pn_space == QUICPacketNumberSpace::Handshake) && !ack_only) {
if ((this->_pn_space == QUICPacketNumberSpace::INITIAL || this->_pn_space == QUICPacketNumberSpace::HANDSHAKE) && !ack_only) {
this->_should_send = true;
}

Expand Down Expand Up @@ -335,7 +335,7 @@ QUICAckFrameManager::QUICAckFrameCreator::_calculate_delay()
ink_hrtime now = Thread::get_hrtime();
uint64_t delay = (now - this->_largest_ack_received_time) / 1000;
uint8_t ack_delay_exponent = 3;
if (this->_pn_space != QUICPacketNumberSpace::Initial && this->_pn_space != QUICPacketNumberSpace::Handshake) {
if (this->_pn_space != QUICPacketNumberSpace::INITIAL && this->_pn_space != QUICPacketNumberSpace::HANDSHAKE) {
ack_delay_exponent = this->_ack_manager->ack_delay_exponent();
}
return delay >> ack_delay_exponent;
Expand Down
2 changes: 1 addition & 1 deletion iocore/net/quic/QUICAckFrameCreator.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class QUICAckFrameManager : public QUICFrameGenerator

QUICAckFrameManager *_ack_manager = nullptr;

QUICPacketNumberSpace _pn_space = QUICPacketNumberSpace::Initial;
QUICPacketNumberSpace _pn_space = QUICPacketNumberSpace::INITIAL;
};

static constexpr int MAXIMUM_PACKET_COUNT = 256;
Expand Down
2 changes: 1 addition & 1 deletion iocore/net/quic/QUICAddrVerifyState.cc
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ QUICAddrVerifyState::consume(uint32_t windows)
}

uint32_t
QUICAddrVerifyState::windows()
QUICAddrVerifyState::windows() const
{
return this->_windows;
}
Expand Down
2 changes: 1 addition & 1 deletion iocore/net/quic/QUICAddrVerifyState.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class QUICAddrVerifyState
void fill(uint32_t windows);
void consume(uint32_t windows);
void set_addr_verifed();
uint32_t windows();
uint32_t windows() const;
bool is_verified() const;

private:
Expand Down

0 comments on commit 42c4054

Please sign in to comment.