Commit 641bcbad authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[5514] Revert "[5191] Remove experimental lightweight 4over6 option"

This reverts commit 401a5a52.

# Conflicts:
#	doc/guide/dhcp6-srv.xml
#	src/lib/dhcp/dhcp6.h
#	src/lib/dhcp/std_option_defs.h
#	src/lib/dhcp/tests/
parent 5a6665f2
......@@ -1315,6 +1315,14 @@ temporarily override a list of interface names and listen on all interfaces.
<!-- <row><entry>dhcpv4-message</entry><entry>87</entry><entry>hex</entry><entry>false</entry></row> -->
<row><entry>s46-rule</entry><entry>89</entry><entry>record (uint8, uint8, uint8, ipv4-address, ipv6-prefix)</entry><entry>false</entry></row>
<row><entry>s46-v4v6bind</entry><entry>92</entry><entry>record (ipv4-address, ipv6-prefix)</entry><entry>false</entry></row>
<row><entry>s46-portparams</entry><entry>93</entry><entry>record(uint8, psid)</entry><entry>false</entry></row>
......@@ -1351,6 +1359,187 @@ temporarily override a list of interface names and listen on all interfaces.
<section id="s46-options">
<title>Common Softwire46 Options</title>
Softwire46 options are involved in IPv4 over IPv6 provisioning by
means of tunneling or translation as specified in the
<ulink url="">RFC 7598</ulink>.
The following sections provide configuration examples of these
<section id="s46-containers">
<title>Softwire46 Container Options</title>
S46 container options group rules and optional port parameters
for a specified domain. There are three container options specified
in the "dhcp6" (top level) option space: MAP-E Container option,
MAP-T Container option and S46 Lightweight 4over6 Container option.
These options only contain encapsulated options specified below.
They do not include any data fields.
In order to configure the server to send specific container option
along with all encapsulated options, the container option must be
included in the server configuration as shown below:
"Dhcp6": {
"option-data": [
"name": "s46-cont-mape"
} ],
This configuration will cause the server to include MAP-E Container
option to the client. Use "s46-cont-mapt" or "s46-cont-lw" for the
MAP-T Container and S46 Lightweight 4over6 Container options
All remaining softwire options described below are included in one
of the container options. Thus, they have to be included in appropriate
option spaces by selecting a "space" name, which specifies in which
option they are supposed to be included.
<title>S46 Rule Option</title>
The S46 Rule option is used for conveying the Basic Mapping Rule (BMR)
and Forwarding Mapping Rule (FMR).
"space": "s46-cont-mape-options",
"name": "s46-rule",
"data": "128, 0, 24,, 2001:db8:1::/64"
Other possible "space" value is "s46-cont-mapt-options".
The S46 Rule option conveys a number of parameters:
<simpara><command>flags</command>, an unsigned 8 bits integer, with
currently only the most significant bit specified. It denotes whether
the rule can be used for forwarding (128) or not (0).
<simpara><command>ea-len</command>, an 8 bits long Embedded Address length. Allowed values
range from 0 to 48.</simpara>
<simpara><command>IPv4 prefix length</command>, 8 bits long; expresses the prefix length of the
Rule IPv4 prefix specified in the ipv4-prefix field. Allowed
values range from 0 to 32.</simpara>
<simpara><command>IPv4 prefix</command>, a fixed-length 32-bit field that specifies the IPv4
prefix for the S46 rule. The bits in the prefix after prefix4-len
number of bits are reserved and MUST be initialized to zero by the
sender and ignored by the receiver.</simpara>
<simpara><command>IPv6 prefix</command> in prefix/length notation that specifies the IPv6 domain
prefix for the S46 rule. The field is padded on the right with zero
bits up to the nearest octet boundary when prefix6-len is not evenly
divisible by 8.</simpara>
<title>S46 BR Option</title>
The S46 BR option is used to convey the IPv6 address of the
Border Relay. This option is mandatory in the MAP-E
Container option and not permitted in the MAP-T and
S46 Lightweight 4over6 Container options.
"space": "s46-cont-mape-options",
"name": "s46-br",
"data": "2001:db8:cafe::1",
Other possible "space" value is "s46-cont-lw-options".
<title>S46 DMR Option</title>
The S46 DMR option is used to convey values for the Default
Mapping Rule (DMR). This option is mandatory in the MAP-T
container option and not permitted in the MAP-E and S46
Lightweight 4over6 Container options.
"space": "s46-cont-mapt-options",
"name": "s46-dmr",
"data": "2001:db8:cafe::/64",
This option must not be included in other containers.
<title>S46 IPv4/IPv6 Address Binding option.</title>
The S46 IPv4/IPv6 Address Binding option may be used to specify
the full or shared IPv4 address of the Customer Edge (CE).
The IPv6 prefix field is used by the CE to identify the
correct prefix to use for the tunnel source.
"space": "s46-cont-lw",
"name": "s46-v4v6bind",
"data": ", 2001:db8:1:cafe::/64"
This option must not be included in other containers.
<title>S46 Port Parameters</title>
The S46 Port Parameters option specifies optional port set
information that MAY be provided to CEs
"space": "s46-rule-options",
"name": "s46-portparams",
"data": "2, 3/4",
Other possible "space" value is "s46-v4v6bind" to include
this option in the S46 IPv4/IPv6 Address Binding option.
Note that the second value in the example above specifies the
PSID and PSID length fields in the format of PSID/PSID length.
This is equivalent to the values of PSID-len=4 and
PSID=12288 conveyed in the S46 Port Parameters option.
<section id="dhcp6-custom-options">
<title>Custom DHCPv6 Options</title>
<para>It is possible to define options in addition to the standard ones.
......@@ -4609,18 +4798,20 @@ autogenerated IDs are not stable across configuration changes.
Let's consider an example where certain parameters are supposed
to be delivered to clients in form of additional options,
and the values of those options are correlated to delegated
prefixes. It seems reasonable to keep those parameters with
the the definition of the PD pool. On the other hand, this
functionality is is not part of the base Kea code so Kea will
not understand any hook-specific keywords in that definition.
The solution to this problem is to use user context. For
each PD pool that is expected to be used with this feature,
a "user context" is defined. This is a structure that holds the
parameters used by the hook library when it is loaded.
An example configuration could look as follows:
Let's consider a lightweight 4over6 deployment as an example. It is an
IPv6 transition technology that allows mapping IPv6 prefix into full
or parts of IPv4 addresses. In DHCP context, these are certain
parameters that are supposed to be delivered to clients in form of
additional options. Values of those options are correlated to
delegated prefixes, so it is reasonable to keep those parameters
together with the PD pool. On the other hand, lightweight 4over6 is
not a commonly used feature, so it is not a part of the base Kea
code. The solution to this problem is to use user context. For each PD
pool that is expected to be used for lightweight 4over6, user context
with extra parameters is defined. Those extra parameters will be used
by hook library that would be loaded only when dynamic calculation of
the lightweight 4over6 option is actually needed. An example
configuration looks as follows:
"Dhcp6": {
"subnet6": [ {
......@@ -4634,7 +4825,11 @@ autogenerated IDs are not stable across configuration changes.
<userinput>"user-context": {
"threshold-percent": 85,
"v4-network": "",
"v4-overflow": ""
"v4-overflow": "",
"lw4over6-sharing-ratio": 64,
"lw4over6-v4-pool": "",
"lw4over6-sysports-exclude": true,
"lw4over6-bind-prefix-len": 56
} ],
"subnet": "2001:db8::/32",
......@@ -4736,6 +4931,13 @@ autogenerated IDs are not stable across configuration changes.
7550</ulink>: All recommendations related to the DHCPv6 server
operation are supported.</simpara>
<simpara><emphasis>DHCPv6 Options for Configuration of Softwire
Address and Port-Mapped Clients</emphasis>,
<ulink url="">RFC
7598</ulink>: All options specified in this specification are
supported by the DHCPv6 server.</simpara>
......@@ -106,14 +106,14 @@ enum DHCPv6OptionType {
// D6O_V6_PCP_SERVER = 86, /* RFC7291 */
D6O_DHCPV4_MSG = 87, /* RFC7341 */
D6O_DHCPV4_O_DHCPV6_SERVER = 88, /* RFC7341 */
// D6O_S46_RULE = 89, /* RFC7598 */
// D6O_S46_BR = 90, /* RFC7598 */
// D6O_S46_DMR = 91, /* RFC7598 */
// D6O_S46_V4V6BIND = 92, /* RFC7598 */
// D6O_S46_PORTPARAMS = 93, /* RFC7598 */
// D6O_S46_CONT_MAPE = 94, /* RFC7598 */
// D6O_S46_CONT_MAPT = 95, /* RFC7598 */
// D6O_S46_CONT_LW = 96, /* RFC7598 */
D6O_S46_RULE = 89, /* RFC7598 */
D6O_S46_BR = 90, /* RFC7598 */
D6O_S46_DMR = 91, /* RFC7598 */
D6O_S46_V4V6BIND = 92, /* RFC7598 */
D6O_S46_PORTPARAMS = 93, /* RFC7598 */
D6O_S46_CONT_MAPE = 94, /* RFC7598 */
D6O_S46_CONT_MAPT = 95, /* RFC7598 */
D6O_S46_CONT_LW = 96, /* RFC7598 */
// D6O_4RD = 97, /* RFC7600 */
// D6O_4RD_MAP_RULE = 98, /* RFC7600 */
// D6O_4RD_NON_MAP_RULE = 99, /* RFC7600 */
......@@ -454,6 +454,12 @@ const OptionDefParams STANDARD_V6_OPTION_DEFINITIONS[] = {
{ "timestamp", D6O_TIMESTAMP, OPT_BINARY_TYPE, false,
{ "s46-cont-mape", D6O_S46_CONT_MAPE, OPT_EMPTY_TYPE, false, NO_RECORD_DEF,
{ "s46-cont-mapt", D6O_S46_CONT_MAPT, OPT_EMPTY_TYPE, false, NO_RECORD_DEF,
{ "s46-cont-lw", D6O_S46_CONT_LW, OPT_EMPTY_TYPE, false, NO_RECORD_DEF,
// @todo There is still a bunch of options for which we have to provide
// definitions but we don't do it because they are not really
......@@ -465,6 +471,14 @@ const int STANDARD_V6_OPTION_DEFINITIONS_SIZE =
// Option definitions that belong to two or more option spaces are defined here.
const OptionDefParams OPTION_DEF_PARAMS_S46_BR = { "s46-br", D6O_S46_BR,
const OptionDefParams OPTION_DEF_PARAMS_S46_RULE = { "s46-rule", D6O_S46_RULE,
const OptionDefParams OPTION_DEF_PARAMS_S46_PORTPARAMS = { "s46-portparams",
/// @brief Definitions of vendor-specific DHCPv6 options, defined by ISC.
/// 4o6-* options are used for inter-process communication. For details, see
......@@ -484,43 +498,52 @@ const int ISC_V6_OPTION_DEFINITIONS_SIZE =
/// @brief MAPE option definitions
const OptionDefParams MAPE_V6_OPTION_DEFINITIONS[] = {
sizeof(const OptionDefParams);
/// @brief MAPT option definitions
const OptionDefParams MAPT_V6_OPTION_DEFINITIONS[] = {
{ "s46-dmr", D6O_S46_DMR, OPT_IPV6_PREFIX_TYPE, false, NO_RECORD_DEF, "" }
sizeof(const OptionDefParams);
/// @brief LW option definitions
const OptionDefParams LW_V6_OPTION_DEFINITIONS[] = {
{ "s46-v4v6bind", D6O_S46_V4V6BIND, OPT_RECORD_TYPE, false,
sizeof(const OptionDefParams);
/// @brief Rule option definitions
const OptionDefParams V4V6_RULE_OPTION_DEFINITIONS[] = {
sizeof(const OptionDefParams);
/// @brief Bind option definitions
const OptionDefParams V4V6_BIND_OPTION_DEFINITIONS[] = {
sizeof(const OptionDefParams);
} // unnamed namespace
......@@ -1750,6 +1750,33 @@ TEST_F(LibDhcpTest, stdOptionDefs6) {
LibDhcpTest::testStdOptionDefs6(D6O_TIMESTAMP, begin, begin + 8,
// RFC7598 options
LibDhcpTest::testOptionDefs6(MAPE_V6_OPTION_SPACE, D6O_S46_RULE, begin, end,
typeid(OptionCustom), "s46-rule-options");
LibDhcpTest::testOptionDefs6(MAPT_V6_OPTION_SPACE, D6O_S46_RULE, begin, end,
typeid(OptionCustom), "s46-rule-options");
LibDhcpTest::testOptionDefs6(MAPE_V6_OPTION_SPACE, D6O_S46_BR, begin, end,
LibDhcpTest::testOptionDefs6(LW_V6_OPTION_SPACE, D6O_S46_BR, begin, end,
LibDhcpTest::testOptionDefs6(MAPT_V6_OPTION_SPACE, D6O_S46_DMR, begin, end,
LibDhcpTest::testOptionDefs6(LW_V6_OPTION_SPACE, D6O_S46_V4V6BIND, begin,
end, typeid(OptionCustom),
LibDhcpTest::testOptionDefs6(V4V6_RULE_OPTION_SPACE, D6O_S46_PORTPARAMS,
begin, end, typeid(OptionCustom), "");
LibDhcpTest::testStdOptionDefs6(D6O_S46_CONT_MAPE, begin, end,
LibDhcpTest::testStdOptionDefs6(D6O_S46_CONT_MAPT, begin, end,
LibDhcpTest::testStdOptionDefs6(D6O_S46_CONT_LW, begin, end,
// This test checks if the DHCPv6 option definition can be searched by
......@@ -937,6 +937,56 @@ TEST_F(ParseConfigTest, optionDataCSVFormatWithOptionDef) {
cfg2.runCfgOptionsTest(family_, config);
// This test verifies that definitions of standard encapsulated
// options can be used.
TEST_F(ParseConfigTest, encapsulatedOptionData) {
std::string config =
"{ \"option-data\": [ {"
" \"space\": \"s46-cont-mape-options\","
" \"name\": \"s46-rule\","
" \"data\": \"1, 0, 24,, 2001:db8:1::/64\""
" } ]"
// Make sure that we're using correct universe.
family_ = AF_INET6;
int rcode = 0;
ASSERT_NO_THROW(rcode = parseConfiguration(config));
ASSERT_EQ(0, rcode);
// Verify that the option data is correct.
OptionCustomPtr s46_rule = boost::dynamic_pointer_cast<OptionCustom>
(getOptionPtr(MAPE_V6_OPTION_SPACE, D6O_S46_RULE));
uint8_t flags;
uint8_t ea_len;
uint8_t prefix4_len;
IOAddress ipv4_prefix(IOAddress::IPV4_ZERO_ADDRESS());
PrefixTuple ipv6_prefix(PrefixLen(0), IOAddress::IPV6_ZERO_ADDRESS());;
flags = s46_rule->readInteger<uint8_t>(0);
ea_len = s46_rule->readInteger<uint8_t>(1);
prefix4_len = s46_rule->readInteger<uint8_t>(2);
ipv4_prefix = s46_rule->readAddress(3);
ipv6_prefix = s46_rule->readPrefix(4);
EXPECT_EQ(1, flags);
EXPECT_EQ(0, ea_len);
EXPECT_EQ(24, prefix4_len);
EXPECT_EQ("", ipv4_prefix.toText());
EXPECT_EQ(64, ipv6_prefix.first.asUnsigned());
EXPECT_EQ("2001:db8:1::", ipv6_prefix.second.toText());
ElementPtr expected = Element::fromJSON(config);
ElementPtr opt_data = expected->get("option-data")->getNonConst(0);
opt_data->set("code", Element::create(D6O_S46_RULE));
CfgOptionsTest cfg(CfgMgr::instance().getStagingCfg());
cfg.runCfgOptionsTest(family_, expected);
// This test checks behavior of the configuration parser for option data
// for different values of csv-format parameter and when there is no
// option definition.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment