]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#2868] Implemented getLeases6ByLink
authorFrancis Dupont <fdupont@isc.org>
Wed, 24 May 2023 00:21:08 +0000 (02:21 +0200)
committerFrancis Dupont <fdupont@isc.org>
Thu, 25 May 2023 21:03:53 +0000 (23:03 +0200)
src/lib/dhcpsrv/dhcpsrv_messages.cc
src/lib/dhcpsrv/dhcpsrv_messages.h
src/lib/dhcpsrv/dhcpsrv_messages.mes
src/lib/dhcpsrv/mysql_lease_mgr.cc
src/lib/dhcpsrv/mysql_lease_mgr.h
src/lib/dhcpsrv/pgsql_lease_mgr.cc
src/lib/dhcpsrv/pgsql_lease_mgr.h
src/lib/dhcpsrv/tests/mysql_lease_extended_info_unittest.cc
src/lib/dhcpsrv/tests/pgsql_lease_extended_info_unittest.cc

index 38ee2217e52adfd5fb944fe3be63096cb49b144e..3b47fcf4d4c7a6637d230e84cd0823449c467841 100644 (file)
@@ -167,6 +167,7 @@ extern const isc::log::MessageID DHCPSRV_MYSQL_GET_HOSTNAME6 = "DHCPSRV_MYSQL_GE
 extern const isc::log::MessageID DHCPSRV_MYSQL_GET_HWADDR = "DHCPSRV_MYSQL_GET_HWADDR";
 extern const isc::log::MessageID DHCPSRV_MYSQL_GET_IAID_DUID = "DHCPSRV_MYSQL_GET_IAID_DUID";
 extern const isc::log::MessageID DHCPSRV_MYSQL_GET_IAID_SUBID_DUID = "DHCPSRV_MYSQL_GET_IAID_SUBID_DUID";
+extern const isc::log::MessageID DHCPSRV_MYSQL_GET_LINKADDR6 = "DHCPSRV_MYSQL_GET_LINKADDR6";
 extern const isc::log::MessageID DHCPSRV_MYSQL_GET_PAGE4 = "DHCPSRV_MYSQL_GET_PAGE4";
 extern const isc::log::MessageID DHCPSRV_MYSQL_GET_PAGE6 = "DHCPSRV_MYSQL_GET_PAGE6";
 extern const isc::log::MessageID DHCPSRV_MYSQL_GET_RELAYID4 = "DHCPSRV_MYSQL_GET_RELAYID4";
@@ -224,6 +225,7 @@ extern const isc::log::MessageID DHCPSRV_PGSQL_GET_HOSTNAME6 = "DHCPSRV_PGSQL_GE
 extern const isc::log::MessageID DHCPSRV_PGSQL_GET_HWADDR = "DHCPSRV_PGSQL_GET_HWADDR";
 extern const isc::log::MessageID DHCPSRV_PGSQL_GET_IAID_DUID = "DHCPSRV_PGSQL_GET_IAID_DUID";
 extern const isc::log::MessageID DHCPSRV_PGSQL_GET_IAID_SUBID_DUID = "DHCPSRV_PGSQL_GET_IAID_SUBID_DUID";
+extern const isc::log::MessageID DHCPSRV_PGSQL_GET_LINKADDR6 = "DHCPSRV_PGSQL_GET_LINKADDR6";
 extern const isc::log::MessageID DHCPSRV_PGSQL_GET_PAGE4 = "DHCPSRV_PGSQL_GET_PAGE4";
 extern const isc::log::MessageID DHCPSRV_PGSQL_GET_PAGE6 = "DHCPSRV_PGSQL_GET_PAGE6";
 extern const isc::log::MessageID DHCPSRV_PGSQL_GET_RELAYID4 = "DHCPSRV_PGSQL_GET_RELAYID4";
