Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions doc/admin-guide/files/records.yaml.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4837,6 +4837,14 @@ removed in the future without prior notice.
UDP Configuration
=====================

.. ts:cv:: CONFIG proxy.config.udp.poll_timeout INT 100
:units: milliseconds

This is the timeout for listening UDP connections to ``epoll_wait()`` on
Linux platforms, and to ``kevent()`` on BSD type OSs. The default value is
100. See :ts:cv:`proxy.config.net.poll_timeout` for general information on
poll_timeout.

.. ts:cv:: CONFIG proxy.config.udp.threads INT 0

Specifies the number of UDP threads to run. By default 0 threads are dedicated to UDP,
Expand Down
8 changes: 5 additions & 3 deletions iocore/net/UnixUDPNet.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ UDPPacket::free()
UDPNetProcessorInternal udpNetInternal;
UDPNetProcessor &udpNet = udpNetInternal;

int g_udp_pollTimeout;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking, but why not int32_t like others below?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The poll_timeout field is an int and int can be 2 bytes. Perhaps I'm the one who was nitpicking.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough. I found one for TCP is also int.

int32_t g_udp_periodicCleanupSlots;
int32_t g_udp_periodicFreeCancelledPkts;
int32_t g_udp_numSendRetries;
Expand Down Expand Up @@ -172,9 +173,10 @@ initialize_thread_for_udp_net(EThread *thread)

PollCont *upc = get_UDPPollCont(thread);
PollDescriptor *upd = upc->pollDescriptor;
// due to ET_UDP is really simple, it should sleep for a long time
// TODO: fixed size
upc->poll_timeout = 100;

REC_ReadConfigInteger(g_udp_pollTimeout, "proxy.config.udp.poll_timeout");
upc->poll_timeout = g_udp_pollTimeout;

// This variable controls how often we cleanup the cancelled packets.
// If it is set to 0, then cleanup never occurs.
REC_ReadConfigInt32(g_udp_periodicFreeCancelledPkts, "proxy.config.udp.free_cancelled_pkts_sec");
Expand Down
2 changes: 2 additions & 0 deletions src/records/RecordsConfig.cc
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ static const RecordElement RecordsConfig[] =
,
{RECT_CONFIG, "proxy.config.udp.send_retries", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
,
{RECT_CONFIG, "proxy.config.udp.poll_timeout", RECD_INT, "100", RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
,
{RECT_CONFIG, "proxy.config.udp.threads", RECD_INT, "0", RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
,
{RECT_CONFIG, "proxy.config.udp.enable_gso", RECD_INT, "1", RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
Expand Down
83 changes: 83 additions & 0 deletions tests/gold_tests/timeout/quic_poll_timeout.test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# 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.

from typing import Optional

Test.Summary = 'Checks ts.proxy.config.udp.poll_timeout'

Test.SkipUnless(
Condition.HasATSFeature('TS_HAS_QUICHE')
)


class TestPollTimeout:
"""Configure a test for poll_timeout."""

ts_counter: int = 0

def __init__(self, name: str, udp_poll_timeout_in: Optional[int] = None) -> None:
"""Initialize the test.

:param name: The name of the test.
:param udp_poll_timeout_in: Configuration value for proxy.config.udp.poll_timeout
"""
self.name = name
self.udp_poll_timeout_in = udp_poll_timeout_in
self.expected_udp_poll_timeout = 100
if udp_poll_timeout_in is not None:
self.expected_udp_poll_timeout = udp_poll_timeout_in

def _configure_traffic_server(self, tr: 'TestRun'):
"""Configure Traffic Server.

:param tr: The TestRun object to associate the ts process with.
"""
ts = tr.MakeATSProcess(f"ts-{TestPollTimeout.ts_counter}", enable_quic=True, enable_tls=True)

TestPollTimeout.ts_counter += 1
self._ts = ts
self._ts.Disk.records_config.update({
'proxy.config.diags.debug.enabled': 1,
'proxy.config.diags.debug.tags': 'net|v_quic|quic|socket|inactivity_cop|v_iocore_net_poll',
})

if self.udp_poll_timeout_in is not None:
self._ts.Disk.records_config.update({
'proxy.config.udp.poll_timeout': self.udp_poll_timeout_in
})

def run(self):
"""Run the test."""
tr = Test.AddTestRun(self.name)
self._configure_traffic_server(tr)

tr.Processes.Default.Command = "echo 'testing ts.proxy.config.udp.poll_timeout'"
tr.Processes.Default.StartBefore(self._ts)

self._ts.Disk.traffic_out.Content += Testers.IncludesExpression(
f"ET_UDP.*timeout: {self.expected_udp_poll_timeout},", "Verify UDP poll timeout.")

# Tests start.


test0 = TestPollTimeout(
"Test ts.proxy.config.udp.poll_timeout with default value.")
test0.run()

test1 = TestPollTimeout(
"Test ts.proxy.config.udp.poll_timeout with value of 10.",
udp_poll_timeout_in=10)
test1.run()