2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-30 13:37:55 +00:00

[4294] Memfile now supports IPv6 lease stats recounting

src/lib/dhcpsrv/memfile_lease_mgr.h
src/lib/dhcpsrv/memfile_lease_mgr.cc
    - MemfileAddressStatsQuery6 - new class, Memfile derivation of
    the IPv6 statistical lease data query
    - Memfile_LeaseMgr::startAddressStatsQuery6() - new virtual
    method that creates and runs the IPv6 lease stats query

src/lib/dhcpsrv/memfile_lease_storage.h
    - Added non-unique index on subnet ID to Lease6Storage

src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc
    TEST_F(MemfileLeaseMgrTest, recountAddressStats6) - new test
This commit is contained in:
Thomas Markwalder
2016-08-16 14:15:25 -04:00
parent efbf437f6d
commit 4a94a1f7b9
5 changed files with 199 additions and 2 deletions

View File

@@ -229,8 +229,8 @@ struct AddressStatsRow6 {
AddressStatsRow6(const SubnetID& subnet_id, const Lease::Type& lease_type,
const Lease::LeaseState& lease_state,
const int64_t state_count)
: subnet_id_(subnet_id), lease_state_(lease_state),
state_count_(state_count) {
: subnet_id_(subnet_id), lease_type_(lease_type),
lease_state_(lease_state), state_count_(state_count) {
}
/// @brief The subnet ID to which this data applies

View File

@@ -393,6 +393,168 @@ MemfileAddressStatsQuery4::getRowCount() {
return (rows_.size());
}
/// @brief Memfile derivation of the IPv6 statistical lease data query
///
/// This class is used to recalculate IPv6 lease statistics for Memfile
/// lease storage. It does so by iterating over the given storage,
/// accumulating counts of leases in each of the monitored lease states
/// for each subnet and storing these counts in an internal collection.
/// The populated result set will contain one entry per monitored state
/// per subnet.
///
class MemfileAddressStatsQuery6 : public AddressStatsQuery6 {
public:
/// @brief Constructor
///
/// @param storage6 A pointer to the v6 lease storage to be counted
MemfileAddressStatsQuery6(Lease6Storage& storage6);
/// @brief Destructor
virtual ~MemfileAddressStatsQuery6() {};
/// @brief Creates the IPv6 lease statistical data result set
///
/// The result is populated by iterating over the IPv6 leases in storage,
/// in ascending order by subnet ID, accumulating the lease state counts
/// per lease type. At the completion of all entries for a given subnet,
/// the counts are used to create AddressStatsRow5 instances which are
/// appended to an internal vector. The process results in a vector
/// containing one entry per state per lease type per subnet.
///
/// Currently the states counted are:
///
/// - Lease::STATE_DEFAULT (i.e. assigned)
/// - Lease::STATE_DECLINED
virtual void start();
/// @brief Fetches the next row in the result set
///
/// Once the internal result set has been populated by invoking the
/// the start() method, this method is used to iterate over the
/// result set rows. Once the last row has been fetched, subsequent
/// calls will return false.
/// @param row Storage for the fetched row
///
/// @return True if the fetch succeeded, false if there are no more
/// rows to fetch.
virtual bool getNextRow(AddressStatsRow6& row);
/// @brief Returns the number of rows in the result set
/// @todo, should this be a virtual member of the base class?
int getRowCount();
private:
/// @brief The Memfile storage containing the IPv6 leases to analyze
Lease6Storage& storage6_;
/// @brief A vector containing the "result set"
std::vector<AddressStatsRow6> rows_;
/// @brief An iterator for accessing the next row within the result set
std::vector<AddressStatsRow6>::iterator next_pos_;
};
MemfileAddressStatsQuery6::MemfileAddressStatsQuery6(Lease6Storage& storage6)
: storage6_(storage6), rows_(0), next_pos_(rows_.end()) {};
void
MemfileAddressStatsQuery6::start() {
// Get the subnet_id index
const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
// Iterate over the leases in order by subnet, accumulating per
// subnet counts for each state of interest. As we finish each
// subnet, add the appropriate rows to our result set.
SubnetID cur_id = 0;
int64_t assigned = 0;
int64_t declined = 0;
int64_t assigned_pds = 0;
for(Lease6StorageSubnetIdIndex::const_iterator lease = idx.begin();
lease != idx.end(); ++lease) {
// If we've hit the next subnet, add rows for the current subnet
// and wipe the accumulators
if ((*lease)->subnet_id_ > cur_id) {
if (cur_id > 0) {
rows_.push_back(AddressStatsRow6(cur_id, Lease::TYPE_NA,
Lease::STATE_DEFAULT,
assigned));
assigned = 0;
rows_.push_back(AddressStatsRow6(cur_id, Lease::TYPE_NA,
Lease::STATE_DECLINED,
declined));
declined = 0;
rows_.push_back(AddressStatsRow6(cur_id, Lease::TYPE_PD,
Lease::STATE_DEFAULT,
assigned_pds));
assigned_pds = 0;
}
// Update current subnet id
cur_id = (*lease)->subnet_id_;
}
// Bump the appropriate accumulator
switch ((*lease)->state_) {
case Lease::STATE_DEFAULT:
switch((*lease)->type_) {
case Lease::TYPE_NA:
++assigned;
break;
case Lease::TYPE_PD:
++assigned_pds;
break;
default:
break;
}
break;
case Lease::STATE_DECLINED:
// In theory only NAs can be declined
if (((*lease)->type_) == Lease::TYPE_NA) {
++declined;
}
break;
default:
// Not one we're tracking.
break;
}
}
// Make the rows for last subnet, unless there were no rows
if (idx.begin() != idx.end()) {
rows_.push_back(AddressStatsRow6(cur_id, Lease::TYPE_NA,
Lease::STATE_DEFAULT,
assigned));
rows_.push_back(AddressStatsRow6(cur_id, Lease::TYPE_NA,
Lease::STATE_DECLINED,
declined));
rows_.push_back(AddressStatsRow6(cur_id, Lease::TYPE_PD,
Lease::STATE_DEFAULT,
assigned_pds));
}
// Set the next row position to the beginning of the rows.
next_pos_ = rows_.begin();
}
bool
MemfileAddressStatsQuery6::getNextRow(AddressStatsRow6& row) {
if (next_pos_ == rows_.end()) {
return (false);
}
row = *next_pos_;
++next_pos_;
return (true);
}
int
MemfileAddressStatsQuery6::getRowCount() {
return (rows_.size());
}
// Explicit definition of class static constants. Values are given in the
// declaration so they're not needed here.
const int Memfile_LeaseMgr::MAJOR_VERSION;
@@ -1193,5 +1355,12 @@ Memfile_LeaseMgr::startAddressStatsQuery4() {
return(query);
}
AddressStatsQuery6Ptr
Memfile_LeaseMgr::startAddressStatsQuery6() {
AddressStatsQuery6Ptr query(new MemfileAddressStatsQuery6(storage6_));
query->start();
return(query);
}
} // end of namespace isc::dhcp
} // end of namespace isc

