]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[5514] Revert "[5191] Remove experimental lightweight 4over6 option"
authorTomek Mrugalski <tomasz@isc.org>
Thu, 25 Jan 2018 14:59:32 +0000 (15:59 +0100)
committerTomek Mrugalski <tomasz@isc.org>
Thu, 25 Jan 2018 14:59:32 +0000 (15:59 +0100)
This reverts commit 401a5a52077789088e48047d2ee4c67c37a07894.

# Conflicts:
# doc/guide/dhcp6-srv.xml
# src/lib/dhcp/dhcp6.h
# src/lib/dhcp/std_option_defs.h
# src/lib/dhcp/tests/libdhcp++_unittest.cc

doc/guide/dhcp6-srv.xml
src/lib/dhcp/dhcp6.h
src/lib/dhcp/std_option_defs.h
src/lib/dhcp/tests/libdhcp++_unittest.cc
src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc

index f0b96148c747ffc2205bd0652fcaa283d70df0db..c5c7851442ca45acb9b9f9844b25ac9e7d4ee133 100644 (file)
@@ -1315,6 +1315,14 @@ temporarily override a list of interface names and listen on all interfaces.
 <row><entry>inf-max-rt</entry><entry>83</entry><entry>uint32</entry><entry>false</entry></row>
 <!-- <row><entry>dhcpv4-message</entry><entry>87</entry><entry>hex</entry><entry>false</entry></row> -->
 <row><entry>dhcp4o6-server-addr</entry><entry>88</entry><entry>ipv6-address</entry><entry>true</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-br</entry><entry>90</entry><entry>ipv6-address</entry><entry>false</entry></row>
+<row><entry>s46-dmr</entry><entry>91</entry><entry>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>
+<row><entry>s46-cont-mape</entry><entry>94</entry><entry>empty</entry><entry>false</entry></row>
+<row><entry>s46-cont-mapt</entry><entry>95</entry><entry>empty</entry><entry>false</entry></row>
+<row><entry>s46-cont-lw</entry><entry>96</entry><entry>empty</entry><entry>false</entry></row>
 <row><entry>v6-captive-portal</entry><entry>103</entry><entry>string</entry><entry>false</entry></row>
 <row><entry>ipv6-address-andsf</entry><entry>143</entry><entry>ipv6-address</entry><entry>true</entry></row>
         </tbody>
@@ -1351,6 +1359,187 @@ temporarily override a list of interface names and listen on all interfaces.
     </para>
     </section>
 
+    <section id="s46-options">
+      <title>Common Softwire46 Options</title>
+      <para>
+        Softwire46 options are involved in IPv4 over IPv6 provisioning by
+        means of tunneling or translation as specified in the
+        <ulink url="http://tools.ietf.org/html/rfc7598">RFC 7598</ulink>.
+        The following sections provide configuration examples of these
+        options.
+      </para>
+
+      <section id="s46-containers">
+      <title>Softwire46 Container Options</title>
+      <para>
+        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.
+      </para>
+
+      <para>
+        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:
+<screen>
+"Dhcp6": {
+    ...
+    "option-data": [
+        {
+            "name": "s46-cont-mape"
+        } ],
+    ...
+}
+</screen>
+
+        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
+        respectively.
+      </para>
+
+      <para>
+        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.
+      </para>
+    </section>
+
+      <section>
+        <title>S46 Rule Option</title>
+        <para>
+          The S46 Rule option is used for conveying the Basic Mapping Rule (BMR)
+          and Forwarding Mapping Rule (FMR).
+<screen>
+{
+    "space": "s46-cont-mape-options",
+    "name": "s46-rule",
+    "data": "128, 0, 24, 192.0.2.0, 2001:db8:1::/64"
+}
+</screen>
+         Other possible "space" value is "s46-cont-mapt-options".
+        </para>
+
+        <para>
+          The S46 Rule option conveys a number of parameters:
+
+      <itemizedlist>
+        <listitem>
+          <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>
+        </listitem>
+
+        <listitem>
+          <simpara><command>ea-len</command>, an 8 bits long Embedded Address length. Allowed values
+          range from 0 to 48.</simpara>
+        </listitem>
+
+        <listitem>
+          <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>
+        </listitem>
+
+        <listitem>
+          <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>
+        </listitem>
+
+        <listitem>
+          <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>
+        </listitem>
+
+      </itemizedlist>
+        </para>
+      </section>
+        <section>
+            <title>S46 BR Option</title>
+            <para>
+              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.
+<screen>
+{
+    "space": "s46-cont-mape-options",
+    "name": "s46-br",
+    "data": "2001:db8:cafe::1",
+}
+</screen>
+           Other possible "space" value is "s46-cont-lw-options".
+          </para>
+        </section>
+
+        <section>
+            <title>S46 DMR Option</title>
+            <para>
+              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.
+<screen>
+{
+    "space": "s46-cont-mapt-options",
+    "name": "s46-dmr",
+    "data": "2001:db8:cafe::/64",
+}
+</screen>
+              This option must not be included in other containers.
+            </para>
+        </section>
+
+        <section>
+            <title>S46 IPv4/IPv6 Address Binding option.</title>
+            <para>
+              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.
+<screen>
+{
+    "space": "s46-cont-lw",
+    "name": "s46-v4v6bind",
+    "data": "192.0.2.3, 2001:db8:1:cafe::/64"
+}
+</screen>
+            This option must not be included in other containers.
+          </para>
+        </section>
+        <section>
+            <title>S46 Port Parameters</title>
+            <para>
+              The S46 Port Parameters option specifies optional port set
+              information that MAY be provided to CEs
+<screen>
+{
+    "space": "s46-rule-options",
+    "name": "s46-portparams",
+    "data": "2, 3/4",
+}
+</screen>
+              Other possible "space" value is "s46-v4v6bind" to include
+              this option in the S46 IPv4/IPv6 Address Binding option.
+            </para>
+            <para>
+              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.
+            </para>
+        </section>
+    </section>
+
     <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.
         </para>
 
         <para>
