diff --git a/iocore/net/QUICNetVConnection_quiche.cc b/iocore/net/QUICNetVConnection_quiche.cc index 278b3b27a22..df0d614b362 100644 --- a/iocore/net/QUICNetVConnection_quiche.cc +++ b/iocore/net/QUICNetVConnection_quiche.cc @@ -149,7 +149,7 @@ QUICNetVConnection::state_handshake(int event, Event *data) this->closed = 1; break; default: - QUICConDebug("Unhandleed event: %d", event); + QUICConDebug("Unhandled event: %d", event); break; } @@ -180,7 +180,7 @@ QUICNetVConnection::state_established(int event, Event *data) this->closed = 1; break; default: - QUICConDebug("Unhandleed event: %d", event); + QUICConDebug("Unhandled event: %d", event); break; } return EVENT_DONE; @@ -593,6 +593,7 @@ QUICNetVConnection::_handle_interval() this->_ctable->erase(this->_original_quic_connection_id, this); if (quiche_conn_is_timed_out(this->_quiche_con)) { + QUICConDebug("QUIC Idle timeout detected"); this->thread->schedule_imm(this, VC_EVENT_INACTIVITY_TIMEOUT); return; } diff --git a/tests/gold_tests/timeout/gold/quic_no_activity_timeout.gold b/tests/gold_tests/timeout/gold/quic_no_activity_timeout.gold new file mode 100644 index 00000000000..c1236240572 --- /dev/null +++ b/tests/gold_tests/timeout/gold/quic_no_activity_timeout.gold @@ -0,0 +1,3 @@ +`` +``Poll timed out waiting to read HTTP/3 content. +`` diff --git a/tests/gold_tests/timeout/quic_no_activity_timeout.test.py b/tests/gold_tests/timeout/quic_no_activity_timeout.test.py new file mode 100644 index 00000000000..32dadf07651 --- /dev/null +++ b/tests/gold_tests/timeout/quic_no_activity_timeout.test.py @@ -0,0 +1,139 @@ +# 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. + +Test.Summary = 'Basic checks on QUIC max_idle_timeout set by ts.quic.no_activity_timeout_in' + + +Test.SkipUnless( + Condition.HasATSFeature('TS_HAS_QUICHE'), + Condition.HasCurlFeature('http3') +) + + +class Test_quic_no_activity_timeout: + """Configure a test for QUIC no_activity_timeout_in.""" + + replay_file = "replay/quic_no_activity_timeout.replay.yaml" + client_counter: int = 0 + ts_counter: int = 0 + server_counter: int = 0 + + def __init__(self, name: str, no_activity_timeout_in=1000, gold_file="", replay_keys="", extra_recs=None): + """Initialize the test. + + :param name: The name of the test. + :param no_activity_timeout_in: Configuration value for ts.quic.no_activity_timeout_in + :param gold_file: Gold file to be checked. + :param replay_keys: Keys to be used by pv + :param extra_recs: Any additional records to be set, either a yaml string or a dict. + """ + self.name = name + self.no_activity_timeout_in = no_activity_timeout_in + self.gold_file = gold_file + self.replay_keys = replay_keys + self.extra_recs = extra_recs + + def _configure_server(self, tr: 'TestRun'): + """Configure the server. + + :param tr: The TestRun object to associate the server process with. + """ + server = tr.AddVerifierServerProcess( + f"server_{Test_quic_no_activity_timeout.server_counter}", + self.replay_file) + Test_quic_no_activity_timeout.server_counter += 1 + self._server = server + + 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-{Test_quic_no_activity_timeout.ts_counter}", enable_quic=True, enable_tls=True) + + Test_quic_no_activity_timeout.ts_counter += 1 + self._ts = ts + self._ts.addSSLfile("ssl/cert.crt") + self._ts.addSSLfile("ssl/private-key.key") + self._ts.Disk.records_config.update({ + 'proxy.config.diags.debug.enabled': 1, + 'proxy.config.diags.debug.tags': 'ssl|net|v_quic|quic|http|socket|inactivity_cop', + 'proxy.config.quic.no_activity_timeout_in': self.no_activity_timeout_in, + 'proxy.config.quic.qlog.file_base': f'log/qlog_{Test_quic_no_activity_timeout.server_counter}', + }) + + if self.extra_recs: + self._ts.Disk.records_config.update(self.extra_recs) + + self._ts.Disk.remap_config.AddLine(f'map / http://127.0.0.1:{self._server.Variables.http_port}') + self._ts.Disk.ssl_multicert_config.AddLine( + f'dest_ip=* ssl_cert_name={self._ts.Variables.SSLDir}/cert.crt ssl_key_name={self._ts.Variables.SSLDir}/private-key.key' + ) + + def run(self, check_for_max_idle_timeout=False): + """Run the test.""" + tr = Test.AddTestRun(self.name) + self._configure_server(tr) + self._configure_traffic_server(tr) + + tr.Processes.Default.StartBefore(self._server) + tr.Processes.Default.StartBefore(self._ts) + + tr.AddVerifierClientProcess( + f'client-{Test_quic_no_activity_timeout.client_counter}', + self.replay_file, + http3_ports=[self._ts.Variables.ssl_port], + keys=self.replay_keys) + Test_quic_no_activity_timeout.client_counter += 1 + + if check_for_max_idle_timeout: + tr.Processes.Default.ReturnCode = 1 # timeout + self._ts.Disk.traffic_out.All = Testers.IncludesExpression( + "QUIC Idle timeout detected", "We should detect the timeout.") + else: + tr.Processes.Default.ReturnCode = 0 + + if self.gold_file: + tr.Processes.Default.Streams.all = self.gold_file + +# Tests start. + + +test0 = Test_quic_no_activity_timeout( + "Test ts.quic.no_activity_timeout_in(quic max_idle_timeout), no delays", + no_activity_timeout_in=0, # no timeout `max_idle_timeout` + replay_keys="nodelays") +test0.run() + +test1 = Test_quic_no_activity_timeout( + "Test ts.quic.no_activity_timeout_in(quic max_idle_timeout) with a 5s delay", + no_activity_timeout_in=3000, # 3s `max_idle_timeout` + replay_keys="delay5s", + gold_file="gold/quic_no_activity_timeout.gold") +test1.run(check_for_max_idle_timeout=True) + +## +# The following tests is commented out as if we have a smaller default_inactivity_timeout +# happening before the configured max_idle_timeout in quiche we will end up crashing. +# The following should be uncommented once the bug is fixed. +# + +# test2 = Test_quic_no_activity_timeout( +# "Test quic ts.quic.no_activity_timeout_in(max_idle_timeout_, default_inactivity_timeout should kick in first.", +# replay_keys="delay5s", +# no_activity_timeout_in=6800, +# extra_recs={'proxy.config.net.default_inactivity_timeout': 1}) +# test2.run() diff --git a/tests/gold_tests/timeout/replay/quic_no_activity_timeout.replay.yaml b/tests/gold_tests/timeout/replay/quic_no_activity_timeout.replay.yaml new file mode 100644 index 00000000000..1937e6e6813 --- /dev/null +++ b/tests/gold_tests/timeout/replay/quic_no_activity_timeout.replay.yaml @@ -0,0 +1,91 @@ +# 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. + +meta: + version: "1.0" + +sessions: +- protocol: + - name: http + version: 3 + - name: tls + sni: test_sni + transactions: + + - client-request: + version: "3" + headers: + fields: + - [ Content-Length, 0 ] + - [:method, GET] + - [:scheme, https] + - [:authority, example.com] + - [:path, /path/test1] + - [ uuid, nodelays ] + server-response: + status: 200 + reason: "OK" + headers: + fields: + - [ Content-Length, 20 ] + + proxy-response: + status: 200 + + - client-request: + delay: 5s + version: "3" + headers: + fields: + - [ Content-Length, 0 ] + - [:method, GET] + - [:scheme, https] + - [:authority, example.com] + - [:path, /path/test2] + - [ uuid, delay5s ] + server-response: + status: 200 + reason: "OK" + headers: + fields: + - [ Content-Length, 20 ] + + proxy-response: + status: 200 + + - client-request: + delay: 1500ms + version: "3" + headers: + fields: + - [ Content-Length, 0 ] + - [:method, GET] + - [:scheme, https] + - [:authority, example.com] + - [:path, /path/test3] + - [ uuid, delay1500ms ] + server-response: + status: 200 + reason: "OK" + headers: + fields: + - [ Content-Length, 20 ] + + proxy-response: + status: 200 + + + diff --git a/tests/gold_tests/timeout/ssl/cert.crt b/tests/gold_tests/timeout/ssl/cert.crt new file mode 100644 index 00000000000..8dedfa250c1 --- /dev/null +++ b/tests/gold_tests/timeout/ssl/cert.crt @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFoDCCA4igAwIBAgIUPWkE7mLk4qWFS6dxtSaFDRdjAm4wDQYJKoZIhvcNAQEL +BQAwZzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFp +biBWaWV3MRcwFQYDVQQKDA5UcmFmZmljIFNlcnZlcjEaMBgGA1UEAwwRdHJhZmZp +Y3NlcnZlci5vcmcwHhcNMjMwMjE3MTIyMzI2WhcNMjUwMjE2MTIyMzI2WjBnMQsw +CQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcx +FzAVBgNVBAoMDlRyYWZmaWMgU2VydmVyMRowGAYDVQQDDBF0cmFmZmljc2VydmVy +Lm9yZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANyUH2QdsM3FuEGS +bZv/GZF4JT2e5zIdlj0AlobvpDntGAuGeAQpRBLrAyWxobCBbEqYvqXo1QXTDdee +Bx9fRiOhHkBC1OMMP5cJ9zdzo1/jXZ5A4WXATaxcX6VdmynxuoHLpyQZg504jFgB +HkpkYD0PCoB2aQ2uhE2O8oSQVVkI0ExyJLyq7mfdqbl/0wKc8XLPh9XtBTSbmELm +wAuCyFutsYGcv/4hMPZC6cbAjCWLQyokkH2mdNXdi4d95KDoL7wyh5inGaymCJbj +ObrqJ6Jj17GkBltqVV9LdBqLcqFQPbvdQycizWgeWmYJvBApgHxpp8aET4r0v+SL +fnXJx6M1ugohv6E832isemM0+yuWD6z9ZH/jBRHAQukLB4fqojFS8qIgEnXzH+vD +jk0mm6gm3hIZ+Xk/f/DGCX/fv8Un+MlZotJqaAEbWH1OxSJ2HpTMoOCIKPvmWZjk +qv9A5rJckXx9rzNukQt3ZU85LyHrDVOp+VQoyzyqGqhKPBC1gkQ/KenweAufMGU2 +9WFP6Oc5J807R3NR4q95DRg14yLB5fLF2R1yXkrxv3/qpRp+LGeYTL9AqOtJWIlf +pm50qbb9G/akxsl050AyXHDqzjTddHtlf0aOI97/DI8+KyfbzlTKPPllUoYcj8S4 +kRnlIvQyFGjZWZNFdksCXJzcG5/JAgMBAAGjRDBCMAsGA1UdDwQEAwIF4DATBgNV +HSUEDDAKBggrBgEFBQcDATAeBgNVHREEFzAVghMqLnRyYWZmaWNzZXJ2ZXIub3Jn +MA0GCSqGSIb3DQEBCwUAA4ICAQAzik7Hq+tjIeFHlFdeIHTlrVcuu+12XQ05bpwS +X2RdVSMj2FzjuOB1OTAMBpFl8hrLN1p5vTpIJ0x/Zx5Ks2YaR/KmF5In8/vPNbIr +ZHVfnLSgg/X+1dtN1LVnue+kQbuc7OlzJpwfmQjA4BYzAb0fbf+IM7E6MfEzT/kB +AChW3WF9eviyklOV0qZlRLDwrQLIT+oLsJNkX7OWFpVrpXrOLj4hYf2N7zxGHxYJ +g9NkmZOTJ4maXEpzNZaewpuIW4ldZccGchwhSX0daaoVmqYSVXjfRaCpRcb0mrPR +oj9x0Jj17v4G3FoyaOoW1DEAZwjFj8r7WaauGagQqBq0kflItrIRjzI+MlJkX3QS +0AKedEllbCpSe5VJcHlaR7K3y9w3hQTKlN4Im6M8eDJ+qxYURbDLE2cHBuaYkI9Q +aZcojBYSRA++fmmS5805CqKrhCCZbORI5zqBoB6iFUG1z+dwdpygDMpuH0bbXwQ1 +mp4S8GRKtTeJ2y2aFw/i/Wi/Qs8nAbQlSc6ei+oWT9ywdvkCFfdcsP+2LrWVVN3w +wAl26S08x9pZPI5kAvIG0DllSXYf65V3YXdzPoZ78igobWzfszAZ6OxfDQgkewfp +h4OSYKHBl3Jfe/Q9B8PcmgW0ikKGcquxFg3hvlMc0GZ/fVqUu++X+9Vb+QtMgyjJ +y4ybug== +-----END CERTIFICATE----- diff --git a/tests/gold_tests/timeout/ssl/private-key.key b/tests/gold_tests/timeout/ssl/private-key.key new file mode 100644 index 00000000000..f4350d6b2b0 --- /dev/null +++ b/tests/gold_tests/timeout/ssl/private-key.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +o6MNJBWDIgSRGCjUC0jfnjes9h8Lf9Q= +-----END PRIVATE KEY-----