@@ -444,6 +446,7 @@ const char* values[] = {
     "DHCPSRV_MYSQL_GET_HWADDR", "obtaining IPv4 leases for hardware address %1",
     "DHCPSRV_MYSQL_GET_IAID_DUID", "obtaining IPv6 leases for IAID %1, DUID %2, lease type %3",
     "DHCPSRV_MYSQL_GET_IAID_SUBID_DUID", "obtaining IPv6 leases for IAID %1, Subnet ID %2, DUID %3, lease type %4",
+    "DHCPSRV_MYSQL_GET_LINKADDR6", "obtaining at most %1 IPv6 leases starting from address %2 with link %3/%4",
     "DHCPSRV_MYSQL_GET_PAGE4", "obtaining at most %1 IPv4 leases starting from address %2",
     "DHCPSRV_MYSQL_GET_PAGE6", "obtaining at most %1 IPv6 leases starting from address %2",
     "DHCPSRV_MYSQL_GET_RELAYID4", "obtaining at most %1 IPv4 leases starting from address %2 with relay id %3 and cltt between %4 and %5",
@@ -501,6 +504,7 @@ const char* values[] = {
     "DHCPSRV_PGSQL_GET_HWADDR", "obtaining IPv4 leases for hardware address %1",
     "DHCPSRV_PGSQL_GET_IAID_DUID", "obtaining IPv4 leases for IAID %1 and DUID %2, lease type %3",
     "DHCPSRV_PGSQL_GET_IAID_SUBID_DUID", "obtaining IPv4 leases for IAID %1, Subnet ID %2, DUID %3, and lease type %4",
+    "DHCPSRV_PGSQL_GET_LINKADDR6", "obtaining at most %1 IPv6 leases starting from address %2 with link %3/%4",
     "DHCPSRV_PGSQL_GET_PAGE4", "obtaining at most %1 IPv4 leases starting from address %2",
     "DHCPSRV_PGSQL_GET_PAGE6", "obtaining at most %1 IPv6 leases starting from address %2",
     "DHCPSRV_PGSQL_GET_RELAYID4", "obtaining at most %1 IPv4 leases starting from address %2 with relay id %3 and cltt between %4 and %5",
index 5640310c4f237a32fe130d1fe7bd2920e2de1b88..0786c21e957d9fe67de974f1e0d414d98a7d27a0 100644 (file)
@@ -168,6 +168,7 @@ extern const isc::log::MessageID DHCPSRV_MYSQL_GET_HOSTNAME6;
 extern const isc::log::MessageID DHCPSRV_MYSQL_GET_HWADDR;
 extern const isc::log::MessageID DHCPSRV_MYSQL_GET_IAID_DUID;
 extern const isc::log::MessageID DHCPSRV_MYSQL_GET_IAID_SUBID_DUID;
+extern const isc::log::MessageID DHCPSRV_MYSQL_GET_LINKADDR6;
 extern const isc::log::MessageID DHCPSRV_MYSQL_GET_PAGE4;
 extern const isc::log::MessageID DHCPSRV_MYSQL_GET_PAGE6;
 extern const isc::log::MessageID DHCPSRV_MYSQL_GET_RELAYID4;
@@ -225,6 +226,7 @@ extern const isc::log::MessageID DHCPSRV_PGSQL_GET_HOSTNAME6;
 extern const isc::log::MessageID DHCPSRV_PGSQL_GET_HWADDR;
 extern const isc::log::MessageID DHCPSRV_PGSQL_GET_IAID_DUID;
 extern const isc::log::MessageID DHCPSRV_PGSQL_GET_IAID_SUBID_DUID;
+extern const isc::log::MessageID DHCPSRV_PGSQL_GET_LINKADDR6;
 extern const isc::log::MessageID DHCPSRV_PGSQL_GET_PAGE4;
 extern const isc::log::MessageID DHCPSRV_PGSQL_GET_PAGE6;
 extern const isc::log::MessageID DHCPSRV_PGSQL_GET_RELAYID4;
index ade253aed9f6c6cf5b2ec4dc7093d89a1484596f..324db1f75c80d4b25ca77a7ca3f9427d1f3949b6 100644 (file)
@@ -861,6 +861,10 @@ A debug message issued when the server is attempting to obtain an IPv6
 lease from the MySQL database for a client with the specified IAID
 (Identity Association ID), Subnet ID and DUID (DHCP Unique Identifier).
 
+% DHCPSRV_MYSQL_GET_LINKADDR6 obtaining at most %1 IPv6 leases starting from address %2 with link %3/%4
+A debug message issued when the server is attempting to obtain a page of
+IPv6 leases beginning with the specified address within a link.
+
 % DHCPSRV_MYSQL_GET_PAGE4 obtaining at most %1 IPv4 leases starting from address %2
 A debug message issued when the server is attempting to obtain a page
 of leases beginning with the specified address.
@@ -1129,6 +1133,10 @@ A debug message issued when the server is attempting to obtain an IPv6
 lease from the PostgreSQL database for a client with the specified IAID
 (Identity Association ID), Subnet ID and DUID (DHCP Unique Identifier).
 
+% DHCPSRV_PGSQL_GET_LINKADDR6 obtaining at most %1 IPv6 leases starting from address %2 with link %3/%4
+A debug message issued when the server is attempting to obtain a page of
+IPv6 leases beginning with the specified address within a link.
+
 % DHCPSRV_PGSQL_GET_PAGE4 obtaining at most %1 IPv4 leases starting from address %2
 A debug message issued when the server is attempting to obtain a page
 of leases beginning with the specified address.
index ad25c8f44dd521b95b1b317f5a0efe2825adb8be..7e2fda1f28c9068b9889681e33bbad72c1d079bd 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <config.h>
 
-#include <asiolink/io_address.h>
+#include <asiolink/addr_utilities.h>
 #include <dhcp/duid.h>
 #include <dhcp/hwaddr.h>
 #include <dhcpsrv/cfg_db_access.h>
@@ -401,6 +401,18 @@ tagged_statements = { {
                             "AND expire < ? "
                             "ORDER BY expire ASC "
                             "LIMIT ?"},
+    {MySqlLeaseMgr::GET_LEASE6_LINK,
+                    "SELECT address, duid, valid_lifetime, "
+                        "expire, subnet_id, pref_lifetime, "
+                        "lease_type, iaid, prefix_len, "
+                        "fqdn_fwd, fqdn_rev, hostname, "
+                        "hwaddr, hwtype, hwaddr_source, "
+                        "state, user_context "
+                            "FROM lease6 "
+                            "WHERE binaddr IS NOT NULL "
+                            "AND binaddr BETWEEN ? AND ? "
+                            "ORDER BY binaddr "
+                            "LIMIT ?"},
     {MySqlLeaseMgr::INSERT_LEASE4,
                     "INSERT INTO lease4(address, hwaddr, client_id, "
                         "valid_lifetime, expire, subnet_id, "
@@ -4031,11 +4043,87 @@ MySqlLeaseMgr::getLeases6ByRemoteId(const OptionBuffer& /* remote_id */,
 }
 
 Lease6Collection
-MySqlLeaseMgr::getLeases6ByLink(const IOAddress& /* link_addr */,
-                                uint8_t /* link_len */,
-                                const IOAddress& /* lower_bound_address */,
-                                const LeasePageSize& /* page_size */) {
-    isc_throw(NotImplemented, "MySqlLeaseMgr::getLeases6ByLink not implemented");
+MySqlLeaseMgr::getLeases6ByLink(const IOAddress& link_addr,
+                                uint8_t link_len,
+                                const IOAddress& lower_bound_address,
+                                const LeasePageSize& page_size) {
+    // Expecting IPv6 valid prefix and address.
+    if (!link_addr.isV6()) {
+        isc_throw(InvalidAddressFamily, "expected IPv6 address while "
+                  "retrieving leases from the lease database, got "
+                  << link_addr);
+    }
+    if ((link_len == 0) || (link_len > 128)) {
+        isc_throw(OutOfRange, "invalid IPv6 prefix length "
+                  << static_cast<unsigned>(link_len));
+    }
+    if (!lower_bound_address.isV6()) {
+        isc_throw(InvalidAddressFamily, "expected IPv6 address while "
+                  "retrieving leases from the lease database, got "
+                  << lower_bound_address);
+    }
+
+    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
+              DHCPSRV_MYSQL_GET_LINKADDR6)
+        .arg(page_size.page_size_)
+        .arg(lower_bound_address.toText())
+        .arg(link_addr.toText())
+        .arg(static_cast<unsigned>(link_len));
+
+    Lease6Collection result;
+    const IOAddress& first_addr = firstAddrInPrefix(link_addr, link_len);
+    const IOAddress& last_addr = lastAddrInPrefix(link_addr, link_len);
+    IOAddress start_addr = lower_bound_address;
+    if (lower_bound_address < first_addr) {
+        start_addr = first_addr;
+    } else if (last_addr <= lower_bound_address) {
+        // Range was already done.
+        return (result);
+    } else {
+        // The lower bound address is from the last call so skip it.
+        start_addr = IOAddress::increase(lower_bound_address);
+    }
+
+    // Prepare WHERE clause
+    MYSQL_BIND inbind[3];
+    memset(inbind, 0, sizeof(inbind));
+
+    // Bind start address
+    std::vector<uint8_t> start_addr_data = start_addr.toBytes();
+    if (start_addr_data.size() != 16) {
+        isc_throw(DbOperationError, "start address is not 16 byte long");
+    }
+    unsigned long start_addr_size = 16;
+    inbind[0].buffer_type = MYSQL_TYPE_BLOB;
+    inbind[0].buffer = reinterpret_cast<char*>(&start_addr_data[0]);
+    inbind[0].buffer_length = 16;
+    inbind[0].length = &start_addr_size;
+
+    // Bind last address
+    std::vector<uint8_t> last_addr_data = last_addr.toBytes();
+    if (last_addr_data.size() != 16) {
+        isc_throw(DbOperationError, "last address is not 16 byte long");
+    }
+    unsigned long last_addr_size = 16;
+    inbind[1].buffer_type = MYSQL_TYPE_BLOB;
+    inbind[1].buffer = reinterpret_cast<char*>(&last_addr_data[0]);
+    inbind[1].buffer_length = 16;
+    inbind[1].length = &last_addr_size;
+
+    // Bind page size value
+    uint32_t ps = static_cast<uint32_t>(page_size.page_size_);
+    inbind[2].buffer_type = MYSQL_TYPE_LONG;
+    inbind[2].buffer = reinterpret_cast<char*>(&ps);
+    inbind[2].is_unsigned = MLM_TRUE;
+
+    // Get a context
+    MySqlLeaseContextAlloc get_context(*this);
+    MySqlLeaseContextPtr ctx = get_context.ctx_;
+
+    // Get the leases
+    getLeaseCollection(ctx, GET_LEASE6_LINK, inbind, result);
+
+    return (result);
 }
 
 size_t
index a08d1909d3f6ef5e551e09ee6fd48a9b5b505241..a3621bd371966398dbdb957a28857a4d3aca9b2c 100644 (file)
@@ -725,6 +725,7 @@ public:
         GET_LEASE6_DUID,             // Get IPv6 leases by DUID
         GET_LEASE6_HOSTNAME,         // Get IPv6 leases by hostname
         GET_LEASE6_EXPIRE,           // Get lease6 by expiration.
+        GET_LEASE6_LINK,             // Get page of lease6 by link
         INSERT_LEASE4,               // Add entry to lease4 table
         INSERT_LEASE6,               // Add entry to lease6 table
         UPDATE_LEASE4,               // Update a Lease4 entry
index e57ceac796c3a1bd37eb54199491d9d373e37f19..0d46c0b873cc89e16edf541f7c439331df731bc0 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <config.h>
 
-#include <asiolink/io_address.h>
+#include <asiolink/addr_utilities.h>
 #include <dhcp/duid.h>
 #include <dhcp/hwaddr.h>
 #include <dhcpsrv/cfg_db_access.h>
@@ -420,6 +420,20 @@ PgSqlTaggedStatement tagged_statements[] = {
       "ORDER BY expire "
       "LIMIT $3"},
 
+    // GET_LEASE6_LINK
+    { 3, { OID_BYTEA, OID_BYTEA, OID_INT8 },
+      "get_lease6_link",
+      "SELECT address, duid, valid_lifetime, "
+        "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
+        "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
+        "hwaddr, hwtype, hwaddr_source, "
+        "state, user_context "
+      "FROM lease6 "
+      "WHERE binaddr IS NOT NULL "
+      "AND binaddr BETWEEN $1 and $2 "
+      "ORDER BY binaddr "
+      "LIMIT $3"},
+
     // INSERT_LEASE4
     { 13, { OID_INT8, OID_BYTEA, OID_BYTEA, OID_INT8, OID_TIMESTAMP, OID_INT8,
             OID_BOOL, OID_BOOL, OID_VARCHAR, OID_INT8, OID_TEXT, OID_BYTEA,
@@ -2264,7 +2278,8 @@ PgSqlLeaseMgr::getLeases6(const IOAddress& lower_bound_address,
     bind_array.add(lb_address_data);
 
     // Bind page size value
-    std::string page_size_data = boost::lexical_cast<std::string>(page_size.page_size_);
+    std::string page_size_data =
+        boost::lexical_cast<std::string>(page_size.page_size_);
     bind_array.add(page_size_data);
 
     // Get the leases
@@ -3159,11 +3174,77 @@ PgSqlLeaseMgr::getLeases6ByRemoteId(const OptionBuffer& /* remote_id */,
 }
 
 Lease6Collection
-PgSqlLeaseMgr::getLeases6ByLink(const IOAddress& /* link_addr */,
-                                uint8_t /* link_len */,
-                                const IOAddress& /* lower_bound_address */,
-                                const LeasePageSize& /* page_size */) {
-    isc_throw(NotImplemented, "PgSqlLeaseMgr::getLeases6ByLink not implemented");
+PgSqlLeaseMgr::getLeases6ByLink(const IOAddress& link_addr,
+                                uint8_t link_len,
+                                const IOAddress& lower_bound_address,
+                                const LeasePageSize& page_size) {
+    // Expecting IPv6 valid prefix and address.
+    if (!link_addr.isV6()) {
+        isc_throw(InvalidAddressFamily, "expected IPv6 address while "
+                  "retrieving leases from the lease database, got "
+                  << link_addr);
+    }
+    if ((link_len == 0) || (link_len > 128)) {
+        isc_throw(OutOfRange, "invalid IPv6 prefix length "
+                  << static_cast<unsigned>(link_len));
+    }
+    if (!lower_bound_address.isV6()) {
+        isc_throw(InvalidAddressFamily, "expected IPv6 address while "
+                  "retrieving leases from the lease database, got "
+                  << lower_bound_address);
+    }
+
+    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
+              DHCPSRV_PGSQL_GET_LINKADDR6)
+        .arg(page_size.page_size_)
+        .arg(lower_bound_address.toText())
+        .arg(link_addr.toText())
+        .arg(static_cast<unsigned>(link_len));
+
+    Lease6Collection result;
+    const IOAddress& first_addr = firstAddrInPrefix(link_addr, link_len);
+    const IOAddress& last_addr = lastAddrInPrefix(link_addr, link_len);
+    IOAddress start_addr = lower_bound_address;
+    if (lower_bound_address < first_addr) {
+        start_addr = first_addr;
+    } else if (last_addr <= lower_bound_address) {
+        // Range was already done.
+        return (result);
+    } else {
+        // The lower bound address is from the last call so skip it.
+        start_addr = IOAddress::increase(lower_bound_address);
+    }
+
+    // Prepare WHERE clause
+    PsqlBindArray bind_array;
+
+    // Bind start address
+    std::vector<uint8_t> start_addr_data = start_addr.toBytes();
+    if (start_addr_data.size() != 16) {
+        isc_throw(DbOperationError, "start address is not 16 byte long");
+    }
+    bind_array.add(start_addr_data);
+
+    // Bind last address
+    std::vector<uint8_t> last_addr_data = last_addr.toBytes();
+    if (last_addr_data.size() != 16) {
+        isc_throw(DbOperationError, "last address is not 16 byte long");
+    }
+    bind_array.add(last_addr_data);
+
+    // Bind page size value
+        std::string page_size_data =
+        boost::lexical_cast<std::string>(page_size.page_size_);
+    bind_array.add(page_size_data);
+
+    // Get a context
+    PgSqlLeaseContextAlloc get_context(*this);
+    PgSqlLeaseContextPtr ctx = get_context.ctx_;
+
+    // Get the leases
+    getLeaseCollection(ctx, GET_LEASE6_LINK, bind_array, result);
+
+    return (result);
 }
 
 size_t
index c3369540ba5039fb405e36127ddd8a9f87b59a03..fe5f363d0da22d53cfb2176ff2cade2cb9d70243 100644 (file)
@@ -701,6 +701,7 @@ public:
         GET_LEASE6_DUID,             // Get IPv6 leases by DUID
         GET_LEASE6_HOSTNAME,         // Get IPv6 leases by hostname
         GET_LEASE6_EXPIRE,           // Get lease6 by expiration.
+        GET_LEASE6_LINK,             // Get page of lease6 by link
         INSERT_LEASE4,               // Add entry to lease4 table
         INSERT_LEASE6,               // Add entry to lease6 table
         UPDATE_LEASE4,               // Update a Lease4 entry
index c3529c2ac6025e4826d206b7424b8a032ad638e6..fc077f5f6fadf34c17d9abfbe7952779668b5a92 100644 (file)
@@ -36,6 +36,12 @@ const vector<string> ADDRESS4 = {
     "192.0.2.4", "192.0.2.5", "192.0.2.6", "192.0.2.7"
 };
 
+/// @brief IPv6 addresses used in the tests.
+const vector<string> ADDRESS6 = {
+    "2001:db8::0", "2001:db8::1", "2001:db8::2", "2001:db8::3",
+    "2001:db8::4", "2001:db8::5", "2001:db8::6", "2001:db8::7"
+};
+
 /// @brief DUIDs used in the tests.
 const vector<string> DUIDS = {
     "wwwwwwww", "BBBBBBBB", "::::::::", "0123456789acdef",
@@ -64,6 +70,7 @@ public:
 
         lease_mgr_ = &(LeaseMgrFactory::instance());
         leases4.clear();
+        leases6.clear();
         MultiThreadingMgr::instance().setMode(false);
         now_ = time(0);
     }
@@ -76,6 +83,7 @@ public:
         destroyMySQLSchema();
 
         leases4.clear();
+        leases6.clear();
         MultiThreadingMgr::instance().setMode(false);
     }
 
@@ -104,6 +112,23 @@ public:
         ASSERT_EQ(ADDRESS4.size(), leases4.size());
     }
 
+    /// @brief Create and set v6 leases.
+    void initLease6() {
+        ASSERT_EQ(ADDRESS6.size(), DUIDS.size());
+        for (size_t i = 0; i < ADDRESS6.size(); ++i) {
+            Lease6Ptr lease;
+            vector<uint8_t> duid_data = createFromString(DUIDS[i]);
+            DuidPtr duid(new DUID(duid_data));
+            IOAddress addr(ADDRESS6[i]);
+            ASSERT_NO_THROW(lease.reset(new Lease6(((i % 2) ? Lease::TYPE_NA : Lease::TYPE_PD), addr, duid,
+                                                   123, 1000, 2000,
+                                                   static_cast<SubnetID>(i))));
+            leases6.push_back(lease);
+            EXPECT_TRUE(lease_mgr_->addLease(lease));
+        }
+        ASSERT_EQ(ADDRESS6.size(), leases6.size());
+    }
+
     /// @brief Create a vector of uint8_t from a string.
     ///
     /// @param content A not empty string holding the content.
@@ -118,6 +143,9 @@ public:
     /// @brief Test initLease4.
     void testInitLease4();
 
+    /// @brief Test initLease6.
+    void testInitLease6();
+
     /// @brief Test getLease4ByRelayId.
     void testGetLeases4ByRelayId();
 
@@ -128,12 +156,18 @@ public:
     void testUpgradeExtendedInfo4(const CfgConsistency::ExtendedInfoSanity& check,
                                   const LeasePageSize& page_size);
 
+    /// @brief Test getLeases6ByLink.
+    void testGetLeases6ByLink();
+
     /// @brief Lease manager.
     LeaseMgr* lease_mgr_;
 
     /// @brief V4 leases.
     Lease4Collection leases4;
 
+    /// @brief V6 leases.
+    Lease6Collection leases6;
+
     /// @brief Current timestamp.
     time_t now_;
 };
@@ -965,4 +999,105 @@ TEST_F(MySqlExtendedInfoTest, upgradeExtendedInfo4_1) {
                              LeasePageSize(1));
 }
 
+/// @brief Verifies that the lease manager can add the v6 leases.
+void
+MySqlExtendedInfoTest::testInitLease6() {
+    initLease6();
+    EXPECT_EQ(8, leases6.size());
+    Lease6Collection got;
+    EXPECT_NO_THROW(got = lease_mgr_->getLeases6());
+    ASSERT_EQ(leases6.size(), got.size());
+    for (size_t i = 0; i < leases6.size(); ++i) {
+        ConstElementPtr expected = leases6[i]->toElement();
+        LeasePtr lease = got[i];
+        ASSERT_TRUE(lease);
+        EXPECT_TRUE(expected->equals(*lease->toElement()))
+            << "expected: " << expected->str() << "\n"
+            << "got: " << lease->toElement()->str() << "\n";
+    }
+}
+
+TEST_F(MySqlExtendedInfoTest, initLease6) {
+    testInitLease6();
+}
+
+TEST_F(MySqlExtendedInfoTest, initLease6MultiThreading) {
+    MultiThreadingTest mt(true);
+    testInitLease6();
+}
+
+/// @brief Verifies that getLeases6ByLink works as expected.
+void
+MySqlExtendedInfoTest::testGetLeases6ByLink() {
+    // Lease manager is created with empty tables.
+    initLease6();
+
+    // Create parameter values.
+    IOAddress link_addr(ADDRESS6[4]);
+    IOAddress other_link_addr("2001:db8:1::4");
+    IOAddress zero = IOAddress::IPV6_ZERO_ADDRESS();
+
+    Lease6Collection got;
+    // Other link: nothing.
+    EXPECT_NO_THROW(got = lease_mgr_->getLeases6ByLink(other_link_addr,
+                                                       64,
+                                                       zero,
+                                                       LeasePageSize(10)));
+    EXPECT_EQ(0, got.size());
+
+    // Link: 8 entries.
+    EXPECT_NO_THROW(got = lease_mgr_->getLeases6ByLink(link_addr,
+                                                       64,
+                                                       zero,
+                                                       LeasePageSize(10)));
+
+    ASSERT_EQ(8, got.size());
+    Lease6Ptr lease;
+    for (size_t i = 0; i < 8; ++i) {
+        lease = got[i];
+        ASSERT_TRUE(lease);
+        EXPECT_EQ(IOAddress(ADDRESS6[i]), lease->addr_);
+    }
+
+    // Link: initial partial: 4 entries.
+    EXPECT_NO_THROW(got = lease_mgr_->getLeases6ByLink(link_addr,
+                                                       64,
+                                                       zero,
+                                                       LeasePageSize(4)));
+    ASSERT_EQ(4, got.size());
+    for (size_t i = 0; i < 4; ++i) {
+        lease = got[i];
+        ASSERT_TRUE(lease);
+        EXPECT_EQ(IOAddress(ADDRESS6[i]), lease->addr_);
+    }
+
+    // Link: next partial: 4 entries.
+    EXPECT_NO_THROW(got = lease_mgr_->getLeases6ByLink(link_addr,
+                                                       64,
+                                                       lease->addr_,
+                                                       LeasePageSize(4)));
+    ASSERT_EQ(4, got.size());
+    for (size_t i = 0; i < 4; ++i) {
+        lease = got[i];
+        ASSERT_TRUE(lease);
+        EXPECT_EQ(IOAddress(ADDRESS6[i + 4]), lease->addr_);
+    }
+
+    // Link: further partial: nothing.
+    EXPECT_NO_THROW(got = lease_mgr_->getLeases6ByLink(link_addr,
+                                                       64,
+                                                       lease->addr_,
+                                                       LeasePageSize(4)));
+    EXPECT_EQ(0, got.size());
+}
+
+TEST_F(MySqlExtendedInfoTest, getLeases6ByLink) {
+    testGetLeases6ByLink();
+}
+
+TEST_F(MySqlExtendedInfoTest, getLeases6ByLinkMultiThreading) {
+    MultiThreadingTest mt(true);
+    testGetLeases6ByLink();
+}
+
 }  // namespace
index be224447bb7d1bbfa1d2d3bb74de4847a7e3989d..1bd829142811fcf0f28f06ecd7cf779bb755e4c3 100644 (file)
@@ -36,6 +36,12 @@ const vector<string> ADDRESS4 = {
     "192.0.2.4", "192.0.2.5", "192.0.2.6", "192.0.2.7"
 };
 
+/// @brief IPv6 addresses used in the tests.
+const vector<string> ADDRESS6 = {
+    "2001:db8::0", "2001:db8::1", "2001:db8::2", "2001:db8::3",
+    "2001:db8::4", "2001:db8::5", "2001:db8::6", "2001:db8::7"
+};
+
 /// @brief DUIDs used in the tests.
 const vector<string> DUIDS = {
     "wwwwwwww", "BBBBBBBB", "::::::::", "0123456789acdef",
@@ -64,6 +70,7 @@ public:
 
         lease_mgr_ = &(LeaseMgrFactory::instance());
         leases4.clear();
+        leases6.clear();
         MultiThreadingMgr::instance().setMode(false);
         now_ = time(0);
     }
@@ -76,6 +83,7 @@ public:
         destroyPgSQLSchema();
 
         leases4.clear();
+        leases6.clear();
         MultiThreadingMgr::instance().setMode(false);
     }
 
@@ -104,6 +112,23 @@ public:
         ASSERT_EQ(ADDRESS4.size(), leases4.size());
     }
 