View File

@@ -604,6 +604,15 @@ public:
/// @return The populated query as a pointer to an AddressStatsQuery4
virtual AddressStatsQuery4Ptr startAddressStatsQuery4();
/// @brief Creates and runs the IPv6 lease stats query
///
/// It creates an instance of a MemfileAddressStatsQuery6 and then
/// invokes it's start method in which the query constructs its
/// statistical data result set. The query object is then returned.
///
/// @return The populated query as a pointer to an AddressStatsQuery6
virtual AddressStatsQuery6Ptr startAddressStatsQuery6();
/// @name Protected methods used for %Lease File Cleanup.
/// The following methods are protected so as they can be accessed and
/// tested by unit tests.

View File

@@ -106,7 +106,17 @@ typedef boost::multi_index_container<
boost::multi_index::const_mem_fun<Lease, int64_t,
&Lease::getExpirationTime>
>
>,
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<SubnetIdIndexTag>,
// The subnet id is held in the subnet_id_ member of Lease6
// class. Note that the subnet_id_ is defined in the base
// class (Lease) so we have to point to this class rather
// than derived class: Lease6.
boost::multi_index::member<Lease, SubnetID, &Lease::subnet_id_>
>
>
> Lease6Storage; // Specify the type name of this container.
@@ -241,6 +251,9 @@ typedef Lease6Storage::index<DuidIaidTypeIndexTag>::type Lease6StorageDuidIaidTy
/// @brief DHCPv6 lease storage index by expiration time.
typedef Lease6Storage::index<ExpirationIndexTag>::type Lease6StorageExpirationIndex;
/// @brief DHCPv6 lease storage index by subnet id.
typedef Lease6Storage::index<SubnetIdIndexTag>::type Lease6StorageSubnetIdIndex;
/// @brief DHCPv4 lease storage index by address.
typedef Lease4Storage::index<AddressIndexTag>::type Lease4StorageAddressIndex;

View File

@@ -1889,4 +1889,10 @@ TEST_F(MemfileLeaseMgrTest, recountAddressStats4) {
testRecountAddressStats4();
}
// Verifies that IPv6 lease statistics can be recalculated.
TEST_F(MemfileLeaseMgrTest, recountAddressStats6) {
startBackend(V6);
testRecountAddressStats6();
}
}; // end of anonymous namespace