Browse Source

[5016] Prefix Exclude option instance created for a pool.

Marcin Siodelski 8 years ago
parent
commit
1a50cc14f1

+ 10 - 12
src/bin/dhcp6/dhcp6_srv.cc

@@ -1582,12 +1582,11 @@ Dhcpv6Srv::assignIA_PD(const Pkt6Ptr& query, const Pkt6Ptr& answer,
                 // include it if the pool configuration specifies this option.
                 // include it if the pool configuration specifies this option.
                 Pool6Ptr pool = boost::dynamic_pointer_cast<
                 Pool6Ptr pool = boost::dynamic_pointer_cast<
                     Pool6>(subnet->getPool(Lease::TYPE_PD, (*l)->addr_));
                     Pool6>(subnet->getPool(Lease::TYPE_PD, (*l)->addr_));
-                if (pool && pool->getExcludedPrefixLength() > 0) {
-                    OptionPtr opt(new Option6PDExclude((*l)->addr_,
-                                                       (*l)->prefixlen_,
-                                                       pool->getExcludedPrefix(),
-                                                       pool->getExcludedPrefixLength()));
-                    addr->addOption(opt);
+                if (pool) {
+                    Option6PDExcludePtr pd_exclude_option = pool->getPrefixExcludeOption();
+                    if (pd_exclude_option) {
+                        addr->addOption(pd_exclude_option);
+                    }
                 }
                 }
             }
             }
         }
         }
@@ -1875,12 +1874,11 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query,
             Pool6Ptr pool = boost::dynamic_pointer_cast<
             Pool6Ptr pool = boost::dynamic_pointer_cast<
                 Pool6>(subnet->getPool(Lease::TYPE_PD, (*l)->addr_));
                 Pool6>(subnet->getPool(Lease::TYPE_PD, (*l)->addr_));
 
 
-            if (pool && pool->getExcludedPrefixLength() > 0) {
-                OptionPtr opt(new Option6PDExclude((*l)->addr_,
-                                                   (*l)->prefixlen_,
-                                                   pool->getExcludedPrefix(),
-                                                   pool->getExcludedPrefixLength()));
-                prf->addOption(opt);
+            if (pool) {
+                Option6PDExcludePtr pd_exclude_option = pool->getPrefixExcludeOption();
+                if (pd_exclude_option) {
+                    prf->addOption(pd_exclude_option);
+                }
             }
             }
         }
         }
 
 

+ 12 - 3
src/bin/dhcp6/tests/config_parser_unittest.cc

@@ -1396,7 +1396,7 @@ TEST_F(Dhcp6ParserTest, pdPoolPrefixExclude) {
         "        { \"prefix\": \"3000::\", "
         "        { \"prefix\": \"3000::\", "
         "          \"prefix-len\": 48, "
         "          \"prefix-len\": 48, "
         "          \"delegated-len\": 64,"
         "          \"delegated-len\": 64,"
-        "          \"excluded-prefix\": \"3000:1::\","
+        "          \"excluded-prefix\": \"3000:0:0:0:1000::\","
         "          \"excluded-prefix-len\": 72"
         "          \"excluded-prefix-len\": 72"
         "        } ],"
         "        } ],"
         "\"valid-lifetime\": 4000 }"
         "\"valid-lifetime\": 4000 }"
@@ -1428,8 +1428,17 @@ TEST_F(Dhcp6ParserTest, pdPoolPrefixExclude) {
     ASSERT_TRUE(p6);
     ASSERT_TRUE(p6);
     EXPECT_EQ("3000::", p6->getFirstAddress().toText());
     EXPECT_EQ("3000::", p6->getFirstAddress().toText());
     EXPECT_EQ(64, p6->getLength());
     EXPECT_EQ(64, p6->getLength());
-    EXPECT_EQ("3000:1::", p6->getExcludedPrefix().toText());
-    EXPECT_EQ(72, static_cast<unsigned>(p6->getExcludedPrefixLength()));
+
+    // This pool should have Prefix Exclude option associated.
+    Option6PDExcludePtr pd_exclude_option = p6->getPrefixExcludeOption();
+    ASSERT_TRUE(pd_exclude_option);
+
+    // Pick a delegated prefix of 3000:0:0:3:1000::/64 which belongs to our
+    // pool of 3000::/48. For this prefix obtain a Prefix Exclude option and
+    // verify that it is correct.
+    EXPECT_EQ("3000:0:0:3:1000::",
+              pd_exclude_option->getExcludedPrefix(IOAddress("3000:0:0:3::"), 64).toText());
+    EXPECT_EQ(72, static_cast<unsigned>(pd_exclude_option->getExcludedPrefixLength()));
 }
 }
 
 
 // Goal of this test is verify that a list of PD pools can be configured.
 // Goal of this test is verify that a list of PD pools can be configured.