-          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:
           <screen>
 "Dhcp6": {
     "subnet6": [ {
@@ -4634,7 +4825,11 @@ autogenerated IDs are not stable across configuration changes.
             <userinput>"user-context": {
                 "threshold-percent": 85,
                 "v4-network": "192.168.0.0/16",
-                "v4-overflow": "10.0.0.0/16"
+                "v4-overflow": "10.0.0.0/16",
+                "lw4over6-sharing-ratio": 64,
+                "lw4over6-v4-pool": "192.0.2.0/24",
+                "lw4over6-sysports-exclude": true,
+                "lw4over6-bind-prefix-len": 56
             }</userinput>
         } ],
         "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>
           </listitem>
+          <listitem>
+            <simpara><emphasis>DHCPv6 Options for Configuration of Softwire
+            Address and Port-Mapped Clients</emphasis>,
+            <ulink url="http://tools.ietf.org/html/rfc7598">RFC
+            7598</ulink>: All options specified in this specification are
+            supported by the DHCPv6 server.</simpara>
+          </listitem>
       </itemizedlist>
     </section>
 
index 5783b15e1de7f371ab4841cff343b7a7e15c630c..cf28ba2bb2c0f8aa4c0de804eb39ae69035f628f 100644 (file)
@@ -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 */
index 69cd4cc8b7dbd133510c5d994a020876b026e2c0..8b16b7316eee406b863e4ac2a728dec264a1f295 100644 (file)
@@ -454,6 +454,12 @@ const OptionDefParams STANDARD_V6_OPTION_DEFINITIONS[] = {
       RECORD_DEF(SIGNATURE_RECORDS), "" },
     { "timestamp", D6O_TIMESTAMP, OPT_BINARY_TYPE, false,
       NO_RECORD_DEF, "" },
+    { "s46-cont-mape", D6O_S46_CONT_MAPE, OPT_EMPTY_TYPE, false, NO_RECORD_DEF,
+        MAPE_V6_OPTION_SPACE },
+    { "s46-cont-mapt", D6O_S46_CONT_MAPT, OPT_EMPTY_TYPE, false, NO_RECORD_DEF,
+        MAPT_V6_OPTION_SPACE },
+    { "s46-cont-lw", D6O_S46_CONT_LW, OPT_EMPTY_TYPE, false, NO_RECORD_DEF,
+        LW_V6_OPTION_SPACE }
 
     // @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 =
     sizeof(STANDARD_V6_OPTION_DEFINITIONS) /
     sizeof(STANDARD_V6_OPTION_DEFINITIONS[0]);
 
+// 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,
+    OPT_IPV6_ADDRESS_TYPE, false, NO_RECORD_DEF, "" };
+const OptionDefParams OPTION_DEF_PARAMS_S46_RULE = { "s46-rule", D6O_S46_RULE,
+    OPT_RECORD_TYPE, false, RECORD_DEF(S46_RULE), V4V6_RULE_OPTION_SPACE };
+const OptionDefParams OPTION_DEF_PARAMS_S46_PORTPARAMS = { "s46-portparams",
+    D6O_S46_PORTPARAMS, OPT_RECORD_TYPE, false, RECORD_DEF(S46_PORTPARAMS), "" };
+
 /// @brief Definitions of vendor-specific DHCPv6 options, defined by ISC.
 /// 4o6-* options are used for inter-process communication. For details, see
 /// http://kea.isc.org/wiki/Dhcp4o6Design
@@ -484,43 +498,52 @@ const int ISC_V6_OPTION_DEFINITIONS_SIZE =
 
 /// @brief MAPE option definitions
 const OptionDefParams MAPE_V6_OPTION_DEFINITIONS[] = {
+    OPTION_DEF_PARAMS_S46_BR,
+    OPTION_DEF_PARAMS_S46_RULE
 };
 
 const int MAPE_V6_OPTION_DEFINITIONS_SIZE =
     sizeof(MAPE_V6_OPTION_DEFINITIONS) /
