mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-01 14:35:29 +00:00
[295-min-max-lease-time-configuration-options] Added DHCPv4 server tests
This commit is contained in:
@@ -546,6 +546,8 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
|
||||
if ( (config_pair.first == "renew-timer") ||
|
||||
(config_pair.first == "rebind-timer") ||
|
||||
(config_pair.first == "valid-lifetime") ||
|
||||
(config_pair.first == "min-valid-lifetime") ||
|
||||
(config_pair.first == "max-valid-lifetime") ||
|
||||
(config_pair.first == "decline-probation-period") ||
|
||||
(config_pair.first == "dhcp4o6-port") ||
|
||||
(config_pair.first == "echo-client-id") ||
|
||||
|
@@ -315,7 +315,7 @@ TEST_F(Dhcp4CBTest, mergeOptions) {
|
||||
" \"name\": \"dhcp-message\", \n"
|
||||
" \"data\": \"0A0B0C0D\", \n"
|
||||
" \"csv-format\": false \n"
|
||||
" },{ \n"
|
||||
" },{ \n"
|
||||
" \"name\": \"host-name\", \n"
|
||||
" \"data\": \"old.example.com\", \n"
|
||||
" \"csv-format\": true \n"
|
||||
@@ -372,7 +372,7 @@ TEST_F(Dhcp4CBTest, mergeOptions) {
|
||||
ASSERT_TRUE(found_opt.option_);
|
||||
EXPECT_EQ("0x0A0B0C0D", found_opt.option_->toHexString());
|
||||
|
||||
// host-name should come from the first back end,
|
||||
// host-name should come from the first back end,
|
||||
// (overwriting the original).
|
||||
found_opt = options->get("dhcp4", DHO_HOST_NAME);
|
||||
ASSERT_TRUE(found_opt.option_);
|
||||
|
@@ -726,10 +726,15 @@ public:
|
||||
/// @param t1 expected renew-timer value
|
||||
/// @param t2 expected rebind-timer value
|
||||
/// @param valid expected valid-lifetime value
|
||||
/// @param min_valid expected min-valid-lifetime value
|
||||
/// (0 (default) means same than valid)
|
||||
/// @param max_valid expected max-valid-lifetime value
|
||||
/// (0 (default) means same than valid)
|
||||
/// @return the subnet that was examined
|
||||
Subnet4Ptr
|
||||
checkSubnet(const Subnet4Collection& col, std::string subnet,
|
||||
uint32_t t1, uint32_t t2, uint32_t valid) {
|
||||
uint32_t t1, uint32_t t2, uint32_t valid,
|
||||
uint32_t min_valid = 0, uint32_t max_valid = 0) {
|
||||
const auto& index = col.get<SubnetPrefixIndexTag>();
|
||||
auto subnet_it = index.find(subnet);
|
||||
if (subnet_it == index.cend()) {
|
||||
@@ -741,6 +746,8 @@ public:
|
||||
EXPECT_EQ(t1, s->getT1());
|
||||
EXPECT_EQ(t2, s->getT2());
|
||||
EXPECT_EQ(valid, s->getValid());
|
||||
EXPECT_EQ(min_valid ? min_valid : valid, s->getValid().getMin());
|
||||
EXPECT_EQ(max_valid ? max_valid : valid, s->getValid().getMax());
|
||||
|
||||
return (s);
|
||||
}
|
||||
@@ -835,6 +842,35 @@ TEST_F(Dhcp4ParserTest, emptySubnet) {
|
||||
checkResult(status, 0);
|
||||
}
|
||||
|
||||
/// Check that valid-lifetime must be between min-valid-lifetime and
|
||||
/// max-valid-lifetime when a bound is specified, *AND* a subnet is
|
||||
/// specified (boundary check is done when lifetimes are applied).
|
||||
TEST_F(Dhcp4ParserTest, outBoundValidLifetime) {
|
||||
|
||||
string too_small = "{ " + genIfaceConfig() + "," +
|
||||
"\"subnet4\": [ { "
|
||||
" \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
|
||||
" \"subnet\": \"192.0.2.0/24\" } ],"
|
||||
"\"valid-lifetime\": 1000, \"min-valid-lifetime\": 1001 }";
|
||||
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseDHCP4(too_small));
|
||||
|
||||
ConstElementPtr status;
|
||||
EXPECT_NO_THROW(status = configureDhcp4Server(*srv_, json));
|
||||
checkResult(status, 1);
|
||||
|
||||
string too_large = "{ " + genIfaceConfig() + "," +
|
||||
"\"subnet4\": [ { "
|
||||
" \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
|
||||
" \"subnet\": \"192.0.2.0/24\" } ],"
|
||||
"\"valid-lifetime\": 4001, \"max-valid-lifetime\": 4000 }";
|
||||
|
||||
ASSERT_NO_THROW(json = parseDHCP4(too_large));
|
||||
EXPECT_NO_THROW(status = configureDhcp4Server(*srv_, json));
|
||||
checkResult(status, 1);
|
||||
}
|
||||
|
||||
/// Check that the renew-timer doesn't have to be specified, in which case
|
||||
/// it is marked unspecified in the Subnet.
|
||||
TEST_F(Dhcp4ParserTest, unspecifiedRenewTimer) {
|
||||
@@ -912,7 +948,9 @@ TEST_F(Dhcp4ParserTest, subnetGlobalDefaults) {
|
||||
"\"subnet4\": [ { "
|
||||
" \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
|
||||
" \"subnet\": \"192.0.2.0/24\" } ],"
|
||||
"\"valid-lifetime\": 4000 }";
|
||||
"\"valid-lifetime\": 4000,"
|
||||
"\"min-valid-lifetime\": 3000,"
|
||||
"\"max-valid-lifetime\": 5000 }";
|
||||
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseDHCP4(config));
|
||||
@@ -932,6 +970,8 @@ TEST_F(Dhcp4ParserTest, subnetGlobalDefaults) {
|
||||
EXPECT_EQ(1000, subnet->getT1());
|
||||
EXPECT_EQ(2000, subnet->getT2());
|
||||
EXPECT_EQ(4000, subnet->getValid());
|
||||
EXPECT_EQ(3000, subnet->getValid().getMin());
|
||||
EXPECT_EQ(5000, subnet->getValid().getMax());
|
||||
|
||||
// Check that subnet-id is 1
|
||||
EXPECT_EQ(1, subnet->getID());
|
||||
@@ -1645,8 +1685,12 @@ TEST_F(Dhcp4ParserTest, subnetLocal) {
|
||||
" \"renew-timer\": 1, "
|
||||
" \"rebind-timer\": 2, "
|
||||
" \"valid-lifetime\": 4,"
|
||||
" \"min-valid-lifetime\": 3,"
|
||||
" \"max-valid-lifetime\": 5,"
|
||||
" \"subnet\": \"192.0.2.0/24\" } ],"
|
||||
"\"valid-lifetime\": 4000 }";
|
||||
"\"valid-lifetime\": 4000,"
|
||||
"\"min-valid-lifetime\": 3000,"
|
||||
"\"max-valid-lifetime\": 5000 }";
|
||||
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseDHCP4(config));
|
||||
@@ -1664,6 +1708,8 @@ TEST_F(Dhcp4ParserTest, subnetLocal) {
|
||||
EXPECT_EQ(1, subnet->getT1());
|
||||
EXPECT_EQ(2, subnet->getT2());
|
||||
EXPECT_EQ(4, subnet->getValid());
|
||||
EXPECT_EQ(3, subnet->getValid().getMin());
|
||||
EXPECT_EQ(5, subnet->getValid().getMax());
|
||||
}
|
||||
|
||||
// This test checks that multiple pools can be defined and handled properly.
|
||||
@@ -5910,6 +5956,8 @@ TEST_F(Dhcp4ParserTest, sharedNetworks1subnet) {
|
||||
TEST_F(Dhcp4ParserTest, sharedNetworks3subnets) {
|
||||
string config = "{\n"
|
||||
"\"valid-lifetime\": 4000, \n"
|
||||
"\"min-valid-lifetime\": 3000, \n"
|
||||
"\"max-valid-lifetime\": 5000, \n"
|
||||
"\"rebind-timer\": 2000, \n"
|
||||
"\"renew-timer\": 1000, \n"
|
||||
"\"shared-networks\": [ {\n"
|
||||
@@ -5924,7 +5972,9 @@ TEST_F(Dhcp4ParserTest, sharedNetworks3subnets) {
|
||||
" \"pools\": [ { \"pool\": \"192.0.2.1-192.0.2.10\" } ],\n"
|
||||
" \"renew-timer\": 2,\n"
|
||||
" \"rebind-timer\": 22,\n"
|
||||
" \"valid-lifetime\": 222\n"
|
||||
" \"valid-lifetime\": 222,\n"
|
||||
" \"min-valid-lifetime\": 111,\n"
|
||||
" \"max-valid-lifetime\": 333\n"
|
||||
" },\n"
|
||||
" { \n"
|
||||
" \"subnet\": \"192.0.3.0/24\",\n"
|
||||
@@ -5954,9 +6004,9 @@ TEST_F(Dhcp4ParserTest, sharedNetworks3subnets) {
|
||||
const Subnet4Collection * subs = net->getAllSubnets();
|
||||
ASSERT_TRUE(subs);
|
||||
EXPECT_EQ(3, subs->size());
|
||||
checkSubnet(*subs, "192.0.1.0/24", 1000, 2000, 4000);
|
||||
checkSubnet(*subs, "192.0.2.0/24", 2, 22, 222);
|
||||
checkSubnet(*subs, "192.0.3.0/24", 1000, 2000, 4000);
|
||||
checkSubnet(*subs, "192.0.1.0/24", 1000, 2000, 4000, 3000, 5000);
|
||||
checkSubnet(*subs, "192.0.2.0/24", 2, 22, 222, 111, 333);
|
||||
checkSubnet(*subs, "192.0.3.0/24", 1000, 2000, 4000, 3000, 5000);
|
||||
|
||||
// Now make sure the subnet was added to global list of subnets.
|
||||
CfgSubnets4Ptr subnets4 = CfgMgr::instance().getStagingCfg()->getCfgSubnets4();
|
||||
@@ -5964,9 +6014,9 @@ TEST_F(Dhcp4ParserTest, sharedNetworks3subnets) {
|
||||
|
||||
subs = subnets4->getAll();
|
||||
ASSERT_TRUE(subs);
|
||||
checkSubnet(*subs, "192.0.1.0/24", 1000, 2000, 4000);
|
||||
checkSubnet(*subs, "192.0.2.0/24", 2, 22, 222);
|
||||
checkSubnet(*subs, "192.0.3.0/24", 1000, 2000, 4000);
|
||||
checkSubnet(*subs, "192.0.1.0/24", 1000, 2000, 4000, 3000, 5000);
|
||||
checkSubnet(*subs, "192.0.2.0/24", 2, 22, 222, 111, 333);
|
||||
checkSubnet(*subs, "192.0.3.0/24", 1000, 2000, 4000, 3000, 5000);
|
||||
}
|
||||
|
||||
// This test checks if parameters are derived properly:
|
||||
@@ -5990,6 +6040,8 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
|
||||
"\"renew-timer\": 1, \n" // global values here
|
||||
"\"rebind-timer\": 2, \n"
|
||||
"\"valid-lifetime\": 4, \n"
|
||||
"\"min-valid-lifetime\": 3, \n"
|
||||
"\"max-valid-lifetime\": 5, \n"
|
||||
"\"shared-networks\": [ {\n"
|
||||
" \"name\": \"foo\"\n," // shared network values here
|
||||
" \"interface\": \"eth0\",\n"
|
||||
@@ -6005,6 +6057,8 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
|
||||
" \"renew-timer\": 10,\n"
|
||||
" \"rebind-timer\": 20,\n"
|
||||
" \"valid-lifetime\": 40,\n"
|
||||
" \"min-valid-lifetime\": 30,\n"
|
||||
" \"max-valid-lifetime\": 50,\n"
|
||||
" \"subnet4\": [\n"
|
||||
" { \n"
|
||||
" \"subnet\": \"192.0.1.0/24\",\n"
|
||||
@@ -6016,6 +6070,8 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
|
||||
" \"renew-timer\": 100,\n"
|
||||
" \"rebind-timer\": 200,\n"
|
||||
" \"valid-lifetime\": 400,\n"
|
||||
" \"min-valid-lifetime\": 300,\n"
|
||||
" \"max-valid-lifetime\": 500,\n"
|
||||
" \"match-client-id\": true,\n"
|
||||
" \"next-server\": \"11.22.33.44\",\n"
|
||||
" \"server-hostname\": \"some-name.example.org\",\n"
|
||||
@@ -6063,7 +6119,7 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
|
||||
// derived from shared-network level. Other parameters a derived
|
||||
// from global scope to shared-network level and later again to
|
||||
// subnet4 level.
|
||||
Subnet4Ptr s = checkSubnet(*subs, "192.0.1.0/24", 10, 20, 40);
|
||||
Subnet4Ptr s = checkSubnet(*subs, "192.0.1.0/24", 10, 20, 40, 30, 50);
|
||||
ASSERT_TRUE(s);
|
||||
|
||||
// These are values derived from shared network scope:
|
||||
@@ -6080,7 +6136,7 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
|
||||
// was specified explicitly. Other parameters a derived
|
||||
// from global scope to shared-network level and later again to
|
||||
// subnet4 level.
|
||||
s = checkSubnet(*subs, "192.0.2.0/24", 100, 200, 400);
|
||||
s = checkSubnet(*subs, "192.0.2.0/24", 100, 200, 400, 300, 500);
|
||||
|
||||
// These are values derived from shared network scope:
|
||||
EXPECT_EQ("eth0", s->getIface().get());
|
||||
@@ -6102,7 +6158,7 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
|
||||
|
||||
// This subnet should derive its renew-timer from global scope.
|
||||
// All other parameters should have default values.
|
||||
s = checkSubnet(*subs, "192.0.3.0/24", 1, 2, 4);
|
||||
s = checkSubnet(*subs, "192.0.3.0/24", 1, 2, 4, 3, 5);
|
||||
EXPECT_EQ("", s->getIface().get());
|
||||
EXPECT_TRUE(s->getMatchClientId());
|
||||
EXPECT_FALSE(s->getAuthoritative());
|
||||
|
@@ -764,6 +764,82 @@ TEST_F(Dhcpv4SrvTest, DiscoverBasic) {
|
||||
checkClientId(offer, clientid);
|
||||
}
|
||||
|
||||
// This test verifies that OFFERs return expected valid lifetimes.
|
||||
TEST_F(Dhcpv4SrvTest, DiscoverValidLifetime) {
|
||||
IfaceMgrTestConfig test_config(true);
|
||||
IfaceMgr::instance().openSockets4();
|
||||
|
||||
boost::scoped_ptr<NakedDhcpv4Srv> srv;
|
||||
ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
|
||||
|
||||
// Recreate subnet
|
||||
Triplet<uint32_t> unspecified;
|
||||
Triplet<uint32_t> valid_lft(500, 1000, 1500);
|
||||
subnet_.reset(new Subnet4(IOAddress("192.0.2.0"), 24,
|
||||
unspecified,
|
||||
unspecified,
|
||||
valid_lft));
|
||||
|
||||
pool_ = Pool4Ptr(new Pool4(IOAddress("192.0.2.100"),
|
||||
IOAddress("192.0.2.110")));
|
||||
subnet_->addPool(pool_);
|
||||
CfgMgr::instance().clear();
|
||||
CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->add(subnet_);
|
||||
CfgMgr::instance().commit();
|
||||
|
||||
// Struct for describing an individual lifetime test scenario
|
||||
struct LifetimeTest {
|
||||
// logged test description
|
||||
std::string description_;
|
||||
// lifetime hint (0 means not send dhcp-lease-time option)
|
||||
uint32_t hint;
|
||||
// expected returned value
|
||||
uint32_t expected;
|
||||
};
|
||||
|
||||
// Test scenarios
|
||||
std::vector<LifetimeTest> tests = {
|
||||
{ "default valid lifetime", 0, 1000 },
|
||||
{ "specified valid lifetime", 1001, 1001 },
|
||||
{ "too small valid lifetime", 100, 500 },
|
||||
{ "too large valid lifetime", 2000, 1500 }
|
||||
};
|
||||
|
||||
// Iterate over the test scenarios.
|
||||
for (auto test : tests) {
|
||||
SCOPED_TRACE(test.description_);
|
||||
|
||||
// Create a discover packet to use
|
||||
Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
|
||||
dis->setRemoteAddr(IOAddress("192.0.2.1"));
|
||||
OptionPtr clientid = generateClientId();
|
||||
dis->addOption(clientid);
|
||||
dis->setIface("eth1");
|
||||
|
||||
// Add dhcp-lease-time option.
|
||||
if (test.hint) {
|
||||
OptionUint32Ptr opt(new OptionUint32(Option::V4,
|
||||
DHO_DHCP_LEASE_TIME,
|
||||
test.hint));
|
||||
dis->addOption(opt);
|
||||
}
|
||||
|
||||
// Pass it to the server and get an offer
|
||||
Pkt4Ptr offer = srv->processDiscover(dis);
|
||||
|
||||
// Check if we get response at all
|
||||
checkResponse(offer, DHCPOFFER, 1234);
|
||||
|
||||
// Check that address was returned from proper range, that its lease
|
||||
// lifetime is correct and has the expected value.
|
||||
checkAddressParams(offer, subnet_, false, false, test.expected);
|
||||
|
||||
// Check identifiers
|
||||
checkServerId(offer, srv->getServerID());
|
||||
checkClientId(offer, clientid);
|
||||
}
|
||||
}
|
||||
|
||||
// Check that option 58 and 59 are only included if they were specified
|
||||
// (and calculate-tee-times = false) and the values are sane:
|
||||
// T2 is less than valid lft; T1 is less than T2 (if given) or valid
|
||||
@@ -1370,6 +1446,377 @@ TEST_F(Dhcpv4SrvTest, RenewBasic) {
|
||||
EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr));
|
||||
}
|
||||
|
||||
// This test verifies that renewal returns the default valid lifetime
|
||||
// when the client does not specify a value.
|
||||
TEST_F(Dhcpv4SrvTest, RenewDefaultLifetime) {
|
||||
IfaceMgrTestConfig test_config(true);
|
||||
IfaceMgr::instance().openSockets4();
|
||||
|
||||
boost::scoped_ptr<NakedDhcpv4Srv> srv;
|
||||
ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
|
||||
|
||||
const IOAddress addr("192.0.2.106");
|
||||
const uint32_t temp_t1 = 50;
|
||||
const uint32_t temp_t2 = 75;
|
||||
const uint32_t temp_valid = 100;
|
||||
const time_t temp_timestamp = time(NULL) - 10;
|
||||
|
||||
// Generate client-id also sets client_id_ member
|
||||
OptionPtr clientid = generateClientId();
|
||||
|
||||
// Check that the address we are about to use is indeed in pool
|
||||
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
|
||||
|
||||
// let's create a lease and put it in the LeaseMgr
|
||||
uint8_t hwaddr2_data[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
|
||||
HWAddrPtr hwaddr2(new HWAddr(hwaddr2_data, sizeof(hwaddr2_data), HTYPE_ETHER));
|
||||
Lease4Ptr used(new Lease4(IOAddress("192.0.2.106"), hwaddr2,
|
||||
&client_id_->getDuid()[0], client_id_->getDuid().size(),
|
||||
temp_valid, temp_t1, temp_t2, temp_timestamp,
|
||||
subnet_->getID()));
|
||||
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
|
||||
|
||||
// Check that the lease is really in the database
|
||||
Lease4Ptr l = LeaseMgrFactory::instance().getLease4(addr);
|
||||
ASSERT_TRUE(l);
|
||||
|
||||
// Check that T1, T2, preferred, valid and cltt really set.
|
||||
// Constructed lease looks as if it was assigned 10 seconds ago
|
||||
// EXPECT_EQ(l->t1_, temp_t1);
|
||||
// EXPECT_EQ(l->t2_, temp_t2);
|
||||
EXPECT_EQ(l->valid_lft_, temp_valid);
|
||||
EXPECT_EQ(l->cltt_, temp_timestamp);
|
||||
|
||||
// Set the valid lifetime interval.
|
||||
subnet_->setValid(Triplet<uint32_t>(2000, 3000, 4000));
|
||||
|
||||
// Let's create a RENEW
|
||||
Pkt4Ptr req = Pkt4Ptr(new Pkt4(DHCPREQUEST, 1234));
|
||||
req->setRemoteAddr(IOAddress(addr));
|
||||
req->setYiaddr(addr);
|
||||
req->setCiaddr(addr); // client's address
|
||||
req->setIface("eth0");
|
||||
req->setHWAddr(hwaddr2);
|
||||
|
||||
req->addOption(clientid);
|
||||
req->addOption(srv->getServerID());
|
||||
|
||||
// There is no valid lifetime hint so the default will be returned.
|
||||
|
||||
// Pass it to the server and hope for a REPLY
|
||||
Pkt4Ptr ack = srv->processRequest(req);
|
||||
|
||||
// Check if we get response at all
|
||||
checkResponse(ack, DHCPACK, 1234);
|
||||
EXPECT_EQ(addr, ack->getYiaddr());
|
||||
|
||||
// Check that address was returned from proper range, that its lease
|
||||
// lifetime is correct, that T1 and T2 are returned properly
|
||||
checkAddressParams(ack, subnet_, true, true, subnet_->getValid());
|
||||
|
||||
// Check identifiers
|
||||
checkServerId(ack, srv->getServerID());
|
||||
checkClientId(ack, clientid);
|
||||
|
||||
// Check that the lease is really in the database
|
||||
l = checkLease(ack, clientid, req->getHWAddr(), addr);
|
||||
ASSERT_TRUE(l);
|
||||
|
||||
// Check that T1, T2, preferred, valid and cltt were really updated
|
||||
EXPECT_EQ(l->t1_, subnet_->getT1());
|
||||
EXPECT_EQ(l->t2_, subnet_->getT2());
|
||||
EXPECT_EQ(l->valid_lft_, subnet_->getValid());
|
||||
|
||||
// Checking for CLTT is a bit tricky if we want to avoid off by 1 errors
|
||||
int32_t cltt = static_cast<int32_t>(l->cltt_);
|
||||
int32_t expected = static_cast<int32_t>(time(NULL));
|
||||
// Equality or difference by 1 between cltt and expected is ok.
|
||||
EXPECT_GE(1, abs(cltt - expected));
|
||||
|
||||
EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr));
|
||||
}
|
||||
|
||||
// This test verifies that renewal returns the specified valid lifetime
|
||||
// when the client adds an in-bound hint in the DISCOVER.
|
||||
TEST_F(Dhcpv4SrvTest, RenewHintLifetime) {
|
||||
IfaceMgrTestConfig test_config(true);
|
||||
IfaceMgr::instance().openSockets4();
|
||||
|
||||
boost::scoped_ptr<NakedDhcpv4Srv> srv;
|
||||
ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
|
||||
|
||||
const IOAddress addr("192.0.2.106");
|
||||
const uint32_t temp_t1 = 50;
|
||||
const uint32_t temp_t2 = 75;
|
||||
const uint32_t temp_valid = 100;
|
||||
const time_t temp_timestamp = time(NULL) - 10;
|
||||
|
||||
// Generate client-id also sets client_id_ member
|
||||
OptionPtr clientid = generateClientId();
|
||||
|
||||
// Check that the address we are about to use is indeed in pool
|
||||
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
|
||||
|
||||
// let's create a lease and put it in the LeaseMgr
|
||||
uint8_t hwaddr2_data[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
|
||||
HWAddrPtr hwaddr2(new HWAddr(hwaddr2_data, sizeof(hwaddr2_data), HTYPE_ETHER));
|
||||
Lease4Ptr used(new Lease4(IOAddress("192.0.2.106"), hwaddr2,
|
||||
&client_id_->getDuid()[0], client_id_->getDuid().size(),
|
||||
temp_valid, temp_t1, temp_t2, temp_timestamp,
|
||||
subnet_->getID()));
|
||||
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
|
||||
|
||||
// Check that the lease is really in the database
|
||||
Lease4Ptr l = LeaseMgrFactory::instance().getLease4(addr);
|
||||
ASSERT_TRUE(l);
|
||||
|
||||
// Check that T1, T2, preferred, valid and cltt really set.
|
||||
// Constructed lease looks as if it was assigned 10 seconds ago
|
||||
// EXPECT_EQ(l->t1_, temp_t1);
|
||||
// EXPECT_EQ(l->t2_, temp_t2);
|
||||
EXPECT_EQ(l->valid_lft_, temp_valid);
|
||||
EXPECT_EQ(l->cltt_, temp_timestamp);
|
||||
|
||||
// Set the valid lifetime interval.
|
||||
subnet_->setValid(Triplet<uint32_t>(2000, 3000, 4000));
|
||||
|
||||
// Let's create a RENEW
|
||||
Pkt4Ptr req = Pkt4Ptr(new Pkt4(DHCPREQUEST, 1234));
|
||||
req->setRemoteAddr(IOAddress(addr));
|
||||
req->setYiaddr(addr);
|
||||
req->setCiaddr(addr); // client's address
|
||||
req->setIface("eth0");
|
||||
req->setHWAddr(hwaddr2);
|
||||
|
||||
req->addOption(clientid);
|
||||
req->addOption(srv->getServerID());
|
||||
|
||||
// Add a dhcp-lease-time with an in-bound valid lifetime hint
|
||||
// which will be returned in the OFFER.
|
||||
uint32_t hint = 3001;
|
||||
OptionPtr opt(new OptionUint32(Option::V4, DHO_DHCP_LEASE_TIME, hint));
|
||||
req->addOption(opt);
|
||||
|
||||
// Pass it to the server and hope for a REPLY
|
||||
Pkt4Ptr ack = srv->processRequest(req);
|
||||
|
||||
// Check if we get response at all
|
||||
checkResponse(ack, DHCPACK, 1234);
|
||||
EXPECT_EQ(addr, ack->getYiaddr());
|
||||
|
||||
// Check that address was returned from proper range, that its lease
|
||||
// lifetime is correct, that T1 and T2 are returned properly
|
||||
checkAddressParams(ack, subnet_, true, true, hint);
|
||||
|
||||
// Check identifiers
|
||||
checkServerId(ack, srv->getServerID());
|
||||
checkClientId(ack, clientid);
|
||||
|
||||
// Check that the lease is really in the database
|
||||
l = checkLease(ack, clientid, req->getHWAddr(), addr);
|
||||
ASSERT_TRUE(l);
|
||||
|
||||
// Check that T1, T2, preferred, valid and cltt were really updated
|
||||
EXPECT_EQ(l->t1_, subnet_->getT1());
|
||||
EXPECT_EQ(l->t2_, subnet_->getT2());
|
||||
EXPECT_EQ(l->valid_lft_, hint);
|
||||
|
||||
// Checking for CLTT is a bit tricky if we want to avoid off by 1 errors
|
||||
int32_t cltt = static_cast<int32_t>(l->cltt_);
|
||||
int32_t expected = static_cast<int32_t>(time(NULL));
|
||||
// Equality or difference by 1 between cltt and expected is ok.
|
||||
EXPECT_GE(1, abs(cltt - expected));
|
||||
|
||||
EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr));
|
||||
}
|
||||
|
||||
// This test verifies that renewal returns the min valid lifetime
|
||||
// when the client adds a too small hint in the DISCOVER.
|
||||
TEST_F(Dhcpv4SrvTest, RenewMinLifetime) {
|
||||
IfaceMgrTestConfig test_config(true);
|
||||
IfaceMgr::instance().openSockets4();
|
||||
|
||||
boost::scoped_ptr<NakedDhcpv4Srv> srv;
|
||||
ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
|
||||
|
||||
const IOAddress addr("192.0.2.106");
|
||||
const uint32_t temp_t1 = 50;
|
||||
const uint32_t temp_t2 = 75;
|
||||
const uint32_t temp_valid = 100;
|
||||
const time_t temp_timestamp = time(NULL) - 10;
|
||||
|
||||
// Generate client-id also sets client_id_ member
|
||||
OptionPtr clientid = generateClientId();
|
||||
|
||||
// Check that the address we are about to use is indeed in pool
|
||||
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
|
||||
|
||||
// let's create a lease and put it in the LeaseMgr
|
||||
uint8_t hwaddr2_data[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
|
||||
HWAddrPtr hwaddr2(new HWAddr(hwaddr2_data, sizeof(hwaddr2_data), HTYPE_ETHER));
|
||||
Lease4Ptr used(new Lease4(IOAddress("192.0.2.106"), hwaddr2,
|
||||
&client_id_->getDuid()[0], client_id_->getDuid().size(),
|
||||
temp_valid, temp_t1, temp_t2, temp_timestamp,
|
||||
subnet_->getID()));
|
||||
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
|
||||
|
||||
// Check that the lease is really in the database
|
||||
Lease4Ptr l = LeaseMgrFactory::instance().getLease4(addr);
|
||||
ASSERT_TRUE(l);
|
||||
|
||||
// Check that T1, T2, preferred, valid and cltt really set.
|
||||
// Constructed lease looks as if it was assigned 10 seconds ago
|
||||
// EXPECT_EQ(l->t1_, temp_t1);
|
||||
// EXPECT_EQ(l->t2_, temp_t2);
|
||||
EXPECT_EQ(l->valid_lft_, temp_valid);
|
||||
EXPECT_EQ(l->cltt_, temp_timestamp);
|
||||
|
||||
// Set the valid lifetime interval.
|
||||
subnet_->setValid(Triplet<uint32_t>(2000, 3000, 4000));
|
||||
|
||||
// Let's create a RENEW
|
||||
Pkt4Ptr req = Pkt4Ptr(new Pkt4(DHCPREQUEST, 1234));
|
||||
req->setRemoteAddr(IOAddress(addr));
|
||||
req->setYiaddr(addr);
|
||||
req->setCiaddr(addr); // client's address
|
||||
req->setIface("eth0");
|
||||
req->setHWAddr(hwaddr2);
|
||||
|
||||
req->addOption(clientid);
|
||||
req->addOption(srv->getServerID());
|
||||
|
||||
// Add a dhcp-lease-time with too small valid lifetime hint.
|
||||
// The min valid lifetime will be returned in the OFFER.
|
||||
OptionPtr opt(new OptionUint32(Option::V4, DHO_DHCP_LEASE_TIME, 1000));
|
||||
req->addOption(opt);
|
||||
|
||||
// Pass it to the server and hope for a REPLY
|
||||
Pkt4Ptr ack = srv->processRequest(req);
|
||||
|
||||
// Check if we get response at all
|
||||
checkResponse(ack, DHCPACK, 1234);
|
||||
EXPECT_EQ(addr, ack->getYiaddr());
|
||||
|
||||
// Check that address was returned from proper range, that its lease
|
||||
// lifetime is correct, that T1 and T2 are returned properly
|
||||
// Note that T2 should be false for a reason which does not matter...
|
||||
checkAddressParams(ack, subnet_, true, false, subnet_->getValid().getMin());
|
||||
|
||||
// Check identifiers
|
||||
checkServerId(ack, srv->getServerID());
|
||||
checkClientId(ack, clientid);
|
||||
|
||||
// Check that the lease is really in the database
|
||||
l = checkLease(ack, clientid, req->getHWAddr(), addr);
|
||||
ASSERT_TRUE(l);
|
||||
|
||||
// Check that T1, T2, preferred, valid and cltt were really updated
|
||||
EXPECT_EQ(l->t1_, subnet_->getT1());
|
||||
EXPECT_EQ(l->t2_, subnet_->getT2());
|
||||
EXPECT_EQ(l->valid_lft_, subnet_->getValid().getMin());
|
||||
|
||||
// Checking for CLTT is a bit tricky if we want to avoid off by 1 errors
|
||||
int32_t cltt = static_cast<int32_t>(l->cltt_);
|
||||
int32_t expected = static_cast<int32_t>(time(NULL));
|
||||
// Equality or difference by 1 between cltt and expected is ok.
|
||||
EXPECT_GE(1, abs(cltt - expected));
|
||||
|
||||
EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr));
|
||||
}
|
||||
|
||||
// This test verifies that renewal returns the max valid lifetime
|
||||
// when the client adds a too large hint in the DISCOVER.
|
||||
TEST_F(Dhcpv4SrvTest, RenewMaxLifetime) {
|
||||
IfaceMgrTestConfig test_config(true);
|
||||
IfaceMgr::instance().openSockets4();
|
||||
|
||||
boost::scoped_ptr<NakedDhcpv4Srv> srv;
|
||||
ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
|
||||
|
||||
const IOAddress addr("192.0.2.106");
|
||||
const uint32_t temp_t1 = 50;
|
||||
const uint32_t temp_t2 = 75;
|
||||
const uint32_t temp_valid = 100;
|
||||
const time_t temp_timestamp = time(NULL) - 10;
|
||||
|
||||
// Generate client-id also sets client_id_ member
|
||||
OptionPtr clientid = generateClientId();
|
||||
|
||||
// Check that the address we are about to use is indeed in pool
|
||||
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
|
||||
|
||||
// let's create a lease and put it in the LeaseMgr
|
||||
uint8_t hwaddr2_data[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
|
||||
HWAddrPtr hwaddr2(new HWAddr(hwaddr2_data, sizeof(hwaddr2_data), HTYPE_ETHER));
|
||||
Lease4Ptr used(new Lease4(IOAddress("192.0.2.106"), hwaddr2,
|
||||
&client_id_->getDuid()[0], client_id_->getDuid().size(),
|
||||
temp_valid, temp_t1, temp_t2, temp_timestamp,
|
||||
subnet_->getID()));
|
||||
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
|
||||
|
||||
// Check that the lease is really in the database
|
||||
Lease4Ptr l = LeaseMgrFactory::instance().getLease4(addr);
|
||||
ASSERT_TRUE(l);
|
||||
|
||||
// Check that T1, T2, preferred, valid and cltt really set.
|
||||
// Constructed lease looks as if it was assigned 10 seconds ago
|
||||
// EXPECT_EQ(l->t1_, temp_t1);
|
||||
// EXPECT_EQ(l->t2_, temp_t2);
|
||||
EXPECT_EQ(l->valid_lft_, temp_valid);
|
||||
EXPECT_EQ(l->cltt_, temp_timestamp);
|
||||
|
||||
// Set the valid lifetime interval.
|
||||
subnet_->setValid(Triplet<uint32_t>(2000, 3000, 4000));
|
||||
|
||||
// Let's create a RENEW
|
||||
Pkt4Ptr req = Pkt4Ptr(new Pkt4(DHCPREQUEST, 1234));
|
||||
req->setRemoteAddr(IOAddress(addr));
|
||||
req->setYiaddr(addr);
|
||||
req->setCiaddr(addr); // client's address
|
||||
req->setIface("eth0");
|
||||
req->setHWAddr(hwaddr2);
|
||||
|
||||
req->addOption(clientid);
|
||||
req->addOption(srv->getServerID());
|
||||
|
||||
// Add a dhcp-lease-time with too large valid lifetime hint.
|
||||
// The max valid lifetime will be returned in the OFFER.
|
||||
OptionPtr opt(new OptionUint32(Option::V4, DHO_DHCP_LEASE_TIME, 5000));
|
||||
req->addOption(opt);
|
||||
|
||||
// Pass it to the server and hope for a REPLY
|
||||
Pkt4Ptr ack = srv->processRequest(req);
|
||||
|
||||
// Check if we get response at all
|
||||
checkResponse(ack, DHCPACK, 1234);
|
||||
EXPECT_EQ(addr, ack->getYiaddr());
|
||||
|
||||
// Check that address was returned from proper range, that its lease
|
||||
// lifetime is correct, that T1 and T2 are returned properly
|
||||
checkAddressParams(ack, subnet_, true, true, subnet_->getValid().getMax());
|
||||
|
||||
// Check identifiers
|
||||
checkServerId(ack, srv->getServerID());
|
||||
checkClientId(ack, clientid);
|
||||
|
||||
// Check that the lease is really in the database
|
||||
l = checkLease(ack, clientid, req->getHWAddr(), addr);
|
||||
ASSERT_TRUE(l);
|
||||
|
||||
// Check that T1, T2, preferred, valid and cltt were really updated
|
||||
EXPECT_EQ(l->t1_, subnet_->getT1());
|
||||
EXPECT_EQ(l->t2_, subnet_->getT2());
|
||||
EXPECT_EQ(l->valid_lft_, subnet_->getValid().getMax());
|
||||
|
||||
// Checking for CLTT is a bit tricky if we want to avoid off by 1 errors
|
||||
int32_t cltt = static_cast<int32_t>(l->cltt_);
|
||||
int32_t expected = static_cast<int32_t>(time(NULL));
|
||||
// Equality or difference by 1 between cltt and expected is ok.
|
||||
EXPECT_GE(1, abs(cltt - expected));
|
||||
|
||||
EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr));
|
||||
}
|
||||
|
||||
// This test verifies that the logic which matches server identifier in the
|
||||
// received message with server identifiers used by a server works correctly:
|
||||
// - a message with no server identifier is accepted,
|
||||
|
@@ -273,7 +273,8 @@ HWAddrPtr Dhcpv4SrvTest::generateHWAddr(size_t size /*= 6*/) {
|
||||
void Dhcpv4SrvTest::checkAddressParams(const Pkt4Ptr& rsp,
|
||||
const Subnet4Ptr subnet,
|
||||
bool t1_present,
|
||||
bool t2_present) {
|
||||
bool t2_present,
|
||||
uint32_t expected_valid) {
|
||||
|
||||
// Technically inPool implies inRange, but let's be on the safe
|
||||
// side and check both.
|
||||
@@ -286,10 +287,18 @@ void Dhcpv4SrvTest::checkAddressParams(const Pkt4Ptr& rsp,
|
||||
if (!opt) {
|
||||
ADD_FAILURE() << "Lease time option missing in response or the"
|
||||
" option has unexpected type";
|
||||
} else if (subnet->getValid().getMin() != subnet->getValid().getMax()) {
|
||||
EXPECT_GE(opt->getValue(), subnet->getValid().getMin());
|
||||
EXPECT_LE(opt->getValue(), subnet->getValid().getMax());
|
||||
} else {
|
||||
EXPECT_EQ(opt->getValue(), subnet->getValid());
|
||||
}
|
||||
|
||||
// Check expected value when wanted.
|
||||
if (opt && expected_valid) {
|
||||
EXPECT_EQ(opt->getValue(), expected_valid);
|
||||
}
|
||||
|
||||
// Check T1 timer
|
||||
opt = boost::dynamic_pointer_cast<
|
||||
OptionUint32>(rsp->getOption(DHO_DHCP_RENEWAL_TIME));
|
||||
|
@@ -354,9 +354,12 @@ public:
|
||||
/// present (false)
|
||||
/// @param t2_present check that t2 must be present (true) or must not be
|
||||
/// present (false)
|
||||
/// @param expected_valid check that lease lifetime has the not-zero
|
||||
/// expected value (zero value means that do not check).
|
||||
void checkAddressParams(const Pkt4Ptr& rsp, const Subnet4Ptr subnet,
|
||||
bool t1_present = false,
|
||||
bool t2_present = false);
|
||||
bool t2_present = false,
|
||||
uint32_t expected_valid = 0);
|
||||
|
||||
/// @brief Basic checks for generated response (message type and trans-id).
|
||||
///
|
||||
|
@@ -123,6 +123,8 @@ const char* EXTRACTED_CONFIGS[] = {
|
||||
" \"interfaces\": [ \"*\" ],\n"
|
||||
" \"re-detect\": false\n"
|
||||
" },\n"
|
||||
" \"max-valid-lifetime\": 5000,\n"
|
||||
" \"min-valid-lifetime\": 3000,\n"
|
||||
" \"rebind-timer\": 2000,\n"
|
||||
" \"renew-timer\": 1000,\n"
|
||||
" \"subnet4\": [\n"
|
||||
@@ -470,10 +472,14 @@ const char* EXTRACTED_CONFIGS[] = {
|
||||
" \"interfaces\": [ \"*\" ],\n"
|
||||
" \"re-detect\": false\n"
|
||||
" },\n"
|
||||
" \"max-valid-lifetime\": 5000,\n"
|
||||
" \"min-valid-lifetime\": 3000,\n"
|
||||
" \"rebind-timer\": 2000,\n"
|
||||
" \"renew-timer\": 1000,\n"
|
||||
" \"subnet4\": [\n"
|
||||
" {\n"
|
||||
" \"max-valid-lifetime\": 5,\n"
|
||||
" \"min-valid-lifetime\": 3,\n"
|
||||
" \"pools\": [\n"
|
||||
" {\n"
|
||||
" \"pool\": \"192.0.2.1 - 192.0.2.100\"\n"
|
||||
@@ -2330,6 +2336,8 @@ const char* UNPARSED_CONFIGS[] = {
|
||||
" \"type\": \"memfile\"\n"
|
||||
" },\n"
|
||||
" \"match-client-id\": true,\n"
|
||||
" \"max-valid-lifetime\": 5000,\n"
|
||||
" \"min-valid-lifetime\": 3000,\n"
|
||||
" \"next-server\": \"0.0.0.0\",\n"
|
||||
" \"option-data\": [ ],\n"
|
||||
" \"option-def\": [ ],\n"
|
||||
@@ -2350,6 +2358,8 @@ const char* UNPARSED_CONFIGS[] = {
|
||||
" \"calculate-tee-times\": false,\n"
|
||||
" \"id\": 1,\n"
|
||||
" \"match-client-id\": true,\n"
|
||||
" \"max-valid-lifetime\": 5000,\n"
|
||||
" \"min-valid-lifetime\": 3000,\n"
|
||||
" \"next-server\": \"0.0.0.0\",\n"
|
||||
" \"option-data\": [ ],\n"
|
||||
" \"pools\": [\n"
|
||||
@@ -3810,6 +3820,8 @@ const char* UNPARSED_CONFIGS[] = {
|
||||
" \"type\": \"memfile\"\n"
|
||||
" },\n"
|
||||
" \"match-client-id\": true,\n"
|
||||
" \"max-valid-lifetime\": 5000,\n"
|
||||
" \"min-valid-lifetime\": 3000,\n"
|
||||
" \"next-server\": \"0.0.0.0\",\n"
|
||||
" \"option-data\": [ ],\n"
|
||||
" \"option-def\": [ ],\n"
|
||||
@@ -3831,6 +3843,8 @@ const char* UNPARSED_CONFIGS[] = {
|
||||
" \"calculate-tee-times\": false,\n"
|
||||
" \"id\": 1,\n"
|
||||
" \"match-client-id\": true,\n"
|
||||
" \"max-valid-lifetime\": 5,\n"
|
||||
" \"min-valid-lifetime\": 3,\n"
|
||||
" \"next-server\": \"0.0.0.0\",\n"
|
||||
" \"option-data\": [ ],\n"
|
||||
" \"pools\": [\n"
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2016-2018 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2016-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
|
||||
@@ -115,6 +115,8 @@ TEST_F(SimpleParser4Test, inheritGlobalToSubnet4) {
|
||||
ElementPtr global = parseJSON("{ \"renew-timer\": 1,"
|
||||
" \"rebind-timer\": 2,"
|
||||
" \"valid-lifetime\": 4,"
|
||||
" \"min-valid-lifetime\": 3,"
|
||||
" \"max-valid-lifetime\": 5,"
|
||||
" \"subnet4\": [ { \"renew-timer\": 100 } ] "
|
||||
"}");
|
||||
ConstElementPtr subnets = global->find("subnet4");
|
||||
@@ -122,17 +124,19 @@ TEST_F(SimpleParser4Test, inheritGlobalToSubnet4) {
|
||||
ConstElementPtr subnet = subnets->get(0);
|
||||
ASSERT_TRUE(subnet);
|
||||
|
||||
// we should inherit 3 parameters. Renew-timer should remain intact,
|
||||
// we should inherit 4 parameters. Renew-timer should remain intact,
|
||||
// as it was already defined in the subnet scope.
|
||||
size_t num;
|
||||
EXPECT_NO_THROW(num = SimpleParser4::deriveParameters(global));
|
||||
EXPECT_EQ(2, num);
|
||||
EXPECT_EQ(4, num);
|
||||
|
||||
// Check the values. 2 of them are inherited, while the third one
|
||||
// was already defined in the subnet, so should not be inherited.
|
||||
checkIntegerValue(subnet, "renew-timer", 100);
|
||||
checkIntegerValue(subnet, "rebind-timer", 2);
|
||||
checkIntegerValue(subnet, "valid-lifetime", 4);
|
||||
checkIntegerValue(subnet, "min-valid-lifetime", 3);
|
||||
checkIntegerValue(subnet, "max-valid-lifetime", 5);
|
||||
}
|
||||
|
||||
// This test checks if the parameters in "subnet4" are assigned default values
|
||||
|
@@ -668,7 +668,11 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
|
||||
if ( (config_pair.first == "renew-timer") ||
|
||||
(config_pair.first == "rebind-timer") ||
|
||||
(config_pair.first == "preferred-lifetime") ||
|
||||
(config_pair.first == "min-preferred-lifetime") ||
|
||||
(config_pair.first == "max-preferred-lifetime") ||
|
||||
(config_pair.first == "valid-lifetime") ||
|
||||
(config_pair.first == "min-valid-lifetime") ||
|
||||
(config_pair.first == "max-valid-lifetime") ||
|
||||
(config_pair.first == "decline-probation-period") ||
|
||||
(config_pair.first == "dhcp4o6-port") ||
|
||||
(config_pair.first == "server-tag") ||
|
||||
|
Reference in New Issue
Block a user