void testAdd6Invalid2Hosts();
void testAllowAddress6AlreadyReserved();
void testAllowPrefix6AlreadyReserved();
+ void testPrefixExclude();
void testDuplicatesSubnet4HWAddr();
void testDuplicatesSubnet4DUID();
void testDuplicatesSubnet6HWAddr();
IOAddress("10.0.0.1")))),
isc::BadValue);
}
+// Test insert and retrieve a v6 host with prefix exclude option.
+TEST_F(CfgHostsTest, prefixExclude) {
+ CfgHosts cfg;
+
+ // Create a host reservation.
+ HostPtr host = HostPtr(new Host(duids_[0]->toText(), "duid",
+ SUBNET_ID_UNUSED, SubnetID(1),
+ IOAddress("0.0.0.0")));
+ IPv6Resrv resv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8::"), 48);
+ resv.setPDExclude(IOAddress("2001:db8:0:1::"), 64);
+ host->addReservation(resv);
+ SubnetID subnet = host->getIPv6SubnetID();
+
+ // Try to add it to the host config.
+ ASSERT_NO_THROW(cfg.add(host));
+
+ // Retrieve it.
+ ConstHostPtr from_cfg = cfg.get6(subnet, Host::IDENT_DUID,
+ &host->getIdentifier()[0],
+ host->getIdentifier().size());
+ ASSERT_TRUE(from_cfg);
+
+ // Compare host and from_cfg.
+ EXPECT_EQ(host->toText(), from_cfg->toText());
+}
// This test verifies that it is not possible to add the same Host to the
// same IPv4 subnet twice.
testUserContext(Element::fromJSON(comment));
}
+/// @brief Test insert and retrieve a v6 host with prefix exclude option.
+TEST_F(MySqlHostDataSourceTest, prefixExclude) {
+ testPrefixExclude("2001:db8::", "2001:db8:0:1::");
+}
+
/// @brief Test verifies if the hardware or client-id query can match hardware address.
TEST_F(MySqlHostDataSourceTest, DISABLED_hwaddrOrClientId1) {
/// @todo: The logic behind ::get4(subnet_id, hwaddr, duid) call needs to
testUserContext(Element::fromJSON(comment));
}
+/// @brief Test insert and retrieve a v6 host with prefix exclude option.
+TEST_F(PgSqlHostDataSourceTest, prefixExclude) {
+ testPrefixExclude("2001:db8::", "2001:db8:0:1::");
+}
+
/// @brief Test verifies if the hardware or client-id query can match hardware address.
TEST_F(PgSqlHostDataSourceTest, DISABLED_hwaddrOrClientId1) {
/// @todo: The logic behind ::get4(subnet_id, hwaddr, duid) call needs to
HostDataSourceUtils::compareHosts(host, from_hds);
}
+void
+GenericHostDataSourceTest::testPrefixExclude(std::string prefix,
+ std::string exclude) {
+
+ // Make sure we have a pointer to the host data source.
+ ASSERT_TRUE(hdsptr_);
+
+ // Create a host reservation.
+ HostPtr host = HostDataSourceUtils::initializeHost6(prefix,
+ exclude,
+ Host::IDENT_DUID,
+ false);
+ ASSERT_TRUE(host);
+ auto const& resvs = host->getIPv6Reservations(IPv6Resrv::TYPE_PD);
+ ASSERT_EQ(1, std::distance(resvs.first, resvs.second));
+ EXPECT_TRUE(resvs.first->second.getPDExclude());
+ SubnetID subnet = host->getIPv6SubnetID();
+
+ // Try to add it to the host data source.
+ ASSERT_NO_THROW(hdsptr_->add(host));
+
+ // Retrieve it.
+ ConstHostPtr from_hds = hdsptr_->get6(subnet, Host::IDENT_DUID,
+ &host->getIdentifier()[0],
+ host->getIdentifier().size());
+ ASSERT_TRUE(from_hds);
+
+ HostDataSourceUtils::compareHosts(host, from_hds);
+
+#if 0
+ // Verify the test is meaningful.
+ HostPtr host2 = HostDataSourceUtils::initializeHost6(prefix,
+ "2001:db8:0:2::",
+ Host::IDENT_DUID,
+ false);
+ host2->setIPv4SubnetID(host->getIPv4SubnetID());
+ host2->setIPv6SubnetID(host->getIPv6SubnetID());
+ ASSERT_TRUE(host2);
+ HostDataSourceUtils::compareHosts(host, host2);
+#endif
+}
void
GenericHostDataSourceTest::testMultipleSubnets(int subnets,
const Host::IdentifierType& id) {
/// @param user_context The user context.
void testUserContext(isc::data::ConstElementPtr user_context);
+ /// @brief Test insert and retrieve a v6 host with prefix exclude option.
+ ///
+ /// Uses gtest macros to report failures.
+ ///
+ /// @param prefix Prefix to reserve (/48).
+ /// @param exclude Prefix to exclude (/64).
+ void testPrefixExclude(std::string prefix, std::string exclude);
+
/// @brief Test inserts multiple reservations for the same host for different
/// subnets and check that they can be retrieved properly.
///
/// @param n_of_hosts number of hosts to insert into and retrieve from the
/// database
void stressTest(uint32_t n_of_hosts);
+
/// @brief Tests that delete(subnet-id, addr4) call works.
///
/// Uses gtest macros to report failures.
return (host);
}
+HostPtr
+HostDataSourceUtils::initializeHost6(std::string prefix,
+ std::string exclude,
+ Host::IdentifierType identifier,
+ bool new_identifier,
+ const std::string auth_key) {
+ std::vector<uint8_t> ident;
+ switch (identifier) {
+ case Host::IDENT_HWADDR:
+ ident = generateHWAddr(new_identifier);
+ break;
+ case Host::IDENT_DUID:
+ ident = generateIdentifier(new_identifier);
+ break;
+ default:
+ ADD_FAILURE() << "Unknown IdType: " << identifier;
+ return HostPtr();
+ }
+
+ // Let's create ever increasing subnet-ids. Let's keep those different,
+ // so subnet4 != subnet6. Useful for catching cases if the code confuses
+ // subnet4 with subnet6.
+ static SubnetID subnet4 = 0;
+ static SubnetID subnet6 = 100;
+ ++subnet4;
+ ++subnet6;
+
+ HostPtr host(new Host(&ident[0], ident.size(), identifier, subnet4, subnet6,
+ IOAddress("0.0.0.0")));
+
+ host->setKey(AuthKey(auth_key));
+
+ // Create IPv6 reservation for a /48 prefix
+ IPv6Resrv resv(IPv6Resrv::TYPE_PD, IOAddress(prefix), 48);
+ resv.setPDExclude(IOAddress(exclude), 64);
+ host->addReservation(resv);
+
+ return (host);
+}
+
bool
HostDataSourceUtils::reservationExists(const IPv6Resrv& resrv,
const IPv6ResrvRange& range) {
for (; r2 != resrv2.second; ++r2) {
// IPv6Resrv object implements equality operator.
if (r1->second == r2->second) {
- break;
+ // but this operator does not check Prefix Exclude options.
+ auto const& p1 = r1->second.getPDExclude();
+ auto const& p2 = r2->second.getPDExclude();
+ if (!p1 && !p2) {
+ break;
+ } else if (p1 && p2 &&
+ (p1->getExcludedPrefixLength() ==
+ p2->getExcludedPrefixLength()) &&
+ (p1->getExcludedPrefixSubnetID() ==
+ p2->getExcludedPrefixSubnetID())) {
+ break;
+ }
}
}
// If r2 iterator reached the end of the range it means that there
// is no match.
if (r2 == resrv2.second) {
ADD_FAILURE() << "No match found for reservation: "
- << resrv1.first->second.getPrefix().toText();
+ << r1->second.getPrefix().toText();
+ return;
}
}
-
- if (std::distance(resrv1.first, resrv1.second) > 0) {
- for (; resrv1.first != resrv1.second; resrv1.first++) {
- IPv6ResrvIterator iter = resrv2.first;
- while (iter != resrv2.second) {
- if ((resrv1.first->second.getType() ==
- iter->second.getType()) &&
- (resrv1.first->second.getPrefixLen() ==
- iter->second.getPrefixLen()) &&
- (resrv1.first->second.getPrefix() ==
- iter->second.getPrefix())) {
+ // Same with 1 and 2 swapped role.
+ for (IPv6ResrvIterator r2 = resrv2.first; r2 != resrv2.second; ++r2) {
+ IPv6ResrvIterator r1 = resrv1.first;
+ for (; r1 != resrv1.second; ++r1) {
+ // IPv6Resrv object implements equality operator.
+ if (r1->second == r2->second) {
+ // but this operator does not check Prefix Exclude options.
+ auto const& p1 = r1->second.getPDExclude();
+ auto const& p2 = r2->second.getPDExclude();
+ if (!p1 && !p1) {
+ break;
+ } else if (p1 && p2 &&
+ (p1->getExcludedPrefixLength() ==
+ p2->getExcludedPrefixLength()) &&
+ (p1->getExcludedPrefixSubnetID() ==
+ p2->getExcludedPrefixSubnetID())) {
break;
- }
- iter++;
- if (iter == resrv2.second) {
- ADD_FAILURE() << "Reservation comparison failed, "
- "no match for reservation: "
- << resrv1.first->second.getPrefix().toText();
}
}
}
+ // If r1 iterator reached the end of the range it means that there
+ // is no match.
+ if (r1 == resrv1.second) {
+ ADD_FAILURE() << "No match found for reservation: "
+ << r2->second.getPrefix().toText();
+ return;
+ }
}
}
}
}
}
-
-// Copyright (C) 2018-2020 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2018-2024 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
bool prefix, bool new_identifier = true,
const std::string key = "");
+ /// @brief Creates a host reservation for specified IPv6 prefix and
+ /// excluded prefix.
+ ///
+ /// @param prefix IPv6 prefix to be reserved
+ /// @param exclude IPv6 prefix to be excluded
+ /// @param id type of identifier (IDENT_DUID or IDENT_HWADDR are supported)
+ /// @param new_identifier Boolean value indicating if new host
+ /// identifier should be generated or the same as previously.
+ ///
+ /// @return generated Host object
+ static HostPtr initializeHost6(std::string prefix,
+ std::string exclude,
+ Host::IdentifierType id,
+ bool new_identifier = true,
+ const std::string key = "");
+
/// @brief Generates a hardware address in text version.
///
/// @param increase A boolean value indicating if new address (increased)
}
}
}
-
#endif