Commit 8564e578 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[3947] Implemented 'new-leases-on-renew' parameter.

parent fc345a3a
......@@ -62,6 +62,12 @@
"item_default": 4000
},
{ "item_name": "new-leases-on-renew",
"item_type": "boolean",
"item_optional": true,
"item_default": true
},
{ "item_name": "option-def",
"item_type": "list",
"item_optional": false,
......
......@@ -1721,7 +1721,7 @@ Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
ctx.ia_rsp_ = ia_rsp;
ctx.hwaddr_ = orig_ctx.hwaddr_;
ctx.host_ = orig_ctx.host_;
ctx.allow_new_leases_in_renewals_ = true;
ctx.allow_new_leases_in_renewals_ = subnet->getAllocLeasesOnRenew();
// Extract the addresses that the client is trying to obtain.
OptionCollection addrs = ia->getOptions();
......@@ -1889,7 +1889,7 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query,
ctx.ia_rsp_ = ia_rsp;
ctx.hwaddr_ = orig_ctx.hwaddr_;
ctx.host_ = orig_ctx.host_;
ctx.allow_new_leases_in_renewals_ = true;
ctx.allow_new_leases_in_renewals_ = subnet->getAllocLeasesOnRenew();
// Extract prefixes that the client is trying to renew.
OptionCollection addrs = ia->getOptions();
......
......@@ -473,14 +473,19 @@ protected:
}
}
// Gather boolean parameters values.
bool rapid_commit = boolean_values_->getOptionalParam("rapid-commit", false);
bool alloc_leases_on_renew = globalContext()->
boolean_values_->getOptionalParam("new-leases-on-renew", true);
std::ostringstream output;
output << addr << "/" << static_cast<int>(len)
<< " with params t1=" << t1 << ", t2="
<< t2 << ", preferred-lifetime=" << pref
<< ", valid-lifetime=" << valid
<< ", rapid-commit is " << (rapid_commit ? "enabled" : "disabled");
<< ", rapid-commit is " << (rapid_commit ? "enabled" : "disabled")
<< ", new-leases-on-renew is " << (alloc_leases_on_renew ? "enabled" : "disabled");
LOG_INFO(dhcp6_logger, DHCP6_CONFIG_NEW_SUBNET).arg(output.str());
......@@ -497,6 +502,8 @@ protected:
// Enable or disable Rapid Commit option support for the subnet.
subnet6->setRapidCommit(rapid_commit);
// Enable or disable allocation of the new leases for the Renew or/and Rebind message.
subnet6->setAllocLeasesOnRenew(alloc_leases_on_renew);
// Try setting up client class (if specified)
try {
......@@ -693,6 +700,8 @@ namespace dhcp {
parser = new RSOOListConfigParser(config_id);
} else if (config_id.compare("control-socket") == 0) {
parser = new ControlSocketParser(config_id);
} else if (config_id.compare("new-leases-on-renew") == 0) {
parser = new BooleanParser(config_id, globalContext()->boolean_values_);
} else {
isc_throw(DhcpConfigError,
"unsupported global configuration parameter: "
......
......@@ -531,6 +531,37 @@ public:
CfgMgr::instance().clear();
}
/// @brief Test the 'new-leases-on-renew' configuration flag.
///
/// @param config Server configuration, possibly including the
/// 'new-leases-on-renew' parameter.
/// @param exp_alloc_leases_on_renew Expected value of the flag
void testAllocLeasesOnRenew(const std::string& config,
const bool exp_alloc_leases_on_renew) {
// Clear any existing configuration.
CfgMgr::instance().clear();
// Configure the server.
ElementPtr json = Element::fromJSON(config);
// Make sure that the configuration was successful.
ConstElementPtr status;
EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
checkResult(status, 0);
// Get the subnet.
Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->
selectSubnet(IOAddress("2001:db8:1::5"), classify_);
ASSERT_TRUE(subnet);
// Check the flag against the expected value.
EXPECT_EQ(exp_alloc_leases_on_renew, subnet->getAllocLeasesOnRenew());
// Clear any existing configuration.
CfgMgr::instance().clear();
}
int rcode_; ///< Return code (see @ref isc::config::parseAnswer)
Dhcpv6Srv srv_; ///< Instance of the Dhcp6Srv used during tests
ConstElementPtr comment_; ///< Comment (see @ref isc::config::parseAnswer)
......@@ -1172,6 +1203,55 @@ TEST_F(Dhcp6ParserTest, subnetRapidCommit) {
}
}
// This test checks the configuration of the Rapid Commit option
// support for the subnet.
TEST_F(Dhcp6ParserTest, subnetAllocLeasesOnRenew) {
{
// new-leases-on-renew implicitly set to false.
SCOPED_TRACE("Default setting for new-leases-on-renew");
testAllocLeasesOnRenew("{ \"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet6\": [ { "
" \"pools\": [ { \"pool\": \"2001:db8:1::1 - "
"2001:db8:1::ffff\" } ],"
" \"subnet\": \"2001:db8:1::/64\" } ],"
"\"valid-lifetime\": 4000 }",
true);
}
{
// new-leases-on-renew explicitly set to true.
SCOPED_TRACE("Enable new-leases-on-renew");
testAllocLeasesOnRenew("{ \"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"new-leases-on-renew\": True,"
"\"subnet6\": [ { "
" \"pools\": [ { \"pool\": \"2001:db8:1::1 - "
"2001:db8:1::ffff\" } ],"
" \"subnet\": \"2001:db8:1::/64\" } ],"
"\"valid-lifetime\": 4000 }",
true);
}
{
// new-leases-on-renew explicitly set to false.
SCOPED_TRACE("Disable new-leases-on-renew");
testAllocLeasesOnRenew("{ \"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"new-leases-on-renew\": False,"
"\"subnet6\": [ { "
" \"pools\": [ { \"pool\": \"2001:db8:1::1 - "
"2001:db8:1::ffff\" } ],"
" \"subnet\": \"2001:db8:1::/64\" } ],"
"\"valid-lifetime\": 4000 }",
false);
}
}
// This test checks that multiple pools can be defined and handled properly.
// The test defines 2 subnets, each with 2 pools.
TEST_F(Dhcp6ParserTest, multiplePools) {
......
......@@ -444,6 +444,9 @@ Dhcpv6SrvTest::testRenewReject(Lease::Type type, const IOAddress& addr) {
// Quick sanity check that the address we're about to use is ok
ASSERT_TRUE(subnet_->inPool(type, addr));
// Do not allocate leases as a result of Renew/Rebind.
subnet_->setAllocLeasesOnRenew(false);
// GenerateClientId() also sets duid_
OptionPtr clientid = generateClientId();
......
......@@ -70,6 +70,7 @@ const char* REBIND_CONFIGS[] = {
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"new-leases-on-renew\": False,"
"\"subnet6\": [ { "
" \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
" \"subnet\": \"2001:db8:1::/48\", "
......@@ -91,6 +92,7 @@ const char* REBIND_CONFIGS[] = {
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"new-leases-on-renew\": False,"
"\"subnet6\": [ { "
" \"pools\": [ { \"pool\": \"2001:db8:3::/64\" } ],"
" \"subnet\": \"2001:db8:3::/48\", "
......@@ -112,6 +114,7 @@ const char* REBIND_CONFIGS[] = {
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"new-leases-on-renew\": False,"
"\"subnet6\": [ { "
" \"pools\": [ { \"pool\": \"3000:1::/64\" } ],"
" \"subnet\": \"3000:1::/48\", "
......@@ -133,6 +136,7 @@ const char* REBIND_CONFIGS[] = {
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"new-leases-on-renew\": False,"
"\"subnet6\": [ { "
" \"pools\": [ { \"pool\": \"3000:3::/64\" } ],"
" \"subnet\": \"3000:3::/48\", "
......@@ -154,6 +158,7 @@ const char* REBIND_CONFIGS[] = {
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"new-leases-on-renew\": False,"
"\"subnet6\": [ { "
" \"pd-pools\": ["
" { \"prefix\": \"3000::\", "
......@@ -183,6 +188,7 @@ const char* REBIND_CONFIGS[] = {
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"new-leases-on-renew\": False,"
"\"subnet6\": [ { "
" \"pd-pools\": ["
" { \"prefix\": \"2001:db8:3:01::\", "
......
......@@ -330,7 +330,8 @@ Subnet6::Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length,
const Triplet<uint32_t>& valid_lifetime,
const SubnetID id)
:Subnet(prefix, length, t1, t2, valid_lifetime, RelayInfo(IOAddress("::")), id),
preferred_(preferred_lifetime), rapid_commit_(false) {
preferred_(preferred_lifetime), rapid_commit_(false),
alloc_leases_on_renew_(true) {
if (!prefix.isV6()) {
isc_throw(BadValue, "Non IPv6 prefix " << prefix
<< " specified in subnet6");
......
......@@ -655,6 +655,21 @@ public:
return (rapid_commit_);
}
/// @brief Enables or disables the allocation of the new leases for the
/// Renew and Rebind case.
///
/// @param alloc_leases_on_renew A boolean value indicating if the server
/// can allocate new leases for the Renew and Rebind case.
void setAllocLeasesOnRenew(const bool alloc_leases_on_renew) {
alloc_leases_on_renew_ = alloc_leases_on_renew;
}
/// @brief Returns boolean value indicating if the new leases are allocated
/// by the server as a result of processing Renew and/or Rebind.
bool getAllocLeasesOnRenew() const {
return (alloc_leases_on_renew_);
}
private:
/// @brief Returns default address for pool selection
......@@ -683,6 +698,18 @@ private:
/// It's default value is false, which indicates that the Rapid
/// Commit is disabled for the subnet.
bool rapid_commit_;
/// @brief A flag indicating if the server may allocate new leases
/// for the client sending a Renew or Rebind message.
///
/// This flag indicates that the client may request allocation of the
/// new leases (of any type) when it renews existing leases. This
/// facilitates the use cases described in RFC7550. If the server is
/// configured to allocate new leases for the Renew and Rebind case
/// but it can't allocate them (e.g. because of the pool exhaustion)
/// it will send the NoAddrsAvail or the NoPrefixAvail status code
/// in the IA, depending on the IA type.
bool alloc_leases_on_renew_;
};
/// @brief A pointer to a Subnet6 object
......
......@@ -1059,6 +1059,24 @@ TEST(Subnet6Test, rapidCommit) {
EXPECT_FALSE(subnet.getRapidCommit());
}
// This test checks that the flag which indicates if the new leases are
// allocated as a result of processing the Renew and Rebind message can
// be set to "enable" or "disable".
TEST(Subnet6Test, allocNewLeasesOnRenew) {
Subnet6 subnet(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4);
// By default, the flag should be enabled.
EXPECT_TRUE(subnet.getAllocLeasesOnRenew());
// Disable it.
subnet.setAllocLeasesOnRenew(false);
EXPECT_FALSE(subnet.getAllocLeasesOnRenew());
// Enable again.
subnet.setAllocLeasesOnRenew(true);
EXPECT_TRUE(subnet.getAllocLeasesOnRenew());
}
// Checks if last allocated address/prefix is stored/retrieved properly
TEST(Subnet6Test, lastAllocated) {
IOAddress ia("2001:db8:1::1");
......
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