Commit 339f45b6 authored by Francis Dupont's avatar Francis Dupont
Browse files

[5374] Addressed non test comments - checkpoint before regen

parent be354058
......@@ -18,6 +18,7 @@ nobase_dist_doc_DATA += examples/kea4/advanced.json
nobase_dist_doc_DATA += examples/kea4/backends.json
nobase_dist_doc_DATA += examples/kea4/cassandra.json
nobase_dist_doc_DATA += examples/kea4/classify.json
nobase_dist_doc_DATA += examples/kea4/classify2.json
nobase_dist_doc_DATA += examples/kea4/dhcpv4-over-dhcpv6.json
nobase_dist_doc_DATA += examples/kea4/hooks.json
nobase_dist_doc_DATA += examples/kea4/leases-expiration.json
......@@ -33,6 +34,7 @@ nobase_dist_doc_DATA += examples/kea6/advanced.json
nobase_dist_doc_DATA += examples/kea6/backends.json
nobase_dist_doc_DATA += examples/kea6/cassandra.json
nobase_dist_doc_DATA += examples/kea6/classify.json
nobase_dist_doc_DATA += examples/kea6/classify2.json
nobase_dist_doc_DATA += examples/kea6/dhcpv4-over-dhcpv6.json
nobase_dist_doc_DATA += examples/kea6/duid.json
nobase_dist_doc_DATA += examples/kea6/hooks.json
......
// This is an example configuration file for the DHCPv4 server in Kea.
// The purpose of this example is to showcase how clients can be classified
// with advanced features.
{ "Dhcp4": {
// Kea is told to listen on ethX interface only.
"interfaces-config": {
"interfaces": [ "ethX" ]
},
// Let's use the simplest backend: memfile and use some reasonable values
// for timers. They are of no concern for the classification demonstration.
"lease-database": { "type": "memfile" },
"renew-timer": 1000,
"rebind-timer": 2000,
"valid-lifetime": 4000,
// This list defines several classes that incoming packets can be assigned to.
// One packet can belong to zero or more classes.
"client-classes": [
// This class is required by the second subnet and is evaluated only
// if it is required. The test expression returns true.
// Note it is not possible to depend on VoIP class because it is not yet
// defined.
{
"name": "second_subnet",
"only-if-required": true,
"test": "member('ALL')",
"option-data": [{
"name": "domain-name-servers",
"data": "127.0.0.1"
}]
},
// Let's classify all incoming DISCOVER (message type 1) to a separate
// class.
{
"name": "discovers",
"test": "pkt4.msgtype == 1"
},
// Clients are supposed to set the transaction-id field to a random value.
// Clients that send it with 0 are most likely broken. Let's mark them
// as such.
{
"name": "broken",
"test": "pkt4.transid == 0"
},
// Let's pick VoIP phones. Those that send their class identifiers
// as Aastra, should belong to VoIP class. For a list of all options,
// see www.iana.org/assignments/bootp-dhcp-parameters/.
// In this particular class, we want to set specific values
// of certain DHCPv4 fields. If the incoming packet matches the
// test, those fields will be set in outgoing responses.
// The option 43 is defined to encapsulate suboption in the aastra space.
{
"name": "VoIP",
"test": "substring(option[60].hex,0,6) == 'Aastra'",
"next-server": "192.0.2.254",
"server-hostname": "hal9000",
"boot-file-name": "/dev/null",
"option-def": [ {
"name": "vendor-encapsulated-options",
"code": 43,
"type": "empty",
"encapsulate": "aastra" } ]
},
// Both a VoIP phone (by evaluation or host reservation) and has a host
// reservation.
{
"name": "VoIP_host",
"test": "member('VoIP') and member('KNOWN')",
"server-hostname": "hal9001"
}
],
// The following list defines subnets. For some subnets we defined
// a class that is allowed in that subnet. If not specified,
// everyone is allowed. When a class is specified, only packets belonging
// to that class are allowed for that subnet.
"subnet4": [
{
// This one is for VoIP devices only.
"pools": [ { "pool": "192.0.2.1 - 192.0.2.200" } ],
"subnet": "192.0.2.0/24",
"client-class": "VoIP",
"interface": "ethX"
},
// This one doesn't have any client-class specified, so everyone
// is allowed in. The normal subnet selection rules still apply,
// though. There is also a static class reservation for a client
// using MAC address 1a:1b:1c:1d:1e:1f. This client will always
// be assigned to this class.
{
"pools": [ { "pool": "192.0.3.1 - 192.0.3.200" } ],
"subnet": "192.0.3.0/24",
"reservations": [
{
"hw-address": "1a:1b:1c:1d:1e:1f",
"client-classes": [ "VoIP" ]
} ],
"interface": "ethX"
},
// The following list defines a subnet with pools. For some pools
// we defined a class that is allowed in that pool. If not specified
// everyone is allowed. When a class is specified, only packets belonging
// to that class are allowed for that pool.
{
"pools": [
{
// This one is for VoIP devices only.
"pool": "192.0.4.1 - 192.0.4.200",
"client-class": "VoIP"
},
// This one doesn't have any client-class specified, so everyone
// is allowed in.
{
"pool": "192.0.5.1 - 192.0.5.200"
} ],
"subnet": "192.0.4.0/23",
"interface": "ethY"
}
]
},
// The following configures logging. It assumes that messages with at
// least informational level (info, warn, error and fatal) should be
// logged to stdout.
"Logging": {
"loggers": [
{
"name": "kea-dhcp4",
"output_options": [
{
"output": "stdout"
}
],
"severity": "INFO"
}
]
}
}
// This is an example configuration file for the DHCPv4 server in Kea.
// The purpose of this example is to showcase how clients can be classified.
{ "Dhcp6":
{
// Kea is told to listen on ethX interface only.
"interfaces-config": {
"interfaces": [ "ethX" ]
},
// Let's use the simplest backend: memfile and use some reasonable values
// for timers. They are of no concern for the classification demonstration.
"lease-database": {
"type": "memfile",
"lfc-interval": 3600
},
"renew-timer": 1000,
"rebind-timer": 2000,
"preferred-lifetime": 3000,
"valid-lifetime": 4000,
// This list defines several classes that incoming packets can be assigned to.
// One packet can belong to zero or more classes.
"client-classes": [
// This class is required by the second subnet and is evaluated only
// if it is required. The test expression returns true.
// Note it is not possible to depend on cable-modems class because it
// is not yet defined.
{
"name": "second_subnet",
"only-if-required": true,
"test": "member('ALL')",
"option-data": [{
"name": "dns-servers",
"data": "2001:db8::1"
}]
},
// Let's classify all incoming RENEW (message type 5) to a separate
// class.
{
"name": "renews",
"test": "pkt6.msgtype == 5"
},
// Let's pick cable modems. In this simple example we'll assume the device
// is a cable modem if it sends a vendor option with enterprise-id equal
// to 4491.
{
"name": "cable-modems",
"test": "vendor.enterprise == 4491"
},
// Both a cable modem (by evaluation or host reservation) and has a host
// reservation.
{
"name": "cable-modem-hosts",
"test": "member('cable-modems') and member('KNOWN')"
}
],
// The following list defines subnets. Each subnet consists of at
// least subnet and pool entries.
"subnet6": [
{
"pools": [ { "pool": "2001:db8:1::/80" } ],
"subnet": "2001:db8:1::/64",
"client-class": "cable-modems",
"interface": "ethX"
},
// The following subnet contains a class reservation for a client using
// DUID 01:02:03:04:05:0A:0B:0C:0D:0E. This client will always be assigned
// to this class.
{
"pools": [ { "pool": "2001:db8:2::/80" } ],
"subnet": "2001:db8:2::/64",
"reservations": [
{
"duid": "01:02:03:04:05:0A:0B:0C:0D:0E",
"client-classes": [ "cable-modems" ]
} ],
"interface": "ethX"
},
// The following subnet contains a pool with a class constraint: only
// clients which belong to the class are allowed to use this pool.
{
"pools": [
{
"pool": "2001:db8:3::/80",
"client-class": "cable-modems"
} ],
"subnet": "2001:db8:4::/64",
"interface": "ethY"
}
]
},
// The following configures logging. It assumes that messages with at
// least informational level (info, warn, error and fatal) should be
// logged to stdout.
"Logging": {
"loggers": [
{
"name": "kea-dhcp6",
"output_options": [
{
"output": "stdout"
}
],
"debuglevel": 0,
"severity": "INFO"
}
]
}
}
......@@ -131,8 +131,10 @@
<note>
<para>
Beginning with 1.4 client classes follow now the insertion order
(vs. alphabetical order in previous versions).
Beginning with Kea 1.4.0 release, client classes follow the order
in which they are specified in the configuration
(vs. alphabetical order in previous versions), or for required
classes the order they are required.
</para>
</note>
......@@ -184,6 +186,14 @@
belongs to, and the KNOWN class. By convention builtin classes
names begin with all caps.
</para>
<para>Currently recognized builtin class names are ALL and KNOWN
and prefixes VENDOR_CLASS_, AFTER_ and EXTERNAL_. The AFTER_ prefix
is a provision for a not yet written hook, the EXTERNAL_ prefix
can be freely used: builtin classes are implicitly defined so
never raise warnings because they do not appear in the configuration.
</para>
</section>
<section id="classification-using-expressions">
......@@ -788,11 +798,11 @@ concatenation of the strings</entry></row>
subnet, shared-network or pools are known but output option
processing not yet done. The only-if-required flag, false by default,
allows to perform the evaluation of the test expression only
when it was required, i.e. in a required-client-classes list.
when it was required, i.e. in a require-client-classes list.
</para>
<para>
The required-client-classes list which is valid for shared-network,
The require-client-classes list which is valid for shared-network,
subnet and pool scope specifies the classes which are evaluated
in the second pass before output option processing.
The list is built in the reversed precedence order of option
......
......@@ -2064,8 +2064,9 @@ It is merely echoed by the server
the DHCP message processing, including the assignment of leases from different
pools, the assignment of different options (or different values of the same
options) etc. In the current release of the software however, there are
only three mechanisms that take advantage of client classification:
subnet selection, assignment of different options, and, for cable modems, there
only some mechanisms that take advantage of client classification:
private options and option 43 deferred unpacking, subnet selection,
pool selection, assignment of different options, and, for cable modems, there
are specific options for use with the TFTP server address and the boot file field.
</para>
......@@ -2091,19 +2092,24 @@ It is merely echoed by the server
</para>
<para>
The process of doing classification is conducted in five steps. The first step
The process of doing classification is conducted in several steps. The first step
is to assess an incoming packet and assign it to zero or more classes. The
second step is to choose a subnet, possibly based on the class information.
The third step is to assign classes from host reservations.
The forth step is to build the list of required classes and perform
the evaluation for each class of the list.
The third step is to assign classes from host reservations and
evaluate class expressions depending on the "KNOWN" class.
After the list of required classes is built and each class of the list
has its expression evaluated: when it returns true the packet is added
as a member of the class.
The last step is to assign options, again possibly based on the class
information.
More complete and detailed description is available in
<xref linkend="classify"/>.
</para>
<para>
There are two methods of doing classification. The first is automatic and relies
on examining the values in the vendor class options. Information from these
There are two main methods of doing classification. The first is automatic and relies
on examining the values in the vendor class options or existence of a
host reservation. Information from these
options is extracted and a class name is constructed from it and added to
the class list for the packet. The second allows you to specify an expression
that is evaluated for each packet. If the result is true the packet is
......@@ -2155,11 +2161,12 @@ It is merely echoed by the server
<para>
If there are multiple classes defined and an incoming packet is matched
to multiple classes, the class which is defined first is used.
to multiple classes, the class which is evaluated first is used.
</para>
<note><para>
In versions before 1.4 the alphabetical order was used.
In Kea versions prior to 1.4.0 the alphabetical order of class names was used.
Starting from Kea 1.4.0 the classes are ordered as specified in the configuration.
</para></note>
</section>
......@@ -2260,13 +2267,15 @@ It is merely echoed by the server
The first one is the per-class <command>only-if-required</command>
flag which is false by default. When it is set to
<command>true</command> the test expression of the class is not
evaluated at the reception of a new incoming ticket.
evaluated at the reception of a new incoming ticket but
later and only if the class evaluation is required.
</para>
<para>
The second is the <command>required-client-classes</command> which
The second is the <command>require-client-classes</command> which
takes a list of class names and is valid in shared-network,
subnet and pool scope. Classes in these lists are evaluated
subnet and pool scope. Classes in these lists are marked as
required and evaluated
after resource assignment and before output option processing.
</para>
......@@ -2279,7 +2288,7 @@ It is merely echoed by the server
"client-classes": [
{<userinput>
"name": "Client_foo",
"test": "'' == ''",
"test": "member('ALL')",
"only-if-required": true</userinput>
},
...
......@@ -2288,7 +2297,7 @@ It is merely echoed by the server
{
"subnet": "192.0.2.0/24",
"pools": [ { "pool": "192.0.2.10 - 192.0.2.20" } ],
<userinput>"required-client-classes": [ "Client_foo" ],</userinput>
<userinput>"require-client-classes": [ "Client_foo" ],</userinput>
...
},
...
......@@ -2296,6 +2305,23 @@ It is merely echoed by the server
...
}</screen>
</para>
<para>
Required evaluation can be used to express complex dependencies
including for instance subnet membership, and to reverse the
precedence: if you set an option-data in a subnet it takes
precedence over an option-data in a class. When you move the
option-data to a (only-if) required class and require it in
the subnet a class evaluted or set before takes precedence.
</para>
<para>
Required evaluation is also available at shared-network and
pool levels. The order required classes are considered is
shared-network, subnet and pool, i.e. the opposite order
option-data are processed.
</para>
</section>
</section>
......@@ -3392,7 +3418,7 @@ It is merely echoed by the server
to configure the server to assign classes to a client based on the content
of the options that this client sends to the server. Host reservations
mechanisms also allow for statically assigning classes to the clients.
The definitions of these classes must exist in the Kea
The definitions of these classes should exist in the Kea
configuration. The following configuration snippet shows how to specify
that a client belongs to classes <command>reserved-class1</command>
and <command>reserved-class2</command>. Those classes are associated with
......@@ -3438,7 +3464,18 @@ It is merely echoed by the server
</screen>
<para>Static class assignments, as shown above, can be used in conjunction
with classification using expressions.</para>
with classification using expressions. The "KNOWN" builtin class is
added to the packet and any class depending on it directly or indirectly
and not only-if-required is evaluted.
</para>
<note>
<para>If you want to force the evaluation of a class expression after
the host reservation lookup, for instance because of a dependency on
"reserved-class1" from the previous example, you should add a
"member('KNOWN')" in the expression.</para>
</note>
</section>
<section id="reservations4-mysql-pgsql">
......
......@@ -1924,8 +1924,8 @@ should include options from the isc option space:
the DHCP message processing, including the assignment of leases from different
pools, the assignment of different options (or different values of the same
options) etc. In the current release of the software however, there are
only two mechanisms that take advantage of client classification:
subnet selection and assignment of different options.
only some mechanisms that take advantage of client classification:
subnet selection, pool selection, and assignment of different options.
</para>
<para>
......@@ -1951,19 +1951,24 @@ should include options from the isc option space:
</para>
<para>
The process of doing classification is conducted in five steps. The first step
The process of doing classification is conducted in several steps. The first step
is to assess an incoming packet and assign it to zero or more classes. The
second step is to choose a subnet, possibly based on the class information.
The third step is to assign classes from host reservations.
The forth step is to build the list of required classes and perform
the evaluation for each class of the list.
The third step is to assign classes from host reservations and
evaluate class expressions depending on the "KNOWN" class.
After the list of required classes is built and each class of the list
has its expression evaluated: when it returns true the packet is added
as a member of the class.
The last step is to assign options again possibly based on the class
information.
More complete and detailed description is available in
<xref linkend="classify"/>.
</para>
<para>
There are two methods of doing classification. The first is automatic and relies
on examining the values in the vendor class options. Information from these
There are two main methods of doing classification. The first is automatic and relies
on examining the values in the vendor class options or existence of a
host reservation. Information from these
options is extracted and a class name is constructed from it and added to
the class list for the packet. The second allows you to specify an expression
that is evaluated for each packet. If the result is true the packet is
......@@ -2053,13 +2058,15 @@ should include options from the isc option space:
The first one is the per-class <command>only-if-required</command>
flag which is false by default. When it is set to
<command>true</command> the test expression of the class is not
evaluated at the reception of a new incoming ticket.
evaluated at the reception of a new incoming ticket but
later and only if the class evaluation is required.
</para>
<para>
The second is the <command>required-client-classes</command> which
The second is the <command>require-client-classes</command> which
takes a list of class names and is valid in shared-network,
subnet and pool scope. Classes in these lists are evaluated
subnet and pool scope. Classes in these lists are marked as
required and evaluated
after resource assignment and before output option processing.
</para>
......@@ -2072,7 +2079,7 @@ should include options from the isc option space:
"client-classes": [
{<userinput>
"name": "Client_foo",
"test": "'' == ''",
"test": "member('ALL')",
"only-if-required": true</userinput>
},
...
......@@ -2085,7 +2092,7 @@ should include options from the isc option space:
"pool": "2001:db8:1::-2001:db8:1::ffff"
}
],
<userinput>"required-client-classes": [ "Client_foo" ],</userinput>
<userinput>"require-client-classes": [ "Client_foo" ],</userinput>
...
},
...
......@@ -2093,6 +2100,23 @@ should include options from the isc option space:
...
}</screen>
</para>
<para>
Required evaluation can be used to express complex dependencies
including for instance subnet membership, and to reverse the
precedence: if you set an option-data in a subnet it takes
precedence over an option-data in a class. When you move the
option-data to a (only-if) required class and require it in
the subnet a class evaluted or set before takes precedence.
</para>
<para>
Required evaluation is also available at shared-network and
pool/pd-pool levels. The order required classes are considered is
shared-network, subnet and (pd-)pool, i.e. the opposite order
option-data are processed.
</para>
</section>
</section>
......@@ -2960,7 +2984,18 @@ should include options from the isc option space:
</screen>
<para>Static class assignments, as shown above, can be used in conjunction
with classification using expressions.</para>
with classification using expressions. The "KNOWN" builtin class is
added to the packet and any class depending on it directly or indirectly
and not only-if-required is evaluted.
</para>
<note>
<para>If you want to force the evaluation of a class expression after
the host reservation lookup, for instance because of a dependency on
"reserved-class1" from the previous example, you should add a
"member('KNOWN')" in the expression.</para>
</note>
</section>
<section id="reservations6-mysql-pgsql">
......
......@@ -795,14 +795,14 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
}
}
\"required-client-classes\" {
\"require-client-classes\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::SUBNET4:
case isc::dhcp::Parser4Context::POOLS:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
return isc::dhcp::Dhcp4Parser::make_REQUIRED_CLIENT_CLASSES(driver.loc_);
return isc::dhcp::Dhcp4Parser::make_REQUIRE_CLIENT_CLASSES(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("required-client-classes", driver.loc_);
return isc::dhcp::Dhcp4Parser::make_STRING("require-client-classes", driver.loc_);