This is an automated email from the ASF dual-hosted git repository.
bneradt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 0e42870205 Add a per client connection max exempt list cript (#12476)
0e42870205 is described below
commit 0e4287020548e7316156a4debfed49c0fedc7312
Author: Brian Neradt <[email protected]>
AuthorDate: Wed Dec 10 22:52:14 2025 -0600
Add a per client connection max exempt list cript (#12476)
This updates our build system to be able to make pre-compiled cripts.
Thus, adding a cript is now as easy as adding a plugin. Simply use
add_cript instead of add_atsplugin in CMakeLists.txt, and it will build
your cript for you.
As a part of this, this adds connection_exempt_list.cript, our first
cript plugin that sets the per client exempt list.
---
.gitignore | 3 +-
.vscode/settings.json | 3 +-
cmake/ExperimentalPlugins.cmake | 1 +
cmake/add_cript.cmake | 35 +++++++
doc/Doxyfile | 2 +-
.../plugins/connection_exempt_list.en.rst | 103 +++++++++++++++++++++
doc/admin-guide/plugins/index.en.rst | 5 +
include/cripts/Epilogue.hpp | 6 +-
plugins/CMakeLists.txt | 1 +
plugins/experimental/CMakeLists.txt | 3 +
.../connection_exempt_list/CMakeLists.txt | 19 ++++
.../connection_exempt_list.cript | 86 +++++++++++++++++
src/api/InkAPI.cc | 6 ++
src/cripts/Instance.cc | 9 ++
src/iocore/net/ConnectionTracker.cc | 5 +
tests/gold_tests/autest-site/setup.cli.ext | 1 +
.../gold_tests/autest-site/trafficserver.test.ext | 7 +-
.../client_connection/exempt_lists/exempt_all.yaml | 19 ++++
.../exempt_lists/exempt_localhost.yaml | 19 ++++
.../exempt_lists/no_localhost.yaml | 19 ++++
.../per_client_connection_max.test.py | 27 +++++-
tests/gold_tests/cripts/files/basic.cript | 12 +--
tools/clang-format.sh | 2 +-
tools/git/pre-commit | 2 +-
24 files changed, 375 insertions(+), 20 deletions(-)
diff --git a/.gitignore b/.gitignore
index b3d53eed65..707dfb8f74 100644
--- a/.gitignore
+++ b/.gitignore
@@ -170,7 +170,8 @@ rc/trafficserver.service
.libs/
.svn/
-.vscode/
+.vscode/*
+!.vscode/settings.json
target
tsxs
diff --git a/.vscode/settings.json b/.vscode/settings.json
index bf5756ef90..9757af98a9 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,6 +1,7 @@
{
"files.associations": {
+ "*.cript": "cpp",
+ "*.test.py": "python",
"*.test.ext": "python"
}
}
-
diff --git a/cmake/ExperimentalPlugins.cmake b/cmake/ExperimentalPlugins.cmake
index e8ea614134..487e0bfed1 100644
--- a/cmake/ExperimentalPlugins.cmake
+++ b/cmake/ExperimentalPlugins.cmake
@@ -31,6 +31,7 @@ auto_option(ACCESS_CONTROL FEATURE_VAR BUILD_ACCESS_CONTROL
DEFAULT ${_DEFAULT})
auto_option(BLOCK_ERRORS FEATURE_VAR BUILD_BLOCK_ERRORS DEFAULT ${_DEFAULT})
auto_option(CACHE_FILL FEATURE_VAR BUILD_CACHE_FILL DEFAULT ${_DEFAULT})
auto_option(CERT_REPORTING_TOOL FEATURE_VAR BUILD_CERT_REPORTING_TOOL DEFAULT
${_DEFAULT})
+auto_option(CONNECTION_EXEMPT_LIST FEATURE_VAR BUILD_CONNECTION_EXEMPT_LIST
DEFAULT ${_DEFAULT})
auto_option(COOKIE_REMAP FEATURE_VAR BUILD_COOKIE_REMAP DEFAULT ${_DEFAULT})
auto_option(CUSTOM_REDIRECT FEATURE_VAR BUILD_CUSTOM_REDIRECT DEFAULT
${_DEFAULT})
auto_option(FQ_PACING FEATURE_VAR BUILD_FQ_PACING DEFAULT ${_DEFAULT})
diff --git a/cmake/add_cript.cmake b/cmake/add_cript.cmake
new file mode 100644
index 0000000000..4a14537073
--- /dev/null
+++ b/cmake/add_cript.cmake
@@ -0,0 +1,35 @@
+#######################
+#
+# 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.
+#
+#######################
+
+# Function to build pre-compiled cript scripts
+function(add_cript name source_file)
+ # Check if ENABLE_CRIPTS is ON, if not, skip
+ if(NOT ENABLE_CRIPTS)
+ message(STATUS "Skipping cript ${name} - ENABLE_CRIPTS is OFF")
+ return()
+ endif()
+
+ # Use the standard ATS plugin macro and link with cripts
+ add_atsplugin(${name} ${source_file})
+ target_link_libraries(${name} PRIVATE ts::cripts)
+
+ # Tell CMake that .cript files are C++ files
+ set_target_properties(${name} PROPERTIES LINKER_LANGUAGE CXX)
+ set_source_files_properties(${source_file} PROPERTIES LANGUAGE CXX)
+
+ verify_remap_plugin(${name})
+endfunction()
diff --git a/doc/Doxyfile b/doc/Doxyfile
index b8022942e6..aa1e06da9c 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -768,7 +768,7 @@ INPUT_ENCODING = UTF-8
# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
# *.qsf, *.as and *.js.
-FILE_PATTERNS = *.c *.cc *.h *.h.in *.i
+FILE_PATTERNS = *.c *.cc *.h *.h.in *.i *.cript
# The RECURSIVE tag can be used to specify whether or not subdirectories should
# be searched for input files as well.
diff --git a/doc/admin-guide/plugins/connection_exempt_list.en.rst
b/doc/admin-guide/plugins/connection_exempt_list.en.rst
new file mode 100644
index 0000000000..cb1f93372e
--- /dev/null
+++ b/doc/admin-guide/plugins/connection_exempt_list.en.rst
@@ -0,0 +1,103 @@
+.. include:: ../../common.defs
+
+.. _admin-plugins-connection-exempt-list:
+
+Connection Exempt List Plugin
+******************************
+
+.. 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.
+
+Description
+===========
+
+:ts:cv:`proxy.config.http.per_client.connection.exempt_list` allows
+administrators to set exemptions to the per-client connection limit. However,
+for large networks, managing this as a comma-separated string in
+:file:`records.yaml` can be cumbersome. This plugin allows administrators to
set
+the exemption list :ts:cv:`proxy.config.http.per_client.connection.exempt_list`
+value via an external YAML file.
+
+Plugin Configuration
+====================
+
+The plugin is configured as a global plugin and requires a path to a YAML
+configuration file. Load the plugin by adding a line to the
+:file:`plugin.config`:
+
+.. code-block:: text
+
+ connection_exempt_list.so /path/to/exempt_list.yaml
+
+Configuration File Format
+==========================
+
+The exempt list configuration file must be in YAML format with the following
+simple structure:
+
+.. code-block:: yaml
+
+ exempt_list:
+ - 127.0.0.1
+ - ::1
+ - 192.168.1.0/24
+ - 10.0.0.0/8
+
+The configuration file supports the same range formats as
+:ts:cv:`proxy.config.http.per_client.connection.exempt_list`.
+
+* Individual IPv4 addresses (e.g., ``192.168.1.100``)
+* Individual IPv6 addresses (e.g., ``::1``, ``2001:db8::1``)
+* IPv4 CIDR ranges (e.g., ``192.168.0.0/16``)
+* Ranges as a dash-separated string (e.g., ``10.0.0.0-10.0.0.255``)
+
+Example Usage
+=============
+
+1. Create an exempt list configuration file (e.g.,
+``/opt/ats/etc/trafficserver/exempt_localhost.yaml``):
+
+ .. code-block:: yaml
+
+ exempt_list:
+ - 127.0.0.1
+ - ::1
+
+2. Enable the plugin in :file:`plugin.config`:
+
+ .. code-block:: text
+
+ connection_exempt_list.so
/opt/ats/etc/trafficserver/exempt_localhost.yaml
+
+3. Configure per-client connection limits in :file:`records.yaml`:
+
+ .. code-block:: yaml
+
+ records:
+ net:
+ per_client:
+ max_connections_in: 300
+
+4. Start |TS|. The plugin will load the exempt list and not apply the
per-client
+ connection limit to the exempted IP addresses and ranges.
+
+See Also
+========
+
+* :ts:cv:`proxy.config.net.per_client.max_connections_in`
+* :ts:cv:`proxy.config.http.per_client.connection.exempt_list`
+* :doc:`../files/plugin.config.en`
diff --git a/doc/admin-guide/plugins/index.en.rst
b/doc/admin-guide/plugins/index.en.rst
index 3334bdc2d7..8de06d9724 100644
--- a/doc/admin-guide/plugins/index.en.rst
+++ b/doc/admin-guide/plugins/index.en.rst
@@ -170,6 +170,7 @@ directory of the |TS| source tree. Experimental plugins can
be compiled by passi
Cache Fill <cache_fill.en>
Certifier <certifier.en>
Cert Reporting Tool <cert_reporting_tool.en>
+ Connection Exempt List <connection_exempt_list.en>
Cookie Remap <cookie_remap.en>
GeoIP ACL <geoip_acl.en>
FQ Pacing <fq_pacing.en>
@@ -208,6 +209,10 @@ directory of the |TS| source tree. Experimental plugins
can be compiled by passi
:doc:`Cert Reporting Tool <cert_reporting_tool.en>`
Examines and logs information on loaded certificates.
+:doc:`Connection Exempt List <connection_exempt_list.en>`
+ Provides a way for administrators to set
+ :ts:cv:`proxy.config.http.per_client.connection.exempt_list` via a YAML
file.
+
:doc:`Cookie Remap <cookie_remap.en>`
Makes decisions on destinations based on cookies.
diff --git a/include/cripts/Epilogue.hpp b/include/cripts/Epilogue.hpp
index c729982898..715673ccb0 100644
--- a/include/cripts/Epilogue.hpp
+++ b/include/cripts/Epilogue.hpp
@@ -753,9 +753,13 @@ TSPluginInit(int argc, const char *argv[])
TSContDataSet(contp, context);
TSHttpHookAdd(TS_HTTP_TXN_START_HOOK, contp); // This acts similarly to
the DoRemap callback
} else {
+ if (needs_glb_init) {
+ CDebug("[%s] - No global hooks, but there is a global init callback",
info.plugin_name);
+ } else {
+ TSError("[%s] - No global hooks, no global init callback",
info.plugin_name);
+ }
delete context;
delete inst;
- TSError("[%s] - No global hooks enabled", info.plugin_name);
}
}
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
index e4f4f7af3f..d61fa837f2 100644
--- a/plugins/CMakeLists.txt
+++ b/plugins/CMakeLists.txt
@@ -16,6 +16,7 @@
#######################
include(add_atsplugin)
+include(add_cript)
# The experimental plugins are handled in cmake/ExperimentalPlugins.cmake.
diff --git a/plugins/experimental/CMakeLists.txt
b/plugins/experimental/CMakeLists.txt
index 20a54f4705..33e9b29faa 100644
--- a/plugins/experimental/CMakeLists.txt
+++ b/plugins/experimental/CMakeLists.txt
@@ -29,6 +29,9 @@ endif()
if(BUILD_CERT_REPORTING_TOOL)
add_subdirectory(cert_reporting_tool)
endif()
+if(BUILD_CONNECTION_EXEMPT_LIST)
+ add_subdirectory(connection_exempt_list)
+endif()
if(BUILD_COOKIE_REMAP)
add_subdirectory(cookie_remap)
endif()
diff --git a/plugins/experimental/connection_exempt_list/CMakeLists.txt
b/plugins/experimental/connection_exempt_list/CMakeLists.txt
new file mode 100644
index 0000000000..e58158b484
--- /dev/null
+++ b/plugins/experimental/connection_exempt_list/CMakeLists.txt
@@ -0,0 +1,19 @@
+#######################
+#
+# 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.
+#
+#######################
+
+# Build the connection_exempt_list cript as a pre-compiled plugin
+add_cript(connection_exempt_list connection_exempt_list.cript)
diff --git
a/plugins/experimental/connection_exempt_list/connection_exempt_list.cript
b/plugins/experimental/connection_exempt_list/connection_exempt_list.cript
new file mode 100644
index 0000000000..b94edace2f
--- /dev/null
+++ b/plugins/experimental/connection_exempt_list/connection_exempt_list.cript
@@ -0,0 +1,86 @@
+/*
+ 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 <cripts/Preamble.hpp>
+#include <yaml-cpp/yaml.h>
+
+glb_init()
+{
+ CDebug("Initializing per-client connection exempt list plugin");
+ if (instance.Size() != 1) {
+ TSError("Expected a single exempt list filepath as argument, %lu
provided.", instance.Size());
+ return;
+ }
+ // First argument (after plugin name) should be the filename
+ auto filename = AsString(instance.data[0]);
+
+ CDebug("Loading exempt list from file: {}", filename);
+
+ // Clear any existing exempt list
+ TSConnectionLimitExemptListClear();
+
+ try {
+ // Load the YAML file
+ YAML::Node config = YAML::LoadFile(filename.c_str());
+ integer added_count = 0;
+
+ // Check if the root node contains the exempt_list key
+ if (!config["exempt_list"]) {
+ TSError("YAML file '%s' does not contain an 'exempt_list' key",
filename.c_str());
+ return;
+ }
+
+ const YAML::Node &exempt_list = config["exempt_list"];
+
+ // Verify that exempt_list is a sequence/array
+ if (!exempt_list.IsSequence()) {
+ TSError("'exempt_list' in YAML file '%s' is not a sequence/array",
filename.c_str());
+ return;
+ }
+
+ // Iterate through each IP range in the exempt list
+ for (const YAML::Node &item : exempt_list) {
+ if (!item.IsScalar()) {
+ TSError("Non-scalar item found in exempt_list, skipping");
+ continue;
+ }
+
+ std::string ip_range = item.as<std::string>();
+
+ // Add IP range to exempt list
+ TSReturnCode result = TSConnectionLimitExemptListAdd(ip_range);
+ if (result == TS_SUCCESS) {
+ added_count++;
+ CDebug("Added IP range: {}", ip_range);
+ } else {
+ TSError("Failed to add IP range '%s'", ip_range.c_str());
+ }
+ }
+
+ CDebug("Successfully processed YAML file, added {} IP ranges to exempt
list", added_count);
+
+ } catch (const YAML::Exception &e) {
+ TSError("YAML parsing error for file '%s': %s", filename.c_str(),
e.what());
+ } catch (const std::exception &e) {
+ TSError("Failed to process exempt list file '%s': %s", filename.c_str(),
e.what());
+ } catch (...) {
+ TSError("Unknown error while processing exempt list file '%s'",
filename.c_str());
+ }
+}
+
+#include <cripts/Epilogue.hpp>
diff --git a/src/api/InkAPI.cc b/src/api/InkAPI.cc
index 1353be4f77..cabfb5309d 100644
--- a/src/api/InkAPI.cc
+++ b/src/api/InkAPI.cc
@@ -8947,12 +8947,15 @@ TSReturnCode
TSConnectionLimitExemptListAdd(std::string_view ip_ranges)
{
swoc::TextView ip_ranges_tv{ip_ranges};
+
while (auto ip_range_tv = ip_ranges_tv.take_prefix_at(',')) {
swoc::IPRange ip_range;
+
if (!ip_range.load(ip_range_tv)) {
return TS_ERROR;
}
bool success = ConnectionTracker::add_client_exempt_range(ip_range);
+
if (!success) {
return TS_ERROR;
}
@@ -8964,12 +8967,15 @@ TSReturnCode
TSConnectionLimitExemptListRemove(std::string_view ip_ranges)
{
swoc::TextView ip_ranges_tv{ip_ranges};
+
while (auto ip_range_tv = ip_ranges_tv.take_prefix_at(',')) {
swoc::IPRange ip_range;
+
if (!ip_range.load(ip_range_tv)) {
return TS_ERROR;
}
bool success = ConnectionTracker::remove_client_exempt_range(ip_range);
+
if (!success) {
return TS_ERROR;
}
diff --git a/src/cripts/Instance.cc b/src/cripts/Instance.cc
index 598e992d17..ebc1f3a34b 100644
--- a/src/cripts/Instance.cc
+++ b/src/cripts/Instance.cc
@@ -37,6 +37,15 @@ Instance::_initialize(int argc, const char *argv[], const
char *filename, bool r
data[i - 2] = s;
}
_size = argc - 2;
+ } else {
+ // Global plugins don't have the from/to url values.
+ for (int i = 1; i < argc && i <= 16; i++) {
+ auto s = cripts::string(argv[i]);
+
+ s.trim("\"\'");
+ data[i - 1] = s;
+ }
+ _size = argc - 1;
}
// Set the debug tag for this plugin, slightly annoying that we have to
calculate
diff --git a/src/iocore/net/ConnectionTracker.cc
b/src/iocore/net/ConnectionTracker.cc
index 5a0b1c59ca..b7ea956723 100644
--- a/src/iocore/net/ConnectionTracker.cc
+++ b/src/iocore/net/ConnectionTracker.cc
@@ -234,12 +234,14 @@ Config_Update_Conntrack_Client_Exempt_List(const char *
/* name ATS_UNUSED */, R
// This ensures we don't lose the previous configuration if parsing fails.
swoc::IPRangeSet new_exempt_list;
swoc::TextView ranges{exempt_list_string};
+
while (!ranges.empty()) {
swoc::TextView range_sv = ranges.take_prefix_at(',');
range_sv.trim_if(&isspace);
if (!range_sv.empty()) {
swoc::IPRange range;
+
if (!range.load(range_sv)) {
Warning("%s: '%.*s' is not a valid IP range in configuration '%s'",
ConnectionTracker::CONFIG_CLIENT_VAR_EXEMPT_LIST.data(),
static_cast<int>(range_sv.size()), range_sv.data(),
ConnectionTracker::CONFIG_CLIENT_VAR_EXEMPT_LIST.data());
@@ -251,6 +253,7 @@ Config_Update_Conntrack_Client_Exempt_List(const char * /*
name ATS_UNUSED */, R
// Parsing succeeded. Now acquire the lock and replace the global exempt
list.
std::lock_guard<ts::bravo::shared_mutex>
lock(config->client_exempt_list_mutex);
+
config->client_exempt_list.clear();
for (auto const &ip_range : new_exempt_list) {
config->client_exempt_list.mark(ip_range);
@@ -267,6 +270,7 @@ ConnectionTracker::GlobalConfig::GlobalConfig(GlobalConfig
const &other)
this->server_alert_delay = other.server_alert_delay;
this->metric_enabled = other.metric_enabled;
this->metric_prefix = other.metric_prefix;
+
// Lock the source to safely copy the exempt list.
// Note: the mutex itself is not copied; it's default-constructed.
ts::bravo::shared_lock<ts::bravo::shared_mutex>
lock(other.client_exempt_list_mutex);
@@ -322,6 +326,7 @@ ConnectionTracker::set_client_exempt_list(swoc::IPRangeSet
const &ip_ranges)
// Acquire exclusive lock and replace the exempt list.
std::lock_guard<ts::bravo::shared_mutex>
lock(_global_config->client_exempt_list_mutex);
+
_global_config->client_exempt_list.clear();
for (auto const &ip_range : ip_ranges) {
_global_config->client_exempt_list.mark(ip_range);
diff --git a/tests/gold_tests/autest-site/setup.cli.ext
b/tests/gold_tests/autest-site/setup.cli.ext
index 8f16da423f..f7460ffa00 100644
--- a/tests/gold_tests/autest-site/setup.cli.ext
+++ b/tests/gold_tests/autest-site/setup.cli.ext
@@ -111,6 +111,7 @@ if ENV['ATS_BIN'] is not None:
host.WriteVerbose(['ats'], "Traffic server version:", out)
Variables.AtsExampleDir = os.path.join(AutestSitePath, '..', '..', '..',
'example')
+Variables.AtsToolsDir = os.path.join(AutestSitePath, '..', '..', '..', 'tools')
Variables.AtsTestToolsDir = os.path.join(AutestSitePath, '..', '..', 'tools')
Variables.VerifierBinPath = ENV['VERIFIER_BIN']
Variables.BuildRoot = ENV['BUILD_ROOT']
diff --git a/tests/gold_tests/autest-site/trafficserver.test.ext
b/tests/gold_tests/autest-site/trafficserver.test.ext
index a76762d029..4cc7a2704f 100755
--- a/tests/gold_tests/autest-site/trafficserver.test.ext
+++ b/tests/gold_tests/autest-site/trafficserver.test.ext
@@ -408,10 +408,11 @@ def MakeATSProcess(
})
if enable_cripts:
- p.Setup.Copy(
- os.path.join(p.Variables.RepoDir, 'tools', 'cripts',
'compiler.sh'), os.path.join(bin_path, 'cripts_compiler.sh'))
+ cripts_compiler = os.path.join(bin_path, 'cripts_compiler.sh')
+ p.Setup.Copy(os.path.join(p.Variables.RepoDir, 'tools', 'cripts',
'compiler.sh'), cripts_compiler)
+ p.Variables.cripts_compiler = cripts_compiler
p.Disk.records_config.update({
- 'proxy.config.plugin.compiler_path': os.path.join(bin_path,
'cripts_compiler.sh'),
+ 'proxy.config.plugin.compiler_path': cripts_compiler,
})
# ATS_ROOT is used by compiler.sh to find the ATS install directory.
p.Env['ATS_ROOT'] = p.Variables.PREFIX
diff --git a/tests/gold_tests/client_connection/exempt_lists/exempt_all.yaml
b/tests/gold_tests/client_connection/exempt_lists/exempt_all.yaml
new file mode 100644
index 0000000000..b6b2b1f105
--- /dev/null
+++ b/tests/gold_tests/client_connection/exempt_lists/exempt_all.yaml
@@ -0,0 +1,19 @@
+# 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.
+
+exempt_list:
+ - 0/0
+ - ::/0
diff --git
a/tests/gold_tests/client_connection/exempt_lists/exempt_localhost.yaml
b/tests/gold_tests/client_connection/exempt_lists/exempt_localhost.yaml
new file mode 100644
index 0000000000..37988009bc
--- /dev/null
+++ b/tests/gold_tests/client_connection/exempt_lists/exempt_localhost.yaml
@@ -0,0 +1,19 @@
+# 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.
+
+exempt_list:
+ - 127.0.0.1
+ - ::1
diff --git a/tests/gold_tests/client_connection/exempt_lists/no_localhost.yaml
b/tests/gold_tests/client_connection/exempt_lists/no_localhost.yaml
new file mode 100644
index 0000000000..31bd6d75f8
--- /dev/null
+++ b/tests/gold_tests/client_connection/exempt_lists/no_localhost.yaml
@@ -0,0 +1,19 @@
+# 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.
+
+exempt_list:
+ - 1.2.3.4
+ - 5.6.0.0/16
diff --git
a/tests/gold_tests/client_connection/per_client_connection_max.test.py
b/tests/gold_tests/client_connection/per_client_connection_max.test.py
index c2eaa2a128..aa887d0768 100644
--- a/tests/gold_tests/client_connection/per_client_connection_max.test.py
+++ b/tests/gold_tests/client_connection/per_client_connection_max.test.py
@@ -18,6 +18,7 @@ Verify the behavior of
proxy.config.net.per_client.connection.max.
# limitations under the License.
from enum import Enum
+import os
Test.Summary = __doc__
@@ -55,15 +56,17 @@ class PerClientConnectionMaxTest:
Protocol.HTTP2: 'http2_slow_origins.replay.yaml',
}
- def __init__(self, protocol: int, exempt_list: str = '',
exempt_list_applies: bool = False) -> None:
+ def __init__(self, protocol: int, exempt_list: str = '', exempt_list_file:
str = '', exempt_list_applies: bool = False) -> None:
"""Configure the test processes in preparation for the TestRun.
:param protocol: The protocol to test.
:param exempt_list: A comma-separated string of IP addresses or ranges
to exempt.
The default empty string implies that no exempt list will be
configured.
+ :param exempt_list_file: A file containing a list of IP addresses or
ranges to exempt.
+ The default empty string implies that no exempt list will be
configured.
:param exempt_list_applies: If True, the exempt list is assumed to
exempt
the test connections. Thus the per client max connections is expected
- to be enforced for the connections.
+ not to be enforced for the connections.
"""
self._process_counter = PerClientConnectionMaxTest._process_counter
PerClientConnectionMaxTest._process_counter += 1
@@ -71,12 +74,18 @@ class PerClientConnectionMaxTest:
protocol_string = Protocol.to_str(protocol)
self._replay_file = self._protocol_to_replay_file[protocol]
self._exempt_list = exempt_list
+ self._exempt_list_file = exempt_list_file
self._exempt_list_applies = exempt_list_applies
exempt_list_description = 'exempted' if exempt_list_applies else 'not
exempted'
+ exempt_description = 'no exempt list'
+ if exempt_list:
+ exempt_description = 'exempt list string'
+ elif exempt_list_file:
+ exempt_description = 'exempt list file'
tr = Test.AddTestRun(
f'proxy.config.net.per_client.connection.max: {protocol_string}, '
- f'exempt_list: {exempt_list_description}')
+ f'{exempt_description}: {exempt_list_description}')
self._configure_dns(tr)
self._configure_server(tr)
self._configure_trafficserver()
@@ -132,14 +141,18 @@ class PerClientConnectionMaxTest:
'proxy.config.dns.nameservers':
f"127.0.0.1:{self._dns.Variables.Port}",
'proxy.config.dns.resolv_conf': 'NULL',
'proxy.config.diags.debug.enabled': 1,
- 'proxy.config.diags.debug.tags':
'socket|http|net_queue|iocore_net|conn_track',
+ 'proxy.config.diags.debug.tags':
'socket|http|net_queue|iocore_net|conn_track|cripts',
'proxy.config.net.per_client.max_connections_in':
self._max_client_connections,
# Disable keep-alive so we close the client connections when
the
# transactions are done. This allows us to verify cleanup is
working
# per the ConnectionTracker metrics.
'proxy.config.http.keep_alive_enabled_in': 0,
})
- if self._exempt_list:
+ if self._exempt_list_file:
+ exempt_list_absolute = os.path.join(self._ts.Variables.CONFIGDIR,
os.path.basename(self._exempt_list_file))
+ self._ts.Setup.Copy(self._exempt_list_file, exempt_list_absolute)
+ self._ts.Disk.plugin_config.AddLine(f'connection_exempt_list.so
{exempt_list_absolute}')
+ elif self._exempt_list:
self._ts.Disk.records_config.update({
'proxy.config.http.per_client.connection.exempt_list':
self._exempt_list,
})
@@ -222,3 +235,7 @@ PerClientConnectionMaxTest(Protocol.HTTP2)
PerClientConnectionMaxTest(Protocol.HTTP, exempt_list='127.0.0.1,::1',
exempt_list_applies=True)
PerClientConnectionMaxTest(Protocol.HTTPS, exempt_list='1.2.3.4,5.6.0.0/16',
exempt_list_applies=False)
PerClientConnectionMaxTest(Protocol.HTTP2, exempt_list='0/0,::/0',
exempt_list_applies=True)
+
+PerClientConnectionMaxTest(Protocol.HTTP,
exempt_list_file='exempt_lists/exempt_localhost.yaml', exempt_list_applies=True)
+PerClientConnectionMaxTest(Protocol.HTTP,
exempt_list_file='exempt_lists/no_localhost.yaml', exempt_list_applies=False)
+PerClientConnectionMaxTest(Protocol.HTTP,
exempt_list_file='exempt_lists/exempt_all.yaml', exempt_list_applies=True)
diff --git a/tests/gold_tests/cripts/files/basic.cript
b/tests/gold_tests/cripts/files/basic.cript
index 9c9343c092..789f40b31e 100644
--- a/tests/gold_tests/cripts/files/basic.cript
+++ b/tests/gold_tests/cripts/files/basic.cript
@@ -20,21 +20,21 @@
do_read_response()
{
- borrow resp = cripts::Server::Response::Get();
+ borrow resp = cripts::Server::Response::Get();
resp["responseHeader"] = "changed";
}
do_send_response()
{
- borrow resp = cripts::Client::Response::Get();
- borrow conn =cripts::Client::Connection::Get();
+ borrow resp = cripts::Client::Response::Get();
+ borrow conn = cripts::Client::Connection::Get();
resp["criptsResponseHeader"] = "response";
if (conn.IsTLS()) {
- const auto tls = cripts::Certs::Server(conn);
- resp["X-Subject"] = tls.subject;
+ const auto tls = cripts::Certs::Server(conn);
+ resp["X-Subject"] = tls.subject;
resp["X-NotBefore"] = tls.notBefore;
- resp["X-NotAfter"] = tls.notAfter;
+ resp["X-NotAfter"] = tls.notAfter;
}
}
diff --git a/tools/clang-format.sh b/tools/clang-format.sh
index 8e1d68d4ec..23e17bb6a4 100755
--- a/tools/clang-format.sh
+++ b/tools/clang-format.sh
@@ -100,7 +100,7 @@ EOF
start_time_file=$(mktemp -t clang-format-start-time.XXXXXXXXXX)
touch ${start_time_file}
- target_files=$(find $DIR -iname \*.[ch] -o -iname \*.cc -o -iname \*.h.in -o
-iname \*.hpp | grep -vE 'lib/(Catch2|fastlz|ls-hpack|swoc|systemtap|yamlcpp)')
+ target_files=$(find $DIR -iname \*.[ch] -o -iname \*.cc -o -iname \*.h.in -o
-iname \*.hpp -o -iname \*.cript | grep -vE
'lib/(Catch2|fastlz|ls-hpack|swoc|systemtap|yamlcpp)')
for file in ${target_files}; do
# The ink_autoconf.h and ink_autoconf.h.in files are generated files,
# so they do not need to be re-formatted by clang-format. Doing so
diff --git a/tools/git/pre-commit b/tools/git/pre-commit
index 285d36afdb..e5a710a6a5 100755
--- a/tools/git/pre-commit
+++ b/tools/git/pre-commit
@@ -67,7 +67,7 @@ REPO_ROOT=$(cd $(dirname $0)/../.. && git rev-parse
--show-toplevel)
YAPF_CONFIG=${REPO_ROOT}/.style.yapf
git diff-index --cached --diff-filter=ACMR --name-only HEAD | grep -vE
"lib/(Catch2|fastlz|ls-hpack|swoc|yamlcpp)" | while read file; do
case "$file" in
- *.cc | *.c | *.h | *.h.in)
+ *.cc | *.c | *.h | *.h.in | *.cript)
${FORMAT} "$file" | diff -u "$file" - >>"$clang_patch_file"
;;
# Keep this list of Python extensions the same with the list of