Parcourir la source

[3799] Add v6 subnet statistics

Using the v4 changes as a guide (3798) add statistics
for subnets for v6.  The four stats are total addresses
and addresses used for both NA and PD.
Shawn Routhier il y a 10 ans
Parent
commit
5f8a84bd13

+ 88 - 0
doc/guide/dhcp6-srv.xml

@@ -2579,6 +2579,94 @@ should include options from the isc option space:
     </para>
     </section>
 
+    <section id="dhcp6-stats">
+      <title>Statistics in DHCPv6 server</title>
+      <note>
+        <para>This section describes DHCPv6-specific statistics. For a general
+        overview and usage of statistics, see <xref linkend="stats" />.</para>
+      </note>
+
+      <para>
+        The DHCPv6 server supports the following statistics:
+      </para>
+        <table frame="all" id="dhcp4-statistics">
+          <title>DHCPv6 Statistics</title>
+          <tgroup cols='3'>
+          <colspec colname='statistic' align='center'/>
+          <colspec colname='type' align='center'/>
+          <colspec colname='description' align='left'/>
+          <thead>
+            <row>
+              <entry>Statistic</entry>
+              <entry>Data Type</entry>
+              <entry>Description</entry>
+            </row>
+          </thead>
+          <tbody>
+
+            <row>
+            <entry>subnet[id].total-NAs</entry>
+            <entry>integer</entry>
+            <entry>
+            This statistic shows the total number of NA addresses available for the
+            DHCPv6 management. In other words, this is the sum of all addresses in
+            all configured pools. This statistic changes only during configuration
+            changes. Note it does not take into account any addresses that may be
+            reserved due to host reservation. The <emphasis>id</emphasis> is the
+            subnet-id of a given subnet. This statistic is exposed for each subnet
+	    separately. This statistic is reset during reconfiguration event.
+            </entry>
+            </row>
+
+            <row>
+            <entry>subnet[id].assigned-NAs</entry>
+            <entry>integer</entry>
+            <entry>
+            This statistic shows the number of assigned NA addresses in a given subnet.
+            This statistic increases every time a new lease is allocated (as a result
+            of receiving a REQUEST message) and is decreased every time a lease is
+            released (a RELEASE message is received). When lease expiration
+            is implemented (planned for Kea 1.0), it will also decrease when a lease
+            is expired. The <emphasis>id</emphasis> is the subnet-id of a given
+            subnet. This statistic is exposed for each subnet separately. This
+            statistic is reset during reconfiguration event.
+            </entry>
+            </row>
+
+            <row>
+            <entry>subnet[id].total-PDs</entry>
+            <entry>integer</entry>
+            <entry>
+            This statistic shows the total number of PD prefixes available for the
+            DHCPv6 management. In other words, this is the sum of all prefixes in
+            all configured pools. This statistic changes only during configuration
+            changes. Note it does not take into account any prefixes that may be
+            reserved due to host reservation. The <emphasis>id</emphasis> is the
+            subnet-id of a given subnet. This statistic is exposed for each subnet
+	    separately. This statistic is reset during reconfiguration event.
+            </entry>
+            </row>
+
+            <row>
+            <entry>subnet[id].assigned-NAs</entry>
+            <entry>integer</entry>
+            <entry>
+            This statistic shows the number of assigned PD prefixes in a given subnet.
+            This statistic increases every time a new lease is allocated (as a result
+            of receiving a REQUEST message) and is decreased every time a lease is
+            released (a RELEASE message is received). When lease expiration
+            is implemented (planned for Kea 1.0), it will also decrease when a lease
+            is expired. The <emphasis>id</emphasis> is the subnet-id of a given
+            subnet. This statistic is exposed for each subnet separately. This
+            statistic is reset during reconfiguration event.
+            </entry>
+            </row>
+
+        </tbody>
+        </tgroup>
+        </table>
+    </section>
+
     <section id="dhcp6-std">
       <title>Supported DHCPv6 Standards</title>
       <para>The following standards are currently