+    /// @brief Create and set v6 leases.
+    void initLease6() {
+        ASSERT_EQ(ADDRESS6.size(), DUIDS.size());
+        for (size_t i = 0; i < ADDRESS6.size(); ++i) {
+            Lease6Ptr lease;
+            vector<uint8_t> duid_data = createFromString(DUIDS[i]);
+            DuidPtr duid(new DUID(duid_data));
+            IOAddress addr(ADDRESS6[i]);
+            ASSERT_NO_THROW(lease.reset(new Lease6(((i % 2) ? Lease::TYPE_NA : Lease::TYPE_PD), addr, duid,
+                                                   123, 1000, 2000,
+                                                   static_cast<SubnetID>(i))));
+            leases6.push_back(lease);
+            EXPECT_TRUE(lease_mgr_->addLease(lease));
+        }
+        ASSERT_EQ(ADDRESS6.size(), leases6.size());
+    }
+
     /// @brief Create a vector of uint8_t from a string.
     ///
     /// @param content A not empty string holding the content.
@@ -118,6 +143,9 @@ public:
     /// @brief Test initLease4.
     void testInitLease4();
 
+    /// @brief Test initLease6.
+    void testInitLease6();
+
     /// @brief Test getLease4ByRelayId.
     void testGetLeases4ByRelayId();
 