-    sizeof(const OptionDefParams);
+    sizeof(MAPE_V6_OPTION_DEFINITIONS[0]);
 
 /// @brief MAPT option definitions
 const OptionDefParams MAPT_V6_OPTION_DEFINITIONS[] = {
+    OPTION_DEF_PARAMS_S46_RULE,
+    { "s46-dmr", D6O_S46_DMR, OPT_IPV6_PREFIX_TYPE, false, NO_RECORD_DEF, "" }
 };
 
 const int MAPT_V6_OPTION_DEFINITIONS_SIZE =
     sizeof(MAPT_V6_OPTION_DEFINITIONS) /
-    sizeof(const OptionDefParams);
+    sizeof(MAPT_V6_OPTION_DEFINITIONS[0]);
 
 /// @brief LW option definitions
 const OptionDefParams LW_V6_OPTION_DEFINITIONS[] = {
+    OPTION_DEF_PARAMS_S46_BR,
+    { "s46-v4v6bind", D6O_S46_V4V6BIND, OPT_RECORD_TYPE, false,
+        RECORD_DEF(S46_V4V6BIND), V4V6_BIND_OPTION_SPACE }
 };
 
 const int LW_V6_OPTION_DEFINITIONS_SIZE =
     sizeof(LW_V6_OPTION_DEFINITIONS) /
-    sizeof(const OptionDefParams);
+    sizeof(LW_V6_OPTION_DEFINITIONS[0]);
 
 /// @brief Rule option definitions
 const OptionDefParams V4V6_RULE_OPTION_DEFINITIONS[] = {
+    OPTION_DEF_PARAMS_S46_PORTPARAMS
 };
 
 const int V4V6_RULE_OPTION_DEFINITIONS_SIZE =
     sizeof(V4V6_RULE_OPTION_DEFINITIONS) /
-    sizeof(const OptionDefParams);
+    sizeof(V4V6_RULE_OPTION_DEFINITIONS[0]);
 
 /// @brief Bind option definitions
 const OptionDefParams V4V6_BIND_OPTION_DEFINITIONS[] = {
+    OPTION_DEF_PARAMS_S46_PORTPARAMS
 };
 
 const int V4V6_BIND_OPTION_DEFINITIONS_SIZE =
     sizeof(V4V6_BIND_OPTION_DEFINITIONS) /
-    sizeof(const OptionDefParams);
+    sizeof(V4V6_BIND_OPTION_DEFINITIONS[0]);
 
 } // unnamed namespace
 
index fc0f38378613313bca2dd42826ad5b3517b3dbb5..8d257ac5c1f32a4d77d27debc633d2acb785233e 100644 (file)
@@ -1750,6 +1750,33 @@ TEST_F(LibDhcpTest, stdOptionDefs6) {
 
     LibDhcpTest::testStdOptionDefs6(D6O_TIMESTAMP, begin, begin + 8,
                                     typeid(Option));
+
+    // 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,
+                                 typeid(OptionCustom));
+    LibDhcpTest::testOptionDefs6(LW_V6_OPTION_SPACE, D6O_S46_BR, begin, end,
+                                 typeid(OptionCustom));
+    LibDhcpTest::testOptionDefs6(MAPT_V6_OPTION_SPACE, D6O_S46_DMR, begin, end,
+                                 typeid(OptionCustom));
+    LibDhcpTest::testOptionDefs6(LW_V6_OPTION_SPACE, D6O_S46_V4V6BIND, begin,
+                                 end, typeid(OptionCustom),
+                                 "s46-v4v6bind-options");
+    LibDhcpTest::testOptionDefs6(V4V6_RULE_OPTION_SPACE, D6O_S46_PORTPARAMS,
+                                 begin, end, typeid(OptionCustom), "");
+    LibDhcpTest::testStdOptionDefs6(D6O_S46_CONT_MAPE, begin, end,
+                                    typeid(OptionCustom),
+                                    "s46-cont-mape-options");
+    LibDhcpTest::testStdOptionDefs6(D6O_S46_CONT_MAPT, begin, end,
+                                    typeid(OptionCustom),
+                                    "s46-cont-mapt-options");
+    LibDhcpTest::testStdOptionDefs6(D6O_S46_CONT_LW, begin, end,
+                                    typeid(OptionCustom),
+                                    "s46-cont-lw-options");
+
 }
 
 // This test checks if the DHCPv6 option definition can be searched by
index 9ce068d667494606b8018684c7fb39d7364102f0..d79d6d2877e8562495a3be1b78533bb4ba7029ef 100644 (file)
@@ -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, 192.0.2.0, 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));
+    ASSERT_TRUE(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());;
+
+    ASSERT_NO_THROW({
+        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("192.0.2.0", 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.