Commit 1a50cc14 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

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

parent 3e7fa856
......@@ -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);
}
}
}
......
......@@ -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<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.
......
......@@ -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<unsigned>(excluded_prefix_len_));
<< excluded_prefix << "/"
<< static_cast<unsigned>(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<unsigned>(excluded_prefix_len_)
<< static_cast<unsigned>(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<unsigned>(excluded_prefix_len_)
<< static_cast<unsigned>(excluded_prefix_len)
<< " must be lower than the delegated prefix length "
<< static_cast<unsigned>(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<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());
}
......
......@@ -8,9 +8,10 @@
#define POOL_H
#include <asiolink/io_address.h>
#include <boost/shared_ptr.hpp>
#include <dhcp/option6_pdexclude.h>
#include <dhcpsrv/cfg_option.h>
#include <dhcpsrv/lease.h>
#include <boost/shared_ptr.hpp>
#include <vector>
......@@ -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
......
......@@ -7,6 +7,7 @@
#include <config.h>
#include <asiolink/io_address.h>
#include <dhcp/option6_pdexclude.h>
#include <dhcpsrv/pool.h>
#include <boost/scoped_ptr.hpp>
......@@ -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<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
// "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<unsigned>(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());
}
......
Markdown is supported
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