summaryrefslogtreecommitdiffstats
path: root/src/bin/dhcp6/dhcp6.dox
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/dhcp6/dhcp6.dox')
-rw-r--r--src/bin/dhcp6/dhcp6.dox612
1 files changed, 612 insertions, 0 deletions
diff --git a/src/bin/dhcp6/dhcp6.dox b/src/bin/dhcp6/dhcp6.dox
new file mode 100644
index 0000000..133c359
--- /dev/null
+++ b/src/bin/dhcp6/dhcp6.dox
@@ -0,0 +1,612 @@
+// Copyright (C) 2012-2018 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/**
+ @page dhcp6 DHCPv6 Server Component
+
+Kea includes the "kea-dhcp6" component, which is the DHCPv6 server
+implementation. This component is built around the
+@ref isc::dhcp::Dhcpv6Srv class which controls all major operations
+performed by the server such as: DHCP messages processing, callouts
+execution for many hook points, FQDN processing and interactions with the
+"kea-dhcp-ddns" component, lease allocation, system signals handling etc.
+
+The "kea-dhcp6" component requires linking with many different libraries
+to obtain access to common functions like: interfaces and sockets
+management, configuration parsing, leases management and allocation,
+hooks infrastructure, statistics management etc.
+
+The following sections walk through some of the details of the "kea-dhcp6"
+component implementation.
+
+@section dhcpv6ConfigParser Configuration Parsers in DHCPv6
+
+This is a three minutes overview. If you are here only to learn absolute minimum about
+the new parser, here's how you use it:
+
+@code
+ // The following code:
+ json = isc::data::Element::fromJSONFile(file_name, true);
+
+ // can be replaced with this:
+ Parser6Context parser;
+ json = parser.parseFile(file_name, Parser6Context::PARSER_DHCP6);
+@endcode
+
+Note: parsers are currently being migrated to @ref isc::data::SimpleParser. See
+@ref ccSimpleParser page for details.
+
+For more detailed background information about flex and bison, see @ref parser.
+
+The common configuration parsers for the DHCP servers are located in the
+src/lib/dhcpsrv/parsers/ directory. Parsers specific to the DHCPv6 component
+are located in the src/bin/dhcp6/json_config_parser.cc. These parsers derive
+from the common configuration parsers and customize their behavior. For
+example: the @c Subnet6ConfigParser is used to parse parameters
+describing a single subnet. It derives from the @c
+isc::dhcp::SubnetConfigParser, which implements the common base for both
+DHCPv4 and DHCPv6 subnets. The @ref Subnet6ConfigParser
+implements the @c initSubnet abstract method, which creates an instance of
+the DHCPv6 subnet. This method is invoked by the parent class.
+
+Some parsers for the DHCPv6 server derive from the isc::dhcp::DhcpConfigParser
+class directly. This is an abstract class, defining a basic interface for
+all configuration parsers. All DHCPv6 parsers deriving from this class
+directly have their entire implementation in the
+src/bin/dhcp6/json_config_parser.cc.
+
+@section dhcpv6ConfigParserBison Configuration Parser for DHCPv6 (bison)
+
+During 1.2 milestone it has been decided to significantly refactor the
+parsers as their old implementation became unsustainable. For the brief overview
+of the problems, see ticket 5014 (http://oldkea.isc.org/ticket/5014). In
+general, the following issues of the existing code were noted:
+
+-# parsers are overwhelmingly complex. Even though each parser is relatively
+ simple class, the complexity comes from too large number of interacting parsers.
+-# the code is disorganized, i.e. spread out between multiple directories
+ (src/bin/dhcp6 and src/lib/dhcpsrv/parsers).
+-# The split into build/commit never worked well. In particular, it is not
+ trivial to revert configuration change. This split originates from BIND10
+ days and was inherited from DNS auth that did receive only changes in
+ the configuration, rather than the full configuration. As a result,
+ the split was abused and many of the parsers have commit() being a
+ no-op operation.
+-# There is no way to generate a list of all directives. We do have .spec files,
+ but they're not actually used by the code. The code has the directives
+ spread out in multiple places in multiple files in multiple directories.
+ Answering a simple question ("can I do X in the scope Y?") requires
+ a short session of reverse engineering. What's worse, we have the .spec
+ files that are kinda kept up to date. This is actually more damaging that
+ way, because there's no strict correlation between the code and .spec file.
+ So there may be parameters that are supported, but are not in .spec files.
+ The opposite is also true - .spec files can be buggy and have different
+ parameters. This is particularly true for default values.
+-# It's exceedingly complex to add comments that don't start at the first
+ column or span several lines. Both Tomek and Marcin tried to implement
+ it, but failed miserably. The same is true for including files (have
+ include statement in the config that includes other files)
+-# The current parsers don't handle the default values, i.e. if there's no
+ directive, the parser is not created at all. We have kludgy workarounds
+ for that, but the code for it is in different place than the parser,
+ which leads to the logic being spread out in different places.
+-# syntax checking is poor. The existing JSON parser allowed things like
+ empty option-data entries:
+ @code
+ "option-data": [ {} ]
+ @endcode
+ having trailing commas:
+ @code
+ "option-data": [
+ {
+ "code": 12,
+ "data": "2001:db8:1:0:ff00::1"
+ },
+ ]
+ @endcode
+ or having incorrect types, e.g. specifying timer values as strings.
+
+To solve those issues a two phase approach was proposed:
+
+PHASE 1: replace isc::data::fromJSON with bison-based parser. This will allow
+ to have a single file that defines the actual syntax, much better syntax
+ checking, and provide more flexibility, like various comment types and
+ file inclusions. As a result, the parser still returns JSON structures that
+ are guaranteed to be correct from the grammar perspective. Sticking with
+ the JSON structures also allows us to continue using existing parsers.
+ Furthermore, it is possible to implement default values at this level
+ as simply inserting extra JSON structures in places that are necessary.
+ This part is covered by ticket 5036.
+
+PHASE 2: simplify existing parsers by getting rid of the build/commit split.
+ Get rid of the inheritance contexts. Essentially the parser should
+ take JSON structure as a parameter and return the configuration structure.
+ For example, for options this should essentially look like this:
+ @code
+ CfgOptionPtr parse(ConstElementPtr options)
+ @endcode
+ The whole complexity behind inheriting contexts should be removed
+ from the existing parsers and implemented in the bison parser.
+ It should return extra JSON elements. The details are TBD, but there is
+ one example for setting up an renew-timer value on the subnet level that
+ is inherited from the global ("Dhcp6") level. This phase is covered by
+ ticket 5039.
+
+The code change for 5036 introduces flex/bison based parser. It is
+essentially defined in two files: dhcp6_lexer.ll, which defines
+regular expressions that are used on the input (be it a file or a
+string in memory). In essence, this code is being called repeatedly
+and each time it returns a token. This repeats until either the
+parsing is complete or syntax error is encountered. For example, for
+the following text:
+
+@code
+{
+ "Dhcp6":
+ {
+ "renew-timer": 100
+ }
+}
+@endcode
+this code would return the following sentence of tokens: LCURLY_BRACKET,
+DHCP6, COLON, LCURLY_BRACKET, RENEW_TIMER, COLON, INTEGER
+(a token with a value of 100), RCURLY_BRACKET, RCURLY_BRACKET, END
+
+This stream of tokens is being consumed by the parser that is defined
+in dhcp6_parser.yy. This file defines a grammar. Here's very simplified
+version of the Dhcp6 grammar:
+
+@code
+dhcp6_object: DHCP6 COLON LCURLY_BRACKET global_params RCURLY_BRACKET;
+
+global_params: global_param
+ | global_params COMMA global_param
+ ;
+
+// These are the parameters that are allowed in the top-level for
+// Dhcp6.
+global_param: preferred_lifetime
+ | valid_lifetime
+ | renew_timer
+ | rebind_timer
+ | subnet6_list
+ | interfaces_config
+ | lease_database
+ | hosts_database
+ | mac_sources
+ | relay_supplied_options
+ | host_reservation_identifiers
+ | client_classes
+ | option_data_list
+ | hooks_libraries
+ | expired_leases_processing
+ | server_id
+ | dhcp4o6_port
+ ;
+
+renew_timer: RENEW_TIMER COLON INTEGER;
+@endcode
+
+This may be slightly difficult to read at the beginning, but after getting used
+to the notation, it's very powerful and easy to extend. The first line defines
+that dhcp6_object consists of certain tokens (DHCP6, COLON and LCURLY_BRACKET)
+followed by 'global_params' expression, followed by RCURLY_BRACKET.
+
+The 'global_params' is defined recursively. It can either be a single
+'global_param' expression, or (a shorter) global_params followed by a
+comma and global_param. Bison will apply this and will be able to
+parse comma separated lists of arbitrary lengths.
+
+A single parameter is defined by 'global_param' expression. This
+represents any parameter that may appear in the global scope of Dhcp6
+object. The complete definition for all of them is complex, but the
+example above includes renew_timer definition. It is defined as a
+series of RENEW_TIMER, COLON, INTEGER tokens.
+
+The above is a simplified version of the actual grammar. If used in the version
+above, it would parse the whole file, but would do nothing with that information.
+To build actual structures, bison allows to inject C++ code at any phase of
+the parsing. For example, when the parser detects Dhcp6 object, it wants to
+create a new MapElement. When the whole object is parsed, we can perform
+some sanity checks, inject defaults for parameters that were not defined,
+log and do other stuff.
+
+@code
+dhcp6_object: DHCP6 COLON LCURLY_BRACKET {
+ // This code is executed when we're about to start parsing
+ // the content of the map
+ ElementPtr m(new MapElement());
+ ctx.stack_.back()->set("Dhcp6", m);
+ ctx.stack_.push_back(m);
+} global_params RCURLY_BRACKET {
+ // Whole Dhcp6 parsing completed. If we ever want to do any wrap up
+ // (maybe some sanity checking, insert defaults if not specified),
+ // this would be the best place for it.
+ ctx.stack_.pop_back();
+};
+@endcode
+
+The above will do the following in order: consume DHCP6 token, consume COLON token,
+consume LCURLY_BRACKET, execute the code in first { ... }, parse global_params
+and do whatever the code for it tells, parser RCURLY_BRACKET, execute the code
+in the second { ... }.
+
+There is a simple stack defined in ctx.stack_, which is isc::dhcp::Parser6Context
+defined in src/bin/dhcp6/parser_context.h. When walking through the config file, each
+new context (e.g. entering into Dhcp6, Subnet6, Pool), a new Element is added
+to the end of the stack. Once the parsing of a given context is complete, it
+is removed from the stack. At the end of parsing, there should be a single
+element on the stack as the top-level parsing (syntax_map) only inserts the
+MapElement object, but does not remove it.
+
+@section dhcpv6ConfigSubParser Parsing Partial Configuration in DHCPv6
+
+For more generic description of the solution, see @ref parserSubgrammar.
+
+One another important capability required is the ability to parse not only the
+whole configuration, but a subset of it. This is done by introducing artificial
+tokens (e.g. TOPLEVEL_JSON and TOPLEVEL_DHCP6). For complete list of available
+starting contexts, see @ref isc::dhcp::Parser6Context::ParserType. The
+Parse6Context::parse() method takes one parameter that specifies, whether the
+data to be parsed is expected to have a generic JSON or the whole configuration
+(DHCP6). This feature is currently mostly used by unit-tests (which often skip
+the '{ "Dhcp6": {' preamble), but it is expected to be soon used for parsing
+subnets only, host reservations only, options or basically any other elements.
+For example, to add the ability to parse only pools, the following could be added:
+
+@code
+start: TOPLEVEL_GENERIC_JSON sub_json
+ | TOPLEVEL_DHCP6 sub_dhcp6
+ | TOPLEVEL_POOL6 sub_pool6
+ ;
+@endcode
+
+The parser code contains the code definition and the Kea-dhcp6 updated
+to use that new parser. That parser is able to to load all examples
+from doc/example/kea6. It is also able to parser # comments (bash
+style, starting at the beginning or middle of the line), // comments
+(C++ style, can start anywhere) or / * * / comments (C style, can span
+multiple lines).
+
+This parser is currently used in production code. See configure()
+method in kea_controller.cc.
+
+There are several new unit-tests written, but the code mostly reuses existing
+one to verify that existing functionality was not compromised. There are
+several new interesting ones, though. ParserTest.file loads all the
+config file examples we have in doc/examples/kea6. This ensures that the
+parser is able to load them and also checks that our examples are sane.
+
+@section dhcp6ParserIncludes Configuration Files Inclusion
+
+The new parser provides an ability to include files. The syntax was chosen
+to look similar to how Apache includes PHP scripts in HTML code. This
+particular syntax was chosen to emphasize that the inclusion directive
+is an additional feature and not really a part of JSON syntax.
+
+To include one file from another, user the following syntax:
+
+@code
+{
+ "Dhcp6": {
+ "interfaces-config": {
+ "interfaces": [ "*" ]},
+ "preferred-lifetime": 3000,
+ "rebind-timer": 2000,
+ "renew-timer": 1000,
+ <?include "subnets.json"?>
+ "valid-lifetime": 4000
+ }
+}
+@endcode
+
+The inclusion is implemented as a stack of files. Typically, when a
+single file is parsed, the files_ (a vector of strings) and sfiles_ (a
+vector of FILE*) both contain a single entry. However, when lexer
+detects &lt;?include "filename.json?&gt;, it calls
+@ref isc::dhcp::Parser6Context::includeFile method. Up to ten nesting
+levels are supported. This arbitrarily chosen limit is a protection
+against recursive inclusions.
+
+@section dhcp6ParserConflicts Avoiding syntactical conflicts in parsers
+
+Syntactic parser has a powerful ability to not only parse the string and
+check if it's a valid JSON syntax, but also check that the resulting structures
+match expected syntax (if subnet6 are really an array, not a map, if
+timers are expressed as integers, not as strings etc.).
+
+However, there are times when we need to parse a string as arbitrary
+JSON. For example, if we're in Dhcp6 and the config contains entries
+for DhcpDdns or Dhcp4. If we were to use naive approach, the lexer
+would go through that content and most likely find some tokens that
+are also used in Dhcp6. for example 'renew-timer' would be detected
+and the parser would complain that it was not expected. To avoid this
+problem, syntactic context was introduced. When the syntactic parser
+expects certain type of content, it calls @ref
+isc::dhcp::Parser6Context::enter() method to indicate what type of
+content is expected. For example, when Dhcp6 parser discovers
+uninteresting content like Dhcp4, it enters NO_KEYWORD mode. In this
+mode, everything is parsed as generic maps, lists, integers, booleans
+or strings. This results in generic JSON structures without any syntax
+checking. A corresponding/balanced @ref
+isc::dhcp::Parser6Context::leave() call is required before leaving the
+context to come back to the previous context.
+
+Entering a new syntactic context is useful in several ways. First, it allows
+the parser to avoid conflicts. Second, it allows the lexer to return different
+tokens depending on context (e.g. if "renew-timer" string is detected, the lexer
+will return STRING token if in JSON mode or RENEW_TIMER if in DHCP6
+mode). Finally, the syntactic context allows the error message to be more
+descriptive if the input string does not parse properly.
+
+Details of the refactor of the classes derived from DhcpConfigParser are
+documented in https://gitlab.isc.org/isc-projects/kea/wikis/designs/simple-parser-design.
+
+For a generic description of the conflict avoidance, see @ref parserFlex.
+
+@section dhcpv6ConfigInherit DHCPv6 Configuration Inheritance
+
+One notable useful feature of DHCP configuration is its parameter inheritance.
+For example, the "renew-timer" value may be specified at a global scope and it then
+applies to all subnets. However, some subnets may have it overwritten with subnet
+specific values that takes precedence over global values that are considered
+defaults. The parameters inheritance is implemented by means of the "global
+context". The global context is represented by the isc::dhcp::ParserContext
+class and it holds pointers to storages of different kind, e.g. text parameters,
+numeric parameters etc. When the server is parsing the top level configuration
+parameters it passes pointers to the storages of the appropriate kind, to the
+parsers being invoked to parse the global values. Parsers will store the
+parsed values into these storages. Once the global parameters are stored in the
+global context, the parsers for the nested configuration parameters are invoked.
+These parsers check the presence of the parameters overriding the values of
+the global parameters. If a value is not present, the value from the global
+context is used.
+
+A good example of inheritance is the implementation of the @ref
+isc::dhcp::SubnetConfigParser. The @c getParam method is used throughout the
+class to obtain values of the parameters defining a subnet. It first checks
+if the specific value is present in the local values storage. If it is not
+present, it uses the value from the global context.
+
+@code
+isc::dhcp::Triplet<uint32_t>
+SubnetConfigParser::getParam(const std::string& name) {
+ uint32_t value = 0;
+ try {
+ // look for local value
+ value = uint32_values_->getParam(name);
+ } catch (const DhcpConfigError &) {
+ try {
+ // no local, use global value
+ value = global_context_->uint32_values_->getParam(name);
+ } catch (const DhcpConfigError &) {
+ isc_throw(DhcpConfigError, "Mandatory parameter " << name
+ << " missing (no global default and no subnet-"
+ << "specific value)");
+ }
+ }
+
+ return (Triplet<uint32_t>(value));
+}
+@endcode
+
+Note that if the value is neither present in the local storage nor in the global
+context, an error is signaled.
+
+Parameter inheritance is done once, during the reconfiguration phase.
+Reconfigurations are rare, so extra logic here is not a problem. On the other
+hand, values of those parameters may be used thousands times per second, so
+access to these parameters must be as efficient as possible. In fact,
+currently the code has to only call @c Subnet6::getT1(), regardless if the
+"renew-timer" has been specified as a global or subnet specific value.
+
+Debugging a configuration parser may be confusing. Therefore there is a special
+class called DebugParser. It does not configure anything, but just
+accepts any parameter of any type. If requested to commit a configuration, it will
+print out received parameter name and its value. This class is not currently used,
+but it is convenient to have it every time a new parameter is added to DHCP
+configuration. For that purpose it should be left in the code.
+
+@section dhcpv6DDNSIntegration DHCPv6 Server Support for the Dynamic DNS Updates
+
+The DHCPv6 server supports processing of the DHCPv6 Client FQDN Option described in
+the RFC4704. This Option is sent by the DHCPv6 client to instruct the server to
+update the DNS mappings for the acquired lease. A client may send its fully
+qualified domain name, a partial name or it may choose that server will generate
+the name. In the last case, the client sends an empty domain-name field in the
+DHCPv6 Client FQDN Option.
+
+As described in RFC4704, client may choose that the server delegates the forward
+DNS update to the client and that the server performs the reverse update only. Current
+version of the DHCPv6 server does not support delegation of the forward update
+to the client. The implementation of this feature is planned for the future releases.
+
+The kea-dhcp-ddns process is responsible for the actual communication with the DNS
+server, i.e. to send DNS Update messages. The kea-dhcp6 module is responsible
+for generating so called @ref isc::dhcp_ddns::NameChangeRequest and sending it to the
+kea-dhcp-ddns module. The @ref isc::dhcp_ddns::NameChangeRequest object represents changes to the
+DNS bindings, related to acquisition, renewal or release of the lease. The kea-dhcp6
+module implements the simple FIFO queue of the NameChangeRequest objects. The module
+logic, which processes the incoming DHCPv6 Client FQDN Options puts these requests
+into the FIFO queue.
+
+@todo Currently the FIFO queue is not processed after the NameChangeRequests are
+generated and added to it. In the future implementation steps it is planned to create
+a code which will check if there are any outstanding requests in the queue and
+send them to the kea-dhcp-ddns module when server is idle waiting for DHCP messages.
+
+In the simplest case, when client gets one address from the server, a DHCPv6 server
+may generate 0, 1 or 2 NameChangeRequests during single message processing.
+The server generates no NameChangeRequests if it is not configured to update DNS
+ or it rejects the DNS update for any other reason.
+
+The server may generate one NameChangeRequest in a situation when a client acquires a
+new lease or it releases an existing lease. In the former case, the NameChangeRequest
+type is CHG_ADD, which indicates that the kea-dhcp-ddns module should add a new DNS
+binding for the client, and it is assumed that there is no DNS binding for this
+client already. In the latter case, the NameChangeRequest type is CHG_REMOVE to
+indicate to the kea-dhcp-ddns module that the existing DNS binding should be removed
+from the DNS. The binding consists of the forward and reverse mapping.
+A server may only remove the mapping which it had added. Therefore, the lease database
+holds an information which updates (no update, reverse only update, forward only update,
+both reverse and forward update) have been performed when the lease was acquired.
+Server checks this information to make a decision which mapping it is supposed to
+remove when a lease is released.
+
+The server may generate two NameChangeRequests in case the client is renewing a lease and
+it already has a DNS binding for that lease. Note, that renewal may be triggered
+as a result of sending a RENEW message as well as the REQUEST message. In both cases
+DHCPv6 server will check if there is an existing lease for the client which has sent
+a message, and it will check in the lease database if the DNS Updates had
+been performed for this client. If the notion of client's FQDN changes comparing to
+the information stored in the lease database, the DHCPv6 has to remove an existing
+binding from the DNS and then add a new binding according to the new FQDN information
+received from the client. If the FQDN sent in the message which triggered a renewal
+doesn't change (comparing to the information in the lease database) the NameChangeRequest
+is not generated.
+
+In the more complex scenarios, when server sends multiple IA_NA options, each holding
+multiple IAADDR options, server will generate more NameChangeRequests for a single
+message being processed. That is 0, 1, 2 for the individual IA_NA. Generation of
+the distinct NameChangeRequests for each IADDR is not supported yet.
+
+The DHCPv6 Client FQDN Option comprises "NOS" flags which communicate to the
+server what updates (if any) client expects the server to perform. Server
+may be configured to obey client's preference or do FQDN processing in a
+different way. If the server overrides client's preference it will communicate it
+by sending the DHCPv6 Client FQDN Option in its responses to a client, with
+appropriate flags set.
+
+@section dhcpv6OptionsParse Custom functions to parse message options
+
+The DHCPv6 server implementation provides a generic support to define option
+formats and set option values. A number of options formats have been defined
+for standard options in libdhcp++. However, the formats for vendor specific
+options are dynamically configured by the server's administrator and thus can't
+be stored in libdhcp++. Such option formats are stored in the
+@ref isc::dhcp::CfgMgr. The libdhcp++ provides functions for recursive parsing
+of options which may be encapsulated by other options up to the any level of
+encapsulation but these functions are unaware of the option formats defined
+in the @ref isc::dhcp::CfgMgr because they belong to a different library.
+Therefore, the generic functions @ref isc::dhcp::LibDHCP::unpackOptions4 and
+@ref isc::dhcp::LibDHCP::unpackOptions6 are only useful to parse standard
+options whose definitions are provided in the libdhcp++. In order to overcome
+this problem a callback mechanism has been implemented in @c Option and @c Pkt6
+classes. By installing a callback function on the instance of the @c Pkt6 the
+server may provide a custom implementation of the options parsing algorithm.
+This callback function will take precedence over the @c LibDHCP::unpackOptions6
+and @c LibDHCP::unpackOptions4 functions. With this approach, the callback is
+implemented within the context of the server and it has access to all objects
+which define its configuration (including dynamically created option
+definitions).
+
+@section dhcpv6Classifier DHCPv6 Client Classification
+
+The Kea DHCPv6 currently supports two classification modes: simplified client
+classification (that was an early implementation that used values of vendor class option)
+and full client classification.
+
+@subsection dhcpv6ClassifierSimple Simple Client Classification in DHCPv6
+
+The Kea DHCPv6 server supports simplified client classification. It is called
+"simplified", because the incoming packets are classified based on the content
+of the vendor class (16) option. More flexible classification was added in 1.0
+and is described in @ref dhcpv6ClassifierFull.
+
+For each incoming packet, @ref isc::dhcp::Dhcpv6Srv::classifyPacket() method is
+called. It attempts to extract content of the vendor class option and interprets
+as a name of the class. Although the RFC 8415 says that the vendor class may
+contain more than one chunk of data, the existing code handles only one data
+block, because that is what actual devices use. For now, the code has been
+tested with two classes used in cable modem networks: eRouter1.0 and docsis3.0,
+but any other content of the vendor class option will be interpreted as a class
+name.
+
+In principle any given packet can belong to zero or more classes. As the current
+classifier is very modest, there's only one way to assign a class (based on vendor class
+option), the ability to assign more than one class to a packet is not yet exercised.
+Nevertheless, there is such a possibility and it will be used in a near future. To
+check whether a packet belongs to given class, isc::dhcp::Pkt6::inClass method should
+be used.
+
+The code sometimes refers to this classification as "simple" or 'built-in", because
+it does not require any configuration and thus is built into the server logic.
+
+@subsection dhcpv6ClassifierFull Full Client Classification in DHCPv6
+
+Kea 1.0 introduced full client classification. Each client class consists of a name
+and an expression that can be evaluated on an incoming packet. If it evaluates to
+true, this packet is considered a member of said class. Class definitions are stored
+in isc::dhcp::ClientClassDef objects that are kept in isc::dhcp::ClientClassDictionary
+and can be retrieved from CfgMgr using isc::dhcp::SrvConfig::getClientClassDictionary().
+This is convenient as there are often multiple classes associated with a given scope.
+As of Kea 1.0, the only supported scope is global, but there are plans to support
+class definitions that are subnet specific.
+
+Client classification is done in isc::dhcp::Dhcpv6Srv::classifyPacket. First, the old
+"built-in" (see @ref dhcpv6ClassifierSimple) classification is called (see @ref
+isc::dhcp::Dhcpv6Srv::classifyByVendor). Then the code iterates over all class definitions
+and for each class definition it calls isc::dhcp::evaluate, which is implemented in libeval
+(see @ref libeval). If the evaluation is successful, the class name is added to the packet
+(by calling isc::dhcp::pkt::addClass).
+
+If packet belongs to at least one class, this fact is logged. If there are any
+exceptions raised during class evaluation, an error is logged and the code attempts
+to evaluate the next class.
+
+@subsection dhcpv6ClassifierUsage How client classification information is used in DHCPv6
+
+It is possible to define class restrictions in subnet, so a given subnet is only
+accessible to clients that belong to a given class. That is implemented as isc::dhcp::Pkt6::classes_
+being passed in isc::dhcp::Dhcpv6Srv::selectSubnet() to isc::dhcp::CfgMgr::getSubnet6().
+Currently this capability is usable, but the number of scenarios it supports is
+limited.
+
+Finally, it is possible to define client class-specific options, so clients belonging
+to a class foo, will get options associated with class foo. This is implemented in
+isc::dhcp::Dhcpv6Srv::buildCfgOptionList.
+
+@section dhcpv6ConfigBackend Configuration backend for DHCPv6
+
+Earlier Kea versions had a concept of backends, which were implementations of
+different ways how configuration could be delivered to Kea. It seems that the
+concept of backends didn't get much enthusiasm from users and having multiple
+backends was cumbersome to maintain, so it was removed in 1.0.
+
+@section dhcpv6SignalBasedReconfiguration Reconfiguring DHCPv6 server with SIGHUP signal
+
+Online reconfiguration (reconfiguration without a need to restart the server) is an
+important feature which is supported by all modern DHCP servers. When using the JSON
+configuration backend, a configuration file name is specified with a command line
+option of the DHCP server binary. The configuration file is used to configure the
+server at startup. If the initial configuration fails, the server will fail to start.
+If the server starts and configures successfully it will use the initial configuration
+until it is reconfigured.
+
+The reconfiguration request can be triggered externally (from other process) by editing
+a configuration file and sending a SIGHUP signal to DHCP server process. After receiving
+the SIGHUP signal, the server will re-read the configuration file specified at startup.
+If the reconfiguration fails, the server will continue to run and use the last good
+configuration.
+
+The signal handler for SIGHUP (also for SIGTERM and SIGINT) are installed in the
+kea_controller.cc using the @c isc::util::SignalSet class. The
+@c isc::dhcp::Dhcp6Srv calls @c isc::dhcp::Daemon::handleSignal on each pass
+through the main loop. This method fetches the last received signal and calls
+a handler function defined in the kea_controller.cc. The handler function
+calls a static function @c configure defined in the kea_controller.cc.
+
+The signal handler reconfigures the server using the configuration file
+specified at server startup. The location of this file is held in the
+@c Daemon class.
+
+@section dhcpv6Other Other DHCPv6 topics
+
+For hooks API support in DHCPv6, see @ref dhcpv6Hooks.
+
+For a description of how DHCPv4-over-DHCPv6 is implemented, see @subpage dhcpv4o6Dhcp6
+
+ */