../src/bin/lfc \
../src/hooks/dhcp/user_chk \
../src/hooks/dhcp/lease_cmds \
+ ../src/hooks/dhcp/stat_cmds \
../src/lib/asiodns \
../src/lib/asiolink \
../src/lib/cc \
* - @subpage hooksmgMaintenanceGuide
* - @subpage libdhcp_user_chk
* - @subpage libdhcp_lease_cmds
+ * - @subpage libdhcp_stat_cmds
*
* @section dhcpMaintenanceGuide DHCP Maintenance Guide
* - @subpage dhcp4
DOCBOOK = kea-guide.xml intro.xml quickstart.xml install.xml admin.xml config.xml
DOCBOOK += keactrl.xml dhcp4-srv.xml dhcp6-srv.xml lease-expiration.xml logging.xml
DOCBOOK += ddns.xml hooks.xml libdhcp.xml lfc.xml stats.xml ctrl-channel.xml faq.xml
-DOCBOOK += hooks-host-cache.xml hooks-radius.xml
+DOCBOOK += hooks-host-cache.xml hooks-radius.xml hooks-stat-cmds.xml
DOCBOOK += classify.xml shell.xml agent.xml
EXTRA_DIST = $(DOCBOOK)
--- /dev/null
+<section xml:id="hooks-stat-cmds">
+ <title>stat_cmds: Supplemental Statistics Commands</title>
+ <para>
+ This library provides additional statistics commands for
+ retrieving lease statistics from kea-dhcp servers. These commands
+ were added to address an issue with obtaining accurate lease
+ statistics in deployments running multiple Kea servers that use
+ shared lease back end. The in-memory statistics kept by individual
+ servers only track lease changes made by that server. Thus in a
+ deployment with multiple servers, these statistics are incomplete.
+ In Kea 1.4, the MySQL and PostgreSQL back ends were modified to track
+ lease allocation changes as they occur via database triggers. Additionally,
+ all four lease back ends were extended to support retrieving lease
+ statistics for all subnets, a single subnet, or a range of subnets.
+ Finally, this library was constructed to provide commands for retrieving
+ these statistics. Additional statistics commands may be added to this
+ library in future releases.
+ </para>
+
+ <para>
+ The commands currently provided by this library are:
+ <itemizedlist>
+ <listitem>
+ <para><command>stat-lease4-get</command> - fetches DHCPv4 lease statistics</para>
+ </listitem>
+ <listitem>
+ <para><command>stat-lease6-get</command> - fetches DHCPv6 lease statistics</para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ The Stat commands library is part of the open source code and is
+ available to every Kea user.
+ </para>
+
+ <para>
+ All commands use JSON syntax and can be issued either using directly to
+ the servers via the control channel (see <xref linkend="ctrl-channel"/>)
+ or via Control Agent (see <xref linkend="kea-ctrl-agent"/>).
+ </para>
+
+ <para>
+ This library may be loaded by both kea-dhcp4 and kea-dhcp6 servers.
+ It is loaded in the same way as other other libraries and currently has
+ no parameters:
+ </para>
+<para>
+<screen>
+"Dhcp6": { <userinput>
+ "hooks-libraries": [
+ {
+ "library": "/path/libdhcp_stat_cmds.so"
+ }
+ ...
+ ] </userinput>
+}
+</screen>
+</para>
+
+ <para>
+ In a deployment with multiple kea-dhcp servers sharing a common lease
+ storage, it may be loaded by any or all of the servers. However, one
+ thing to keep in mind is that a server's response to a stat-lease{4/6}-get
+ command will only contain data for subnets known to that server. In
+ other words, if subnet does not appear in a server's configuration, it
+ will not retrieve statistics for it.
+ </para>
+
+<section>
+ <title>stat-lease4-get, stat-lease6-get commands</title>
+ <para>
+ The <command>stat-lease4-get</command> and <command>stat-lease6-get</command>
+ commands fetch lease statistics for a range of known subnets. The
+ range of subnets is determined through the use of optional command
+ input parameters:
+ <itemizedlist>
+ <listitem>
+ <para><command>subnet-id</command> - ID of the subnet for which
+ lease statistics should be fetched. Use this to get statistics for
+ a single subnet. If the subnet does not exist the command result
+ code will be 2 (i.e. CONTROL_RESULT_EMPTY).
+ </para>
+ </listitem>
+ <listitem>
+ <para><command>subnet-range</command> - A pair of subnet IDs which
+ describe an inclusive range of subnets for which statistics should
+ be retrieved. Note that fuzzy values are supported thus allowing
+ for a query for statistics using approximate ID values. If the
+ range does not include any known subnets, the command result code
+ will be 2 (i.e. CONTROL_RESULT_EMPTY).
+ <itemizedlist>
+ <listitem>
+ <command>first-subnet-id</command> - ID of the first
+ subnet in the range.
+ </listitem>
+ <listitem>
+ <command>last-subnet-id</command> - ID of the first
+ subnet in the range.
+ </listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+ </itemizedlist>
+ The use of subnet-id and subnet-range are mutually exclusive.
+ If no parameters are given, the result will contain data for all
+ known subnets. Note that in configurations with large numbers of
+ subnets, this can be result in a large response.
+ <para>
+ The following command would fetch lease statistcis for all known subnets from kea-dhcp4 server:
+<screen>
+{
+ "command": "stat-lease4-get",
+ "arguments": {
+ }
+}
+</screen>
+</para>
+ <para>
+ The following command would fetch lease statistcis for subnet ID 10 from kea-dhcp6 server:
+<screen>
+{
+ "command": "stat-lease6-get",
+ "arguments": {
+ "subnet-id" : 10
+ }
+}
+</screen>
+</para>
+ <para>
+ The following command would fetch lease statistcis for all subnets from subnet ID 10 through 50 from kea-dhcp4 server:
+<screen>
+{
+ "command": "stat-lease4-get",
+ "arguments": {
+ "subnet-range" {
+ "first-subnet-id": 10,
+ "last-subnet-id": 50,
+ }
+ }
+}
+</screen>
+</para>
+
+<para>
+ The response to the either command will contain three elements:
+ <itemizedlist>
+ <listitem>
+ <para><command>result</command> - numeric value indicating the outcome of the
+ command where:
+ <itemizedlist>
+ <listitem><command>0</command> - command was successful</listitem>
+ <listitem><command>1</command> - an error occurred, an explanation will
+ be the "text" element</listitem>
+ <listitem><command>2</command> - indicates the fetch found no matching data</listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+ <listitem>
+ <para><command>text</command> - an explanation of the command outcome. When the command
+ succeeds it will contain the command name along with the number of rows returned.</para>
+ </listitem>
+ <listitem>
+ <para><command>arguments</command></para> - a map containing the data returned by the
+ command as the element "result-set", which patterned after SQL statement responses:
+ <itemizedlist>
+ <listitem><command>columns</command> - a list of text column labels.
+ The columns returned for DHCPv4 are:
+ <itemizedlist>
+ <listitem><command>subnet-id</command> - ID of the subnet</listitem>
+ <listitem><command>total-addresses</command> - total number of addresses
+ available for DHCPv4 management. In other words, this is the sum of all
+ addresses in all configured pools. This statistic changes only during
+ configuration changes. Note it does not take into account any addresses that
+ may be reserved due to host reservation.
+ </listitem>
+ <listitem><command>assigned-addresses</command> - number of assigned
+ addresses in a given subnet. It increases every time a new lease is
+ allocated (as a result of receiving a DHCPREQUEST message) and is decreased
+ every time a lease is released (a DHCPRELEASE message is received) or expires.
+ </listitem>
+ <listitem><command>declined-addresses</command> - number of IPv4 addresses
+ that are currently declined in a given subnet, so is a count of the number
+ of leases currently unavailable. Once a lease is recovered, this statistic
+ will be decreased. Ideally, this statistic should be zero. If this statistic
+ is non-zero (or worse increasing), a network administrator should investigate
+ if there is a misbehaving device in his network.
+ </listitem>
+ </itemizedlist>
+ The columns returned for DHCPv6 are:
+ <itemizedlist>
+ <listitem><command>subnet-id</command> - ID of the subnet</listitem>
+ <listitem><command>total-nas</command> - number of NA addresses available
+ for DHCPv6 management for a given subnet. In other words, this is the
+ sum of all addresses in all configured pools. This statistic changes
+ only during configuration changes. Note that it does not take into account
+ any addresses that may be reserved due to host reservation.
+ </listitem>
+ <listitem><command>assigned-nas</command> - number of NA addresses in a
+ the subnet that are assigned. This statistic increases every time a new
+ lease is allocated (as a result of receiving a REQUEST message) and is
+ decreased every time a lease is released (a RELEASE message is received)
+ or expires.
+ </listitem>
+ <listitem><command>declined-nas</command> - number of IPv6 addresses that
+ are currently declined and so counts the number of leases currently
+ unavailable. Once a lease is recovered, this statistic will be decreased.
+ Ideally, this statistic should be zero. If this statistic is non-zero
+ (or worse, increasing), the network administrator should investigate if
+ there is a misbehaving device in the network.
+ </listitem>
+ <listitem><command>total-pds</command> - total number of PD prefixes available
+ of DHCPv6 management for a given subnet. In other words, this is the sum
+ of all prefixes in all configured pools. This statistic changes only during
+ configuration changes. Note it does not take into account any prefixes that
+ may be reserved due to host reservation.
+ </listitem>
+ <listitem><command>assigned-pds</command> - number of PD prefixes in a given
+ subnet that are assigned. This statistic increases every time a new lease is
+ allocated (as a result of receiving a REQUEST message) and is decreased every
+ time a lease is released (a RELEASE message is received) or expires.
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem><command>rows</command> - a list of rows, one per subnet ID. Each row
+ contains a data value for corresponding to and in the same order as each column
+ listed in "columns" for a given subnet.
+ </listitem>
+ <listitem><command>timestamp</command> - textual date and time the data was fetched,
+ expressed as GMT</listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+<para>
+ The response to a DHCPv4 command might look as follows:
+<screen>
+ {
+ "result": 0,
+ "text": "stat-lease4-get: 2 rows found",
+ "arguments": {
+ "result-set": {
+ "columns": [ "subnet-id", "total-addresses", "assigned-addresses", "declined-addresses" ]
+ "rows": [
+ [ 10, 256, 111, 0 ], [ 20, 4098, 2034, 4 ]
+ ],
+ "timestamp": "2018-05-04 15:03:37.000000"
+ }
+ }
+ }
+</screen>
+</para>
+<para>
+ The response to a DHCPv6 command might look as follows:
+<screen>
+ {
+ "result": 0,
+ "text": "stat-lease6-get: 2 rows found",
+ "arguments": {
+ "result-set": {
+ "columns": [ "subnet-id", "total-nas", "assigned-nas", "declined-nas", "total-pds", "assigned-pds" ]
+ "rows": [
+ [ 10, 256, 111, 0 ],
+ [ 20, 4098, 2034, 4 ]
+ ],
+ "timestamp": "2018-05-04 15:03:37.000000"
+ }
+ }
+ }
+</screen>
+</para>
+
+
+
+</para>
+
+
+
+</para>
+
+
+
+</section>
+</section>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="hooks-host-cache.xml"/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="hooks-stat-cmds.xml"/>
+
</section>
isc::Exception(file, line, what) { };
};
-///@brief Implements command handlinge for stat-lease<x>-get commands
+///@brief Implements command handlinge for stat-leaseX-get commands
class LeaseStatCmdsImpl : private CmdsImpl {
public:
- /// @brief Wrapper class stat-lease<x>-get command parameters.
+ /// @brief Wrapper class stat-leaseX-get command parameters.
class Parameters {
public:
/// @brief Specifies the subnet-id for a single subnet, or
int
statLease6GetHandler(CalloutHandle& handle);
- /// @Brief Parses command arguments into stat-lease<x>-get parameters
+ /// @brief Parses command arguments into stat-leaseX-get parameters
/// @param cmd_args Element form of command arguments to parse
/// @throw BadValue if any of the following rules are broken:
///
/// @brief Adds a row of Lease4 stat values to a list of value rows
///
/// @param[out] value_rows list of rows to which to add
- /// @param[out] subent_id id of the subnet of the new row. This value is
+ /// @param[out] subnet_id id of the subnet of the new row. This value is
/// also used for fetching the total addresses in the subnet
/// @param assigned number of assigned addresses in the subnet
- /// @param assigned number of declined addresses in the subnet
+ /// @param declined number of declined addresses in the subnet
void addValueRow4(ElementPtr value_rows, const SubnetID &subnet_id,
int64_t assigned, int64_t declined);
/// @brief Adds a row of Lease6 stat values to a list of value rows
///
/// @param[out] value_rows list of rows to which to add
- /// @param[out] subent_id id of the subnet of the new row. This value is
+ /// @param[out] subnet_id id of the subnet of the new row. This value is
/// also used for fetching the total NAs and PDs in the subnet
/// @param assigned number of assigned NAs in the subnet
/// @param declined number of declined NAs in the subnet
@section stat_cmds Stat Commands Overview
-Stat Commands (or stat_cmds) is a Hook library that can be loaded by Kea to
-extend it with additional mechanisms.
-
-The primary purpose of this library is to provide commands that manage leases.
-As such, the whole library is structured around command handlers. When the
-library is loaded it registers a number of handlers for new commands. When a
-command is issued (be it directly via control channel or indirectly via REST
+Stat Commands (or stat_cmds) is a Hook library that can be loaded by
+either kea-dhcp4 and kea-dhcp6 servers to extend them with additional
+statistics mechanisms.
+
+The initial purpose of this library is provide supplemental commands for
+obtaining accurate lease statistics in deployments that share lease storage
+between multiple Kea DHCP servers. It is likely that additional statistics
+related commands will be added to this library in future releases as use
+cases for them arise.
+
+The library is structured around command handlers. When the library is
+loaded it registers handlers for new commands. When a command
+is issued (be it directly via control channel or indirectly via REST
interface from control agent), the code receives a JSON command with
-parameters. Those are parsed and then actual operation commences. This
-operation always interacts with an instantiation of isc::dhcp::StatMgr
-instance, which is Kea's way of storing leases. At the time of writing this text
-(Aug. 2017), Kea supports four types of lease managers: memfile, MySQL,
-PostgreSQL or Cassandra. The lease commands provided by this library
-provide a unified interface for those backends.
-
-As with other hooks, this one also keeps its code in a separate namespace which
+parameters. The command is routed the appropriate handler, its parameters
+are parsed and command executed accordingly. Lastly, a response is
+constructed and shipped back to the client.
+
+This lease statistics commands interact with both the isc::dhcp::StatsMgr
+and the isc::dhcp::LeaseMgr instance. At the time of writing this text
+(May, 2018), Kea supports four types of lease managers: memfile, MySQL,
+PostgreSQL or Cassandra. The lease statistics commands provided by this
+library provide a unified interface supported by all four of these backends.
+
+As with other hooks, this one keeps its code in a separate namespace which
corresponds to the file name of the library: isc::stat_cmds.
+For background on the design and design choices please refer to: <a
+href="http://kea.isc.org/wiki/SharedLeaseStorageStats">Shared Lease Stats Design</a>
+
@section stat_cmdsCode Stat Commands Code Overview
-The library operation starts with Kea calling the load() function (file
-load_unload.cc). It instantiates an isc::stat_cmds::StatCmds object.
-The constructor of that object registers all of the lease commands. For a list,
-see @ref isc::stat_cmds::StatCmds class documentation. This class uses Pimpl
-design pattern, thus the real implementation is hidden in isc::stat_cmds::StatCmdsImpl.
-
-Almost every command has its own handler, except few that share the same handler
-between v4 and v6 due to its similarity. For example
-isc::stat_cmds::StatCmdsImpl::leaseAddHandler handles lease4-add and lease6-add
-commands. Although the details differ between handlers, the general approach
-is the same. First, it starts with parameters sanitization and then some
-interaction with isc::dhcp::StatMgr is conducted.
-
-For commands that do something with a specific lease (lease4-get, lease6-get,
-lease4-del, lease6-del), there is a @ref isc::stat_cmds::StatCmdsImpl::Parameters
-class that contains parsed elements.
-
-For details see documentation and code of the following handlers:
-- @ref isc::stat_cmds::StatCmdsImpl::leaseAddHandler (lease4-add, lease6-add)
-- @ref isc::stat_cmds::StatCmdsImpl::leaseGetHandler (lease4-get, lease6-get)
-- @ref isc::stat_cmds::StatCmdsImpl::lease4DelHandler (lease4-del)
-- @ref isc::stat_cmds::StatCmdsImpl::lease6DelHandler (lease6-del)
-- @ref isc::stat_cmds::StatCmdsImpl::lease4UpdateHandler (lease4-update)
-- @ref isc::stat_cmds::StatCmdsImpl::lease6UpdateHandler (lease6-update)
-- @ref isc::stat_cmds::StatCmdsImpl::lease4WipeHandler (lease4-wipe)
-- @ref isc::stat_cmds::StatCmdsImpl::lease6WipeHandler (lease6-wipe)
-
-@section stat_cmdsDesigns Stat Commands Design choices
-
-The lease manipulation commands were implemented to provide a convenient interface
-for sysadmins. The primary goal was to offer a way to interact with the live
-lease database in unified way, regardless of the actual backend being used.
-
-For some backends (MySQL, PostgreSQL and Cassandra) it is possible to interact
-directly with the backend while Kea is running and possibly change its content. This
-ability is both powerful and dangerous. In particular, only rudimentary
-checks are enforced by the DB schemas (e.g. not possible to have two leases
-for the same address). However, it does not prevent sysadmins from making
-more obscure errors, like inserting leases for subnets that do not exist
-or configuring an address that is topologically outside of the subnet to which
-it should belong. These kind of checks are only possible by DHCP-aware
-code, which this library provides.
-
-Some of the queries may require a seemingly odd set of parameters. For example,
-lease6-get query requires at least DUID, subnet-id and IAID to retrieve a lease
-by DUID. The need for a sysadmin to know and specify an IAID is troublesome.
-However, the guiding principle here was to use whatever queries were already
-exposed by the lease manager and not introduce new indexes, unless absolutely
-necessary. This ensures that there is no performance degradation when the
-library is loaded. The only exception for that was lease4-wipe and lease6-wipe
-commands that remove all leases from specific subnet. As there were no
-queries that could retrieve or otherwise enumerate leases for a specific subnet,
-a new query type and a new index had to be added.
+Library operation starts with Kea calling the load() function (file
+stat_cmds_callouts.cc). This function registers the command callout
+functions for each of the libraries commands. For a list,
+see @ref isc::stat_cmds::StatCmds class documentation. This class uses
+the Pimpl design pattern, and thus the actual implementation is hidden
+in @ref isc::stat_cmds::LeaseStatCmdsImpl.
+
+Unlike similar libraries, the Pimpl class is differentiated from the
+the StatCmds class by the prefix "Lease" and it is instantiated in the outer
+handler (e.g. @ref isc::stat_cmds::StatCmds::statLease4GetHandler) rather than
+the StatCmds constructor. This was done in the event that commands, unrelated
+to lease statistics, are added to this library and that would be better served
+by Pimpl derviations specific to them.
+
+@subsection stat_cmdsLeaseStatCode Lease Stat Commands Code Overview
+
+There are two shared lease statistic commands, "stat-lease4-get" and "stat-lease6-get".
+Both of these support the same input parameters and have their own command handlers:
+
+- @ref isc::stat_cmds::LeaseStatCmdsImpl::statLease4GetHandler (stat-lease4-get)
+- @ref isc::stat_cmds::LeaseStatCmdsImpl::statLease6GetHandler (stat-lease6-get)
+
+Briefly, the commands are intended to fetch the lease statistics per subnet
+for the range of subnets described by the input parameters. JSON text structure
+of the commands is as follows:
+
+DHCPv4 command:
+
+@code
+{
+ "command": "stat-lease4-get",
+ "arguments": {
+ "subnet-id": x
+ "subnet-range": {
+ "first-subnet-id": x,
+ "last-subnet-id": y
+ }
+ }
+}
+
+ where subnet-id and subnet-range are optional and mutually exclusive
+@endcode
+
+DHCPv6 command:
+
+@code
+{
+ "command": "stat-lease6-get",
+ "arguments": {
+ "subnet-id": x
+ "subnet-range": {
+ "first-subnet-id": x,
+ "last-subnet-id": y
+ }
+ }
+}
+
+ where subnet-id and subnet-range are optional and mutually exclusive
+@endcode
+
+
+
+Command handling
+for both commands is symetrical consists of the following steps:
+
+-# The input parameters (if any) are parsed. Invalid values or
+combinations if detected result in generating a CONTROL_RESULT_ERROR
+response to the client. (See @ref isc::stat_cmds::LeaseStatCmdsImpl::getParameters
+and @ref isc::stat_cmds::LeaseStatCmdsImpl::Parameters)
+
+-# The parameters are used to identify the range of configured subnets
+to include in the response. This is done by querying subnet configuration
+housed by @ref isc::dhcp::CfgMgr. If the range contains no known subnets then a
+CONTROL_RESULT_EMPTY response is sent back to the client.
+
+-# The initial result-set response is constructed. Essentially this is
+an @ref isc::data::Element tree, which converted to JSON would appear as follows:
+
+@code
+ "result-set": {
+ "timestamp": "2018-03-22 09:43:30.815371",
+ "columns": ["<label-1>, <label-2>, ... ],
+ "rows": []
+ }
+@endcode
+
+-# The acutal lease statistics are then retrieved from @ref isc::dhcp::LeaseMgr instance
+by invoking of the three functions based on the input parameters:
+
+DHCPv4 functions:
+
+- @ref isc::dhcp::LeaseMgr::startLeaseStatsQuery4
+- @ref isc::dhcp::LeaseMgr::startSubnetLeaseStatsQuery4
+- @ref isc::dhcp::LeaseMgr::startSubnetRangeLeaseStatsQuery4
+
+DHCPv6 functions:
+
+- @ref isc::dhcp::LeaseMgr::startLeaseStatsQuery6
+- @ref isc::dhcp::LeaseMgr::startSubnetLeaseStatsQuery6
+- @ref isc::dhcp::LeaseMgr::startSubnetRangeLeaseStatsQuery6
+
+-# Iterate over the range of qualifying subnets adding a row of statistics for
+each subnet to the result-set. Each row combines the subnet total(s) from isc::dhcp::StatsMgr
+with the type and state counts from the lease query results. For subnets with no query
+data (i.e. no leases), their rows have non-zero values for totals only.
+
+-# Finally, a CONTROL_RESULT_SUCCESS repsonse is generated containing the populated result-set.
+
+A DHCPv4 response might look like this:
+
+@code
+ {
+ "result-set\": {
+ "columns\": [
+ "subnet-id", "total-addreses",
+ "assigned-addreses", "declined-addreses"
+ ],
+ "rows\": [
+ [ 30, 256, 100, 2 ],
+ [ 40, 16, 0, 0 ],
+ [ 50, 256, 35, 0 ],
+ ],
+ timestamp\": \"2018-05-04 15:03:37.000000\" }
+ }
+@endcode
+
+and DHCPv6 response might look like this:
+
+@code
+ {
+ "result-set": {
+ "columns": [
+ "subnet-id", "total-nas", "assigned-nas",
+ "declined-nas", "total-pds", "assigned-pds"
+ ],
+ "rows": [
+ [ 30, 16, 6, 0, 65536, 400 ],
+ [ 40, 16777216, 989837, 0, 0, 0 ]
+ ],
+ "timestamp": "2018-05-04 15:03:37.000000" }
+ }
+@endcode
*/
/// {
/// "command": "stat-lease4-get",
/// "arguments": {
- /// "from_storage: true/false, // optional - maybe?
- /// "subnet-id": x, // optional
- /// "subnet-id-range": { // optional
+ /// "subnet-id": x // optional
+ /// "subnet-range": { // optional
/// "first-subnet-id": x, // id >= x
/// "last-subnet-id": y // id <= x
/// }
/// {
/// "command": "stat-lease6-get",
/// "arguments": {
- /// "from_storage: true/false,
- /// "subnet-id": x, // optional
- /// "subnet-id-range": { // optional
+ /// "subnet-id": x // optional
+ /// "subnet-range": { // optional
/// "first-subnet-id": x, // id >= x
/// "last-subnet-id": y // id <= x
/// }
/// ordered ascending by subnet ID.
///
/// @param first_subnet_id first subnet in the range of subnets
- /// @param last last_subnet_id subnet in the range of subnets
+ /// @param last_subnet_id last subnet in the range of subnets
/// @return A populated LeaseStatsQuery
virtual LeaseStatsQueryPtr startSubnetRangeLeaseStatsQuery6(const SubnetID& first_subnet_id,
const SubnetID& last_subnet_id);