@@ -128,12 +156,18 @@ public:
     void testUpgradeExtendedInfo4(const CfgConsistency::ExtendedInfoSanity& check,
                                   const LeasePageSize& page_size);
 
+    /// @brief Test getLeases6ByLink.
+    void testGetLeases6ByLink();
+
     /// @brief Lease manager.
     LeaseMgr* lease_mgr_;
 
     /// @brief V4 leases.
     Lease4Collection leases4;
 
+    /// @brief V6 leases.
+    Lease6Collection leases6;
+
     /// @brief Current timestamp.
     time_t now_;
 };
@@ -965,4 +999,105 @@ TEST_F(PgSqlExtendedInfoTest, upgradeExtendedInfo4_1) {
                              LeasePageSize(1));
 }
 
+/// @brief Verifies that the lease manager can add the v6 leases.
+void
+PgSqlExtendedInfoTest::testInitLease6() {
+    initLease6();
+    EXPECT_EQ(8, leases6.size());
+    Lease6Collection got;
+    EXPECT_NO_THROW(got = lease_mgr_->getLeases6());
+    ASSERT_EQ(leases6.size(), got.size());
+    for (size_t i = 0; i < leases6.size(); ++i) {
+        ConstElementPtr expected = leases6[i]->toElement();
+        LeasePtr lease = got[i];
+        ASSERT_TRUE(lease);
+        EXPECT_TRUE(expected->equals(*lease->toElement()))
+            << "expected: " << expected->str() << "\n"
+            << "got: " << lease->toElement()->str() << "\n";
+    }
+}
+
+TEST_F(PgSqlExtendedInfoTest, initLease6) {
+    testInitLease6();
+}
+
+TEST_F(PgSqlExtendedInfoTest, initLease6MultiThreading) {
+    MultiThreadingTest mt(true);
+    testInitLease6();
+}
+
+/// @brief Verifies that getLeases6ByLink works as expected.
+void
+PgSqlExtendedInfoTest::testGetLeases6ByLink() {
+    // Lease manager is created with empty tables.
+    initLease6();
+
+    // Create parameter values.
+    IOAddress link_addr(ADDRESS6[4]);
+    IOAddress other_link_addr("2001:db8:1::4");
+    IOAddress zero = IOAddress::IPV6_ZERO_ADDRESS();
+
+    Lease6Collection got;
+    // Other link: nothing.
+    EXPECT_NO_THROW(got = lease_mgr_->getLeases6ByLink(other_link_addr,
+                                                       64,
+                                                       zero,
+                                                       LeasePageSize(10)));
+    EXPECT_EQ(0, got.size());
+
+    // Link: 8 entries.
+    EXPECT_NO_THROW(got = lease_mgr_->getLeases6ByLink(link_addr,
+                                                       64,
+                                                       zero,
+                                                       LeasePageSize(10)));
+
+    ASSERT_EQ(8, got.size());
+    Lease6Ptr lease;
+    for (size_t i = 0; i < 8; ++i) {
+        lease = got[i];
+        ASSERT_TRUE(lease);
+        EXPECT_EQ(IOAddress(ADDRESS6[i]), lease->addr_);
+    }
+
+    // Link: initial partial: 4 entries.
+    EXPECT_NO_THROW(got = lease_mgr_->getLeases6ByLink(link_addr,
+                                                       64,
+                                                       zero,
+                                                       LeasePageSize(4)));
+    ASSERT_EQ(4, got.size());
+    for (size_t i = 0; i < 4; ++i) {
+        lease = got[i];
+        ASSERT_TRUE(lease);
+        EXPECT_EQ(IOAddress(ADDRESS6[i]), lease->addr_);
+    }
+
+    // Link: next partial: 4 entries.
+    EXPECT_NO_THROW(got = lease_mgr_->getLeases6ByLink(link_addr,
+                                                       64,
+                                                       lease->addr_,
+                                                       LeasePageSize(4)));
+    ASSERT_EQ(4, got.size());
+    for (size_t i = 0; i < 4; ++i) {
+        lease = got[i];
+        ASSERT_TRUE(lease);
+        EXPECT_EQ(IOAddress(ADDRESS6[i + 4]), lease->addr_);
+    }
+
+    // Link: further partial: nothing.
+    EXPECT_NO_THROW(got = lease_mgr_->getLeases6ByLink(link_addr,
+                                                       64,
+                                                       lease->addr_,
+                                                       LeasePageSize(4)));
+    EXPECT_EQ(0, got.size());
+}
+
+TEST_F(PgSqlExtendedInfoTest, getLeases6ByLink) {
+    testGetLeases6ByLink();
+}
+
+TEST_F(PgSqlExtendedInfoTest, getLeases6ByLinkMultiThreading) {
+    MultiThreadingTest mt(true);
+    testGetLeases6ByLink();
+}
+
 }  // namespace