mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-31 14:05:33 +00:00
[2238] Changes after review.
This commit is contained in:
@@ -1,9 +1,8 @@
|
|||||||
4XX. [func] tomek
|
4XX. [func] tomek
|
||||||
A new library (libb10-dhcpsrv) has been create. Currently its
|
A new library (libb10-dhcpsrv) has been created. At present, it
|
||||||
functionality is limited to a Configuration Manager. CfgMgr
|
only holds the code for the DHCP Configuration Manager. Currently
|
||||||
currently only supports basic configuration storage for DHCPv6
|
this object only supports basic configuration storage for the DHCPv6
|
||||||
server, but that capability is expected to be expanded in a near
|
server, but that capability will be expanded.
|
||||||
future.
|
|
||||||
(Trac #2238, git TBD)
|
(Trac #2238, git TBD)
|
||||||
|
|
||||||
475. [func] naokikambe
|
475. [func] naokikambe
|
||||||
|
@@ -150,19 +150,16 @@ public:
|
|||||||
/// Operations within one protocol family are obvious.
|
/// Operations within one protocol family are obvious.
|
||||||
/// Comparisons between v4 and v6 will allways return v4
|
/// Comparisons between v4 and v6 will allways return v4
|
||||||
/// being smaller. This follows boost::asio::ip implementation
|
/// being smaller. This follows boost::asio::ip implementation
|
||||||
bool smallerThan(const IOAddress& other) const {
|
bool lessThan(const IOAddress& other) const {
|
||||||
if (this->getFamily() < other.getFamily()) {
|
if (this->getFamily() == other.getFamily()) {
|
||||||
return (true);
|
|
||||||
}
|
|
||||||
if (this->getFamily() > other.getFamily()) {
|
|
||||||
return (false);
|
|
||||||
}
|
|
||||||
if (this->getFamily() == AF_INET6) {
|
if (this->getFamily() == AF_INET6) {
|
||||||
return (this->asio_address_.to_v6() < other.asio_address_.to_v6());
|
return (this->asio_address_.to_v6() < other.asio_address_.to_v6());
|
||||||
} else {
|
} else {
|
||||||
return (this->asio_address_.to_v4() < other.asio_address_.to_v4());
|
return (this->asio_address_.to_v4() < other.asio_address_.to_v4());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return (this->getFamily() < other.getFamily());
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Checks if one address is smaller or equal than the other
|
/// \brief Checks if one address is smaller or equal than the other
|
||||||
///
|
///
|
||||||
@@ -173,7 +170,7 @@ public:
|
|||||||
if (equals(other)) {
|
if (equals(other)) {
|
||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
return (smallerThan(other));
|
return (lessThan(other));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Checks if one address is smaller than the other
|
/// \brief Checks if one address is smaller than the other
|
||||||
@@ -182,7 +179,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// See \ref smaller_than method for details.
|
/// See \ref smaller_than method for details.
|
||||||
bool operator<(const IOAddress& other) const {
|
bool operator<(const IOAddress& other) const {
|
||||||
return (smallerThan(other));
|
return (lessThan(other));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Checks if one address is smaller or equal than the other
|
/// \brief Checks if one address is smaller or equal than the other
|
||||||
|
@@ -100,7 +100,7 @@ TEST(IOAddressTest, uint32) {
|
|||||||
EXPECT_EQ(addr3.toText(), "192.0.2.5");
|
EXPECT_EQ(addr3.toText(), "192.0.2.5");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(IOAddressTest, compare) {
|
TEST(IOAddressTest, lessThanEqual) {
|
||||||
IOAddress addr1("192.0.2.5");
|
IOAddress addr1("192.0.2.5");
|
||||||
IOAddress addr2("192.0.2.6");
|
IOAddress addr2("192.0.2.6");
|
||||||
IOAddress addr3("0.0.0.0");
|
IOAddress addr3("0.0.0.0");
|
||||||
|
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
#include <dhcp/addr_utilities.h>
|
#include <dhcp/addr_utilities.h>
|
||||||
|
|
||||||
|
using namespace isc::asiolink;
|
||||||
|
|
||||||
namespace isc {
|
namespace isc {
|
||||||
namespace dhcp {
|
namespace dhcp {
|
||||||
|
|
||||||
@@ -21,19 +23,34 @@ isc::asiolink::IOAddress firstAddrInPrefix(const isc::asiolink::IOAddress& prefi
|
|||||||
uint8_t len) {
|
uint8_t len) {
|
||||||
|
|
||||||
static char bitMask[]= { 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
|
static char bitMask[]= { 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
|
||||||
uint8_t packed[16];
|
uint8_t packed[V6ADDRESS_LEN];
|
||||||
|
|
||||||
|
// First we copy the whole address as 16 bytes.
|
||||||
memcpy(packed, prefix.getAddress().to_v6().to_bytes().data(), 16);
|
memcpy(packed, prefix.getAddress().to_v6().to_bytes().data(), 16);
|
||||||
|
|
||||||
|
// If the length is divisible by 8, it is simple. We just zero out the host
|
||||||
|
// part. Otherwise we need to handle the byte that has to be partially
|
||||||
|
// zeroed.
|
||||||
if (len % 8 != 0) {
|
if (len % 8 != 0) {
|
||||||
|
|
||||||
|
// Get the appropriate mask. It has relevant bits (those that should
|
||||||
|
// stay) set and irrelevant (those that should be wiped) cleared.
|
||||||
uint8_t mask = bitMask[len % 8];
|
uint8_t mask = bitMask[len % 8];
|
||||||
|
|
||||||
|
// Let's leave only whatever the mask says should not be cleared.
|
||||||
packed[len / 8] = packed[len / 8] & mask;
|
packed[len / 8] = packed[len / 8] & mask;
|
||||||
|
|
||||||
|
// Since we have just dealt with this byte, let's move the prefix length
|
||||||
|
// to the beginning of the next byte (len is expressed in bits).
|
||||||
len = (len / 8 + 1) * 8;
|
len = (len / 8 + 1) * 8;
|
||||||
}
|
}
|
||||||
for (int i = len / 8; i < 16; ++i) {
|
|
||||||
|
// Clear out the remaining bits.
|
||||||
|
for (int i = len / 8; i < sizeof(packed); ++i) {
|
||||||
packed[i] = 0x0;
|
packed[i] = 0x0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finally, let's wrap this into nice and easy IOAddress object.
|
||||||
return (isc::asiolink::IOAddress::from_bytes(AF_INET6, packed));
|
return (isc::asiolink::IOAddress::from_bytes(AF_INET6, packed));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,19 +58,36 @@ isc::asiolink::IOAddress lastAddrInPrefix(const isc::asiolink::IOAddress& prefix
|
|||||||
uint8_t len) {
|
uint8_t len) {
|
||||||
|
|
||||||
static char bitMask[]= { 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
|
static char bitMask[]= { 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
|
||||||
uint8_t packed[16];
|
uint8_t packed[V6ADDRESS_LEN];
|
||||||
|
|
||||||
|
// First we copy the whole address as 16 bytes.
|
||||||
memcpy(packed, prefix.getAddress().to_v6().to_bytes().data(), 16);
|
memcpy(packed, prefix.getAddress().to_v6().to_bytes().data(), 16);
|
||||||
|
|
||||||
|
// if the length is divisible by 8, it is simple. We just fill the host part
|
||||||
|
// with ones. Otherwise we need to handle the byte that has to be partially
|
||||||
|
// zeroed.
|
||||||
if (len % 8 != 0) {
|
if (len % 8 != 0) {
|
||||||
|
// Get the appropriate mask. It has relevant bits (those that should
|
||||||
|
// stay) set and irrelevant (those that should be set to 1) cleared.
|
||||||
uint8_t mask = bitMask[len % 8];
|
uint8_t mask = bitMask[len % 8];
|
||||||
|
|
||||||
|
// Let's set those irrelevant bits with 1. It would be perhaps
|
||||||
|
// easier to not use negation here and invert bitMask content. However,
|
||||||
|
// with this approach, we can use the same mask in first and last
|
||||||
|
// address calculations.
|
||||||
packed[len / 8] = packed[len / 8] | ~mask;
|
packed[len / 8] = packed[len / 8] | ~mask;
|
||||||
|
|
||||||
|
// Since we have just dealt with this byte, let's move the prefix length
|
||||||
|
// to the beginning of the next byte (len is expressed in bits).
|
||||||
len = (len / 8 + 1) * 8;
|
len = (len / 8 + 1) * 8;
|
||||||
}
|
}
|
||||||
for (int i = len / 8; i < 16; ++i) {
|
|
||||||
|
// Finally set remaining bits to 1.
|
||||||
|
for (int i = len / 8; i < sizeof(packed); ++i) {
|
||||||
packed[i] = 0xff;
|
packed[i] = 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finally, let's wrap this into nice and easy IOAddress object.
|
||||||
return (isc::asiolink::IOAddress::from_bytes(AF_INET6, packed));
|
return (isc::asiolink::IOAddress::from_bytes(AF_INET6, packed));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -18,13 +18,15 @@ namespace isc {
|
|||||||
namespace dhcp {
|
namespace dhcp {
|
||||||
|
|
||||||
/// This code is based on similar code from the Dibbler project. I, Tomasz Mrugalski,
|
/// This code is based on similar code from the Dibbler project. I, Tomasz Mrugalski,
|
||||||
/// as a sole creater of that code hereby release it under BSD license for the benefit
|
/// as a sole creator of that code hereby release it under BSD license for the benefit
|
||||||
/// of the BIND10 project.
|
/// of the BIND10 project.
|
||||||
|
|
||||||
/// @brief returns a first address in a given prefix
|
/// @brief returns a first address in a given prefix
|
||||||
///
|
///
|
||||||
/// Example: For 2001:db8:1::deaf:beef and length /120 the function will return
|
/// Example: For 2001:db8:1::deaf:beef and length /120 the function will return
|
||||||
/// 2001:db8:1::dead:bee0. See also @ref lastAddrInPrefix.
|
/// 2001:db8:1::dead:be00. See also @ref lastAddrInPrefix.
|
||||||
|
///
|
||||||
|
/// @todo It currently works for v6 only and will throw if v4 address is passed.
|
||||||
///
|
///
|
||||||
/// @param prefix and address that belongs to a prefix
|
/// @param prefix and address that belongs to a prefix
|
||||||
/// @param len prefix length
|
/// @param len prefix length
|
||||||
@@ -38,6 +40,8 @@ isc::asiolink::IOAddress firstAddrInPrefix(const isc::asiolink::IOAddress& prefi
|
|||||||
/// Example: For 2001:db8:1::deaf:beef and length /112 the function will return
|
/// Example: For 2001:db8:1::deaf:beef and length /112 the function will return
|
||||||
/// 2001:db8:1::dead:ffff. See also @ref firstAddrInPrefix.
|
/// 2001:db8:1::dead:ffff. See also @ref firstAddrInPrefix.
|
||||||
///
|
///
|
||||||
|
/// @todo It currently works for v6 only and will throw if v4 address is passed.
|
||||||
|
///
|
||||||
/// @param prefix and address that belongs to a prefix
|
/// @param prefix and address that belongs to a prefix
|
||||||
/// @param len prefix length
|
/// @param len prefix length
|
||||||
///
|
///
|
||||||
|
@@ -27,7 +27,7 @@ Pool::Pool(const isc::asiolink::IOAddress& first,
|
|||||||
:id_(getNextID()), first_(first), last_(last) {
|
:id_(getNextID()), first_(first), last_(last) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Pool::inRange(const isc::asiolink::IOAddress& addr) {
|
bool Pool::inRange(const isc::asiolink::IOAddress& addr) const {
|
||||||
return (first_.smallerEqual(addr) && addr.smallerEqual(last_));
|
return (first_.smallerEqual(addr) && addr.smallerEqual(last_));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,12 +46,14 @@ Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& first,
|
|||||||
// we need to comment it and uncomment lines below.
|
// we need to comment it and uncomment lines below.
|
||||||
// On one hand, letting the user specify 2001::f - 2001::1 is nice, but
|
// On one hand, letting the user specify 2001::f - 2001::1 is nice, but
|
||||||
// on the other hand, 2001::1 may be a typo and the user really meant
|
// on the other hand, 2001::1 may be a typo and the user really meant
|
||||||
// 2001::1:0 (or 1something), so a at least a warning would be useful.
|
// 2001::1:0 (or 1 followed by some hex digit), so a at least a warning
|
||||||
|
// would be useful.
|
||||||
|
|
||||||
// first_ = last;
|
// first_ = last;
|
||||||
// last_ = first;
|
// last_ = first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TYPE_PD is not supported by this constructor. first-last style
|
// TYPE_PD is not supported by this constructor. first-last style
|
||||||
// parameters are for IA and TA only. There is another dedicated
|
// parameters are for IA and TA only. There is another dedicated
|
||||||
// constructor for that (it uses prefix/length)
|
// constructor for that (it uses prefix/length)
|
||||||
@@ -75,6 +77,9 @@ Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& prefix,
|
|||||||
isc_throw(BadValue, "Invalid prefix length");
|
isc_throw(BadValue, "Invalid prefix length");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @todo: We should probably implement checks against weird addresses
|
||||||
|
/// here, like ::, starting with fe80, starting with ff etc. .
|
||||||
|
|
||||||
// Let's now calculate the last address in defined pool
|
// Let's now calculate the last address in defined pool
|
||||||
last_ = lastAddrInPrefix(prefix, prefix_len);
|
last_ = lastAddrInPrefix(prefix, prefix_len);
|
||||||
}
|
}
|
||||||
@@ -91,7 +96,7 @@ Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Subnet::inRange(const isc::asiolink::IOAddress& addr) {
|
bool Subnet::inRange(const isc::asiolink::IOAddress& addr) const {
|
||||||
IOAddress first = firstAddrInPrefix(prefix_, prefix_len_);
|
IOAddress first = firstAddrInPrefix(prefix_, prefix_len_);
|
||||||
IOAddress last = lastAddrInPrefix(prefix_, prefix_len_);
|
IOAddress last = lastAddrInPrefix(prefix_, prefix_len_);
|
||||||
|
|
||||||
@@ -106,7 +111,7 @@ Subnet6::Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length,
|
|||||||
:Subnet(prefix, length, t1, t2, valid_lifetime),
|
:Subnet(prefix, length, t1, t2, valid_lifetime),
|
||||||
preferred_(preferred_lifetime){
|
preferred_(preferred_lifetime){
|
||||||
if (prefix.getFamily() != AF_INET6) {
|
if (prefix.getFamily() != AF_INET6) {
|
||||||
isc_throw(BadValue, "Invalid prefix " << prefix.toText()
|
isc_throw(BadValue, "Non IPv6 prefix " << prefix.toText()
|
||||||
<< " specified in subnet6");
|
<< " specified in subnet6");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,6 +126,8 @@ void Subnet6::addPool6(const Pool6Ptr& pool) {
|
|||||||
<< ") subnet6");
|
<< ") subnet6");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @todo: Check that pools do not overlap
|
||||||
|
|
||||||
pools_.push_back(pool);
|
pools_.push_back(pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,6 +160,13 @@ Subnet6Ptr
|
|||||||
CfgMgr::getSubnet6(const isc::asiolink::IOAddress& hint) {
|
CfgMgr::getSubnet6(const isc::asiolink::IOAddress& hint) {
|
||||||
|
|
||||||
// If there's only one subnet configured, let's just use it
|
// If there's only one subnet configured, let's just use it
|
||||||
|
// The idea is to keep small deployments easy. In a small network - one
|
||||||
|
// router that also runs DHCPv6 server. Users specifies a single pool and
|
||||||
|
// expects it to just work. Without this, the server would complain that it
|
||||||
|
// doesn't have IP address on its interfaces that matches that
|
||||||
|
// configuration. Such requirement makes sense in IPv4, but not in IPv6.
|
||||||
|
// The server does not need to have a global address (using just link-local
|
||||||
|
// is ok for DHCPv6 server) from the pool it serves.
|
||||||
if (subnets6_.size() == 1) {
|
if (subnets6_.size() == 1) {
|
||||||
return (subnets6_[0]);
|
return (subnets6_[0]);
|
||||||
}
|
}
|
||||||
|
@@ -31,7 +31,7 @@ class Pool6;
|
|||||||
|
|
||||||
class Subnet6;
|
class Subnet6;
|
||||||
|
|
||||||
/// @brief this template specifes a parameter value
|
/// @brief this template specifies a parameter value
|
||||||
///
|
///
|
||||||
/// This template class is used to store configuration parameters, like lifetime or T1.
|
/// This template class is used to store configuration parameters, like lifetime or T1.
|
||||||
/// It defines 3 parameters: min, default, and max value. There are 2 constructors:
|
/// It defines 3 parameters: min, default, and max value. There are 2 constructors:
|
||||||
@@ -48,8 +48,11 @@ public:
|
|||||||
///
|
///
|
||||||
/// Typically: uint32_t to Triplet assignment. It is very convenient
|
/// Typically: uint32_t to Triplet assignment. It is very convenient
|
||||||
/// to be able to simply write Triplet<uint32_t> x = 7;
|
/// to be able to simply write Triplet<uint32_t> x = 7;
|
||||||
Triplet<T>& operator = (T base_type) {
|
Triplet<T> operator=(T other) {
|
||||||
return Triplet<T>(base_type);
|
min_ = other;
|
||||||
|
default_ = other;
|
||||||
|
max_ = other;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief triplet to base type conversion
|
/// @brief triplet to base type conversion
|
||||||
@@ -127,6 +130,7 @@ public:
|
|||||||
|
|
||||||
/// @brief returns Pool-id
|
/// @brief returns Pool-id
|
||||||
///
|
///
|
||||||
|
/// @return pool-id value
|
||||||
/// Pool-id is an unique value that can be used to identify a pool.
|
/// Pool-id is an unique value that can be used to identify a pool.
|
||||||
uint32_t getId() const {
|
uint32_t getId() const {
|
||||||
return (id_);
|
return (id_);
|
||||||
@@ -148,7 +152,7 @@ public:
|
|||||||
/// @brief Checks if a given address is in the range.
|
/// @brief Checks if a given address is in the range.
|
||||||
///
|
///
|
||||||
/// @return true, if the address is in pool
|
/// @return true, if the address is in pool
|
||||||
bool inRange(const isc::asiolink::IOAddress& addr);
|
bool inRange(const isc::asiolink::IOAddress& addr) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@@ -170,7 +174,7 @@ protected:
|
|||||||
|
|
||||||
/// @brief pool-id
|
/// @brief pool-id
|
||||||
///
|
///
|
||||||
/// This ID is used to indentify this specific pool.
|
/// This ID is used to identify this specific pool.
|
||||||
uint32_t id_;
|
uint32_t id_;
|
||||||
|
|
||||||
/// @brief The first address in a pool
|
/// @brief The first address in a pool
|
||||||
@@ -227,7 +231,7 @@ public:
|
|||||||
return (type_);
|
return (type_);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
/// @brief defines a pool type
|
/// @brief defines a pool type
|
||||||
Pool6Type type_;
|
Pool6Type type_;
|
||||||
|
|
||||||
@@ -255,7 +259,7 @@ typedef std::vector<Pool6Ptr> Pool6Collection;
|
|||||||
class Subnet {
|
class Subnet {
|
||||||
public:
|
public:
|
||||||
/// @brief checks if specified address is in range
|
/// @brief checks if specified address is in range
|
||||||
bool inRange(const isc::asiolink::IOAddress& addr);
|
bool inRange(const isc::asiolink::IOAddress& addr) const;
|
||||||
|
|
||||||
/// @brief return valid-lifetime for addresses in that prefix
|
/// @brief return valid-lifetime for addresses in that prefix
|
||||||
Triplet<uint32_t> getValid() const {
|
Triplet<uint32_t> getValid() const {
|
||||||
@@ -317,29 +321,54 @@ protected:
|
|||||||
/// This class represents an IPv6 subnet.
|
/// This class represents an IPv6 subnet.
|
||||||
class Subnet6 : public Subnet {
|
class Subnet6 : public Subnet {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/// @brief Constructor with all parameters
|
||||||
|
///
|
||||||
|
/// @param prefix Subnet6 prefix
|
||||||
|
/// @param length prefix length
|
||||||
|
/// @param t1 renewal timer (in seconds)
|
||||||
|
/// @param t2 rebind timer (in seconds)
|
||||||
|
/// @param preferred_lifetime preferred lifetime of leases (in seconds)
|
||||||
|
/// @param valid_lifetime preferred lifetime of leases (in seconds)
|
||||||
Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length,
|
Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length,
|
||||||
const Triplet<uint32_t>& t1,
|
const Triplet<uint32_t>& t1,
|
||||||
const Triplet<uint32_t>& t2,
|
const Triplet<uint32_t>& t2,
|
||||||
const Triplet<uint32_t>& preferred_lifetime,
|
const Triplet<uint32_t>& preferred_lifetime,
|
||||||
const Triplet<uint32_t>& valid_lifetime);
|
const Triplet<uint32_t>& valid_lifetime);
|
||||||
|
|
||||||
|
/// @brief Returns preverred lifetime (in seconds)
|
||||||
|
///
|
||||||
|
/// @return a triplet with preferred lifetime
|
||||||
Triplet<uint32_t> getPreferred() const {
|
Triplet<uint32_t> getPreferred() const {
|
||||||
return (preferred_);
|
return (preferred_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Returns a pool that specified address belongs to
|
||||||
|
///
|
||||||
|
/// @param hint address that the returned pool should cover (optional)
|
||||||
|
/// @return Pointer to found pool6 (or NULL)
|
||||||
Pool6Ptr getPool6(const isc::asiolink::IOAddress& hint =
|
Pool6Ptr getPool6(const isc::asiolink::IOAddress& hint =
|
||||||
isc::asiolink::IOAddress("::"));
|
isc::asiolink::IOAddress("::"));
|
||||||
|
|
||||||
|
/// @brief Adds a new pool.
|
||||||
|
/// @param pool pool to be added
|
||||||
void addPool6(const Pool6Ptr& pool);
|
void addPool6(const Pool6Ptr& pool);
|
||||||
|
|
||||||
|
/// @brief returns all pools
|
||||||
|
///
|
||||||
|
/// The reference is only valid as long as the object that
|
||||||
|
/// returned it.
|
||||||
|
///
|
||||||
|
/// @return a collection of all pools
|
||||||
const Pool6Collection& getPools() const {
|
const Pool6Collection& getPools() const {
|
||||||
return pools_;
|
return pools_;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// collection of pools in that list
|
/// @brief collection of pools in that list
|
||||||
Pool6Collection pools_;
|
Pool6Collection pools_;
|
||||||
|
|
||||||
|
/// @brief a triplet with preferred lifetime (in seconds)
|
||||||
Triplet<uint32_t> preferred_;
|
Triplet<uint32_t> preferred_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -51,6 +51,7 @@ libdhcpsrv_unittests_LDADD = $(GTEST_LDADD)
|
|||||||
libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
|
libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
|
||||||
libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
|
libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
|
||||||
libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libb10-dhcpsrv.la
|
libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libb10-dhcpsrv.la
|
||||||
|
libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/log/libb10-log.la
|
||||||
|
|
||||||
|
|
||||||
if USE_CLANGPP
|
if USE_CLANGPP
|
||||||
@@ -66,6 +67,7 @@ libdhcp___unittests_LDADD += $(top_builddir)/src/lib/log/libb10-log.la
|
|||||||
libdhcp___unittests_LDADD += $(top_builddir)/src/lib/util/libb10-util.la
|
libdhcp___unittests_LDADD += $(top_builddir)/src/lib/util/libb10-util.la
|
||||||
libdhcp___unittests_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
|
libdhcp___unittests_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
|
||||||
libdhcp___unittests_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
|
libdhcp___unittests_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
|
||||||
|
libdhcp___unittests_LDADD += $(top_builddir)/src/lib/log/libb10-log.la
|
||||||
libdhcp___unittests_LDADD += $(GTEST_LDADD)
|
libdhcp___unittests_LDADD += $(GTEST_LDADD)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@@ -53,6 +53,14 @@ TEST(Pool6Test, lastAddrInPrefix) {
|
|||||||
EXPECT_EQ("2001::3f", lastAddrInPrefix(addr2, 122).toText());
|
EXPECT_EQ("2001::3f", lastAddrInPrefix(addr2, 122).toText());
|
||||||
EXPECT_EQ("2001::7f", lastAddrInPrefix(addr2, 121).toText());
|
EXPECT_EQ("2001::7f", lastAddrInPrefix(addr2, 121).toText());
|
||||||
EXPECT_EQ("2001::ff", lastAddrInPrefix(addr2, 120).toText());
|
EXPECT_EQ("2001::ff", lastAddrInPrefix(addr2, 120).toText());
|
||||||
|
|
||||||
|
// Let's check extreme cases
|
||||||
|
IOAddress anyAddr("::");
|
||||||
|
EXPECT_EQ("7fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
|
||||||
|
lastAddrInPrefix(anyAddr, 1).toText());
|
||||||
|
EXPECT_EQ("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
|
||||||
|
lastAddrInPrefix(anyAddr, 0).toText());
|
||||||
|
EXPECT_EQ("::", lastAddrInPrefix(anyAddr, 128).toText());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Pool6Test, firstAddrInPrefix) {
|
TEST(Pool6Test, firstAddrInPrefix) {
|
||||||
|
@@ -35,28 +35,28 @@ namespace {
|
|||||||
// constructor validation
|
// constructor validation
|
||||||
TEST(TripletTest, constructor) {
|
TEST(TripletTest, constructor) {
|
||||||
|
|
||||||
uint32_t min = 10;
|
const uint32_t min = 10;
|
||||||
uint32_t value = 20;
|
const uint32_t value = 20;
|
||||||
uint32_t max = 30;
|
const uint32_t max = 30;
|
||||||
|
|
||||||
Triplet<uint32_t> x(min, value, max);
|
Triplet<uint32_t> x(min, value, max);
|
||||||
|
|
||||||
EXPECT_EQ(10, x.getMin());
|
EXPECT_EQ(min, x.getMin());
|
||||||
EXPECT_EQ(20, x.get());
|
EXPECT_EQ(value, x.get());
|
||||||
EXPECT_EQ(30, x.getMax());
|
EXPECT_EQ(max, x.getMax());
|
||||||
|
|
||||||
// requested values below min should return allowed min value
|
// requested values below min should return allowed min value
|
||||||
EXPECT_EQ(10, x.get(5));
|
EXPECT_EQ(min, x.get(min - 5));
|
||||||
|
|
||||||
EXPECT_EQ(10, x.get(10));
|
EXPECT_EQ(min, x.get(min));
|
||||||
|
|
||||||
// requesting a value from within the range (min < x < max) should
|
// requesting a value from within the range (min < x < max) should
|
||||||
// return the requested value
|
// return the requested value
|
||||||
EXPECT_EQ(17, x.get(17));
|
EXPECT_EQ(17, x.get(17));
|
||||||
|
|
||||||
EXPECT_EQ(30, x.get(30));
|
EXPECT_EQ(max, x.get(max));
|
||||||
|
|
||||||
EXPECT_EQ(30, x.get(35));
|
EXPECT_EQ(max, x.get(max + 5));
|
||||||
|
|
||||||
// this will be boring. It is expected to return 42 no matter what
|
// this will be boring. It is expected to return 42 no matter what
|
||||||
Triplet<uint32_t> y(42);
|
Triplet<uint32_t> y(42);
|
||||||
@@ -77,15 +77,26 @@ TEST(TripletTest, operator) {
|
|||||||
|
|
||||||
uint32_t x = 47;
|
uint32_t x = 47;
|
||||||
|
|
||||||
// assignment operator: uint32_t => triplet
|
Triplet<uint32_t> foo(1,2,3);
|
||||||
Triplet<uint32_t> y = x;
|
Triplet<uint32_t> bar(4,5,6);
|
||||||
|
|
||||||
EXPECT_EQ(47, y.get());
|
foo = bar;
|
||||||
|
|
||||||
|
EXPECT_EQ(4, foo.getMin());
|
||||||
|
EXPECT_EQ(5, foo.get());
|
||||||
|
EXPECT_EQ(6, foo.getMax());
|
||||||
|
|
||||||
|
// assignment operator: uint32_t => triplet
|
||||||
|
Triplet<uint32_t> y(0);
|
||||||
|
y = x;
|
||||||
|
|
||||||
|
EXPECT_EQ(x, y.get());
|
||||||
|
|
||||||
// let's try the other way around: triplet => uint32_t
|
// let's try the other way around: triplet => uint32_t
|
||||||
uint32_t z = y;
|
uint32_t z = 0;
|
||||||
|
z = y;
|
||||||
|
|
||||||
EXPECT_EQ(47, z);
|
EXPECT_EQ(x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if specified values are sane
|
// check if specified values are sane
|
||||||
@@ -131,6 +142,14 @@ TEST(Pool6Test, constructor_prefix_len) {
|
|||||||
EXPECT_EQ("2001:db8:1::", pool1.getFirstAddress().toText());
|
EXPECT_EQ("2001:db8:1::", pool1.getFirstAddress().toText());
|
||||||
EXPECT_EQ("2001:db8:1::ffff:ffff", pool1.getLastAddress().toText());
|
EXPECT_EQ("2001:db8:1::ffff:ffff", pool1.getLastAddress().toText());
|
||||||
|
|
||||||
|
// No such thing as /130 prefix
|
||||||
|
EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::"), 130),
|
||||||
|
BadValue);
|
||||||
|
|
||||||
|
// /0 prefix does not make sense
|
||||||
|
EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::"), 0),
|
||||||
|
BadValue);
|
||||||
|
|
||||||
// This is Pool6, IPv4 addresses do not belong here
|
// This is Pool6, IPv4 addresses do not belong here
|
||||||
EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("192.168.0.2"), 96),
|
EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("192.168.0.2"), 96),
|
||||||
BadValue);
|
BadValue);
|
||||||
|
@@ -13,10 +13,12 @@
|
|||||||
// PERFORMANCE OF THIS SOFTWARE.
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
#include <log/logger_support.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char* argv[]) {
|
main(int argc, char* argv[]) {
|
||||||
::testing::InitGoogleTest(&argc, argv);
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
isc::log::initLogger();
|
||||||
|
|
||||||
int result = RUN_ALL_TESTS();
|
int result = RUN_ALL_TESTS();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user