Commit 22b8b335 authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[3150] checkType in Subnets implemented

parent f6619e64
......@@ -117,7 +117,7 @@ AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet,
if (it == pools.end()) {
// ok to access first element directly. We checked that pools is non-empty
IOAddress next = pools[0]->getFirstAddress();
subnet->setLastAllocated(next, lease_type_);
subnet->setLastAllocated(lease_type_, next);
return (next);
}
......@@ -126,7 +126,7 @@ AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet,
IOAddress next = increaseAddress(last); // basically addr++
if ((*it)->inRange(next)) {
// the next one is in the pool as well, so we haven't hit pool boundary yet
subnet->setLastAllocated(next, lease_type_);
subnet->setLastAllocated(lease_type_, next);
return (next);
}
......@@ -136,13 +136,13 @@ AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet,
// Really out of luck today. That was the last pool. Let's rewind
// to the beginning.
next = pools[0]->getFirstAddress();
subnet->setLastAllocated(next, lease_type_);
subnet->setLastAllocated(lease_type_, next);
return (next);
}
// there is a next pool, let's try first address from it
next = (*it)->getFirstAddress();
subnet->setLastAllocated(next, lease_type_);
subnet->setLastAllocated(lease_type_, next);
return (next);
}
......@@ -173,17 +173,21 @@ AllocEngine::RandomAllocator::pickAddress(const SubnetPtr&,
}
AllocEngine::AllocEngine(AllocType engine_type, unsigned int attempts)
AllocEngine::AllocEngine(AllocType engine_type, unsigned int attempts,
bool ipv6)
:attempts_(attempts) {
Pool::PoolType pool_type = ipv6?Pool::TYPE_IA:Pool::TYPE_V4;
switch (engine_type) {
case ALLOC_ITERATIVE:
allocator_.reset(new IterativeAllocator(Pool6::TYPE_IA));
allocator_.reset(new IterativeAllocator(pool_type));
break;
case ALLOC_HASHED:
allocator_.reset(new HashedAllocator(Pool6::TYPE_IA));
allocator_.reset(new HashedAllocator(pool_type));
break;
case ALLOC_RANDOM:
allocator_.reset(new RandomAllocator(Pool6::TYPE_IA));
allocator_.reset(new RandomAllocator(pool_type));
break;
default:
......
......@@ -193,7 +193,8 @@ protected:
/// @param engine_type selects allocation algorithm
/// @param attempts number of attempts for each lease allocation before
/// we give up (0 means unlimited)
AllocEngine(AllocType engine_type, unsigned int attempts);
/// @param ipv6 specifies if the engine should work for IPv4 or IPv6
AllocEngine(AllocType engine_type, unsigned int attempts, bool ipv6 = true);
/// @brief Returns IPv4 lease.
///
......
......@@ -102,8 +102,12 @@ isc::asiolink::IOAddress Subnet::getLastAllocated(Pool::PoolType type) const {
}
}
void Subnet::setLastAllocated(const isc::asiolink::IOAddress& addr,
Pool::PoolType type) {
void Subnet::setLastAllocated(Pool::PoolType type,
const isc::asiolink::IOAddress& addr) {
// check if the type is valid (and throw if it isn't)
checkType(type);
switch (type) {
case Pool::TYPE_V4:
case Pool::TYPE_IA:
......@@ -127,6 +131,12 @@ Subnet::toText() const {
return (tmp.str());
}
void Subnet4::checkType(Pool::PoolType type) {
if (type != Pool::TYPE_V4) {
isc_throw(BadValue, "Only TYPE_V4 is allowed for Subnet4");
}
}
Subnet4::Subnet4(const isc::asiolink::IOAddress& prefix, uint8_t length,
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
......@@ -273,6 +283,14 @@ Subnet6::Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length,
}
}
void Subnet6::checkType(Pool::PoolType type) {
if ( (type != Pool::TYPE_IA) && (type != Pool::TYPE_TA) &&
(type != Pool::TYPE_PD)) {
isc_throw(BadValue, "Invalid Pool type: " << static_cast<int>(type)
<< ", must be TYPE_IA, TYPE_TA or TYPE_PD for Subnet6");
}
}
void
Subnet6::validateOption(const OptionPtr& option) const {
if (!option) {
......
......@@ -254,8 +254,8 @@ public:
/// AllocEngine::IterativeAllocator and keep the data there
/// @param addr address/prefix to that was tried last
/// @param type lease type to be set
void setLastAllocated(const isc::asiolink::IOAddress& addr,
Pool::PoolType type);
void setLastAllocated(Pool::PoolType type,
const isc::asiolink::IOAddress& addr);
/// @brief returns unique ID for that subnet
/// @return unique ID for that subnet
......@@ -309,12 +309,12 @@ public:
/// @param iface_name name of the interface
void setIface(const std::string& iface_name);
/// @brief network interface name used to reach subnet (or "" for remote
/// @brief network interface name used to reach subnet (or "" for remote
/// subnets)
/// @return network interface name for directly attached subnets or ""
std::string getIface() const;
/// @brief returns textual representation of the subnet (e.g.
/// @brief returns textual representation of the subnet (e.g.
/// "2001:db8::/64")
///
/// @return textual representation
......@@ -344,6 +344,16 @@ protected:
return (id++);
}
/// @brief Checks if used pool type is valid
///
/// Allowed type for Subnet4 is Pool::TYPE_V4.
/// Allowed types for Subnet6 are Pool::TYPE_{IA,TA,PD}.
/// This method is implemented in derived classes.
///
/// @param type type to be checked
/// @throw BadValue if invalid value is used
virtual void checkType(Pool::PoolType type) = 0;
/// @brief Check if option is valid and can be added to a subnet.
///
/// @param option option to be validated.
......@@ -447,6 +457,14 @@ protected:
virtual isc::asiolink::IOAddress default_pool() const {
return (isc::asiolink::IOAddress("0.0.0.0"));
}
/// @brief Checks if used pool type is valid
///
/// Allowed type for Subnet4 is Pool::TYPE_V4.
///
/// @param type type to be checked
/// @throw BadValue if invalid value is used
virtual void checkType(Pool::PoolType type);
};
/// @brief A pointer to a Subnet4 object
......@@ -511,6 +529,14 @@ protected:
return (isc::asiolink::IOAddress("::"));
}
/// @brief Checks if used pool type is valid
///
/// allowed types for Subnet6 are Pool::TYPE_{IA,TA,PD}.
///
/// @param type type to be checked
/// @throw BadValue if invalid value is used
virtual void checkType(Pool::PoolType type);
/// @brief specifies optional interface-id
OptionPtr interface_id_;
......
......@@ -55,8 +55,10 @@ public:
/// @brief the sole constructor
/// @param engine_type specifies engine type (e.g. iterative)
/// @param attempts number of lease selection attempts before giving up
NakedAllocEngine(AllocEngine::AllocType engine_type, unsigned int attempts)
:AllocEngine(engine_type, attempts) {
/// @param ipv6 specifies if the engine is IPv6 or IPv4
NakedAllocEngine(AllocEngine::AllocType engine_type,
unsigned int attempts, bool ipv6 = true)
:AllocEngine(engine_type, attempts, ipv6) {
}
// Expose internal classes for testing purposes
......@@ -607,7 +609,8 @@ TEST_F(AllocEngine6Test, requestReuseExpiredLease6) {
// This test checks if the simple IPv4 allocation can succeed
TEST_F(AllocEngine4Test, simpleAlloc4) {
boost::scoped_ptr<AllocEngine> engine;
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
100, false)));
ASSERT_TRUE(engine);
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
......@@ -636,7 +639,8 @@ TEST_F(AllocEngine4Test, simpleAlloc4) {
// This test checks if the fake allocation (for DISCOVER) can succeed
TEST_F(AllocEngine4Test, fakeAlloc4) {
boost::scoped_ptr<AllocEngine> engine;
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
100, false)));
ASSERT_TRUE(engine);
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
......@@ -664,7 +668,8 @@ TEST_F(AllocEngine4Test, fakeAlloc4) {
// in pool and free) can succeed
TEST_F(AllocEngine4Test, allocWithValidHint4) {
boost::scoped_ptr<AllocEngine> engine;
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
100, false)));
ASSERT_TRUE(engine);
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
......@@ -697,7 +702,8 @@ TEST_F(AllocEngine4Test, allocWithValidHint4) {
// in pool, but is currently used) can succeed
TEST_F(AllocEngine4Test, allocWithUsedHint4) {
boost::scoped_ptr<AllocEngine> engine;
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
100, false)));
ASSERT_TRUE(engine);
// Let's create a lease and put it in the LeaseMgr
......@@ -745,7 +751,8 @@ TEST_F(AllocEngine4Test, allocWithUsedHint4) {
// can succeed. The invalid hint should be ignored completely.
TEST_F(AllocEngine4Test, allocBogusHint4) {
boost::scoped_ptr<AllocEngine> engine;
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
100, false)));
ASSERT_TRUE(engine);
// Client would like to get a 3000::abc lease, which does not belong to any
......@@ -780,7 +787,8 @@ TEST_F(AllocEngine4Test, allocBogusHint4) {
// This test checks that NULL values are handled properly
TEST_F(AllocEngine4Test, allocateAddress4Nulls) {
boost::scoped_ptr<AllocEngine> engine;
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
100, false)));
ASSERT_TRUE(engine);
// Allocations without subnet are not allowed
......@@ -898,7 +906,8 @@ TEST_F(AllocEngine4Test, IterativeAllocator_manyPools4) {
// This test checks if really small pools are working
TEST_F(AllocEngine4Test, smallPool4) {
boost::scoped_ptr<AllocEngine> engine;
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
100, false)));
ASSERT_TRUE(engine);
IOAddress addr("192.0.2.17");
......@@ -940,7 +949,8 @@ TEST_F(AllocEngine4Test, smallPool4) {
// to find out a new lease fails.
TEST_F(AllocEngine4Test, outOfAddresses4) {
boost::scoped_ptr<AllocEngine> engine;
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
100, false)));
ASSERT_TRUE(engine);
IOAddress addr("192.0.2.17");
......@@ -978,7 +988,8 @@ TEST_F(AllocEngine4Test, outOfAddresses4) {
// This test checks if an expired lease can be reused in DISCOVER (fake allocation)
TEST_F(AllocEngine4Test, discoverReuseExpiredLease4) {
boost::scoped_ptr<AllocEngine> engine;
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
100, false)));
ASSERT_TRUE(engine);
IOAddress addr("192.0.2.15");
......@@ -1045,7 +1056,8 @@ TEST_F(AllocEngine4Test, discoverReuseExpiredLease4) {
// This test checks if an expired lease can be reused in REQUEST (actual allocation)
TEST_F(AllocEngine4Test, requestReuseExpiredLease4) {
boost::scoped_ptr<AllocEngine> engine;
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
100, false)));
ASSERT_TRUE(engine);
IOAddress addr("192.0.2.105");
......@@ -1098,7 +1110,8 @@ TEST_F(AllocEngine4Test, renewLease4) {
boost::scoped_ptr<AllocEngine> engine;
CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
100, false)));
ASSERT_TRUE(engine);
IOAddress addr("192.0.2.102");
......@@ -1471,7 +1484,8 @@ TEST_F(HookAllocEngine4Test, lease4_select) {
// Create allocation engine (hook names are registered in its ctor)
boost::scoped_ptr<AllocEngine> engine;
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
100, false)));
ASSERT_TRUE(engine);
// Initialize Hooks Manager
......@@ -1534,7 +1548,8 @@ TEST_F(HookAllocEngine4Test, change_lease4_select) {
// Create allocation engine (hook names are registered in its ctor)
boost::scoped_ptr<AllocEngine> engine;
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
100, false)));
ASSERT_TRUE(engine);
// Initialize Hooks Manager
......
......@@ -175,6 +175,28 @@ TEST(Subnet4Test, get) {
EXPECT_EQ(28, subnet->get().second);
}
// Checks if last allocated address/prefix is stored/retrieved properly
TEST(Subnet4Test, lastAllocated) {
IOAddress addr("192.0.2.17");
IOAddress last("192.0.2.255");
Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
// Check initial conditions (all should be set to the last address in range)
EXPECT_EQ(last.toText(), subnet->getLastAllocated(Pool::TYPE_V4).toText());
// Now set last allocated for IA
EXPECT_NO_THROW(subnet->setLastAllocated(Pool::TYPE_V4, addr));
EXPECT_EQ(addr.toText(), subnet->getLastAllocated(Pool::TYPE_V4).toText());
// No, you can't set the last allocated IPv6 address in IPv4 subnet
EXPECT_THROW(subnet->setLastAllocated(Pool::TYPE_IA, addr), BadValue);
EXPECT_THROW(subnet->setLastAllocated(Pool::TYPE_TA, addr), BadValue);
EXPECT_THROW(subnet->setLastAllocated(Pool::TYPE_PD, addr), BadValue);
}
// Tests for Subnet6
TEST(Subnet6Test, constructor) {
......@@ -532,4 +554,39 @@ TEST(Subnet6Test, interfaceId) {
}
// Checks if last allocated address/prefix is stored/retrieved properly
TEST(Subnet6Test, lastAllocated) {
IOAddress ia("2001:db8:1::1");
IOAddress ta("2001:db8:1::abcd");
IOAddress pd("2001:db8:1::1234:5678");
IOAddress last("2001:db8:1::ffff:ffff:ffff:ffff");
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 64, 1, 2, 3, 4));
// Check initial conditions (all should be set to the last address in range)
EXPECT_EQ(last.toText(), subnet->getLastAllocated(Pool::TYPE_IA).toText());
EXPECT_EQ(last.toText(), subnet->getLastAllocated(Pool::TYPE_TA).toText());
EXPECT_EQ(last.toText(), subnet->getLastAllocated(Pool::TYPE_PD).toText());
// Now set last allocated for IA
EXPECT_NO_THROW(subnet->setLastAllocated(Pool::TYPE_IA, ia));
EXPECT_EQ(ia.toText(), subnet->getLastAllocated(Pool::TYPE_IA).toText());
// TA and PD should be unchanged
EXPECT_EQ(last.toText(), subnet->getLastAllocated(Pool::TYPE_TA).toText());
EXPECT_EQ(last.toText(), subnet->getLastAllocated(Pool::TYPE_PD).toText());
// Now set TA and PD
EXPECT_NO_THROW(subnet->setLastAllocated(Pool::TYPE_TA, ta));
EXPECT_NO_THROW(subnet->setLastAllocated(Pool::TYPE_PD, pd));
EXPECT_EQ(ia.toText(), subnet->getLastAllocated(Pool::TYPE_IA).toText());
EXPECT_EQ(ta.toText(), subnet->getLastAllocated(Pool::TYPE_TA).toText());
EXPECT_EQ(pd.toText(), subnet->getLastAllocated(Pool::TYPE_PD).toText());
// No, you can't set the last allocated IPv4 address in IPv6 subnet
EXPECT_THROW(subnet->setLastAllocated(Pool::TYPE_V4, ia), BadValue);
}
};
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment