From: Andrei Pavel Date: Sun, 10 Jul 2022 12:49:19 +0000 (+0300) Subject: [#2481] document lease limits in the ARM X-Git-Tag: Kea-2.2.0~55 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6c2c8a3fae417764aca1358e83cf938eb89c1773;p=thirdparty%2Fkea.git [#2481] document lease limits in the ARM --- diff --git a/doc/sphinx/arm/classify.rst b/doc/sphinx/arm/classify.rst index f5c4caabc3..40facc3540 100644 --- a/doc/sphinx/arm/classify.rst +++ b/doc/sphinx/arm/classify.rst @@ -42,6 +42,11 @@ private (codes 224-254) and code 43 options, assignment of different options, and, for DHCPv4 cable modems, the setting of specific options for use with the TFTP server address and the boot file field. +.. _classify-classification-steps: + +Classification Steps +-------------------- + The classification process is conducted in several steps: 1. The ``ALL`` class is associated with the incoming packet. @@ -63,6 +68,10 @@ The classification process is conducted in several steps: dropped and an informational message is logged with the packet information. +.. note:: + + pkt4_receive, pkt6_receive callouts are called here. + 6. When the ``early-global-reservations-lookup`` global parameter is configured to true global reservations are looked for and the 8, 9 and 10 steps are partially performed: the lookup is limited to @@ -77,6 +86,10 @@ The classification process is conducted in several steps: class associated with it, or has a class which matches one of the packet's classes. +.. note:: + + subnet4_select, subnet6_select callouts are called here. + 8. The server looks for host reservations. If an identifier from the incoming packet matches a host reservation in the subnet or shared network, the packet is associated with the ``KNOWN`` class and all @@ -104,6 +117,11 @@ The classification process is conducted in several steps: based on the class information when some pools are reserved for class members. +.. note:: + + lease4_select, lease4_renew, lease6_select, lease6_renew, lease6_rebind + callouts are called here. + 12. Classes marked as "required" are evaluated in the order in which they are listed: first the shared network, then the subnet, and finally the pools that assigned resources belong to. @@ -955,11 +973,10 @@ To enable the debug statements in the classification system, the severity must be set to ``DEBUG`` and the debug level to at least 55. The specific loggers are ``kea-dhcp4.eval`` and ``kea-dhcp6.eval``. -To understand the logging statements, it is essential to understand a bit -about how expressions are evaluated; for a more complete description, -refer to the design document at -https://gitlab.isc.org/isc-projects/kea/wikis/designs/Design-documents. In -brief, there are two structures used during the evaluation of an +To understand the logging statements, it is essential to understand a bit about +how expressions are evaluated; for a more complete description, refer to +[the design document](https://gitlab.isc.org/isc-projects/kea/-/wikis/designs/client-classification-design). +In brief, there are two structures used during the evaluation of an expression: a list of tokens which represent the expressions, and a value stack which represents the values being manipulated. diff --git a/doc/sphinx/arm/hooks-limits.rst b/doc/sphinx/arm/hooks-limits.rst index d013fd3c5e..79562d4e7d 100644 --- a/doc/sphinx/arm/hooks-limits.rst +++ b/doc/sphinx/arm/hooks-limits.rst @@ -1,67 +1,46 @@ .. _hooks-limits: -``limits``: Limits to Manage Packet Processing -============================================== +``limits``: Limits to Manage Lease Allocation and Packet Processing +=================================================================== -This hook library enables limiting of the rate at which packets are processed. +This hook library enables two types of limits: + +1. Lease limiting: allow a maximum of `n` leases assigned at any one time. +2. Rate limiting: allow a maximum of `n` packets per `time_unit` to receive a response. The Limits hook library is only available to ISC customers with a paid support contract. +.. _hooks-limits-configuration: + Configuration ~~~~~~~~~~~~~ +The following examples are for ``kea-dhcp6``, but they can be easily extrapolated to its +``kea-dhcp4`` counterpart. Wildcards ``""`` and ``""`` need be replaced +with the respective keys and values for each limit type described in the sections following this +one. + The library can be loaded by both ``kea-dhcp4`` and ``kea-dhcp6`` servers by adding its path in the ``"hooks-libraries"`` element of the server's configuration. -The rate limit can be specified in the format ``"

packets per "``. ``

`` is any -number that can be represented by an unsigned integer on 32 bits i.e. between ``0`` and -``4,294,967,295``. ```` can be any of ``second``, ``minute``, ``hour``, ``day``, -``week``, ``month``, ``year``. ``month`` is considered to be 30 days for simplicity. Similarly, -``year`` is 365 days for all intents and purposes of limiting. This syntax covers a high range of -rates from one lease per year to four billion leases per second. - -The configured value of ``0`` packets is a convenient way of disabling packet processing for certain -clients entirely. As such, it means its literal value and is not a special value for disabling -limiting altogether as it might be imagined. Disabling limiting altogether is achieved by removing -the `"rate-limit"` leaf configuration entry, the `"limits"` map around it or the user context around -it or the hook library configuration. - -There are two ways to configure which packets get limited. One is through the client classes that are -initially assigned to the packet. In this case, the limit is configured in the user context -in the client class definition. Class rate limits are checked early in packet processing cycle -and are thus limited to those classes which are assigned to the packet via test expression, that do -not depend on host reservations, the special "BOOTP" or "KNOWN" classes, and that are not marked -with "only-if-required". - -.. note:: - - The limits hook library uses the name to identify a client class and the ID to identify a subnet. - Changing a test expression in a client class or the network range of a subnet while leaving the - name, or the ID respectively, unchanged will not reset the limit for the respective client class - or subnet and what counted towards the limit prior to the change, will continue to take effect. - To start over, consider changing the client class name or the subnet ID. - -.. note:: - - It can be tempting to think that assigning a rate limit of `n` packets per time unit results in - `n` DORA or `n` SARR exchanges. By default, all inbound packets are counted. That means that - a full message exchange accounts for 2 packets. To achieve the desired effect of counting an - exchange only once, you may use client class rate limiting with a test expression that binds - `pkt4.msgtype` to DHCPDISCOVER messages or `pkt6.msgtype` to SOLICIT messages. - -The other way is through the subnet that the Kea selects for the packet. To achieve this, the limit -is added to the user context of the subnet definition. +.. code-block:: json -.. note:: + { + "Dhcp6": { + "hooks-libraries": [ + { + "library": "/usr/local/lib/libdhcp_limits.so" + } + ] + } + } - Subnet rate limits are enforced only on the initially selected subnet for a given packet. - If the selected subnet is subsequently changed, as may be the case for subnets in a - shared-network or when reselection is enabled in libraries such as the RADIUS hook, rate - limits on the newly selected subnet will be ignored. In other words, packets are gated - only by the rate limit on the original subnet. +This alone does not limit anything. The desired limits are added to the user context in the +configuration portion of the element that identifies the clients to be limited: a client class or a +subnet. Upon reconfiguration, if Kea picked up on the configured limits, it logs one line for +each configured limit. The log message contains ``LIMITS_CONFIGURED`` in its identifier. -The following is an example that adds one rate limit on a client class and another one in a subnet -in `kea-dhcp6`. A valid configuration for `kea-dhcp4` can be easily extrapolated. +This is how a lease limit is defined for a client class: .. code-block:: json @@ -69,33 +48,177 @@ in `kea-dhcp6`. A valid configuration for `kea-dhcp4` can be easily extrapolated "Dhcp6": { "client-classes": [ { - "name": "gold", + "name": "cable-modem-1", + "test": "option[123].hex == 0x000C4B1E", "user-context": { "limits": { - "rate-limit": "1000 packets per second" + "": "" } } } - ], - "hooks-libraries": [ - { - "library": "/usr/local/lib/libdhcp_limits.so" - } - ], + ] + } + } + +This is how a lease limit is defined for a global subnet: + +.. code-block:: json + + { + "Dhcp6": { "subnet6": [ { "id": 1, - "pools": [ + "subnet": "2001:db8::/64", + "user-context": { + "limits": { + "": "" + } + } + } + ] + } + } + +This is how a lease limit is defined for a subnet inside a shared network: + +.. code-block:: json + + { + "Dhcp6": { + "shared-networks": [ + { + "subnet6": [ { - "pool": "2001:db8::/64" + "id": 1, + "subnet": "2001:db8::/64", + "user-context": { + "limits": { + "": "" + } + } } - ], - "subnet": "2001:db8::/64", + ] + } + ] + } + } + +A trick to enforce a global limit (same limit for all clients) is to define the special client class +``"ALL"`` and assign the limit to it. + +.. code-block:: json + + { + "Dhcp6": { + "client-classes": [ + { + "name": "ALL", "user-context": { "limits": { - "rate-limit": "10 packets per minute" + "": "" } } } ] } + } + +.. note:: + + The Limits hook library uses the name to identify a client class and the ID to identify a subnet. + Changing a test expression in a client class or the network range of a subnet while leaving the + name, or the ID respectively, unchanged will not reset the limit for the respective client class + or subnet. What counted towards the limit prior to the change will continue to take effect. + To start over, consider changing the client class name or the subnet ID. + +.. _hooks-limits-lease-limiting: + +Lease Limiting +~~~~~~~~~~~~~~ + +It is possible to limit the number of leases that a group of clients can get from a Kea DHCP server +or from a set of collaborating Kea DHCP servers. + +The value of a lease limit can be specified as an unsigned integer on 32 bits i.e. between ``0`` and +``4,294,967,295``. Each lease type can be limited individually. IPv4 leases and IPv6 IA_NA leases +are limited through the ``"address-limit"`` configuration entry. IPv6 IA_PD leases are limited +through the ``"prefix-limit"`` configuration entry. Here are some examples: + +* ``"address-limit": 4`` +* ``"prefix-limit": 2`` + +Inasmuch as lease limiting is regarded, client classes and the associated lease counts that are +checked against the configued limits, are updated for each lease in the following hook callouts: + +* ``lease4_select`` +* ``lease4_renew`` +* ``lease6_select`` +* ``lease6_renew`` +* ``lease6_rebind`` + +As a result, packets that are marked with ``"only-if-required": true`` cannot be lease limited. +See :ref:`the classification steps ` to have the full picture on what +client classes can be used to limit the number of leases. + +.. warning:: + + Due to technical conveniences, lease limits are not strictly enforced. Occasionally, a Kea DHCP + server may allocate more leases than the limit would strictly allow. This only has a chance of + happening during high traffic surges coming from clients belonging to the same class or to the + same subnet (based on what is limited). Even in those scenarios and other circumstances that + would favor the race condition that causes surpassing the limit e.g. a global rate of inbound + packets that matches the server's response rate performance, and a thread count close to the + the number of cores, empirically, it seems that the unfortunate event is rare and only results + in one lease past the limit. One hard guarantee is that the race can only happen again after the + lease count has retreated below the limit. For an airtight solution, follow the development of + `GitLab issue #2449 atomic lease limits `__. + +.. _hooks-limits-rate-limiting: + +Rate Limiting +~~~~~~~~~~~~~ + +It is possible to limit the frequency or rate at which inbound packets receive a response. + +The value of a rate limit can be specified in the format ``"

