Commit 7616e3b3 authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[master] Merge branch 'trac3795' (DHCPv6 statistics)

Conflicts:
	doc/guide/dhcp4-srv.xml
parents 6efd66dc 10079452
......@@ -2643,12 +2643,13 @@ temporarily override a list of interface names and listen on all interfaces.
<entry>pkt4-received</entry>
<entry>integer</entry>
<entry>
Number of packets received. This includes all packets: valid, bogus, corrupted,
rejected etc. This statistic is expected to grow rapidly.
Number of DHCPv4 packets received. This includes all packets: valid,
bogus, corrupted, rejected etc. This statistic is expected to grow
rapidly.
</entry>
</row>
<row>
<row>
<entry>pkt4-discover-received</entry>
<entry>integer</entry>
<entry>
......@@ -2820,46 +2821,36 @@ temporarily override a list of interface names and listen on all interfaces.
</entry>
</row>
<row>
<entry>subnet[id].total-addresses</entry>
<entry>integer</entry>
<entry>The total number of addresses available for the 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. The
<emphasis>id</emphasis> is the subnet-id of a given subnet. This
statistic is exposed for each subnet separately. This statistic is
reset during reconfiguration event.</entry>
</row>
<row>
<entry>subnet[id].assigned-addresses</entry>
<entry>integer</entry>
<entry>This statistic shows the number of assigned addresses in a
given subnet. This statistic 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). When lease expiration is implemented (planned for Kea
1.0), it will also decrease when a lease is expired. The
<emphasis>id</emphasis> is the subnet-id of a given subnet. This
statistic is exposed for each subnet separately. This statistic is
reset during reconfiguration event.</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<!-- proper section structure added in ticket 3794, will merge it
appropiately -->
<section id="dummy">
<title>MERGE ME</title>
<para>
<itemizedlist>
<listitem>
<simpara><emphasis>subnet[id].total-addresses</emphasis> (integer) -
this statistic shows the total number of addresses available for the
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. The <emphasis>id</emphasis> is the
subnet-id of a given subnet. This statistic is exposed for each subnet
separately. This statistic is reset during reconfiguration event.
</simpara>
</listitem>
<listitem>
<simpara><emphasis>subnet[id].assigned-addresses</emphasis> (integer) -
this statistic shows the number of assigned addresses in a given subnet.
This statistic 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). When lease expiration
is implemented (planned for Kea 1.0), it will also decrease when a lease
is expired. The <emphasis>id</emphasis> is the subnet-id of a given
subnet. This statistic is exposed for each subnet separately. This
statistic is reset during reconfiguration event.
</simpara>
</listitem>
</itemizedlist>
</para>
</section>
<section id="dhcp4-ctrl-channel">
<title>Management API for the DHCPv4 server</title>
<para>
......
......@@ -88,9 +88,9 @@ strings <userinput>path</userinput>/kea-dhcp6 | sed -n 's/;;;; //p'
</para>
<para>
When running in a console, the server can be shut down by
pressing ctrl-c. It detects the key combination and shuts
down gracefully.
When running in a console, the server can be shut down by
pressing ctrl-c. It detects the key combination and shuts
down gracefully.
</para>
<para>
......@@ -506,10 +506,10 @@ temporarily override a list of interface names and listen on all interfaces.
</para>
<para>
The following configuration will assign the specified subnet
identifier to the newly configured subnet:
The following configuration will assign the specified subnet
identifier to the newly configured subnet:
<screen>
<screen>
"Dhcp6": {
"subnet6": [
{
......@@ -520,9 +520,9 @@ temporarily override a list of interface names and listen on all interfaces.
]
}
</screen>
This identifier will not change for this subnet unless the "id" parameter is
removed or set to 0. The value of 0 forces auto-generation of the subnet
identifier.
This identifier will not change for this subnet unless the "id" parameter is
removed or set to 0. The value of 0 forces auto-generation of the subnet
identifier.
</para>
<!-- @todo: describe whether database needs to be updated after changing
id -->
......@@ -673,15 +673,15 @@ temporarily override a list of interface names and listen on all interfaces.
<title>Subnet and Prefix Delegation Pools</title>
<para>
Subnets may also be configured to delegate prefixes, as defined in
<ulink url="http://tools.ietf.org/html/rfc3633">RFC 3633</ulink>.
<ulink url="http://tools.ietf.org/html/rfc3633">RFC 3633</ulink>.
A subnet may have one or more prefix delegation pools. Each pool has
a prefixed address, which is specified as a prefix and a prefix length,
as well as a delegated prefix length. <command>delegated-len</command>
must not be shorter (that is it must be numerically greater or equal)
than <command>prefix-len</command>.
If both <command>delegated-len</command>
and <command>prefix-len</command> are equal, the server will be able to
delegate only one prefix. The delegated <command>prefix</command> does
must not be shorter (that is it must be numerically greater or equal)
than <command>prefix-len</command>.
If both <command>delegated-len</command>
and <command>prefix-len</command> are equal, the server will be able to
delegate only one prefix. The delegated <command>prefix</command> does
not have to match the <command>subnet</command> prefix.
</para>
<para> Below is a sample subnet configuration which enables prefix
......@@ -1317,7 +1317,7 @@ should include options from the isc option space:
to designate that a given subnet is local, i.e. reachable directly over
the specified interface. For example the server that is intended to serve
a local subnet over eth0 may be configured as follows:
<screen>
<screen>
"Dhcp6": {
"subnet6": [
{
......@@ -2262,14 +2262,14 @@ should include options from the isc option space:
<para>
An example configuration that disables reservation looks like follows:
<screen>
<screen>
"Dhcp6": {
"subnet6": [
{
{
"subnet": "2001:db8:1::/64",
<userinput>"reservation-mode": "disabled"</userinput>,
...
}
}
]
}
</screen>
......@@ -2392,9 +2392,9 @@ should include options from the isc option space:
"pool": "2001:db8:1::1-2001:db8:1::ffff"
}
],
<userinput>"relay": {
"ip-address": "3000::1"
}</userinput>
<userinput>"relay": {
"ip-address": "3000::1"
}</userinput>
}
]
}
......@@ -2425,11 +2425,11 @@ should include options from the isc option space:
"Dhcp6": {
"subnet6": [
{
"subnet": "3000::/64",
"pools": [
{ "pool": "3000::2 - 3000::ffff" }
],
<userinput>"client-class": "VENDOR_CLASS_docsis3.0",
"subnet": "3000::/64",
"pools": [
{ "pool": "3000::2 - 3000::ffff" }
],
<userinput>"client-class": "VENDOR_CLASS_docsis3.0",
"relay": {
"ip-address": "3000::1"
}</userinput>
......@@ -2442,9 +2442,9 @@ should include options from the isc option space:
"pool": "2001:db8:1::1-2001:db8:1::ffff"
}
],
<userinput>"relay": {
"ip-address": "3000::1"
}</userinput>
<userinput>"relay": {
"ip-address": "3000::1"
}</userinput>
}
]
}
......@@ -2579,6 +2579,206 @@ should include options from the isc option space:
</para>
</section>
<section id="dhcp6-stats">
<title>Statistics in DHCPv6 server</title>
<note>
<para>This section describes DHCPv6-specific statistics. For a general
overview and usage of statistics, see <xref linkend="stats" />.</para>
</note>
<para>
The DHCPv6 server supports the following statistics:
</para>
<table frame="all" id="dhcp6-statistics">
<title>DHCPv4 Statistics</title>
<tgroup cols='3'>
<colspec colname='statistic' align='center'/>
<colspec colname='type' align='center'/>
<colspec colname='description' align='left'/>
<thead>
<row>
<entry>Statistic</entry>
<entry>Data Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>pkt6-received</entry>
<entry>integer</entry>
<entry>Number of DHCPv6 packets received. This includes all packets:
valid, bogus, corrupted, rejected etc. This statistic is expected
to grow rapidly.</entry>
</row>
<row>
<entry>pkt6-receive-drop</entry>
<entry>integer</entry>
<entry>Number of incoming packets that were dropped. Exact reason
for dropping packets is logged, but the most common reasons may
be: an unacceptable or not supported packet type, direct responses
are forbidden, the server-id sent by the client does not match the
server's server-id or the packet is malformed.</entry>
</row>
<row>
<entry>pkt6-parse-failed</entry>
<entry>integer</entry>
<entry>Number of incoming packets that could not be parsed.
A non-zero value of this statistic indicates that the server
received a malformed or truncated packet. This may indicate problems
in your network, faulty clients, faulty relay agents or server
code bug.</entry>
</row>
<row>
<entry>pkt6-solicit-received</entry>
<entry>integer</entry>
<entry>
Number of SOLICIT packets received. This statistic is expected
to grow. Its increase means that clients that just booted
started their configuration process and their initial packets
reached your server.
</entry>
</row>
<row>
<entry>pkt6-advertise-received</entry>
<entry>integer</entry>
<entry>
Number of ADVERTISE packets received. Advertise packets are sent
by the server and the server is never expected to receive them. A non-zero
value of this statistic indicates an error ocurring in the network.
One likely cause would be a misbehaving relay agent that incorrectly
forwards ADVERTISE messages towards the server, rather back to the
clients.
</entry>
</row>
<row>
<entry>pkt6-request-received</entry>
<entry>integer</entry>
<entry>Number of REQUEST packets received. This statistic
is expected to grow. Its increase means that clients that just booted
received the server's response (ADVERTISE), accepted it and are now
requesting an address (REQUEST).
</entry>
</row>
<row>
<entry>pkt6-reply-received</entry>
<entry>integer</entry>
<entry>Number of REPLY packets received. This statistic is
expected to remain zero at all times, as REPLY packets are sent by
the server and the server is never expected to receive
them. A non-zero value indicates an error. One likely cause would be
a misbehaving relay agent that incorrectly forwards REPLY messages
towards the server, rather back to the clients.
</entry>
</row>
<row>
<entry>pkt6-renew-received</entry>
<entry>integer</entry>
<entry>Number of RENEW packets received. This statistic
is expected to grow. Its increase means that clients received their
addresses and prefixes and are trying to renew them.
</entry>
</row>
<row>
<entry>pkt6-rebind-received</entry>
<entry>integer</entry>
<entry>Number of REBIND packets received. A non-zero value
indicates that clients didn't receive responses to their RENEW messages
(regular lease renewal mechanism) and are attempting to find any server
that is able to take over their leases. It may mean that some server's
REPLY messages never reached the clients.
</entry>
</row>
<row>
<entry>pkt6-release-received</entry>
<entry>integer</entry>
<entry>Number of RELEASE packets received. This statistic is expected
to grow when a device is being shut down in the network. It
indicates that the address or prefix assigned is reported as no longer
needed. Note that many devices, especially wireless, do not send RELEASE,
because of design choice or due to moving out of range.
</entry>
</row>
<row>
<entry>pkt6-decline-received</entry>
<entry>integer</entry>
<entry>
Number of DECLINE packets received. This statistic is expected to
remain close to zero. Its increase means that a client leased an
address, but discovered that the address is currently used by an
unknown device in your network. If this statistic is growing, it
may indicate misconfigured server or devices that have statically
assigned conflicting addresses.
</entry>
</row>
<row>
<entry>pkt6-infrequest-received</entry>
<entry>integer</entry>
<entry>
Number of INFORMATION-REQUEST packets received. This statistic
is expected to grow if there are devices that are using
stateless DHCPv6. INFORMATION-REQUEST messages are used by
clients that request stateless configuration, i.e. options
and parameters other than addresses or prefixes.
</entry>
</row>
<row>
<entry>pkt6-unknown-received</entry>
<entry>integer</entry>
<entry>Number of packets received of an unknown type. Non-zero
value of this statistic indicates that the server received a
packet that it wasn't able to recognize: either with unsupported
type or possibly malformed.</entry>
</row>
<row>
<entry>pkt6-sent</entry>
<entry>integer</entry>
<entry>Number of DHCPv6 packets sent. This statistic is expected
to grow every time the server transmits a packet. In general, it
should roughly match pkt6-received, as most incoming packets cause
the server to respond. There are exceptions (e.g. server receiving a
REQUEST with server-id matching other server), so do not worry, if
it is lesser than pkt6-received.</entry>
</row>
<row>
<entry>pkt6-advertise-sent</entry>
<entry>integer</entry>
<entry>Number of ADVERTISE packets sent. This statistic is
expected to grow in most cases after a SOLICIT is processed. There
are certain uncommon, but valid cases where incoming SOLICIT is
dropped, but in general this statistic is expected to be close to
pkt6-solicit-received.</entry>
</row>
<row>
<entry>pkt6-reply-sent</entry>
<entry>integer</entry>
<entry>Number of REPLY packets sent. This statistic is expected to
grow in most cases after a SOLICIT (with rapid-commit), REQUEST,
RENEW, REBIND, RELEASE, DECLINE or INFORMATION-REQUEST is
processed. There are certain cases where there is no response.
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="dhcp6-std">
<title>Supported DHCPv6 Standards</title>
<para>The following standards are currently
......@@ -2623,13 +2823,13 @@ should include options from the isc option space:
to echo back the options, checks whether an option is RSOO-enabled,
ability to mark additional options as RSOO-enabled.</simpara>
</listitem>
<listitem>
<simpara><emphasis>Client Link-Layer Address Option in
DHCPv6</emphasis>,
<ulink url="http://tools.ietf.org/html/rfc6939">RFC
6939</ulink>: Supported option is client link-layer
address option.</simpara>
</listitem>
<listitem>
<simpara><emphasis>Client Link-Layer Address Option in
DHCPv6</emphasis>,
<ulink url="http://tools.ietf.org/html/rfc6939">RFC
6939</ulink>: Supported option is client link-layer
address option.</simpara>
</listitem>
</itemizedlist>
</section>
......
......@@ -45,6 +45,7 @@
#include <hooks/callout_handle.h>
#include <hooks/hooks_log.h>
#include <hooks/hooks_manager.h>
#include <stats/stats_mgr.h>
#include <util/encode/hex.h>
#include <util/io_utilities.h>
......@@ -73,6 +74,7 @@ using namespace isc::dhcp;
using namespace isc::dhcp_ddns;
using namespace isc::hooks;
using namespace isc::log;
using namespace isc::stats;
using namespace isc::util;
using namespace std;
......@@ -330,6 +332,12 @@ bool Dhcpv6Srv::run() {
.arg(query->getLocalPort())
.arg(query->getIface());
// Log reception of the packet. We need to increase it early, as
// any failures in unpacking will cause the packet to be dropped.
// we will increase type specific packets further down the road.
// See processStatsReceived().
StatsMgr::instance().addValue("pkt6-received", static_cast<int64_t>(1));
} else {
LOG_DEBUG(packet_logger, DBG_DHCP6_DETAIL, DHCP6_BUFFER_WAIT_INTERRUPTED)
.arg(timeout);
......@@ -431,12 +439,25 @@ bool Dhcpv6Srv::run() {
.arg(query->getLocalAddr().toText())
.arg(query->getIface())
.arg(e.what());
// Increase the statistics of parse failures and dropped packets.
StatsMgr::instance().addValue("pkt6-parse-failed",
static_cast<int64_t>(1));
StatsMgr::instance().addValue("pkt6-receive-drop",
static_cast<int64_t>(1));
continue;
}
}
// Update statistics accordingly for received packet.
processStatsReceived(query);
// Check if received query carries server identifier matching
// server identifier being used by the server.
if (!testServerID(query)) {
// Increase the statistic of dropped packets.
StatsMgr::instance().addValue("pkt6-receive-drop", static_cast<int64_t>(1));
continue;
}
......@@ -444,6 +465,9 @@ bool Dhcpv6Srv::run() {
// The Solicit, Confirm, Rebind and Information Request will be
// discarded if sent to unicast address.
if (!testUnicast(query)) {
// Increase the statistic of dropped packets.
StatsMgr::instance().addValue("pkt6-receive-drop", static_cast<int64_t>(1));
continue;
}
......@@ -541,6 +565,9 @@ bool Dhcpv6Srv::run() {
.arg(query->getRemoteAddr().toText())
.arg(e.what());
// Increase the statistic of dropped packets.
StatsMgr::instance().addValue("pkt6-receive-drop", static_cast<int64_t>(1));
} catch (const isc::Exception& e) {
// Catch-all exception (at least for ones based on the isc Exception
......@@ -553,6 +580,9 @@ bool Dhcpv6Srv::run() {
.arg(query->getName())
.arg(query->getRemoteAddr().toText())
.arg(e.what());
// Increase the statistic of dropped packets.
StatsMgr::instance().addValue("pkt6-receive-drop", static_cast<int64_t>(1));
}
if (rsp) {
......@@ -665,6 +695,10 @@ bool Dhcpv6Srv::run() {
.arg(static_cast<int>(rsp->getType())).arg(rsp->toText());
sendPacket(rsp);
// Update statistics accordingly for sent packet.
processStatsSent(rsp);
} catch (const std::exception& e) {
LOG_ERROR(packet_logger, DHCP6_PACKET_SEND_FAIL)
.arg(e.what());
......@@ -2898,5 +2932,74 @@ void Dhcpv6Srv::processRSOO(const Pkt6Ptr& query, const Pkt6Ptr& rsp) {
}
}
void Dhcpv6Srv::processStatsReceived(const Pkt6Ptr& query) {
// Note that we're not bumping pkt6-received statistic as it was
// increased early in the packet reception code.
string stat_name = "pkt6-unknown-received";
switch (query->getType()) {
case DHCPV6_SOLICIT:
stat_name = "pkt6-solicit-received";
break;
case DHCPV6_ADVERTISE:
// Should not happen, but let's keep a counter for it
stat_name = "pkt6-advertise-received";
break;
case DHCPV6_REQUEST:
stat_name = "pkt6-request-received";
break;
case DHCPV6_CONFIRM:
stat_name = "pkt6-confirm-received";
break;
case DHCPV6_RENEW:
stat_name = "pkt6-renew-received";
break;
case DHCPV6_REBIND:
stat_name = "pkt6-rebind-received";
break;
case DHCPV6_REPLY:
// Should not happen, but let's keep a counter for it
stat_name = "pkt6-reply-received";
break;
case DHCPV6_RELEASE:
stat_name = "pkt6-release-received";
break;
case DHCPV6_DECLINE:
stat_name = "pkt6-decline-received";
break;
case DHCPV6_RECONFIGURE:
stat_name = "pkt6-reconfigure-received";
break;
case DHCPV6_INFORMATION_REQUEST:
stat_name = "pkt6-infrequest-received";
break;
default:
; // do nothing
}
StatsMgr::instance().addValue(stat_name, static_cast<int64_t>(1));
}
void Dhcpv6Srv::processStatsSent(const Pkt6Ptr& response) {
// Increase generic counter for sent packets.
StatsMgr::instance().addValue("pkt6-sent", static_cast<int64_t>(1));
// Increase packet type specific counter for packets sent.
string stat_name;
switch (response->getType()) {
case DHCPV6_ADVERTISE:
stat_name = "pkt6-advertise-sent";
break;
case DHCPV6_REPLY:
stat_name = "pkt6-reply-sent";
break;
default:
// That should never happen
return;
}
StatsMgr::instance().addValue(stat_name, static_cast<int64_t>(1));
}
};
};
......@@ -740,6 +740,14 @@ private:
Lease6Ptr& new_lease, const std::string& hostname,
bool do_fwd, bool do_rev);
/// @brief Updates statistics for received packets
/// @param query packet received
static void processStatsReceived(const Pkt6Ptr& query);
/// @brief Updates statistics for transmitted packets
/// @param query packet transmitted
static void processStatsSent(const Pkt6Ptr& response);
/// @brief Allocation Engine.
/// Pointer to the allocation engine that we are currently using
/// It must be a pointer, because we will support changing engines
......
......@@ -295,6 +295,9 @@ Dhcp6Client::doSARR() {
void
Dhcp6Client::doSolicit() {
context_.query_ = createMsg(DHCPV6_SOLICIT);
if (forced_server_id_) {
context_.query_->addOption(forced_server_id_);
}