]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
rate-limiting config: use more precise types docs-develop-rrl-8r8r8r/deployments/5522
authorVladimír Čunát <vladimir.cunat@nic.cz>
Wed, 6 Nov 2024 10:16:11 +0000 (11:16 +0100)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Wed, 6 Nov 2024 19:56:23 +0000 (20:56 +0100)
This gives us a bit more consistency.
I suppose that IntRangeBase isn't worth doing for the other cases.

Aleš helped with this.

doc/_static/config.schema.json
python/knot_resolver/datamodel/rate_limiting_schema.py
python/knot_resolver/datamodel/templates/rate_limiting.lua.j2
python/knot_resolver/datamodel/types/__init__.py
python/knot_resolver/datamodel/types/types.py

index c6934109a3a83b2d353c6ee751192ac7dd4d959e..a0572813efd37954c2da685bd222c5a060377761 100644 (file)
             "properties": {
                 "capacity": {
                     "type": "integer",
+                    "minimum": 1,
                     "description": "Expected maximal number of blocked networks/hosts at the same time.",
                     "default": 524288
                 },
                 "rate-limit": {
                     "type": "integer",
+                    "minimum": 1,
                     "description": "Maximal number of allowed queries per second from a single host."
                 },
                 "instant-limit": {
                     "type": "integer",
+                    "minimum": 1,
                     "description": "Maximal number of allowed queries at a single point in time from a single host.",
                     "default": 50
                 },
                 "slip": {
                     "type": "integer",
+                    "minimum": 0,
+                    "maximum": 32,
                     "description": "Number of restricted responses out of which one is sent as truncated, the others are dropped.",
                     "default": 2
                 },
                 "log-period": {
-                    "type": "integer",
-                    "description": "Minimal time in msec between two log messages, or zero to disable.",
-                    "default": 0
+                    "type": "string",
+                    "pattern": "^(\\d+)(us|ms|s|m|h|d)$",
+                    "description": "Minimal time between two log messages, or '0s' to disable.",
+                    "default": "0s"
                 },
                 "dry-run": {
                     "type": "boolean",
index d93272da49174f52dfbaa5c36b792b52d6b07620..60994c2068e59da370f416e1d22731d711de89d5 100644 (file)
@@ -1,3 +1,8 @@
+from knot_resolver.datamodel.types import (
+    Int0_32,
+    IntPositive,
+    TimeUnit,
+)
 from knot_resolver.utils.modeling import ConfigSchema
 
 
@@ -10,26 +15,20 @@ class RateLimitingSchema(ConfigSchema):
     rate_limit: Maximal number of allowed queries per second from a single host.
     instant_limit: Maximal number of allowed queries at a single point in time from a single host.
     slip: Number of restricted responses out of which one is sent as truncated, the others are dropped.
-    log_period: Minimal time in msec between two log messages, or zero to disable.
+    log_period: Minimal time between two log messages, or '0s' to disable.
     dry_run: Perform only classification and logging but no restrictions.
     """
 
-    capacity: int = 524288
-    rate_limit: int
-    instant_limit: int = 50
-    slip: int = 2
-    log_period: int = 0
+    capacity: IntPositive = IntPositive(524288)
+    rate_limit: IntPositive
+    instant_limit: IntPositive = IntPositive(50)
+    slip: Int0_32 = Int0_32(2)
+    log_period: TimeUnit = TimeUnit("0s")
     dry_run: bool = False
 
     def _validate(self) -> None:
-        max_instant_limit = int(2**32 / 768 - 1)
-        if not 1 <= self.instant_limit <= max_instant_limit:
+        max_instant_limit = int(2 ** 32 // 768 - 1)
+        if not int(self.instant_limit) <= max_instant_limit:
             raise ValueError(f"'instant-limit' has to be in range 1..{max_instant_limit}")
-        if not 1 <= self.rate_limit <= 1000 * self.instant_limit:
+        if not int(self.rate_limit) <= 1000 * int(self.instant_limit):
             raise ValueError("'rate-limit' has to be in range 1..(1000 * instant-limit)")
-        if not 0 < self.capacity:
-            raise ValueError("'capacity' has to be positive")
-        if not 0 <= self.slip <= 100:
-            raise ValueError("'slip' has to be in range 0..100")
-        if not 0 <= self.log_period:
-            raise ValueError("'log-period' has to be non-negative")
index 4f9547f54fea55af196182b9314b25c5ff2d4e29..63f92125717fd997da8014f7dadf168b1e31dcb4 100644 (file)
@@ -7,6 +7,6 @@ assert(C.ratelimiting_init(
        {{ cfg.rate_limiting.instant_limit }},
        {{ cfg.rate_limiting.rate_limit }},
        {{ cfg.rate_limiting.slip }},
-       {{ cfg.rate_limiting.log_period }},
+       {{ cfg.rate_limiting.log_period.millis() }},
        {{ boolean(cfg.rate_limiting.dry_run) }}) == 0)
 {%- endif %}
index a3d7db3e6c26b5f8759b69e23e160eec2ac9c279..d1334b5a272e0004e8c1d70ebf931d0e00ba53cb 100644 (file)
@@ -6,6 +6,7 @@ from .types import (
     EscapedStr,
     EscapedStr32B,
     IDPattern,
+    Int0_32,
     Int0_512,
     Int0_65535,
     InterfaceName,
@@ -37,6 +38,7 @@ __all__ = [
     "EscapedStr",
     "EscapedStr32B",
     "IDPattern",
+    "Int0_32",
     "Int0_512",
     "Int0_65535",
     "InterfaceName",
index 6cd1e4cbdab3378738b0e17fa64d15e4ad4974e5..3c9b9fe1c8f6ee184ff26ed0e6628537f5bffb15 100644 (file)
@@ -14,6 +14,11 @@ class IntPositive(IntRangeBase):
     _min: int = 1
 
 
+class Int0_32(IntRangeBase):  # noqa: N801
+    _min: int = 0
+    _max: int = 32
+
+
 class Int0_512(IntRangeBase):  # noqa: N801
     _min: int = 0
     _max: int = 512