/// starting host id of the range. If not zero this host id is
/// excluded from the returned range. When a source is exhausted
/// the index is updated. There is no guarantee about the order
- /// of returned host reservations, only the sources are ordered.
+ /// of returned host reservations, only the sources and
+ /// reservations from the same source are ordered.
///
/// @param subnet_id Subnet identifier.
/// @param source_index Index of the source.
/// starting host id of the range. If not zero this host id is
/// excluded from the returned range. When a source is exhausted
/// the index is updated. There is no guarantee about the order
- /// of returned host reservations, only the sources are ordered.
+ /// of returned host reservations, only the sources and
+ /// reservations from the same source are ordered.
///
/// @param subnet_id Subnet identifier.
/// @param source_index Index of the source.
CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_PAGE,
where_values);
+ // Sort result.
+ std::sort(result.begin(), result.end(),
+ [] (const ConstHostPtr& host1,
+ const ConstHostPtr& host2) {
+ return (host1->getHostId() < host2->getHostId()); });
+
return (result);
}
CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_PAGE,
where_values);
+ // Sort result.
+ std::sort(result.begin(), result.end(),
+ [] (const ConstHostPtr& host1,
+ const ConstHostPtr& host2) {
+ return (host1->getHostId() < host2->getHostId()); });
+
return (result);
}
}
ConstHostCollection hosts;
if (source_index == 0) {
- hosts = getCfgHosts()->getPage4(subnet_id,
- source_index,
- lower_host_id,
- page_size);
+ hosts = getCfgHosts()->
+ getPage4(subnet_id, source_index, lower_host_id, page_size);
} else {
- hosts = alternate_sources_[source_index]->getPage4(subnet_id,
- source_index,
- lower_host_id,
- page_size);
+ hosts = alternate_sources_[source_index - 1]->
+ getPage4(subnet_id, source_index, lower_host_id, page_size);
}
if (!hosts.empty()) {
return (hosts);
}
ConstHostCollection hosts;
if (source_index == 0) {
- hosts = getCfgHosts()->getPage6(subnet_id,
- source_index,
- lower_host_id,
- page_size);
+ hosts = getCfgHosts()->
+ getPage6(subnet_id, source_index, lower_host_id, page_size);
} else {
- hosts = alternate_sources_[source_index]->getPage6(subnet_id,
- source_index,
- lower_host_id,
- page_size);
+ hosts = alternate_sources_[source_index - 1]->
+ getPage6(subnet_id, source_index, lower_host_id, page_size);
}
if (!hosts.empty()) {
return (hosts);
"LEFT JOIN ipv6_reservations AS r "
"ON h.host_id = r.host_id "
"WHERE h.dhcp6_subnet_id = ? AND h.host_id > ? "
- "ORDER BY h.host_id, o.option_id, r.reservation_id"
+ "ORDER BY h.host_id, o.option_id, r.reservation_id "
"LIMIT ?"}
}
};
-// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
}
}
+// This test checks that hosts in the same subnet can be retrieved from
+// the host configuration by pages.
+TEST_F(CfgHostsTest, getPage4) {
+ CfgHosts cfg;
+ // Add 25 hosts identified by DUID in the same subnet.
+ for (unsigned i = 0; i < 25; ++i) {
+ cfg.add(HostPtr(new Host(duids_[i]->toText(), "duid",
+ SubnetID(1), SubnetID(1),
+ addressesa_[i])));
+ }
+ size_t idx(0);
+ uint64_t host_id(0);
+ HostPageSize page_size(10);
+
+ // Check that other subnets are empty.
+ HostCollection page = cfg.getPage4(SubnetID(100), idx, host_id, page_size);
+ EXPECT_EQ(0, page.size());
+
+ // Try to retrieve all added reservations.
+ // Get first page.
+ page = cfg.getPage4(SubnetID(1), idx, host_id, page_size);
+ EXPECT_EQ(10, page.size());
+ host_id = page[9]->getHostId();
+
+ // Get second and last pages.
+ page = cfg.getPage4(SubnetID(1), idx, host_id, page_size);
+ EXPECT_EQ(10, page.size());
+ host_id = page[9]->getHostId();
+ page = cfg.getPage4(SubnetID(1), idx, host_id, page_size);
+ EXPECT_EQ(5, page.size());
+ host_id = page[4]->getHostId();
+
+ // Verify we have everything.
+ page = cfg.getPage4(SubnetID(1), idx, host_id, page_size);
+ EXPECT_EQ(0, page.size());
+}
+
+// This test checks that hosts in the same subnet can be retrieved from
+// the host configuration by pages.
+TEST_F(CfgHostsTest, getPage6) {
+ CfgHosts cfg;
+ // Add 25 hosts identified by HW address in the same subnet.
+ for (unsigned i = 0; i < 25; ++i) {
+ HostPtr host = HostPtr(new Host(hwaddrs_[i]->toText(false),
+ "hw-address",
+ SubnetID(1), SubnetID(1),
+ IOAddress("0.0.0.0")));
+ host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
+ increase(IOAddress("2001:db8:1::1"),
+ i)));
+ cfg.add(host);
+ }
+ size_t idx(0);
+ uint64_t host_id(0);
+ HostPageSize page_size(10);
+
+ // Check that other subnets are empty.
+ HostCollection page = cfg.getPage6(SubnetID(100), idx, host_id, page_size);
+ EXPECT_EQ(0, page.size());
+
+ // Try to retrieve all added reservations.
+ // Get first page.
+ page = cfg.getPage6(SubnetID(1), idx, host_id, page_size);
+ EXPECT_EQ(10, page.size());
+ host_id = page[9]->getHostId();
+
+ // Get second and last pages.
+ page = cfg.getPage6(SubnetID(1), idx, host_id, page_size);
+ EXPECT_EQ(10, page.size());
+ host_id = page[9]->getHostId();
+ page = cfg.getPage6(SubnetID(1), idx, host_id, page_size);
+ EXPECT_EQ(5, page.size());
+ host_id = page[4]->getHostId();
+
+ // Verify we have everything.
+ page = cfg.getPage6(SubnetID(1), idx, host_id, page_size);
+ EXPECT_EQ(0, page.size());
+}
+
// This test checks that all reservations for the specified IPv4 address can
// be retrieved.
TEST_F(CfgHostsTest, getAll4ByAddress) {
testGetAll6(Host::IDENT_DUID);
}
+// Verifies that IPv4 host reservations in the same subnet can be retrieved
+// by pages.
+// Does not work because TOKEN(id) order is not the same than id...
+TEST_F(CqlHostDataSourceTest, DISABLED_getPage4) {
+ testGetPage4(Host::IDENT_DUID);
+}
+
+// Verifies that IPv6 host reservations in the same subnet can be retrieved
+// by pages.
+TEST_F(CqlHostDataSourceTest, DISABLED_getPage6) {
+ testGetPage6(Host::IDENT_HWADDR);
+}
+
// Test verifies if a host reservation can be added and later retrieved by IPv4
// address. Host uses hw address as identifier.
TEST_F(CqlHostDataSourceTest, basic4HWAddr) {
testGetAll6(Host::IDENT_DUID);
}
+// Verifies that IPv4 host reservations in the same subnet can be retrieved
+// by pages.
+TEST_F(MySqlHostDataSourceTest, getPage4) {
+ testGetPage4(Host::IDENT_DUID);
+}
+
+// Verifies that IPv6 host reservations in the same subnet can be retrieved
+// by pages.
+TEST_F(MySqlHostDataSourceTest, getPage6) {
+ testGetPage6(Host::IDENT_HWADDR);
+}
+
// Test verifies if a host reservation can be added and later retrieved by IPv4
// address. Host uses client-id (DUID) as identifier.
TEST_F(MySqlHostDataSourceTest, basic4ClientId) {
testGetAll6(Host::IDENT_DUID);
}
+// Verifies that IPv4 host reservations in the same subnet can be retrieved
+// by pages.
+TEST_F(PgSqlHostDataSourceTest, getPage4) {
+ testGetPage4(Host::IDENT_DUID);
+}
+
+// Verifies that IPv6 host reservations in the same subnet can be retrieved
+// by pages.
+TEST_F(PgSqlHostDataSourceTest, getPage6) {
+ testGetPage6(Host::IDENT_HWADDR);
+}
+
// Test verifies if a host reservation can be added and later retrieved by IPv4
// address. Host uses client-id (DUID) as identifier.
TEST_F(PgSqlHostDataSourceTest, basic4ClientId) {
}
}
+void
+GenericHostDataSourceTest::testGetPage4(const Host::IdentifierType& id) {
+ // Make sure we have a pointer to the host data source.
+ ASSERT_TRUE(hdsptr_);
+
+ // Let's create some hosts...
+ IOAddress addr("192.0.2.0");
+ SubnetID subnet4(4);
+ SubnetID subnet6(6);
+ for (unsigned i = 0; i < 25; ++i) {
+ addr = IOAddress::increase(addr);
+
+ HostPtr host = HostDataSourceUtils::initializeHost4(addr.toText(), id);
+ host->setIPv4SubnetID(subnet4);
+ host->setIPv6SubnetID(subnet6);
+
+ ASSERT_NO_THROW(hdsptr_->add(host));
+ }
+
+ // Get first page.
+ size_t idx(1);
+ uint64_t host_id(0);
+ HostPageSize page_size(10);
+ ConstHostCollection page;
+ ASSERT_NO_THROW(page = hdsptr_->getPage4(subnet4, idx, host_id, page_size));
+ ASSERT_EQ(10, page.size());
+ host_id = page[9]->getHostId();
+ ASSERT_NE(0, host_id);
+
+ // Get second and last pages.
+ ASSERT_NO_THROW(page = hdsptr_->getPage4(subnet4, idx, host_id, page_size));
+ ASSERT_EQ(10, page.size());
+ host_id = page[9]->getHostId();
+ ASSERT_NO_THROW(page = hdsptr_->getPage4(subnet4, idx, host_id, page_size));
+ ASSERT_EQ(5, page.size());
+ host_id = page[4]->getHostId();
+
+ // Verify we have everything.
+ ASSERT_NO_THROW(page = hdsptr_->getPage4(subnet4, idx, host_id, page_size));
+ ASSERT_EQ(0, page.size());
+ host_id = 0;
+
+ // Other subnets are empty.
+ ASSERT_NO_THROW(page = hdsptr_->getPage4(subnet6, idx, host_id, page_size));
+ ASSERT_EQ(0, page.size());
+}
+
+void
+GenericHostDataSourceTest::testGetPage6(const Host::IdentifierType& id) {
+ // Make sure we have a pointer to the host data source.
+ ASSERT_TRUE(hdsptr_);
+
+ // Let's create some hosts...
+ IOAddress addr("2001:db8:1::");
+ SubnetID subnet4(4);
+ SubnetID subnet6(6);
+ for (unsigned i = 0; i < 25; ++i) {
+ addr = IOAddress::increase(addr);
+
+ HostPtr host = HostDataSourceUtils::initializeHost6(addr.toText(), id, false);
+ host->setIPv4SubnetID(subnet4);
+ host->setIPv6SubnetID(subnet6);
+
+ ASSERT_NO_THROW(hdsptr_->add(host));
+ }
+
+ // Get first page.
+ size_t idx(1);
+ uint64_t host_id(0);
+ HostPageSize page_size(10);
+ ConstHostCollection page;
+ ASSERT_NO_THROW(page = hdsptr_->getPage6(subnet6, idx, host_id, page_size));
+ ASSERT_EQ(10, page.size());
+ host_id = page[9]->getHostId();
+ ASSERT_NE(0, host_id);
+
+ // Get second and last pages.
+ ASSERT_NO_THROW(page = hdsptr_->getPage6(subnet6, idx, host_id, page_size));
+ ASSERT_EQ(10, page.size());
+ host_id = page[9]->getHostId();
+ ASSERT_NO_THROW(page = hdsptr_->getPage6(subnet6, idx, host_id, page_size));
+ ASSERT_EQ(5, page.size());
+ host_id = page[4]->getHostId();
+
+ // Verify we have everything.
+ ASSERT_NO_THROW(page = hdsptr_->getPage6(subnet6, idx, host_id, page_size));
+ ASSERT_EQ(0, page.size());
+ host_id = 0;
+
+ // Other subnets are empty.
+ ASSERT_NO_THROW(page = hdsptr_->getPage6(subnet4, idx, host_id, page_size));
+ ASSERT_EQ(0, page.size());
+}
+
void
GenericHostDataSourceTest::testGetByIPv4(const Host::IdentifierType& id) {
// Make sure we have a pointer to the host data source.
/// @param id Identifier type.
void testGetAll6(const Host::IdentifierType& id);
+ /// @brief Test that Verifies that pages of host reservations in the
+ /// same subnet can be retrieved properly.
+ ///
+ /// Uses gtest macros to report failures.
+ /// @param id Identifier type.
+ void testGetPage4(const Host::IdentifierType& id);
+
+ /// @brief Test that Verifies that pages of host reservations in the
+ /// same subnet can be retrieved properly.
+ ///
+ /// Uses gtest macros to report failures.
+ /// @param id Identifier type.
+ void testGetPage6(const Host::IdentifierType& id);
+
/// @brief Test inserts several hosts with unique IPv4 address and
/// checks that they can be retrieved properly.
///
}
ConstHostCollection
-MemHostDataSource::getPage4(const SubnetID& /*subnet_id*/,
+MemHostDataSource::getPage4(const SubnetID& subnet_id,
size_t& /*source_index*/,
- uint64_t /*lower_host_id*/,
- const HostPageSize& /*page_size*/) const {
- return (ConstHostCollection());
+ uint64_t lower_host_id,
+ const HostPageSize& page_size) const {
+ ConstHostCollection hosts;
+ for (auto h = store_.begin(); h != store_.end(); ++h) {
+ // Skip it when subnet_id does not match.
+ if ((*h)->getIPv4SubnetID() != subnet_id) {
+ continue;
+ }
+ if (lower_host_id && ((*h)->getHostId() <= lower_host_id)) {
+ continue;
+ }
+ hosts.push_back(*h);
+ if (hosts.size() == page_size.page_size_) {
+ break;
+ }
+ }
+ return (hosts);
}
ConstHostCollection
-MemHostDataSource::getPage6(const SubnetID& /*subnet_id*/,
+MemHostDataSource::getPage6(const SubnetID& subnet_id,
size_t& /*source_index*/,
- uint64_t /*lower_host_id*/,
- const HostPageSize& /*page_size*/) const {
- return (ConstHostCollection());
+ uint64_t lower_host_id,
+ const HostPageSize& page_size) const {
+ ConstHostCollection hosts;
+ for (auto h = store_.begin(); h != store_.end(); ++h) {
+ // Skip it when subnet_id does not match.
+ if ((*h)->getIPv6SubnetID() != subnet_id) {
+ continue;
+ }
+ if (lower_host_id && ((*h)->getHostId() <= lower_host_id)) {
+ continue;
+ }
+ hosts.push_back(*h);
+ if (hosts.size() == page_size.page_size_) {
+ break;
+ }
+ }
+ return (hosts);
}
ConstHostCollection
/// @brief Return range of hosts in a DHCPv4 subnet.
///
- /// Currently not implemented.
- ///
/// @param subnet_id Subnet identifier.
/// @param source_index Index of the source (unused).
/// @param lower_host_id Host identifier used as lower bound for the
/// @brief Return range of hosts in a DHCPv6 subnet.
///
- /// Currently not implemented.
- ///
/// @param subnet_id Subnet identifier.
/// @param source_index Index of the source (unused).
/// @param lower_host_id Host identifier used as lower bound for the