+ 26 - 25
src/lib/dhcpsrv/pool.cc

@@ -76,9 +76,7 @@ Pool4::Pool4( const isc::asiolink::IOAddress& prefix, uint8_t prefix_len)
 
 
 Pool6::Pool6(Lease::Type type, const isc::asiolink::IOAddress& first,
 Pool6::Pool6(Lease::Type type, const isc::asiolink::IOAddress& first,
              const isc::asiolink::IOAddress& last)
              const isc::asiolink::IOAddress& last)
-    : Pool(type, first, last), prefix_len_(128),
-      excluded_prefix_(IOAddress::IPV6_ZERO_ADDRESS()),
-      excluded_prefix_len_(0) {
+    : Pool(type, first, last), prefix_len_(128), pd_exclude_option_() {
 
 
     // check if specified address boundaries are sane
     // check if specified address boundaries are sane
     if (!first.isV6() || !last.isV6()) {
     if (!first.isV6() || !last.isV6()) {
@@ -121,9 +119,7 @@ Pool6::Pool6(Lease::Type type, const isc::asiolink::IOAddress& first,
 Pool6::Pool6(Lease::Type type, const isc::asiolink::IOAddress& prefix,
 Pool6::Pool6(Lease::Type type, const isc::asiolink::IOAddress& prefix,
              const uint8_t prefix_len, const uint8_t delegated_len /* = 128 */)
              const uint8_t prefix_len, const uint8_t delegated_len /* = 128 */)
     : Pool(type, prefix, IOAddress::IPV6_ZERO_ADDRESS()),
     : Pool(type, prefix, IOAddress::IPV6_ZERO_ADDRESS()),
-      prefix_len_(delegated_len),
-      excluded_prefix_(IOAddress::IPV6_ZERO_ADDRESS()),
-      excluded_prefix_len_(0) {
+      prefix_len_(delegated_len), pd_exclude_option_() {
 
 
     init(type, prefix, prefix_len, delegated_len,
     init(type, prefix, prefix_len, delegated_len,
          IOAddress::IPV6_ZERO_ADDRESS(), 0);
          IOAddress::IPV6_ZERO_ADDRESS(), 0);
@@ -134,9 +130,7 @@ Pool6::Pool6(const asiolink::IOAddress& prefix, const uint8_t prefix_len,
              const asiolink::IOAddress& excluded_prefix,
              const asiolink::IOAddress& excluded_prefix,
              const uint8_t excluded_prefix_len)
              const uint8_t excluded_prefix_len)
     : Pool(Lease::TYPE_PD, prefix, IOAddress::IPV6_ZERO_ADDRESS()),
     : Pool(Lease::TYPE_PD, prefix, IOAddress::IPV6_ZERO_ADDRESS()),
-      prefix_len_(delegated_len),
-      excluded_prefix_(excluded_prefix),
-      excluded_prefix_len_(excluded_prefix_len) {
+      prefix_len_(delegated_len), pd_exclude_option_() {
 
 
     init(Lease::TYPE_PD, prefix, prefix_len, delegated_len, excluded_prefix,
     init(Lease::TYPE_PD, prefix, prefix_len, delegated_len, excluded_prefix,
          excluded_prefix_len);
          excluded_prefix_len);
@@ -144,33 +138,33 @@ Pool6::Pool6(const asiolink::IOAddress& prefix, const uint8_t prefix_len,
     // The excluded prefix can only be specified using this constructor.
     // The excluded prefix can only be specified using this constructor.
     // Therefore, the initialization of the excluded prefix is takes place
     // Therefore, the initialization of the excluded prefix is takes place
     // here, rather than in the init(...) function.
     // here, rather than in the init(...) function.
-    if (!excluded_prefix_.isV6()) {
+    if (!excluded_prefix.isV6()) {
         isc_throw(BadValue, "excluded prefix must be an IPv6 prefix");
         isc_throw(BadValue, "excluded prefix must be an IPv6 prefix");
     }
     }
 
 
     // An "unspecified" prefix should have both value and length equal to 0.
     // An "unspecified" prefix should have both value and length equal to 0.
-    if ((excluded_prefix_.isV6Zero() && (excluded_prefix_len_ != 0)) ||
-        (!excluded_prefix_.isV6Zero() && (excluded_prefix_len_ == 0))) {
+    if ((excluded_prefix.isV6Zero() && (excluded_prefix_len != 0)) ||
+        (!excluded_prefix.isV6Zero() && (excluded_prefix_len == 0))) {
         isc_throw(BadValue, "invalid excluded prefix "
         isc_throw(BadValue, "invalid excluded prefix "
-                  << excluded_prefix_ << "/"
-                  << static_cast<unsigned>(excluded_prefix_len_));
+                  << excluded_prefix << "/"
+                  << static_cast<unsigned>(excluded_prefix_len));
     }
     }
 
 
     // If excluded prefix has been specified.
     // If excluded prefix has been specified.
-    if (!excluded_prefix_.isV6Zero() && (excluded_prefix_len_ != 0)) {
+    if (!excluded_prefix.isV6Zero() && (excluded_prefix_len != 0)) {
 
 
         // Excluded prefix length must not be greater than 128.
         // Excluded prefix length must not be greater than 128.
-        if (excluded_prefix_len_ > 128) {
+        if (excluded_prefix_len > 128) {
             isc_throw(BadValue, "excluded prefix length "
             isc_throw(BadValue, "excluded prefix length "
-                      << static_cast<unsigned>(excluded_prefix_len_)
+                      << static_cast<unsigned>(excluded_prefix_len)
                       << " must not be greater than 128");
                       << " must not be greater than 128");
         }
         }
 
 
         // Excluded prefix must be a sub-prefix of a delegated prefix. First
         // Excluded prefix must be a sub-prefix of a delegated prefix. First
         // check the prefix length as it is less involved.
         // check the prefix length as it is less involved.
-        if (excluded_prefix_len_ <= prefix_len_) {
+        if (excluded_prefix_len <= prefix_len_) {
             isc_throw(BadValue, "excluded prefix length "
             isc_throw(BadValue, "excluded prefix length "
-                      << static_cast<unsigned>(excluded_prefix_len_)
+                      << static_cast<unsigned>(excluded_prefix_len)
                       << " must be lower than the delegated prefix length "
                       << " must be lower than the delegated prefix length "
                       << static_cast<unsigned>(prefix_len_));
                       << static_cast<unsigned>(prefix_len_));
         }
         }
@@ -188,7 +182,7 @@ Pool6::init(const Lease::Type& type,
             const asiolink::IOAddress& prefix,
             const asiolink::IOAddress& prefix,
             const uint8_t prefix_len,
             const uint8_t prefix_len,
             const uint8_t delegated_len,
             const uint8_t delegated_len,
-            const asiolink::IOAddress& /*excluded_prefix*/,
+            const asiolink::IOAddress& excluded_prefix,
             const uint8_t excluded_prefix_len) {
             const uint8_t excluded_prefix_len) {
     // Check if the prefix is sane
     // Check if the prefix is sane
     if (!prefix.isV6()) {
     if (!prefix.isV6()) {
@@ -231,6 +225,14 @@ Pool6::init(const Lease::Type& type,
     // For addresses, we could use addrsInRange(prefix, last_), but it's
     // For addresses, we could use addrsInRange(prefix, last_), but it's
     // much faster to do calculations on prefix lengths.
     // much faster to do calculations on prefix lengths.
     capacity_ = prefixesInRange(prefix_len, delegated_len);
     capacity_ = prefixesInRange(prefix_len, delegated_len);
+
+    // If user specified an excluded prefix, create an option that will
+    // be sent to clients obtaining prefixes from this pool.
+    if (excluded_prefix_len > 0) {
+        pd_exclude_option_.reset(new Option6PDExclude(prefix, delegated_len,
+                                                      excluded_prefix,
+                                                      excluded_prefix_len));
+    }
 }
 }
 
 
 std::string
 std::string
@@ -238,12 +240,11 @@ Pool6::toText() const {
     std::ostringstream s;
     std::ostringstream s;
     s << "type=" << Lease::typeToText(type_) << ", " << first_
     s << "type=" << Lease::typeToText(type_) << ", " << first_
       << "-" << last_ << ", delegated_len="
       << "-" << last_ << ", delegated_len="
-      << static_cast<int>(prefix_len_);
+      << static_cast<unsigned>(prefix_len_);
 
 
-    if (excluded_prefix_len_ > 0) {
-       s << ", excluded_prefix=" << excluded_prefix_
-         << ", excluded_prefix_len="
-         << static_cast<unsigned>(excluded_prefix_len_);
+    if (pd_exclude_option_) {
+       s << ", excluded_prefix_len="
+         << static_cast<unsigned>(pd_exclude_option_->getExcludedPrefixLength());
     }
     }
     return (s.str());
     return (s.str());
 }
 }

+ 9 - 31
src/lib/dhcpsrv/pool.h

@@ -8,9 +8,10 @@
 #define POOL_H
 #define POOL_H
 
 
 #include <asiolink/io_address.h>
 #include <asiolink/io_address.h>
-#include <boost/shared_ptr.hpp>
+#include <dhcp/option6_pdexclude.h>
 #include <dhcpsrv/cfg_option.h>
 #include <dhcpsrv/cfg_option.h>
 #include <dhcpsrv/lease.h>
 #include <dhcpsrv/lease.h>
+#include <boost/shared_ptr.hpp>
 
 
 #include <vector>
 #include <vector>
 
 
@@ -250,27 +251,12 @@ public:
         return (prefix_len_);
         return (prefix_len_);
     }
     }
 
 
-    /// @brief Returns an excluded prefix.
-    ///
-    /// An excluded prefix can be specified for a prefix pool as specified
-    /// in RFC6603.
+    /// @brief Returns instance of the pool specific Prefix Exclude option.
     ///
     ///
-    /// @return Reference to an IOAddress object representing an excluded
-    /// prefix pool. A value of '::' if the excluded prefix is not specified.
-    const isc::asiolink::IOAddress& getExcludedPrefix() const{
-        return (excluded_prefix_);
-    }
-
-    /// @brief Returns an excluded prefix length.
-    ///
-    /// An excluded prefix can be specified for a prefix pool as specified
-    /// in RFC6603.
-    ///
-    /// @return Excluded prefix length in the range of 2 to 128, if the
-    /// excluded prefix is specified. A value of 0 if the excluded prefix
-    /// is not specified.
-    uint8_t getExcludedPrefixLength() const{
-        return (excluded_prefix_len_);
+    /// @return An instance of the Prefix Exclude option (RFC 6603) or NULL
+    /// if such option hasn't been specified for the pool.
+    Option6PDExcludePtr getPrefixExcludeOption() const {
+        return (pd_exclude_option_);
     }
     }
 
 
     /// @brief returns textual representation of the pool
     /// @brief returns textual representation of the pool
@@ -308,17 +294,9 @@ private:
     /// @brief Defines prefix length (for TYPE_PD only)
     /// @brief Defines prefix length (for TYPE_PD only)
     uint8_t prefix_len_;
     uint8_t prefix_len_;
 
 
-    /// @brief The excluded prefix (RFC6603).
-    ///
-    /// This prefix can only be specified for DHCPv6 prefix pools.
-    /// An "unspecified" prefix has a value of '::'.
-    isc::asiolink::IOAddress excluded_prefix_;
+    /// @brief A pointer to the Prefix Exclude option (RFC 6603).
+    Option6PDExcludePtr pd_exclude_option_;
 
 
-    /// @brief The excluded prefix length (RFC6603).
-    ///
-    /// This value can only be specified for DHCPv6 prefix pool.
-    /// An "unspecified" prefix has a length of 0.
-    uint8_t excluded_prefix_len_;
 };
 };
 
 
 /// @brief a pointer an IPv6 Pool
 /// @brief a pointer an IPv6 Pool

+ 12 - 6
src/lib/dhcpsrv/tests/pool_unittest.cc

@@ -7,6 +7,7 @@
 #include <config.h>
 #include <config.h>
 
 
 #include <asiolink/io_address.h>
 #include <asiolink/io_address.h>
+#include <dhcp/option6_pdexclude.h>
 #include <dhcpsrv/pool.h>
 #include <dhcpsrv/pool.h>
 
 
 #include <boost/scoped_ptr.hpp>
 #include <boost/scoped_ptr.hpp>
@@ -213,15 +214,20 @@ TEST(Pool6Test, PDExclude) {
     // Create a pool with a good excluded prefix. The good excluded prefix
     // Create a pool with a good excluded prefix. The good excluded prefix
     // is the one for which is a sub-prefix of the main prefix.
     // is the one for which is a sub-prefix of the main prefix.
     ASSERT_NO_THROW(pool.reset(new Pool6(IOAddress("2001:db8:1::"), 96, 112,
     ASSERT_NO_THROW(pool.reset(new Pool6(IOAddress("2001:db8:1::"), 96, 112,
-                                         IOAddress("2001:db8:1:2::"), 120)));
+                                         IOAddress("2001:db8:1::2000"), 120)));
 
 
     // Verify pool properties.
     // Verify pool properties.
     EXPECT_EQ(Lease::TYPE_PD, pool->getType());
     EXPECT_EQ(Lease::TYPE_PD, pool->getType());
     EXPECT_EQ(112, pool->getLength());
     EXPECT_EQ(112, pool->getLength());
     EXPECT_EQ("2001:db8:1::", pool->getFirstAddress().toText());
     EXPECT_EQ("2001:db8:1::", pool->getFirstAddress().toText());
     EXPECT_EQ("2001:db8:1::ffff:ffff", pool->getLastAddress().toText());
     EXPECT_EQ("2001:db8:1::ffff:ffff", pool->getLastAddress().toText());
-    EXPECT_EQ("2001:db8:1:2::", pool->getExcludedPrefix().toText());
-    EXPECT_EQ(120, static_cast<unsigned>(pool->getExcludedPrefixLength()));
+
+    // It should include Prefix Exclude option.
+    Option6PDExcludePtr pd_exclude_option = pool->getPrefixExcludeOption();
+    ASSERT_TRUE(pd_exclude_option);
+    EXPECT_EQ("2001:db8:1::2:2000", pd_exclude_option->
+              getExcludedPrefix(IOAddress("2001:db8:1:0:0:0:2::"), 112).toText());
+    EXPECT_EQ(120, static_cast<unsigned>(pd_exclude_option->getExcludedPrefixLength()));
 
 
     // Create another pool instance, but with the excluded prefix being
     // Create another pool instance, but with the excluded prefix being
     // "unspecified".
     // "unspecified".
@@ -232,8 +238,8 @@ TEST(Pool6Test, PDExclude) {
     EXPECT_EQ(112, pool->getLength());
     EXPECT_EQ(112, pool->getLength());
     EXPECT_EQ("2001:db8:1::", pool->getFirstAddress().toText());
     EXPECT_EQ("2001:db8:1::", pool->getFirstAddress().toText());
     EXPECT_EQ("2001:db8:1::ffff:ffff", pool->getLastAddress().toText());
     EXPECT_EQ("2001:db8:1::ffff:ffff", pool->getLastAddress().toText());
-    EXPECT_TRUE(pool->getExcludedPrefix().isV6Zero());
-    EXPECT_EQ(0, static_cast<unsigned>(pool->getExcludedPrefixLength()));
+
+    ASSERT_FALSE(pool->getPrefixExcludeOption());
 
 
     // Excluded prefix length must be greater than the main prefix length.
     // Excluded prefix length must be greater than the main prefix length.
     EXPECT_THROW(Pool6(IOAddress("2001:db8:1::"), 96, 112,
     EXPECT_THROW(Pool6(IOAddress("2001:db8:1::"), 96, 112,
@@ -336,7 +342,7 @@ TEST(Pool6Test,toText) {
     Pool6 pool3(IOAddress("2001:db8:1::"), 96, 112,
     Pool6 pool3(IOAddress("2001:db8:1::"), 96, 112,
                 IOAddress("2001:db8:1::1000"), 120);
                 IOAddress("2001:db8:1::1000"), 120);
     EXPECT_EQ("type=IA_PD, 2001:db8:1::-2001:db8:1::ffff:ffff, delegated_len=112,"
     EXPECT_EQ("type=IA_PD, 2001:db8:1::-2001:db8:1::ffff:ffff, delegated_len=112,"
-              " excluded_prefix=2001:db8:1::1000, excluded_prefix_len=120",
+              " excluded_prefix_len=120",
               pool3.toText());
               pool3.toText());
 
 
 }
 }