packets per "``. ``

`` +is any number that can be represented by an unsigned integer on 32 bits i.e. between ``0`` and +``4,294,967,295``. ```` can be any of ``second``, ``minute``, ``hour``, ``day``, +``week``, ``month``, ``year``. ``month`` is considered to be 30 days for simplicity. Similarly, +``year`` is 365 days for all intents and purposes of limiting. This syntax covers a high range of +rates from one lease per year to four billion leases per second. This vaue is assigned to the +``"rate-limit"`` configuration entry. Here are some examples: + +* ``"rate-limit": 1 packet per second`` +* ``"rate-limit": 4 packets per minute`` +* ``"rate-limit": 16 packets per hour`` + +The configured value of ``0`` packets is a convenient way of disabling packet processing for certain +clients entirely. As such, it means its literal value and is not a special value for disabling +limiting altogether as it might be imagined. Disabling limiting altogether is achieved by removing +the ``"rate-limit"`` leaf configuration entry, the ``"limits"`` map around it or the user context +around it or the hook library configuration. The same can be said about the value of ``0`` in lease +limiting. However, that use case is best achieved with rate limiting as it puts less computational +strain on Kea since the action of dropping the request or sending a NAK is decided earlier on. + +Inasmuch as rate limiting is regarded, client classes are evalated at the ``pkt4_receive`` and the +``pkt6_receive`` callout respectively so that rate limits are checked as early as possible in the +packet processing cycle. Thus, only those classes which are assigned to the packet solely via an +independent test expression can be used. Classes that depend on host reservations or the special +``BOOTP`` or ``KNOWN`` classes, and classes that are marked with ``"only-if-required": true``, +cannot be rate limited. See :ref:`the classification steps ` to +have the full picture on what client classes can be used to limit packet rate. + +Rate limits based on subnet are enforced only on the initially selected subnet for a given packet. +If the selected subnet is subsequently changed, as may be the case for subnets in a +shared-network or when reselection is enabled in libraries such as the RADIUS hook, rate +limits on the newly selected subnet will be ignored. In other words, packets are gated only by +the rate limit on the original subnet. + +.. note:: + + It can be tempting to think that assigning a rate limit of ``n`` packets per time unit results + in ``n`` DORA or ``n`` SARR exchanges. By default, all inbound packets are counted. That means + that a full message exchange accounts for 2 packets. To achieve the desired effect of counting an + exchange only once, you may use client class rate limiting with a test expression that binds + ``pkt4.msgtype`` to DHCPDISCOVER messages or ``pkt6.msgtype`` to SOLICIT messages. diff --git a/doc/sphinx/arm/hooks.rst b/doc/sphinx/arm/hooks.rst index 934e92e242..eb8468ae09 100644 --- a/doc/sphinx/arm/hooks.rst +++ b/doc/sphinx/arm/hooks.rst @@ -1,8 +1,8 @@ .. _hooks-libraries: -*************** +************** Hook Libraries -*************** +************** .. _hooks-libraries-introduction: @@ -308,40 +308,46 @@ The DDNS-Tuning Hook uses user-context to configure per subnet behavior. Example The Limits hook uses user-context in classes and subnets to set parameters. Example: -:: +.. code-block:: json - "Dhcp6": { + { + "Dhcp6": { "client-classes": [ - { + { "name": "gold", "user-context": { - "limits": { + "limits": { + "address-limit": 2, + "prefix-limit": 1, "rate-limit": "1000 packets per second" + } } - } - } + } ], "hooks-libraries": [ - { + { "library": "/usr/local/lib/libdhcp_limits.so" - } + } ], "subnet6": [ - { + { "id": 1, "pools": [ - { + { "pool": "2001:db8::/64" - } + } ], "subnet": "2001:db8::/64", "user-context": { - "limits": { + "limits": { + "address-limit": 4, + "prefix-limit": 2, "rate-limit": "10 packets per minute" + } } - } - } + } ] + } } Available Hook Libraries