Commit c76416e5 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[5306] Implemented getNextSubnet() function for subnets.

parent c27b6b24
......@@ -2192,9 +2192,7 @@ void findClientLease(AllocEngine::ClientContext4& ctx, Lease4Ptr& client_lease)
// Some of the subnets within a shared network may not be allowed
// for the client if classification restrictions have been applied.
if (!subnet->clientSupported(ctx.query_->getClasses())) {
if (network) {
subnet = network->getNextSubnet(original_subnet, subnet);
}
subnet = subnet->getNextSubnet(original_subnet);
continue;
}
......@@ -2235,7 +2233,7 @@ void findClientLease(AllocEngine::ClientContext4& ctx, Lease4Ptr& client_lease)
subnet.reset();
} else {
subnet = network->getNextSubnet(original_subnet, subnet);
subnet = subnet->getNextSubnet(original_subnet);
}
}
}
......@@ -2271,15 +2269,7 @@ inAllowedPool(AllocEngine::ClientContext4& ctx, const IOAddress& address) {
}
}
if (network) {
// Address is not within pools or client class not supported, so
// let's proceed to the next subnet.
current_subnet = network->getNextSubnet(ctx.subnet_, current_subnet);
} else {
// No shared network, so there are no more subnets to try.
current_subnet.reset();
}
current_subnet = current_subnet->getNextSubnet(ctx.subnet_);
}
return (false);
......@@ -2966,9 +2956,7 @@ AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
// Some of the subnets within a shared network may not be allowed
// for the client if classification restrictions have been applied.
if (!subnet->clientSupported(ctx.query_->getClasses())) {
if (network) {
subnet = network->getNextSubnet(original_subnet, subnet);
}
subnet = subnet->getNextSubnet(original_subnet);
continue;
}
......@@ -2993,23 +2981,16 @@ AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
break;
}
}
++total_attempts;
}
total_attempts += max_attempts;
// If our current subnet belongs to a shared network, let's try other
// subnets in the same shared network.
if (network) {
subnet = network->getNextSubnet(original_subnet, subnet);
// This pointer may be set to NULL if hooks set SKIP status.
if (subnet) {
subnet = subnet->getNextSubnet(original_subnet);
if (subnet) {
ctx.subnet_ = subnet;
}
} else {
// Subnet doesn't belong to a shared network so we have no more
// subnets/address pools to try. The client won't get the lease.
subnet.reset();
}
}
......
......@@ -157,16 +157,7 @@ public:
template<typename SubnetPtrType, typename SubnetCollectionType>
static SubnetPtrType getNextSubnet(const SubnetCollectionType& subnets,
const SubnetPtrType& first_subnet,
const SubnetPtrType& current_subnet) {
// Current subnet must not be null. The caller must explicitly set it
// to one of the pointers that belong to this shared network, typically
// to a selected subnet.
if (!current_subnet) {
isc_throw(BadValue, "null subnet specified for a shared"
" network while searching for next subnet is this"
" network");
}
const SubnetID& current_subnet) {
// It is ok to have a shared network without any subnets, but in this
// case there is nothing else we can return but null pointer.
if (subnets.empty()) {
......@@ -177,9 +168,9 @@ public:
// subnet must exist in this container, thus we throw if the iterator
// is not found.
const auto& index = subnets.template get<SubnetSubnetIdIndexTag>();
auto subnet_id_it = index.find(current_subnet->getID());
auto subnet_id_it = index.find(current_subnet);
if (subnet_id_it == index.cend()) {
isc_throw(BadValue, "no such subnet " << current_subnet->getID()
isc_throw(BadValue, "no such subnet " << current_subnet
<< " within shared network");
}
......@@ -235,7 +226,7 @@ SharedNetwork4::getSubnet(const SubnetID& subnet_id) const {
Subnet4Ptr
SharedNetwork4::getNextSubnet(const Subnet4Ptr& first_subnet,
const Subnet4Ptr& current_subnet) const {
const SubnetID& current_subnet) const {
return (Impl::getNextSubnet(subnets_, first_subnet, current_subnet));
}
......@@ -283,7 +274,7 @@ SharedNetwork6::getSubnet(const SubnetID& subnet_id) const {
Subnet6Ptr
SharedNetwork6::getNextSubnet(const Subnet6Ptr& first_subnet,
const Subnet6Ptr& current_subnet) const {
const SubnetID& current_subnet) const {
return (Impl::getNextSubnet(subnets_, first_subnet,
current_subnet));
}
......
......@@ -103,7 +103,7 @@ public:
/// @param first_subnet Pointer to a subnet from which the caller is
/// iterating over subnets within shared network. This is typically a
/// subnet selected during "subnet selection" step.
/// @param current_subnet Pointer to a subnet for which next subnet is
/// @param current_subnet Identifier of a subnet for which next subnet is
/// to be found.
///
/// @return Pointer to next subnet or null pointer if no more subnets found.
......@@ -111,7 +111,7 @@ public:
/// @throw isc::BadValue if invalid arguments specified, e.g. unable to
/// find first or current subnet within shared network.
Subnet4Ptr getNextSubnet(const Subnet4Ptr& first_subnet,
const Subnet4Ptr& current_subnet) const;
const SubnetID& current_subnet) const;
/// @brief Unparses shared network object.
///
......@@ -226,7 +226,7 @@ public:
/// @param first_subnet Pointer to a subnet from which the caller is
/// iterating over subnets within shared network. This is typically a
/// subnet selected during "subnet selection" step.
/// @param current_subnet Pointer to a subnet for which next subnet is
/// @param current_subnet Identifier of a subnet for which next subnet is
/// to be found.
///
/// @return Pointer to next subnet or null pointer if no more subnets found.
......@@ -234,7 +234,7 @@ public:
/// @throw isc::BadValue if invalid arguments specified, e.g. unable to
/// find first or current subnet within shared network.
Subnet6Ptr getNextSubnet(const Subnet6Ptr& first_subnet,
const Subnet6Ptr& current_subnet) const;
const SubnetID& current_subnet) const;
/// @brief Unparses shared network object.
///
......
......@@ -9,6 +9,7 @@
#include <asiolink/io_address.h>
#include <dhcp/option_space.h>
#include <dhcpsrv/addr_utilities.h>
#include <dhcpsrv/shared_network.h>
#include <dhcpsrv/subnet.h>
#include <algorithm>
#include <sstream>
......@@ -176,6 +177,17 @@ Subnet4::Subnet4(const isc::asiolink::IOAddress& prefix, uint8_t length,
setValid(valid_lifetime);
}
Subnet4Ptr
Subnet4::getNextSubnet(const Subnet4Ptr& first_subnet) const {
SharedNetwork4Ptr network;
getSharedNetwork(network);
if (network) {
return (network->getNextSubnet(first_subnet, getID()));
}
return (Subnet4Ptr());
}
bool
Subnet4::clientSupported(const isc::dhcp::ClientClasses& client_classes) const {
NetworkPtr network;
......@@ -450,6 +462,17 @@ void Subnet6::checkType(Lease::Type type) const {
}
}
Subnet6Ptr
Subnet6::getNextSubnet(const Subnet6Ptr& first_subnet) const {
SharedNetwork6Ptr network;
getSharedNetwork(network);
if (network) {
return (network->getNextSubnet(first_subnet, getID()));
}
return (Subnet6Ptr());
}
bool
Subnet6::clientSupported(const isc::dhcp::ClientClasses& client_classes) const {
NetworkPtr network;
......
......@@ -371,6 +371,14 @@ protected:
typedef boost::shared_ptr<Subnet> SubnetPtr;
class Subnet4;
/// @brief A const pointer to a @c Subnet4 object.
typedef boost::shared_ptr<const Subnet4> ConstSubnet4Ptr;
/// @brief A pointer to a @c Subnet4 object.
typedef boost::shared_ptr<Subnet4> Subnet4Ptr;
/// @brief A configuration holder for IPv4 subnet.
///
/// This class represents an IPv4 subnet.
......@@ -394,6 +402,20 @@ public:
const Triplet<uint32_t>& valid_lifetime,
const SubnetID id = 0);
/// @brief Returns next subnet within shared network.
///
/// If the current subnet doesn't belong to any shared network or if
/// the next subnet is the same as first subnet (specified in the
/// arguments) a NULL pointer is returned.
///
/// @param first_subnet Pointer to the subnet from which iterations have
/// started.
///
/// @return Pointer to the next subnet or NULL pointer if the next subnet
/// is the first subnet or if the current subnet doesn't belong to a
/// shared network.
Subnet4Ptr getNextSubnet(const Subnet4Ptr& first_subnet) const;
/// @brief Checks whether this subnet and parent shared network supports
/// the client that belongs to specified classes.
///
......@@ -464,12 +486,13 @@ private:
Cfg4o6 dhcp4o6_;
};
/// @brief A const pointer to a @c Subnet4 object.
typedef boost::shared_ptr<const Subnet4> ConstSubnet4Ptr;
class Subnet6;
/// @brief A pointer to a @c Subnet4 object.
typedef boost::shared_ptr<Subnet4> Subnet4Ptr;
/// @brief A const pointer to a @c Subnet6 object.
typedef boost::shared_ptr<const Subnet6> ConstSubnet6Ptr;
/// @brief A pointer to a Subnet6 object
typedef boost::shared_ptr<Subnet6> Subnet6Ptr;
/// @brief A configuration holder for IPv6 subnet.
///
......@@ -496,6 +519,20 @@ public:
const Triplet<uint32_t>& valid_lifetime,
const SubnetID id = 0);
/// @brief Returns next subnet within shared network.
///
/// If the current subnet doesn't belong to any shared network or if
/// the next subnet is the same as first subnet (specified in the
/// arguments) a NULL pointer is returned.
///
/// @param first_subnet Pointer to the subnet from which iterations have
/// started.
///
/// @return Pointer to the next subnet or NULL pointer if the next subnet
/// is the first subnet or if the current subnet doesn't belong to a
/// shared network.
Subnet6Ptr getNextSubnet(const Subnet6Ptr& first_subnet) const;
/// @brief Checks whether this subnet and parent shared network supports
/// the client that belongs to specified classes.
///
......@@ -533,12 +570,6 @@ private:
};
/// @brief A const pointer to a @c Subnet6 object.
typedef boost::shared_ptr<const Subnet6> ConstSubnet6Ptr;
/// @brief A pointer to a Subnet6 object
typedef boost::shared_ptr<Subnet6> Subnet6Ptr;
/// @name Definition of the multi index container holding subnet information
///
//@{
......
......@@ -164,7 +164,7 @@ TEST(SharedNetwork4Test, getNextSubnet) {
// Iterate over the subnets starting from the subnet with index i.
for (auto j = 0; j < subnets.size(); ++j) {
// Get next subnet (following the one currently in s).
s = networks[0]->getNextSubnet(subnets[i], s);
s = networks[0]->getNextSubnet(subnets[i], s->getID());
// The last iteration should return empty pointer to indicate end of
// the subnets within shared network. If we're not at last iteration
// check that the subnet identifier of the returned subnet is valid.
......@@ -426,7 +426,7 @@ TEST(SharedNetwork6Test, getNextSubnet) {
// Iterate over the subnets starting from the subnet with index i.
for (auto j = 0; j < subnets.size(); ++j) {
// Get next subnet (following the one currently in s).
s = networks[0]->getNextSubnet(subnets[i], s);
s = networks[0]->getNextSubnet(subnets[i], s->getID());
// The last iteration should return empty pointer to indicate end of
// the subnets within shared network. If we're not at last iteration
// check that the subnet identifier of the returned subnet is valid.
......
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