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
The following commit(s) were added to refs/heads/quic-latest by this push: new 2bebf6c QUIC: Limit the sending after 3 packets with unavlidated path 2bebf6c is described below commit 2bebf6c7338e28c6ef0f8c1cdb3fb6c4e57fcc26 Author: scw00 <sc...@apache.org> AuthorDate: Sat Feb 2 09:59:30 2019 +0800 QUIC: Limit the sending after 3 packets with unavlidated path --- iocore/net/P_QUICNetVConnection.h | 5 +- iocore/net/QUICNetVConnection.cc | 31 ++++++----- iocore/net/quic/Makefile.am | 13 ++++- iocore/net/quic/QUICAddrVerifyState.cc | 66 ++++++++++++++++++++++++ iocore/net/quic/QUICAddrVerifyState.h | 43 +++++++++++++++ iocore/net/quic/test/test_QUICAddrVerifyState.cc | 61 ++++++++++++++++++++++ 6 files changed, 199 insertions(+), 20 deletions(-) diff --git a/iocore/net/P_QUICNetVConnection.h b/iocore/net/P_QUICNetVConnection.h index 38b9284..8890ca9 100644 --- a/iocore/net/P_QUICNetVConnection.h +++ b/iocore/net/P_QUICNetVConnection.h @@ -59,6 +59,7 @@ #include "quic/QUICPathValidator.h" #include "quic/QUICApplicationMap.h" #include "quic/QUICPacketReceiveQueue.h" +#include "quic/QUICAddrVerifyState.h" // These are included here because older OpenQUIC libraries don't have them. // Don't copy these defines, or use their values directly, they are merely @@ -363,7 +364,6 @@ private: void _update_peer_cid(const QUICConnectionId &new_cid); void _update_local_cid(const QUICConnectionId &new_cid); void _rerandomize_original_cid(); - bool _is_src_addr_verified(); QUICHandshakeProtocol *_setup_handshake_protocol(SSL_CTX *ctx); @@ -379,9 +379,10 @@ private: uint64_t _stream_frames_sent = 0; // TODO: Source addresses verification through an address validation token - bool _src_addr_verified = false; bool _has_ack_only_packet_out = false; + QUICAddrVerifyState _verfied_state; + // QUICFrameGenerator void _on_frame_lost(QUICFrameInformationUPtr &info) override; std::vector<QUICEncryptionLevel> diff --git a/iocore/net/QUICNetVConnection.cc b/iocore/net/QUICNetVConnection.cc index 9872d5c..453002f 100644 --- a/iocore/net/QUICNetVConnection.cc +++ b/iocore/net/QUICNetVConnection.cc @@ -69,8 +69,6 @@ static constexpr ink_hrtime WRITE_READY_INTERVAL = HRTIME_MSECONDS(2); static constexpr uint32_t PACKET_PER_EVENT = 256; static constexpr uint32_t MAX_CONSECUTIVE_STREAMS = 8; //< Interrupt sending STREAM frames to send ACK frame -static constexpr uint32_t MAX_PACKETS_WITHOUT_SRC_ADDR_VARIDATION = 3; - static constexpr uint32_t STATE_CLOSING_MAX_SEND_PKT_NUM = 8; // Max number of sending packets which contain a closing frame. static constexpr uint32_t STATE_CLOSING_MAX_RECV_PKT_WIND = 1 << STATE_CLOSING_MAX_SEND_PKT_NUM; @@ -1052,8 +1050,8 @@ QUICNetVConnection::_state_handshake_process_handshake_packet(QUICPacketUPtr pac { // Source address is verified by receiving any message from the client encrypted using the // Handshake keys. - if (this->netvc_context == NET_VCONNECTION_IN && !this->_src_addr_verified) { - this->_src_addr_verified = true; + if (this->netvc_context == NET_VCONNECTION_IN && !this->_verfied_state.is_verified()) { + this->_verfied_state.set_addr_verifed(); } return this->_recv_and_ack(*packet); } @@ -1226,14 +1224,14 @@ QUICNetVConnection::_state_common_send_packet() continue; } - if (this->netvc_context == NET_VCONNECTION_IN && !this->_is_src_addr_verified() && - this->_handshake_packets_sent >= MAX_PACKETS_WITHOUT_SRC_ADDR_VARIDATION) { - error = 1; - break; + uint32_t max_packet_size = udp_payload_len - written; + if (this->netvc_context == NET_VCONNECTION_IN && !this->_verfied_state.is_verified()) { + uint32_t windows = this->_verfied_state.windows(); + QUICConDebug("send to unverified window: %u", windows); + max_packet_size = std::min(max_packet_size, windows); } - uint32_t max_packet_size = udp_payload_len - written; - QUICPacketUPtr packet = this->_packetize_frames(level, max_packet_size); + QUICPacketUPtr packet = this->_packetize_frames(level, max_packet_size); if (packet) { if (this->netvc_context == NET_VCONNECTION_IN && @@ -1241,6 +1239,10 @@ QUICNetVConnection::_state_common_send_packet() ++this->_handshake_packets_sent; } + if (this->netvc_context == NET_VCONNECTION_IN && !this->_verfied_state.is_verified()) { + this->_verfied_state.consume(packet->size()); + } + // TODO: do not write two QUIC Short Header Packets uint8_t *buf = reinterpret_cast<uint8_t *>(udp_payload->end()); size_t len = 0; @@ -1688,6 +1690,9 @@ QUICNetVConnection::_dequeue_recv_packet(QUICPacketCreationResult &result) } this->_last_received_packet_type = packet->type(); + if (!this->_verfied_state.is_verified()) { + this->_verfied_state.fill(packet->size()); + } } // Debug prints @@ -2083,12 +2088,6 @@ QUICNetVConnection::_rerandomize_original_cid() } } -bool -QUICNetVConnection::_is_src_addr_verified() -{ - return this->_src_addr_verified; -} - QUICHandshakeProtocol * QUICNetVConnection::_setup_handshake_protocol(SSL_CTX *ctx) { diff --git a/iocore/net/quic/Makefile.am b/iocore/net/quic/Makefile.am index ba75683..2b12239 100644 --- a/iocore/net/quic/Makefile.am +++ b/iocore/net/quic/Makefile.am @@ -81,7 +81,8 @@ libquic_a_SOURCES = \ QUICPathValidator.cc \ QUICPinger.cc \ QUICFrameGenerator.cc \ - QUICFrameRetransmitter.cc + QUICFrameRetransmitter.cc \ + QUICAddrVerifyState.cc # # Check Programs @@ -107,7 +108,8 @@ check_PROGRAMS = \ test_QUICType \ test_QUICTypeUtil \ test_QUICVersionNegotiator \ - test_QUICFrameRetransmitter + test_QUICFrameRetransmitter \ + test_QUICAddrVerifyState TESTS = $(check_PROGRAMS) @@ -288,6 +290,13 @@ test_QUICFrameRetransmitter_SOURCES = \ $(test_main_SOURCES) \ ./test/test_QUICFrameRetransmitter.cc +test_QUICAddrVerifyState_CPPFLAGS = $(test_CPPFLAGS) +test_QUICAddrVerifyState_LDFLAGS = @AM_LDFLAGS@ +test_QUICAddrVerifyState_LDADD = $(test_LDADD) +test_QUICAddrVerifyState_SOURCES = \ + $(test_main_SOURCES) \ + ./test/test_QUICAddrVerifyState.cc + # # clang-tidy # diff --git a/iocore/net/quic/QUICAddrVerifyState.cc b/iocore/net/quic/QUICAddrVerifyState.cc new file mode 100644 index 0000000..67281b5 --- /dev/null +++ b/iocore/net/quic/QUICAddrVerifyState.cc @@ -0,0 +1,66 @@ +/** @file + + A brief file description + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "QUICAddrVerifyState.h" + +void +QUICAddrVerifyState::fill(uint32_t windows) +{ + uint64_t tmp = this->_windows; + if (tmp + windows * 3 > UINT32_MAX) { + // overflow + this->_windows = UINT32_MAX; + return; + } + + this->_windows += windows * 3; +} + +void +QUICAddrVerifyState::consume(uint32_t windows) +{ + if (this->_windows <= windows) { + this->_windows = 0; + return; + } + + this->_windows -= windows; +} + +uint32_t +QUICAddrVerifyState::windows() +{ + return this->_windows; +} + +void +QUICAddrVerifyState::set_addr_verifed() +{ + this->_src_addr_verified = true; +} + +bool +QUICAddrVerifyState::is_verified() const +{ + return this->_src_addr_verified; +} diff --git a/iocore/net/quic/QUICAddrVerifyState.h b/iocore/net/quic/QUICAddrVerifyState.h new file mode 100644 index 0000000..d6d6c7c --- /dev/null +++ b/iocore/net/quic/QUICAddrVerifyState.h @@ -0,0 +1,43 @@ +/** @file + + A brief file description + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#pragma once + +#include <cstdint> + +class QUICAddrVerifyState +{ +public: + QUICAddrVerifyState(uint8_t packets, uint32_t windows) : _windows(windows) {} + QUICAddrVerifyState() = default; + + void fill(uint32_t windows); + void consume(uint32_t windows); + void set_addr_verifed(); + uint32_t windows(); + bool is_verified() const; + +private: + bool _src_addr_verified = false; + uint32_t _windows = 0; +}; diff --git a/iocore/net/quic/test/test_QUICAddrVerifyState.cc b/iocore/net/quic/test/test_QUICAddrVerifyState.cc new file mode 100644 index 0000000..a90135c --- /dev/null +++ b/iocore/net/quic/test/test_QUICAddrVerifyState.cc @@ -0,0 +1,61 @@ +/** @file + * + * A brief file description + * + * @section license License + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "catch.hpp" + +#include "P_QUICNetVConnection.h" +#include <memory> + +TEST_CASE("QUICAddrVerifyState", "[quic]") +{ + QUICAddrVerifyState state; + + // without consuming + CHECK(state.windows() == 0); + state.fill(10240); + CHECK(state.windows() == 10240 * 3); + + // consume + CHECK(state.windows() == 10240 * 3); + state.consume(10240); + CHECK(state.windows() == 10240 * 2); + state.consume(10240); + CHECK(state.windows() == 10240); + state.consume(10240); + CHECK(state.windows() == 0); + + // fill + state.fill(1); + CHECK(state.windows() == 3); + state.consume(1); + CHECK(state.windows() == 2); + state.consume(1); + CHECK(state.windows() == 1); + state.consume(1); + CHECK(state.windows() == 0); + + // fill overflow + state.fill(UINT32_MAX); + state.fill(2); + CHECK(state.windows() == UINT32_MAX); +}