From 1a50cc14f177e6c23872210c591e942fa5d7eb57 Mon Sep 17 00:00:00 2001 From: Marcin Siodelski Date: Sat, 29 Oct 2016 12:42:48 +0200 Subject: [PATCH] [5016] Prefix Exclude option instance created for a pool. --- src/bin/dhcp6/dhcp6_srv.cc | 22 ++++---- src/bin/dhcp6/tests/config_parser_unittest.cc | 15 ++++-- src/lib/dhcpsrv/pool.cc | 51 ++++++++++--------- src/lib/dhcpsrv/pool.h | 40 ++++----------- src/lib/dhcpsrv/tests/pool_unittest.cc | 18 ++++--- 5 files changed, 69 insertions(+), 77 deletions(-) diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc index e6ab1be386..df6f1b86f8 100644 --- a/src/bin/dhcp6/dhcp6_srv.cc +++ b/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. Pool6Ptr pool = boost::dynamic_pointer_cast< 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< 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); + } } } diff --git a/src/bin/dhcp6/tests/config_parser_unittest.cc b/src/bin/dhcp6/tests/config_parser_unittest.cc index 767ffcff53..3b9b0591a8 100644 --- a/src/bin/dhcp6/tests/config_parser_unittest.cc +++ b/src/bin/dhcp6/tests/config_parser_unittest.cc @@ -1396,7 +1396,7 @@ TEST_F(Dhcp6ParserTest, pdPoolPrefixExclude) { " { \"prefix\": \"3000::\", " " \"prefix-len\": 48, " " \"delegated-len\": 64," - " \"excluded-prefix\": \"3000:1::\"," + " \"excluded-prefix\": \"3000:0:0:0:1000::\"," " \"excluded-prefix-len\": 72" " } ]," "\"valid-lifetime\": 4000 }" @@ -1428,8 +1428,17 @@ TEST_F(Dhcp6ParserTest, pdPoolPrefixExclude) { ASSERT_TRUE(p6); EXPECT_EQ("3000::", p6->getFirstAddress().toText()); EXPECT_EQ(64, p6->getLength()); - EXPECT_EQ("3000:1::", p6->getExcludedPrefix().toText()); - EXPECT_EQ(72, static_cast(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(pd_exclude_option->getExcludedPrefixLength())); } // Goal of this test is verify that a list of PD pools can be configured. diff --git a/src/lib/dhcpsrv/pool.cc b/src/lib/dhcpsrv/pool.cc index 38d594112b..15112b0147 100644 --- a/src/lib/dhcpsrv/pool.cc +++ b/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, 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 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, const uint8_t prefix_len, const uint8_t delegated_len /* = 128 */) : 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, 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 uint8_t excluded_prefix_len) : 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, 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. // Therefore, the initialization of the excluded prefix is takes place // 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"); } // 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 " - << excluded_prefix_ << "/" - << static_cast(excluded_prefix_len_)); + << excluded_prefix << "/" + << static_cast(excluded_prefix_len)); } // 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. - if (excluded_prefix_len_ > 128) { + if (excluded_prefix_len > 128) { isc_throw(BadValue, "excluded prefix length " - << static_cast(excluded_prefix_len_) + << static_cast(excluded_prefix_len) << " must not be greater than 128"); } // Excluded prefix must be a sub-prefix of a delegated prefix. First // 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 " - << static_cast(excluded_prefix_len_) + << static_cast(excluded_prefix_len) << " must be lower than the delegated prefix length " << static_cast(prefix_len_)); } @@ -188,7 +182,7 @@ Pool6::init(const Lease::Type& type, const asiolink::IOAddress& prefix, const uint8_t prefix_len, const uint8_t delegated_len, - const asiolink::IOAddress& /*excluded_prefix*/, + const asiolink::IOAddress& excluded_prefix, const uint8_t excluded_prefix_len) { // Check if the prefix is sane if (!prefix.isV6()) { @@ -231,6 +225,14 @@ Pool6::init(const Lease::Type& type, // For addresses, we could use addrsInRange(prefix, last_), but it's // much faster to do calculations on prefix lengths. 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 @@ -238,12 +240,11 @@ Pool6::toText() const { std::ostringstream s; s << "type=" << Lease::typeToText(type_) << ", " << first_ << "-" << last_ << ", delegated_len=" - << static_cast(prefix_len_); + << static_cast(prefix_len_); - if (excluded_prefix_len_ > 0) { - s << ", excluded_prefix=" << excluded_prefix_ - << ", excluded_prefix_len=" - << static_cast(excluded_prefix_len_); + if (pd_exclude_option_) { + s << ", excluded_prefix_len=" + << static_cast(pd_exclude_option_->getExcludedPrefixLength()); } return (s.str()); } diff --git a/src/lib/dhcpsrv/pool.h b/src/lib/dhcpsrv/pool.h index a4c500287a..173ede17f2 100644 --- a/src/lib/dhcpsrv/pool.h +++ b/src/lib/dhcpsrv/pool.h @@ -8,9 +8,10 @@ #define POOL_H #include -#include +#include #include #include +#include #include @@ -250,27 +251,12 @@ public: 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 @@ -308,17 +294,9 @@ private: /// @brief Defines prefix length (for TYPE_PD only) 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 diff --git a/src/lib/dhcpsrv/tests/pool_unittest.cc b/src/lib/dhcpsrv/tests/pool_unittest.cc index 0e08bd4f7a..1ce452fd3b 100644 --- a/src/lib/dhcpsrv/tests/pool_unittest.cc +++ b/src/lib/dhcpsrv/tests/pool_unittest.cc @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -213,15 +214,20 @@ TEST(Pool6Test, PDExclude) { // 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. 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. EXPECT_EQ(Lease::TYPE_PD, pool->getType()); EXPECT_EQ(112, pool->getLength()); EXPECT_EQ("2001:db8:1::", pool->getFirstAddress().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(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(pd_exclude_option->getExcludedPrefixLength())); // Create another pool instance, but with the excluded prefix being // "unspecified". @@ -232,8 +238,8 @@ TEST(Pool6Test, PDExclude) { EXPECT_EQ(112, pool->getLength()); EXPECT_EQ("2001:db8:1::", pool->getFirstAddress().toText()); EXPECT_EQ("2001:db8:1::ffff:ffff", pool->getLastAddress().toText()); - EXPECT_TRUE(pool->getExcludedPrefix().isV6Zero()); - EXPECT_EQ(0, static_cast(pool->getExcludedPrefixLength())); + + ASSERT_FALSE(pool->getPrefixExcludeOption()); // Excluded prefix length must be greater than the main prefix length. EXPECT_THROW(Pool6(IOAddress("2001:db8:1::"), 96, 112, @@ -336,7 +342,7 @@ TEST(Pool6Test,toText) { Pool6 pool3(IOAddress("2001:db8:1::"), 96, 112, IOAddress("2001:db8:1::1000"), 120); 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()); } -- 2.47.3