You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2023/03/09 15:36:44 UTC

[trafficserver] branch 9.2.x updated: Adds a new percentage option, cleans up pressure calculations (#9491)

This is an automated email from the ASF dual-hosted git repository.

zwoop pushed a commit to branch 9.2.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/9.2.x by this push:
     new c2651a1cf Adds a new percentage option, cleans up pressure calculations (#9491)
c2651a1cf is described below

commit c2651a1cf039f8d413b33fca273df4d24a0646d0
Author: Leif Hedstrom <zw...@apache.org>
AuthorDate: Tue Mar 7 09:55:43 2023 -0700

    Adds a new percentage option, cleans up pressure calculations (#9491)
    
    * Adds a new percentage options, cleans up pressure calculations
    
    * Changes the italic to proper code quotes
    
    (cherry picked from commit 624b8e0e5cbc21857f4a7589a20b151a457b6677)
    
     Conflicts:
            plugins/experimental/rate_limit/sni_limiter.cc
    
    Clang-format changed in 10.x
---
 doc/admin-guide/plugins/rate_limit.en.rst      | 57 +++++++++++++++-----------
 plugins/experimental/rate_limit/sni_limiter.cc |  4 ++
 plugins/experimental/rate_limit/sni_limiter.h  |  7 +++-
 3 files changed, 41 insertions(+), 27 deletions(-)

diff --git a/doc/admin-guide/plugins/rate_limit.en.rst b/doc/admin-guide/plugins/rate_limit.en.rst
index 406a88ee2..0498be80d 100644
--- a/doc/admin-guide/plugins/rate_limit.en.rst
+++ b/doc/admin-guide/plugins/rate_limit.en.rst
@@ -60,21 +60,21 @@ are available:
    queued transactions we will allow. When this threshold is reached, all
    additional transactions are immediately served with an error message.
 
-   The queue is effectively disabled if this is set to `0`, which implies
+   The queue is effectively disabled if this is set to ``0``, which implies
    that when the transaction limit is reached, we immediately start serving
    error responses.
 
-   The default queue size is `UINT_MAX`, which is essentially unlimited.
+   The default queue size is ``UINT_MAX``, which is essentially unlimited.
 
 .. option:: --error
 
    An optional HTTP status error code, to be used together with the
-   :option:`--queue` option above. The default is `429`.
+   :option:`--queue` option above. The default is ``429``.
 
 .. option:: --retry
 
-   An optional retry-after value, which if set will cause rejected (e.g. `429`)
-   responses to also include a header `Retry-After`.
+   An optional retry-after value, which if set will cause rejected (e.g. ``429``)
+   responses to also include a header ``Retry-After``.
 
 .. option:: --header
 
@@ -83,12 +83,12 @@ are available:
    header is the delay, in milliseconds. This can be useful to for example
    log the delays for later analysis.
 
-   It is recommended that an `@` header is used here, e.g. `@RateLimit-Delay`,
+   It is recommended that an `@` header is used here, e.g. ``@RateLimit-Delay``,
    since this header will not leave the ATS server instance.
 
 .. option:: --maxage
 
-   An optional `max-age` for how long a transaction can sit in the delay queue.
+   An optional ``max-age`` for how long a transaction can sit in the delay queue.
    The value (default 0) is the age in milliseconds.
 
 .. option:: --prefix
@@ -137,15 +137,15 @@ The following options are available:
    queued transactions we will allow. When this threshold is reached, all
    additional connections are immediately errored out in the TLS handshake.
 
-   The queue is effectively disabled if this is set to `0`, which implies
+   The queue is effectively disabled if this is set to ``0``, which implies
    that when the transaction limit is reached, we immediately start serving
    error responses.
 
-   The default queue size is `UINT_MAX`, which is essentially unlimited.
+   The default queue size is ``UINT_MAX``, which is essentially unlimited.
 
 .. option:: --maxage
 
-   An optional `max-age` for how long a transaction can sit in the delay queue.
+   An optional ``max-age`` for how long a transaction can sit in the delay queue.
    The value (default 0) is the age in milliseconds.
 
 .. option:: --prefix
@@ -161,21 +161,28 @@ The following options are available:
 .. option:: --iprep_buckets
 
    The number of LRU buckets to use for the IP reputation. A good number here
-   is 10, but can be configured. The reason for the different buckets is to
-   account for a pseudo-sorted list of IPs on the frequency seen. Too few buckets
-   will not be enough to keep such a sorting, rendering the algorithm useless. To
-   function in our setup, the number of buckets must be less than ``100``.
+   is ``10``, which is the default, but can be configured. The reason for the different
+   buckets is to account for a pseudo-sorted list of IPs on the frequency seen. Too
+   few buckets will not be enough to keep such sorting, rendering the algorithm useless.
+   To function in our setup, the number of buckets must be less than ``100``.
 
 .. option:: --iprep_bucketsize
 
-   This is the size of the largest LRU bucket (the `entry bucket`), `15` is a good
-   value. This is a power of 2, so `15` means the largest LRU can hold `32768` entries.
-   Note that this option must be bigger then the `--iprep_buckets` setting, for the
+   This is the size of the largest LRU bucket (the ``entry bucket``), ``15`` is a good
+   value. This is a power of 2, so ``15`` means the largest LRU can hold ``32768`` entries.
+   Note that this option must be bigger then the ``--iprep_buckets`` setting, for the
    bucket halfing to function.
 
+   The default here is ``0``, which means the IP reputation filter is not enabled!
+
+.. option:: --iprep_percentage
+
+   This is the minimum percentage of the ``limit`` that the pressure must be at, before
+   we start blocking IPs. The default is ``0.9`` which means ``90%`` of the limit.
+
 .. option:: --iprep_maxage
 
-   This is used for aging out entries out of the LRU, the default is `0` which means
+   This is used for aging out entries out of the LRU, the default is ``0`` which means
    no aging happens. Even with no aging, entries will eventually fall out of buckets
    because of the LRU mechanism that kicks in. The aging is here to make sure a spike
    in traffic from an IP doesn't keep the entry for too long in the LRUs.
@@ -188,12 +195,12 @@ The following options are available:
 .. option:: --iprep_permablock_pressure
 
    This option specifies from which bucket an IP is allowed to move from into the
-   perma block bucket. A good value here is likely `0` or `1`, which is very conservative.
+   perma block bucket. A good value here is likely ``0`` or ``1``, which is very conservative.
 
 .. option:: --iprep_permablock_maxage
 
-   Similar to `--iprep_maxage` above, but only applies to the long term (`perma-block`)
-   bucket. Default is `0`, which means no aging to this bucket is applied.
+   Similar to ``--iprep_maxage`` above, but only applies to the long term (`perma-block`)
+   bucket. Default is ``0``, which means no aging to this bucket is applied.
 
 Metrics
 -------
@@ -258,9 +265,9 @@ for longer term blocking, only the most abusive elements would end up here.
 Examples
 --------
 
-This example shows a simple rate limiting of `128` concurrently active client
-transactions, with a maximum queue size of `256`. The default of HTTP status
-code `429` is used when queue is full: ::
+This example shows a simple rate limiting of ``128`` concurrently active client
+transactions, with a maximum queue size of ``256``. The default of HTTP status
+code ``429`` is used when queue is full: ::
 
     map http://cdn.example.com/ http://some-server.example.com \
       @plugin=rate_limit.so @pparam=--limit=128 @pparam=--queue=256
@@ -274,7 +281,7 @@ queue, and add a header with the transaction delay if it was queued: ::
       @pparam=--header=@RateLimit-Delay
 
 This final example will limit the active transaction, queue size, and also
-add a `Retry-After` header once the queue is full and we return a `429` error: ::
+add a ``Retry-After`` header once the queue is full and we return a ``429`` error: ::
 
     map http://cdn.example.com/ http://some-server.example.com \
       @plugin=rate_limit.so @pparam=--limit=256 @pparam=--queue=1024 \
diff --git a/plugins/experimental/rate_limit/sni_limiter.cc b/plugins/experimental/rate_limit/sni_limiter.cc
index fcc8fb838..11d0c1a24 100644
--- a/plugins/experimental/rate_limit/sni_limiter.cc
+++ b/plugins/experimental/rate_limit/sni_limiter.cc
@@ -151,6 +151,7 @@ SniRateLimiter::initialize(int argc, const char *argv[])
     {const_cast<char *>("iprep_maxage"), required_argument, nullptr, 'a'},
     {const_cast<char *>("iprep_buckets"), required_argument, nullptr, 'B'},
     {const_cast<char *>("iprep_bucketsize"), required_argument, nullptr, 'S'},
+    {const_cast<char *>("iprep_percentage"), required_argument, nullptr, 'C'},
     {const_cast<char *>("iprep_permablock_limit"), required_argument, nullptr, 'L'},
     {const_cast<char *>("iprep_permablock_pressure"), required_argument, nullptr, 'P'},
     {const_cast<char *>("iprep_permablock_maxage"), required_argument, nullptr, 'A'},
@@ -192,6 +193,9 @@ SniRateLimiter::initialize(int argc, const char *argv[])
     case 'S':
       this->_iprep_size = strtol(optarg, nullptr, 10);
       break;
+    case 'C':
+      this->_iprep_percent = strtol(optarg, nullptr, 10);
+      break;
     case 'L':
       this->iprep_permablock_count = strtol(optarg, nullptr, 10);
       break;
diff --git a/plugins/experimental/rate_limit/sni_limiter.h b/plugins/experimental/rate_limit/sni_limiter.h
index 93b1b5558..78a8bde45 100644
--- a/plugins/experimental/rate_limit/sni_limiter.h
+++ b/plugins/experimental/rate_limit/sni_limiter.h
@@ -52,7 +52,9 @@ public:
   int32_t
   pressure() const
   {
-    return ((active() - 1) / static_cast<float>(limit) * 100) - (99 - _iprep_num_buckets);
+    int32_t p = ((active() / static_cast<float>(limit) * 100) - _iprep_percent) / (100 - _iprep_percent) * (_iprep_num_buckets + 1);
+
+    return (p >= static_cast<int32_t>(_iprep_num_buckets) ? _iprep_num_buckets : p);
   }
 
 private:
@@ -61,5 +63,6 @@ private:
   std::chrono::seconds _iprep_max_age       = std::chrono::seconds::zero(); // Max age in the SieveLRUs for regular buckets
   std::chrono::seconds _iprep_perma_max_age = std::chrono::seconds::zero(); // Max age in the SieveLRUs for perma-block buckets
   uint32_t _iprep_num_buckets               = 10;                           // Number of buckets. ToDo: leave this at 10 always
-  uint32_t _iprep_size                      = 15;                           // Size of the biggest bucket; 15 == 2^15 == 32768
+  uint32_t _iprep_percent                   = 90;                           // At what percentage of limit we start blocking
+  uint32_t _iprep_size                      = 0;                            // Size of the biggest bucket; 15 == 2^15 == 32768
 };