+ 1 - 0
src/bin/dhcp6/Makefile.am

@@ -78,6 +78,7 @@ kea_dhcp6_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
 kea_dhcp6_LDADD += $(top_builddir)/src/lib/log/libkea-log.la
 kea_dhcp6_LDADD += $(top_builddir)/src/lib/util/libkea-util.la
 kea_dhcp6_LDADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la
+kea_dhcp6_LDADD += $(top_builddir)/src/lib/stats/libkea-stats.la
 kea_dhcp6_LDADD += $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la
 kea_dhcp6_LDADD += $(top_builddir)/src/bin/cfgrpt/libcfgrpt.la
 

+ 12 - 0
src/bin/dhcp6/dhcp6_srv.cc

@@ -45,6 +45,7 @@
 #include <hooks/callout_handle.h>
 #include <hooks/hooks_log.h>
 #include <hooks/hooks_manager.h>
+#include <stats/stats_mgr.h>
 
 #include <util/encode/hex.h>
 #include <util/io_utilities.h>
@@ -74,6 +75,7 @@ using namespace isc::dhcp_ddns;
 using namespace isc::hooks;
 using namespace isc::log;
 using namespace isc::util;
+using namespace isc::stats;
 using namespace std;
 
 namespace {
@@ -2210,6 +2212,11 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query,
         ia_rsp->addOption(createStatusCode(*query, *ia_rsp, STATUS_Success,
                           "Lease released. Thank you, please come again."));
 
+        // Need to decrease statistic for assigned addresses.
+        StatsMgr::instance().addValue(
+            StatsMgr::generateName("subnet", lease->subnet_id_, "assigned-NAs"),
+            static_cast<int64_t>(-1));
+
         // Check if a lease has flags indicating that the FQDN update has
         // been performed. If so, create NameChangeRequest which removes
         // the entries.
@@ -2360,6 +2367,11 @@ Dhcpv6Srv::releaseIA_PD(const DuidPtr& duid, const Pkt6Ptr& query,
 
         ia_rsp->addOption(createStatusCode(*query, *ia_rsp, STATUS_Success,
                           "Lease released. Thank you, please come again."));
+
+        // Need to decrease statistic for assigned prefixes.
+        StatsMgr::instance().addValue(
+            StatsMgr::generateName("subnet", lease->subnet_id_, "assigned-PDs"),
+            static_cast<int64_t>(-1));
     }
 
     return (ia_rsp);

+ 1 - 0
src/bin/dhcp6/tests/Makefile.am

@@ -105,6 +105,7 @@ dhcp6_unittests_LDADD += $(top_builddir)/src/lib/dhcpsrv/libkea-dhcpsrv.la
 dhcp6_unittests_LDADD += $(top_builddir)/src/lib/dhcpsrv/testutils/libdhcpsrvtest.la
 dhcp6_unittests_LDADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la
 dhcp6_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
+dhcp6_unittests_LDADD += $(top_builddir)/src/lib/stats/libkea-stats.la
 dhcp6_unittests_LDADD += $(top_builddir)/src/lib/log/libkea-log.la
 dhcp6_unittests_LDADD += $(top_builddir)/src/lib/util/libkea-util.la
 dhcp6_unittests_LDADD += $(top_builddir)/src/lib/util/io/libkea-util-io.la

+ 26 - 1
src/lib/dhcpsrv/alloc_engine.cc

@@ -812,6 +812,13 @@ AllocEngine::removeNonmatchingReservedLeases6(ClientContext6& ctx,
         // Remove this lease from LeaseMgr
         LeaseMgrFactory::instance().deleteLease((*candidate)->addr_);
 
+        // Need to decrease statistic for assigned addresses.
+        StatsMgr::instance().addValue(
+            StatsMgr::generateName("subnet", ctx.subnet_->getID(),
+                                   ctx.type_ == Lease::TYPE_NA ? "assigned-NAs" :
+                                                                 "assigned-PDs"),
+            static_cast<int64_t>(-1));
+
         // In principle, we could trigger a hook here, but we will do this
         // only if we get serious complaints from actual users. We want the
         // conflict resolution procedure to really work and user libraries
@@ -868,6 +875,13 @@ AllocEngine::removeNonreservedLeases6(ClientContext6& ctx,
             // Remove this lease from LeaseMgr
             LeaseMgrFactory::instance().deleteLease((*lease)->addr_);
 
+            // Need to decrease statistic for assigned addresses.
+            StatsMgr::instance().addValue(
+                StatsMgr::generateName("subnet", ctx.subnet_->getID(),
+                                       ctx.type_ == Lease::TYPE_NA ? "assigned-NAs" :
+                                                                     "assigned-PDs"),
+                static_cast<int64_t>(-1));
+
             /// @todo: Probably trigger a hook here
 
             // Add this to the list of removed leases.
@@ -1024,6 +1038,12 @@ Lease6Ptr AllocEngine::createLease6(ClientContext6& ctx,
         bool status = LeaseMgrFactory::instance().addLease(lease);
 
         if (status) {
+            // The lease insertion succeeded, let's bump up the statistic.
+            StatsMgr::instance().addValue(
+                StatsMgr::generateName("subnet", ctx.subnet_->getID(),
+                                       ctx.type_ == Lease::TYPE_NA ? "assigned-NAs" :
+                                                                     "assigned-PDs"),
+                static_cast<int64_t>(1));
 
             return (lease);
         } else {
@@ -1140,6 +1160,11 @@ AllocEngine::extendLease6(ClientContext6& ctx, Lease6Ptr lease) {
         // Remove this lease from LeaseMgr
         LeaseMgrFactory::instance().deleteLease(lease->addr_);
 
+        // Need to decrease statistic for assigned addresses.
+        StatsMgr::instance().addValue(
+            StatsMgr::generateName("subnet", ctx.subnet_->getID(), "assigned-NAs"),
+            static_cast<int64_t>(-1));
+
         // Add it to the removed leases list.
         ctx.old_leases_.push_back(lease);
 
@@ -1779,7 +1804,7 @@ AllocEngine::createLease4(const ClientContext4& ctx, const IOAddress& addr) {
         if (status) {
 
             // The lease insertion succeeded, let's bump up the statistic.
-            isc::stats::StatsMgr::instance().addValue(
+            StatsMgr::instance().addValue(
                 StatsMgr::generateName("subnet", ctx.subnet_->getID(), "assigned-addresses"),
                 static_cast<int64_t>(1));
 

+ 48 - 0
src/lib/dhcpsrv/cfg_subnets6.cc

@@ -16,6 +16,7 @@
 #include <dhcpsrv/cfg_subnets6.h>
 #include <dhcpsrv/dhcpsrv_log.h>
 #include <dhcpsrv/subnet_id.h>
+#include <stats/stats_mgr.h>
 
 using namespace isc::asiolink;
 
@@ -179,5 +180,52 @@ CfgSubnets6::isDuplicate(const Subnet6& subnet) const {
     return (false);
 }
 
+void
+CfgSubnets6::removeStatistics() {
+    using namespace isc::stats;
+
+    // For each v6 subnet currently configured, remove the statistic.
+    /// @todo: May move this to CfgSubnets6 class if there will be more
+    /// statistics here.
+    for (Subnet6Collection::const_iterator subnet6 = subnets_.begin();
+         subnet6 != subnets_.end(); ++subnet6) {
+
+        StatsMgr::instance().del(StatsMgr::generateName("subnet",
+                                                        (*subnet6)->getID(),
+                                                        "total-NAs"));
+
+        StatsMgr::instance().del(StatsMgr::generateName("subnet",
+                                                        (*subnet6)->getID(),
+                                                        "assigned-NAs"));
+
+        StatsMgr::instance().del(StatsMgr::generateName("subnet",
+                                                        (*subnet6)->getID(),
+                                                        "total-PDs"));
+
+        StatsMgr::instance().del(StatsMgr::generateName("subnet",
+                                                        (*subnet6)->getID(),
+                                                        "assigned-PDs"));
+    }
+}
+
+void
+CfgSubnets6::updateStatistics() {
+    using namespace isc::stats;
+
+    /// @todo: May move this to CfgSubnets6 class if there will be more
+    /// statistics here.
+    for (Subnet6Collection::const_iterator subnet = subnets_.begin();
+         subnet != subnets_.end(); ++subnet) {
+
+        StatsMgr::instance().setValue(
+            StatsMgr::generateName("subnet", (*subnet)->getID(), "total-NAs"),
+            static_cast<int64_t>((*subnet)->getPoolCapacity(Lease::TYPE_NA)));
+
+        StatsMgr::instance().setValue(
+            StatsMgr::generateName("subnet", (*subnet)->getID(), "total-PDs"),
+            static_cast<int64_t>((*subnet)->getPoolCapacity(Lease::TYPE_PD)));
+    }
+}
+
 } // end of namespace isc::dhcp
 } // end of namespace isc

+ 18 - 1
src/lib/dhcpsrv/cfg_subnets6.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -132,6 +132,23 @@ public:
                  const ClientClasses& client_classes = ClientClasses(),
                  const bool is_relay_address = false) const;
 
+    /// @brief Updates statistics.
+    ///
+    /// This method updates statistics that are affected by the newly committed
+    /// configuration. In particular, it updates the number of available addresses
+    /// and prefixes in each subnet. Other statistics may be added in the future. In
+    /// general, these are statistics that are dependant only on configuration, so
+    /// they are not expected to change until the next reconfiguration event.
+    void updateStatistics();
+
+    /// @brief Removes statistics.
+    ///
+    /// During commitment of a new configuration, we need to get rid of the old
+    /// statistics for the old configuration. In particular, we need to remove
+    /// anything related to subnets, as there may be fewer subnets in the new
+    /// configuration and also subnet-ids may change.
+    void removeStatistics();
+
 private:
 
     /// @brief Selects a subnet using the interface name.

+ 7 - 4
src/lib/dhcpsrv/srv_config.cc

@@ -148,16 +148,19 @@ SrvConfig::equals(const SrvConfig& other) const {
 void
 SrvConfig::removeStatistics() {
 
-    // For now, this method only removes statistics for v4 subnets, but in the
-    // near future, we'll also get statistics for v6 subnets.
+    // Removes statistics for v4 and v6 subnets
     getCfgSubnets4()->removeStatistics();
+
+    getCfgSubnets6()->removeStatistics();
 }
 
 void
 SrvConfig::updateStatistics() {
-    // For now, this method only updates statistics for v4 subnets, but in the
-    // near future, we'll also get statistics for v6 subnets.
+
+    // Updates  statistics for v4 and v6 subnets
     getCfgSubnets4()->updateStatistics();
+
+    getCfgSubnets6()->updateStatistics();
 }
 
 }

+ 4 - 2
src/lib/dhcpsrv/srv_config.h

@@ -352,13 +352,15 @@ public:
     /// @brief Updates statistics.
     ///
     /// This method calls appropriate methods in child objects that update
-    /// related statistics. See @ref CfgSubnets4::updateStatistics for details.
+    /// related statistics. See @ref CfgSubnets4::updateStatistics and
+    /// @ref CfgSubnets6::updateStatistics for details.
     void updateStatistics();
 
     /// @brief Removes statistics.
     ///
     /// This method calls appropriate methods in child objects that remove
-    /// related statistics. See @ref CfgSubnets4::removeStatistics for details.
+    /// related statistics. See @ref CfgSubnets4::removeStatistics and
+    /// @ref CfgSubnets6::removeStatistics for details.
     void removeStatistics();
 
 private:

+ 92 - 1
src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc

@@ -17,10 +17,12 @@
 #include <dhcp/pkt6.h>
 #include <dhcpsrv/tests/alloc_engine_utils.h>
 #include <dhcpsrv/tests/test_utils.h>
+#include <stats/stats_mgr.h>
 
 using namespace std;
 using namespace isc::hooks;
 using namespace isc::asiolink;
+using namespace isc::stats;
 
 namespace isc {
 namespace dhcp {
@@ -52,23 +54,61 @@ TEST_F(AllocEngine6Test, constructor) {
 
 // This test checks if the simple allocation (REQUEST) can succeed
 TEST_F(AllocEngine6Test, simpleAlloc6) {
+
+    // Pretend our pool has allocated 100 addresses
+    string name = StatsMgr::generateName("subnet", subnet_->getID(), "assigned-NAs");
+    StatsMgr::instance().addValue(name, static_cast<int64_t>(100));
+
     simpleAlloc6Test(pool_, IOAddress("::"), false);
+
+    // We should have bumped the address counter by 1
+    ObservationPtr stat = StatsMgr::instance().getObservation(name);
+    ASSERT_TRUE(stat);
+    EXPECT_EQ(101, stat->getInteger().first);
 }
 
 // This test checks if the simple PD allocation (REQUEST) can succeed
 TEST_F(AllocEngine6Test, pdSimpleAlloc6) {
+
+    // Pretend our pool has allocated 100 prefixes
+    string name = StatsMgr::generateName("subnet", subnet_->getID(), "assigned-PDs");
+    StatsMgr::instance().addValue(name, static_cast<int64_t>(100));
+
     simpleAlloc6Test(pd_pool_, IOAddress("::"), false);
+
+    // We should have bumped the address counter by 1
+    ObservationPtr stat = StatsMgr::instance().getObservation(name);
+    ASSERT_TRUE(stat);
+    EXPECT_EQ(101, stat->getInteger().first);
 }
 
 // This test checks if the fake allocation (for SOLICIT) can succeed
 TEST_F(AllocEngine6Test, fakeAlloc6) {
 
+    // Pretend our pool has allocated 100 prefixes
+    string name = StatsMgr::generateName("subnet", subnet_->getID(), "assigned-NAs");
+    StatsMgr::instance().addValue(name, static_cast<int64_t>(100));
+
     simpleAlloc6Test(pool_, IOAddress("::"), true);
+
+    // We should not have bumped the address counter
+    ObservationPtr stat = StatsMgr::instance().getObservation(name);
+    ASSERT_TRUE(stat);
+    EXPECT_EQ(100, stat->getInteger().first);
 }
 
 // This test checks if the fake PD allocation (for SOLICIT) can succeed
 TEST_F(AllocEngine6Test, pdFakeAlloc6) {
+    // Pretend our pool has allocated 100 prefixes
+    string name = StatsMgr::generateName("subnet", subnet_->getID(), "assigned-PDs");
+    StatsMgr::instance().addValue(name, static_cast<int64_t>(100));
+
     simpleAlloc6Test(pd_pool_, IOAddress("::"), true);
+
+    // We should not have bumped the address counter
+    ObservationPtr stat = StatsMgr::instance().getObservation(name);
+    ASSERT_TRUE(stat);
+    EXPECT_EQ(100, stat->getInteger().first);
 };
 
 // This test checks if the allocation with a hint that is valid (in range,
@@ -568,7 +608,7 @@ TEST_F(AllocEngine6Test, requestReuseExpiredLease6) {
 // - Client sends SOLICIT without any hints.
 // - Client is allocated a reserved address.
 //
-// Note that DHCPv6 client can, but don't have to send any hints in its
+// Note that a DHCPv6 client can, but doesn't have to send any hints in its
 // Solicit message.
 TEST_F(AllocEngine6Test, reservedAddressInPoolSolicitNoHint) {
     // Create reservation for the client. This is in-pool reservation,
@@ -599,9 +639,18 @@ TEST_F(AllocEngine6Test, reservedAddressInPoolRequestNoHint) {
 
     AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100, false);
 
+    // Pretend our pool has allocated 100 addresses
+    string name = StatsMgr::generateName("subnet", subnet_->getID(), "assigned-NAs");
+    StatsMgr::instance().addValue(name, static_cast<int64_t>(100));
+
     Lease6Ptr lease = simpleAlloc6Test(pool_, IOAddress("::"), false);
     ASSERT_TRUE(lease);
     EXPECT_EQ("2001:db8:1::1c", lease->addr_.toText());
+
+    // We should have bumped the address counter
+    ObservationPtr stat = StatsMgr::instance().getObservation(name);
+    ASSERT_TRUE(stat);
+    EXPECT_EQ(101, stat->getInteger().first);
 }
 
 // Checks that a client gets the address reserved (in-pool case)
@@ -857,16 +906,28 @@ TEST_F(AllocEngine6Test, reservedAddressOutOfPoolRequestMatchingHint) {
 TEST_F(AllocEngine6Test, reservedAddressInPoolReassignedThis) {
     AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100, false);
 
+    // Pretend our pool has allocated 100 addresses
+    string name = StatsMgr::generateName("subnet", subnet_->getID(), "assigned-NAs");
+    StatsMgr::instance().addValue(name, static_cast<int64_t>(100));
+
     // Client gets an address
     Lease6Ptr lease1 = simpleAlloc6Test(pool_, IOAddress("::"), false);
     ASSERT_TRUE(lease1);
 
+    // We should have bumped the address counter
+    ObservationPtr stat = StatsMgr::instance().getObservation(name);
+    ASSERT_TRUE(stat);
+    EXPECT_EQ(101, stat->getInteger().first);
+
     // Just check that if the client requests again, it will get the same
     // address.
     Lease6Ptr lease2 = simpleAlloc6Test(pool_, lease1->addr_, false);
     ASSERT_TRUE(lease2);
     detailCompareLease(lease1, lease2);
 
+    // We should not have bumped the address counter again
+    EXPECT_EQ(101, stat->getInteger().first);
+
     // Now admin creates a reservation for this client. This is in-pool
     // reservation, as the pool is 2001:db8:1::10 - 2001:db8:1::20.
     createHost6(true, IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::1c"), 128);
@@ -894,6 +955,11 @@ TEST_F(AllocEngine6Test, reservedAddressInPoolReassignedThis) {
 
     // Now check that the lease in LeaseMgr has the same parameters
     detailCompareLease(lease3, from_mgr);
+
+    // Lastly check to see that the address counter is still 101 we should have
+    // have decremented it on the implied release and incremented it on the reserved
+    EXPECT_EQ(101, stat->getInteger().first);
+
 }
 
 // In the following situation:
@@ -1363,6 +1429,31 @@ TEST_F(AllocEngine6Test, reservedAddressByMacInPoolRequestValidHint) {
     EXPECT_EQ("2001:db8:1::1c", lease->addr_.toText());
 }
 
+
+// This test checks that NULL values are handled properly
+TEST_F(AllocEngine6Test, allocateAddress6Stats) {
+    boost::scoped_ptr<AllocEngine> engine;
+    ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
+    ASSERT_TRUE(engine);
+
+    // Verify our pool hasn't allocated any addresses
+    string name = StatsMgr::generateName("subnet", subnet_->getID(), "assigned-NAs");
+    StatsMgr::instance().addValue(name, static_cast<int64_t>(100));
+
+    Lease6Ptr lease;
+    AllocEngine::ClientContext6 ctx1(subnet_, duid_, iaid_, IOAddress("::"),
+                                     Lease::TYPE_NA, false, false, "", false);
+    ctx1.query_.reset(new Pkt6(DHCPV6_REQUEST, 1234));
+    EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx1)));
+    ASSERT_TRUE(lease);
+
+    // We should have bumped the address counter by 1
+    ObservationPtr stat = StatsMgr::instance().getObservation(name);
+    ASSERT_TRUE(stat);
+    EXPECT_EQ(101, stat->getInteger().first);
+}
+
+
 }; // namespace test
 }; // namespace dhcp
 }; // namespace isc

+ 91 - 4
src/lib/dhcpsrv/tests/cfgmgr_unittest.cc

@@ -578,12 +578,12 @@ TEST_F(CfgMgrTest, verbosity) {
 
 // This test verifies that once the configuration is committed, statistics
 // are updated appropriately.
-TEST_F(CfgMgrTest, commitStats) {
+TEST_F(CfgMgrTest, commitStats4) {
     CfgMgr& cfg_mgr = CfgMgr::instance();
     StatsMgr& stats_mgr = StatsMgr::instance();
 
     // Let's prepare the "old" configuration: a subnet with id 123
-    // and pretent there ware addresses assigned, so statistics are non-zero.
+    // and pretend there ware addresses assigned, so statistics are non-zero.
     Subnet4Ptr subnet1(new Subnet4(IOAddress("192.1.2.0"), 24, 1, 2, 3, 123));
     CfgSubnets4Ptr subnets = cfg_mgr.getStagingCfg()->getCfgSubnets4();
     subnets->add(subnet1);
@@ -617,12 +617,12 @@ TEST_F(CfgMgrTest, commitStats) {
 
 // This test verifies that once the configuration is cleared, the statistics
 // are removed.
-TEST_F(CfgMgrTest, clearStats) {
+TEST_F(CfgMgrTest, clearStats4) {
     CfgMgr& cfg_mgr = CfgMgr::instance();
     StatsMgr& stats_mgr = StatsMgr::instance();
 
     // Let's prepare the "old" configuration: a subnet with id 123
-    // and pretent there ware addresses assigned, so statistics are non-zero.
+    // and pretend there ware addresses assigned, so statistics are non-zero.
     Subnet4Ptr subnet1(new Subnet4(IOAddress("192.1.2.0"), 24, 1, 2, 3, 123));
     CfgSubnets4Ptr subnets = cfg_mgr.getStagingCfg()->getCfgSubnets4();
     subnets->add(subnet1);
@@ -642,6 +642,93 @@ TEST_F(CfgMgrTest, clearStats) {
     EXPECT_FALSE(stats_mgr.getObservation("subnet[123].assigned-addresses"));
 }
 
+// This test verifies that once the configuration is committed, statistics
+// are updated appropriately.
+TEST_F(CfgMgrTest, commitStats6) {
+    CfgMgr& cfg_mgr = CfgMgr::instance();
+    StatsMgr& stats_mgr = StatsMgr::instance();
+
+    // Let's prepare the "old" configuration: a subnet with id 123
+    // and pretend there ware addresses assigned, so statistics are non-zero.
+    Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 48, 1, 2, 3, 4, 123));
+    CfgSubnets6Ptr subnets = cfg_mgr.getStagingCfg()->getCfgSubnets6();
+    subnets->add(subnet1);
+    cfg_mgr.commit();
+    stats_mgr.addValue("subnet[123].total-NAs", static_cast<int64_t>(256));
+    stats_mgr.setValue("subnet[123].assigned-NAs", static_cast<int64_t>(150));
+
+    stats_mgr.addValue("subnet[123].total-PDs", static_cast<int64_t>(256));
+    stats_mgr.setValue("subnet[123].assigned-PDs", static_cast<int64_t>(150));
+
+    // Now, let's change the configuration to something new.
+
+    // There's a subnet 2001:db8:2::/48 with ID=42
+    Subnet6Ptr subnet2(new Subnet6(IOAddress("2001:db8:2::"), 48, 1, 2, 3, 4, 42));
+
+    // Let's make pools with 128 addresses and 65536 prefixes available.
+    PoolPtr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:2::"), 121)); // 128 addrs
+    PoolPtr pool2(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:3::"), 96, 112)); // 65536 prefixes
+    subnet2->addPool(pool1);
+    subnet2->addPool(pool2);
+
+    subnets = cfg_mgr.getStagingCfg()->getCfgSubnets6();
+    subnets->add(subnet2);
+
+    // Let's commit it
+    cfg_mgr.commit();
+
+    EXPECT_FALSE(stats_mgr.getObservation("subnet[123].total-NAs"));
+    EXPECT_FALSE(stats_mgr.getObservation("subnet[123].assigned-NAs"));
+
+    EXPECT_FALSE(stats_mgr.getObservation("subnet[123].total-PDs"));
+    EXPECT_FALSE(stats_mgr.getObservation("subnet[123].assigned-PDs"));
+
+    ObservationPtr total_addrs;
+    EXPECT_NO_THROW(total_addrs = stats_mgr.getObservation("subnet[42].total-NAs"));
+    ASSERT_TRUE(total_addrs);
+    EXPECT_EQ(128, total_addrs->getInteger().first);
+
+    EXPECT_NO_THROW(total_addrs = stats_mgr.getObservation("subnet[42].total-PDs"));
+    ASSERT_TRUE(total_addrs);
+    EXPECT_EQ(65536, total_addrs->getInteger().first);
+}
+
+// This test verifies that once the configuration is cleared, the v6 statistics
+// are removed.
+TEST_F(CfgMgrTest, clearStats6) {
+    CfgMgr& cfg_mgr = CfgMgr::instance();
+    StatsMgr& stats_mgr = StatsMgr::instance();
+
+    // Let's prepare the "old" configuration: a subnet with id 123
+    // and pretend there ware addresses assigned, so statistics are non-zero.
+    Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 48, 1, 2, 3, 4, 123));
+    CfgSubnets6Ptr subnets = cfg_mgr.getStagingCfg()->getCfgSubnets6();
+    subnets->add(subnet1);
+    cfg_mgr.commit();
+    stats_mgr.addValue("subnet[123].total-NAs", static_cast<int64_t>(256));
+    stats_mgr.setValue("subnet[123].assigned-NAs", static_cast<int64_t>(150));
+
+    stats_mgr.addValue("subnet[123].total-PDs", static_cast<int64_t>(256));
+    stats_mgr.setValue("subnet[123].assigned-PDs", static_cast<int64_t>(150));
+
+    // The stats should be there.
+    EXPECT_TRUE(stats_mgr.getObservation("subnet[123].total-NAs"));
+    EXPECT_TRUE(stats_mgr.getObservation("subnet[123].assigned-NAs"));
+
+    EXPECT_TRUE(stats_mgr.getObservation("subnet[123].total-PDs"));
+    EXPECT_TRUE(stats_mgr.getObservation("subnet[123].assigned-PDs"));
+
+    // Let's remove all configurations
+    cfg_mgr.clear();
+
+    // The stats should not be there anymore.
+    EXPECT_FALSE(stats_mgr.getObservation("subnet[123].total-NAs"));
+    EXPECT_FALSE(stats_mgr.getObservation("subnet[123].assigned-NAs"));
+
+    EXPECT_FALSE(stats_mgr.getObservation("subnet[123].total-PDs"));
+    EXPECT_FALSE(stats_mgr.getObservation("subnet[123].assigned-PDs"));
+}
+
 /// @todo Add unit-tests for testing:
 /// - addActiveIface() with invalid interface name
 /// - addActiveIface() with the same interface twice