diff --git a/cmd/traffic_quic/quic_client.cc b/cmd/traffic_quic/quic_client.cc index c42410cbd8d..d6a7176c508 100644 --- a/cmd/traffic_quic/quic_client.cc +++ b/cmd/traffic_quic/quic_client.cc @@ -51,6 +51,7 @@ QUICClient::start() NetVCOptions opt; opt.ip_proto = NetVCOptions::USE_UDP; opt.ip_family = info->ai_family; + opt.etype = ET_NET; opt.socket_recv_bufsize = 1048576; opt.socket_send_bufsize = 1048576; diff --git a/cmd/traffic_quic/quic_client.h b/cmd/traffic_quic/quic_client.h index 05d0c47581d..575d7a18c41 100644 --- a/cmd/traffic_quic/quic_client.h +++ b/cmd/traffic_quic/quic_client.h @@ -23,6 +23,7 @@ #pragma once +#include "P_Net.h" #include "I_EventSystem.h" #include "I_NetVConnection.h" #include "P_QUICNetProcessor.h" diff --git a/cmd/traffic_quic/traffic_quic.cc b/cmd/traffic_quic/traffic_quic.cc index 5e483491d7c..c46e80f4d49 100644 --- a/cmd/traffic_quic/traffic_quic.cc +++ b/cmd/traffic_quic/traffic_quic.cc @@ -74,17 +74,21 @@ main(int argc, const char **argv) Thread *main_thread = new EThread; main_thread->set_specific(); net_config_poll_timeout = 10; + ink_net_init(makeModuleVersion(1, 0, PRIVATE_MODULE_HEADER)); SSLInitializeLibrary(); SSLConfig::startup(); + netProcessor.init(); + quic_NetProcessor.init(); + ink_event_system_init(EVENT_SYSTEM_MODULE_VERSION); eventProcessor.start(THREADS); udpNet.start(1, stacksize); quic_NetProcessor.start(-1, stacksize); QUICClient client(addr, port); - eventProcessor.schedule_in(&client, 1, ET_UDP); + eventProcessor.schedule_in(&client, 1, ET_NET); this_thread()->execute(); } @@ -118,7 +122,7 @@ DNSConnection::trigger() void StatPagesManager::register_http(char const *, Action *(*)(Continuation *, HTTPHdr *)) { - ink_assert(false); + // ink_assert(false); } #include "ParentSelection.h" diff --git a/iocore/net/Makefile.am b/iocore/net/Makefile.am index b044e80c34e..f32cc13678a 100644 --- a/iocore/net/Makefile.am +++ b/iocore/net/Makefile.am @@ -162,10 +162,12 @@ libinknet_a_SOURCES = \ if ENABLE_QUIC libinknet_a_SOURCES += \ P_QUICPacketHandler.h \ + P_QUICNet.h \ P_QUICNetProcessor.h \ P_QUICNetVConnection.h \ P_QUICNextProtocolAccept.h \ QUICPacketHandler.cc \ + QUICNet.cc \ QUICNetProcessor.cc \ QUICNetVConnection.cc \ QUICNextProtocolAccept.cc diff --git a/iocore/net/P_Net.h b/iocore/net/P_Net.h index 0a7a502a3ea..38504ee0c0a 100644 --- a/iocore/net/P_Net.h +++ b/iocore/net/P_Net.h @@ -113,6 +113,7 @@ extern RecRawStatBlock *net_rsb; #include "P_QUICNetVConnection.h" #include "P_QUICNetProcessor.h" #include "P_QUICPacketHandler.h" +#include "P_QUICNet.h" #endif // #include "P_QUICCertLookup.h" diff --git a/iocore/net/P_QUICNet.h b/iocore/net/P_QUICNet.h new file mode 100644 index 00000000000..297ddbe3521 --- /dev/null +++ b/iocore/net/P_QUICNet.h @@ -0,0 +1,84 @@ +/** @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. + */ + +#ifndef __P_QUICNET_H__ +#define __P_QUICNET_H__ + +#include + +#include "ts/ink_platform.h" + +#include "P_Net.h" + +class NetHandler; +typedef int (NetHandler::*NetContHandler)(int, void *); + +void initialize_thread_for_quic_net(EThread *thread); + +struct QUICPollEvent { + typedef union data_t { + void *ptr; + uint32_t u32; + uint64_t u64; + } data_t; + + void free(); + + data_t data; + UDPPacketInternal *packet; + + SLINK(QUICPollEvent, alink); + LINK(QUICPollEvent, link); +}; + +struct QUICPollCont : public Continuation { + NetHandler *net_handler; + PollDescriptor *pollDescriptor; + + QUICPollCont(Ptr &m); + QUICPollCont(Ptr &m, NetHandler *nh); + ~QUICPollCont(); + int pollEvent(int, Event *); + +public: + // Atomic Queue to save incoming packets + ASLL(QUICPollEvent, alink) inQueue; + + // Internal Queue to save Long Header Packet + Que(UDPPacketInternal, link) longInQueue; + // Internal Queue to save Short Header Packet + Que(UDPPacketInternal, link) shortInQueue; + +private: + void _process_short_header_packet(QUICPollEvent *e, NetHandler *nh); + void _process_long_header_packet(QUICPollEvent *e, NetHandler *nh); +}; + +static inline QUICPollCont * +get_QUICPollCont(EThread *t) +{ + return (QUICPollCont *)ETHREAD_GET_PTR(t, quic_NetProcessor.quicPollCont_offset); +} + +extern ClassAllocator quicPollEventAllocator; +#endif diff --git a/iocore/net/P_QUICNetProcessor.h b/iocore/net/P_QUICNetProcessor.h index 29720609a00..c9d6c2adfb5 100644 --- a/iocore/net/P_QUICNetProcessor.h +++ b/iocore/net/P_QUICNetProcessor.h @@ -56,6 +56,7 @@ class QUICNetProcessor : public UnixNetProcessor QUICNetProcessor(); virtual ~QUICNetProcessor(); + void init() override; virtual int start(int, size_t stacksize) override; void cleanup(); // TODO: refactoring NetProcessor::connect_re and UnixNetProcessor::connect_re_internal @@ -67,6 +68,8 @@ class QUICNetProcessor : public UnixNetProcessor Action *main_accept(Continuation *cont, SOCKET fd, AcceptOptions const &opt) override; + off_t quicPollCont_offset; + private: QUICNetProcessor(const QUICNetProcessor &); QUICNetProcessor &operator=(const QUICNetProcessor &); diff --git a/iocore/net/P_QUICNetVConnection.h b/iocore/net/P_QUICNetVConnection.h index a82c37bd297..8f4d7e56656 100644 --- a/iocore/net/P_QUICNetVConnection.h +++ b/iocore/net/P_QUICNetVConnection.h @@ -145,6 +145,9 @@ class QUICNetVConnection : public UnixNetVConnection, public QUICConnection QUICNetVConnection() {} void init(QUICConnectionId original_cid, UDPConnection *, QUICPacketHandler *, QUICConnectionTable *ctable = nullptr); + // accept new conn_id + int acceptEvent(int event, Event *e); + // UnixNetVConnection void reenable(VIO *vio) override; VIO *do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf) override; @@ -302,4 +305,6 @@ class QUICNetVConnection : public UnixNetVConnection, public QUICConnection QUICStatelessResetToken _reset_token; }; +typedef int (QUICNetVConnection::*QUICNetVConnHandler)(int, void *); + extern ClassAllocator quicNetVCAllocator; diff --git a/iocore/net/P_UDPNet.h b/iocore/net/P_UDPNet.h index 599b6af6068..52de3b8b0ef 100644 --- a/iocore/net/P_UDPNet.h +++ b/iocore/net/P_UDPNet.h @@ -59,6 +59,8 @@ extern UDPNetProcessorInternal udpNetInternal; #define SLOT_TIME HRTIME_MSECONDS(SLOT_TIME_MSEC) #define N_SLOTS 2048 +constexpr int UDP_PERIOD = 9; + class PacketQueue { public: diff --git a/iocore/net/P_UnixNet.h b/iocore/net/P_UnixNet.h index 6c69bd35957..ab45b663017 100644 --- a/iocore/net/P_UnixNet.h +++ b/iocore/net/P_UnixNet.h @@ -83,6 +83,7 @@ struct EventIO { int events = 0; #endif EventLoop event_loop = nullptr; + bool syscall = true; int type = 0; union { Continuation *c; @@ -587,6 +588,10 @@ EventIO::start(EventLoop l, UnixUDPConnection *vc, int events) TS_INLINE int EventIO::close() { + if (!this->syscall) { + return 0; + } + stop(); switch (type) { default: @@ -608,6 +613,10 @@ EventIO::close() TS_INLINE int EventIO::start(EventLoop l, int afd, Continuation *c, int e) { + if (!this->syscall) { + return 0; + } + data.c = c; fd = afd; event_loop = l; @@ -643,6 +652,10 @@ EventIO::start(EventLoop l, int afd, Continuation *c, int e) TS_INLINE int EventIO::modify(int e) { + if (!this->syscall) { + return 0; + } + ink_assert(event_loop); #if TS_USE_EPOLL && !defined(USE_EDGE_TRIGGER) struct epoll_event ev; @@ -722,6 +735,10 @@ EventIO::modify(int e) TS_INLINE int EventIO::refresh(int e) { + if (!this->syscall) { + return 0; + } + ink_assert(event_loop); #if TS_USE_KQUEUE && defined(USE_EDGE_TRIGGER) e = e & events; @@ -763,6 +780,10 @@ EventIO::refresh(int e) TS_INLINE int EventIO::stop() { + if (!this->syscall) { + return 0; + } + if (event_loop) { int retval = 0; #if TS_USE_EPOLL diff --git a/iocore/net/QUICNet.cc b/iocore/net/QUICNet.cc new file mode 100644 index 00000000000..68c3bee11c1 --- /dev/null +++ b/iocore/net/QUICNet.cc @@ -0,0 +1,168 @@ +/** @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 "P_Net.h" + +ClassAllocator quicPollEventAllocator("quicPollEvent"); + +void +QUICPollEvent::free() +{ + quicPollEventAllocator.free(this); +} + +QUICPollCont::QUICPollCont(Ptr &m) : Continuation(m.get()), net_handler(nullptr) +{ + SET_HANDLER(&QUICPollCont::pollEvent); +} + +QUICPollCont::QUICPollCont(Ptr &m, NetHandler *nh) : Continuation(m.get()), net_handler(nh) +{ + SET_HANDLER(&QUICPollCont::pollEvent); +} + +QUICPollCont::~QUICPollCont() +{ +} + +void +QUICPollCont::_process_long_header_packet(QUICPollEvent *e, NetHandler *nh) +{ + uint8_t *buf; + QUICPacketType ptype; + UDPPacketInternal *p = e->packet; + // FIXME: VC is nullptr ? + QUICNetVConnection *vc = static_cast(e->data.ptr); + buf = (uint8_t *)p->getIOBlockChain()->buf(); + + e->free(); + if (!QUICTypeUtil::has_connection_id(reinterpret_cast(buf))) { + // TODO: Some packets may not have connection id + p->free(); + return; + } + + ptype = static_cast(buf[0] & 0x7f); + switch (ptype) { + case QUICPacketType::INITIAL: + vc->read.triggered = 1; + vc->handle_received_packet(p); + this->mutex->thread_holding->schedule_imm(vc); + return; + case QUICPacketType::ZERO_RTT_PROTECTED: + // TODO:: do something ? + // break; + case QUICPacketType::HANDSHAKE: + default: + // Just Pass Through + if (vc) { + vc->read.triggered = 1; + vc->handle_received_packet(p); + } else { + longInQueue.push(p); + } + + // Push QUICNetVC into nethandler's enabled list + if (vc != nullptr) { + int isin = ink_atomic_swap(&vc->read.in_enabled_list, 1); + if (!isin) { + nh->read_enable_list.push(vc); + } + } + break; + } +} + +void +QUICPollCont::_process_short_header_packet(QUICPollEvent *e, NetHandler *nh) +{ + uint8_t *buf; + UDPPacketInternal *p = e->packet; + QUICNetVConnection *vc = static_cast(e->data.ptr); + buf = (uint8_t *)p->getIOBlockChain()->buf(); + + e->free(); + if (!QUICTypeUtil::has_connection_id(reinterpret_cast(buf))) { + // TODO: Some packets may not have connection id + p->free(); + return; + } + + if (vc) { + vc->read.triggered = 1; + vc->handle_received_packet(p); + } else { + shortInQueue.push(p); + } + + // Push QUICNetVC into nethandler's enabled list + if (vc != nullptr) { + int isin = ink_atomic_swap(&vc->read.in_enabled_list, 1); + if (!isin) { + nh->read_enable_list.push(vc); + } + } +} + +// +// QUICPollCont continuation which traverse the inQueue(ASLL) +// and create new QUICNetVC for Initial Packet, +// and push the triggered QUICNetVC into enable list. +// +int +QUICPollCont::pollEvent(int, Event *) +{ + ink_assert(this->mutex->thread_holding == this_thread()); + uint8_t *buf; + QUICPollEvent *e; + NetHandler *nh = get_NetHandler(this->mutex->thread_holding); + + // Process the ASLL + SList(QUICPollEvent, link) aq(inQueue.popall()); + Queue result; + while ((e = aq.pop())) { + result.push(e); + } + + while ((e = result.pop())) { + buf = (uint8_t *)e->packet->getIOBlockChain()->buf(); + if (QUICTypeUtil::has_long_header(buf)) { // Long Header Packet with Connection ID, has a valid type value. + this->_process_long_header_packet(e, nh); + } else { // Short Header Packet with Connection ID, has a valid type value. + this->_process_short_header_packet(e, nh); + } + } + + return EVENT_CONT; +} + +void +initialize_thread_for_quic_net(EThread *thread) +{ + NetHandler *nh = get_NetHandler(thread); + QUICPollCont *quicpc = get_QUICPollCont(thread); + + new ((ink_dummy_for_new *)quicpc) QUICPollCont(thread->mutex, nh); + + thread->schedule_every(quicpc, -HRTIME_MSECONDS(UDP_PERIOD)); +} diff --git a/iocore/net/QUICNetProcessor.cc b/iocore/net/QUICNetProcessor.cc index 8dc335f6653..979af876c56 100644 --- a/iocore/net/QUICNetProcessor.cc +++ b/iocore/net/QUICNetProcessor.cc @@ -50,6 +50,16 @@ QUICNetProcessor::cleanup() SSL_CTX_free(this->_ssl_ctx); } +void +QUICNetProcessor::init() +{ + // first we allocate a QUICPollCont. + this->quicPollCont_offset = eventProcessor.allocate(sizeof(QUICPollCont)); + + // schedule event + eventProcessor.schedule_spawn(&initialize_thread_for_quic_net, ET_NET); +} + int QUICNetProcessor::start(int, size_t stacksize) { @@ -113,6 +123,7 @@ QUICNetProcessor::allocate_vc(EThread *t) } } + vc->ep.syscall = false; return vc; } @@ -171,8 +182,29 @@ QUICNetProcessor::connect_re(Continuation *cont, sockaddr const *remote_addr, Ne vc->mutex = cont->mutex; vc->action_ = cont; + SET_CONTINUATION_HANDLER(vc, &QUICNetVConnection::startEvent); + vc->start(this->_ssl_ctx); - vc->connectUp(t, NO_FD); + + if (t->is_event_type(opt->etype)) { + MUTEX_TRY_LOCK(lock, cont->mutex, t); + if (lock.is_locked()) { + MUTEX_TRY_LOCK(lock2, get_NetHandler(t)->mutex, t); + if (lock2.is_locked()) { + vc->connectUp(t, NO_FD); + return ACTION_RESULT_DONE; + } + } + } + + // Try to stay on the current thread if it is the right type + if (t->is_event_type(opt->etype)) { + t->schedule_imm(vc); + } else { // Otherwise, pass along to another thread of the right type + eventProcessor.schedule_imm(vc, opt->etype); + } + + // vc->connectUp(t, NO_FD); return ACTION_RESULT_DONE; } diff --git a/iocore/net/QUICNetVConnection.cc b/iocore/net/QUICNetVConnection.cc index 3967513b74c..dc8823f3ff7 100644 --- a/iocore/net/QUICNetVConnection.cc +++ b/iocore/net/QUICNetVConnection.cc @@ -63,7 +63,7 @@ void QUICNetVConnection::init(QUICConnectionId original_cid, UDPConnection *udp_con, QUICPacketHandler *packet_handler, QUICConnectionTable *ctable) { - SET_HANDLER((NetVConnHandler)&QUICNetVConnection::state_pre_handshake); + SET_HANDLER((NetVConnHandler)&QUICNetVConnection::acceptEvent); this->_packet_transmitter_mutex = new_ProxyMutex(); this->_frame_transmitter_mutex = new_ProxyMutex(); this->_udp_con = udp_con; @@ -94,8 +94,69 @@ QUICNetVConnection::do_io_write(Continuation *c, int64_t nbytes, IOBufferReader } int -QUICNetVConnection::startEvent(int /*event ATS_UNUSED */, Event *e) +QUICNetVConnection::acceptEvent(int event, Event *e) { + EThread *t = (e == nullptr) ? this_ethread() : e->ethread; + NetHandler *h = get_NetHandler(t); + + MUTEX_TRY_LOCK(lock, h->mutex, t); + if (!lock.is_locked()) { + if (event == EVENT_NONE) { + t->schedule_in(this, HRTIME_MSECONDS(net_retry_delay)); + return EVENT_DONE; + } else { + e->schedule_in(HRTIME_MSECONDS(net_retry_delay)); + return EVENT_CONT; + } + } + + thread = t; + + // Send this NetVC to NetHandler and start to polling read & write event. + if (h->startIO(this) < 0) { + free(t); + return EVENT_DONE; + } + + // FIXME: complete do_io_xxxx instead + this->read.enabled = 1; + + // Handshake callback handler. + SET_HANDLER((NetVConnHandler)&QUICNetVConnection::state_pre_handshake); + + // Send this netvc to InactivityCop. + nh->startCop(this); + + if (inactivity_timeout_in) { + set_inactivity_timeout(inactivity_timeout_in); + } else { + set_inactivity_timeout(0); + } + + if (active_timeout_in) { + set_active_timeout(active_timeout_in); + } + + action_.continuation->handleEvent(NET_EVENT_ACCEPT, this); + return EVENT_DONE; +} + +int +QUICNetVConnection::startEvent(int event, Event *e) +{ + ink_assert(event == EVENT_IMMEDIATE); + MUTEX_TRY_LOCK(lock, get_NetHandler(e->ethread)->mutex, e->ethread); + if (!lock.is_locked()) { + e->schedule_in(HRTIME_MSECONDS(net_retry_delay)); + return EVENT_CONT; + } + + if (!action_.cancelled) { + this->connectUp(e->ethread, NO_FD); + } else { + this->free(e->ethread); + } + return EVENT_DONE; } @@ -173,6 +234,17 @@ QUICNetVConnection::reenable(VIO *vio) int QUICNetVConnection::connectUp(EThread *t, int fd) { + int res = 0; + NetHandler *nh = get_NetHandler(t); + this->thread = this_ethread(); + ink_assert(nh->mutex->thread_holding == this->thread); + + SET_HANDLER((NetVConnHandler)&QUICNetVConnection::state_pre_handshake); + + if ((res = nh->startIO(this)) < 0) { + // FIXME: startIO only return 0 now! what should we do if it failed ? + } + // create stream for handshake QUICErrorUPtr error = this->_stream_manager->create_stream(STREAM_ID_FOR_HANDSHAKE); if (error->cls != QUICErrorClass::NONE) { @@ -181,6 +253,11 @@ QUICNetVConnection::connectUp(EThread *t, int fd) return CONNECT_FAILURE; } + nh->startCop(this); + + // FIXME: complete do_io_xxxx instead + this->read.enabled = 1; + // start QUIC handshake this->_handshake_handler->handleEvent(VC_EVENT_WRITE_READY, nullptr); @@ -589,8 +666,7 @@ QUICNetVConnection::get_udp_con() void QUICNetVConnection::net_read_io(NetHandler *nh, EThread *lthread) { - ink_assert(false); - + this->handleEvent(QUIC_EVENT_PACKET_READ_READY, nullptr); return; } diff --git a/iocore/net/QUICPacketHandler.cc b/iocore/net/QUICPacketHandler.cc index e60b442afcf..5eb99662816 100644 --- a/iocore/net/QUICPacketHandler.cc +++ b/iocore/net/QUICPacketHandler.cc @@ -124,7 +124,10 @@ QUICPacketHandlerIn::init_accept(EThread *t = nullptr) void QUICPacketHandlerIn::_recv_packet(int event, UDPPacket *udp_packet) { - IOBufferBlock *block = udp_packet->getIOBlockChain(); + EThread *eth = nullptr; + QUICPollEvent *qe = nullptr; + QUICNetVConnection *vc = nullptr; + IOBufferBlock *block = udp_packet->getIOBlockChain(); if (is_debug_tag_set("quic_sec")) { ip_port_text_buffer ipb; @@ -158,14 +161,17 @@ QUICPacketHandlerIn::_recv_packet(int event, UDPPacket *udp_packet) return; } + eth = eventProcessor.assign_thread(ET_NET); + // Create a new NetVConnection QUICConnectionId original_cid = this->_read_connection_id(block); - QUICNetVConnection *vc = static_cast(getNetProcessor()->allocate_vc(nullptr)); + vc = static_cast(getNetProcessor()->allocate_vc(nullptr)); vc->init(original_cid, udp_packet->getConnection(), this, &this->_ctable); vc->id = net_next_connection_number(); vc->con.move(con); vc->submit_time = Thread::get_hrtime(); - vc->mutex = this->mutex; + vc->thread = eth; + vc->mutex = new_ProxyMutex(); vc->action_ = *this->action_; vc->set_is_transparent(this->opt.f_inbound_transparent); vc->set_context(NET_VCONNECTION_IN); @@ -174,20 +180,19 @@ QUICPacketHandlerIn::_recv_packet(int event, UDPPacket *udp_packet) vc->options.ip_proto = NetVCOptions::USE_UDP; vc->options.ip_family = udp_packet->from.sa.sa_family; - this->action_->continuation->handleEvent(NET_EVENT_ACCEPT, vc); qc = vc; - } - - if (qc->is_closed()) { - this->_ctable.erase(qc->connection_id(), qc); - // FIXME QUICNetVConnection is NOT freed to prevent crashes. #2674 - // QUICNetVConnections are going to be freed by QUICNetHandler - // vc->free(vc->thread); } else { - qc->handle_received_packet(udp_packet); - // FIXME This cast is temporal. It'll be removed when we introduce QUICNetHandler. - eventProcessor.schedule_imm(static_cast(qc), ET_CALL, QUIC_EVENT_PACKET_READ_READY, nullptr); + vc = static_cast(qc); + eth = vc->thread; } + + qe = quicPollEventAllocator.alloc(); + + qe->data.ptr = vc; + // should we use dynamic_cast ?? + qe->packet = static_cast(udp_packet); + // Push the packet into QUICPollCont + get_QUICPollCont(eth)->inQueue.push(qe); } // TODO: Should be called via eventProcessor? diff --git a/iocore/net/UnixUDPNet.cc b/iocore/net/UnixUDPNet.cc index 5a682062463..e3891b8ff4b 100644 --- a/iocore/net/UnixUDPNet.cc +++ b/iocore/net/UnixUDPNet.cc @@ -86,7 +86,7 @@ initialize_thread_for_udp_net(EThread *thread) REC_ReadConfigInt32(g_udp_numSendRetries, "proxy.config.udp.send_retries"); g_udp_numSendRetries = g_udp_numSendRetries < 0 ? 0 : g_udp_numSendRetries; - thread->schedule_every(get_UDPPollCont(thread), -9); + thread->schedule_every(get_UDPPollCont(thread), -HRTIME_MSECONDS(UDP_PERIOD)); thread->schedule_imm(get_UDPNetHandler(thread)); } @@ -923,7 +923,7 @@ UDPNetHandler::startNetEvent(int event, Event *e) (void)event; SET_HANDLER((UDPNetContHandler)&UDPNetHandler::mainNetEvent); trigger_event = e; - e->schedule_every(-HRTIME_MSECONDS(9)); + e->schedule_every(-HRTIME_MSECONDS(UDP_PERIOD)); return EVENT_CONT; } diff --git a/proxy/Main.cc b/proxy/Main.cc index 5e36c0e16df..5614444ba0f 100644 --- a/proxy/Main.cc +++ b/proxy/Main.cc @@ -1800,6 +1800,10 @@ main(int /* argc ATS_UNUSED */, const char **argv) // Do the inits for NetProcessors that use ET_NET threads. MUST be before starting those threads. netProcessor.init(); init_HttpProxyServer(); +#if TS_USE_QUIC == 1 + // OK, pushing a spawn scheduling here + quic_NetProcessor.init(); +#endif // !! ET_NET threads start here !! // This means any spawn scheduling must be done before this point.