Skip to content

Commit 6861ed9

Browse files
committed
[#3683] Addressed more comments
1 parent c217732 commit 6861ed9

File tree

13 files changed

+299
-19
lines changed

13 files changed

+299
-19
lines changed

doc/sphinx/arm/dhcp6-srv.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6869,6 +6869,13 @@ added or updated and a ADDR-REG-REPLY (37) is sent back to the client.
68696869
Kea accepts and handles the Option Request option in the ADDR-REG-INFORM
68706870
message (the RFC specifies the client MUST NOT put such option in it).
68716871

6872+
.. note::
6873+
6874+
Kea currently only accepts addresses which are "appropriate to the link"
6875+
but not yet "within a prefix delegated to the client" which is not
6876+
compatible with the way the topology is described in the Kea
6877+
configuration.
6878+
68726879
.. _dhcp6-stats:
68736880

68746881
Statistics in the DHCPv6 Server

src/bin/admin/tests/mysql_tests.sh.in

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2200,7 +2200,7 @@ mysql_lease6_stat_per_type() {
22002200
# insert a lease, update it, and delete checking the
22012201
# lease stat counts along the way. It assumes the
22022202
# database has been created but is empty.
2203-
# param addr - address to use to add to subnet 1
2203+
# param addr, addr1, addr2 - addresses to use to add to subnet 1
22042204
mysql_lease6_stat_registered() {
22052205
addr=$1;shift
22062206
addr1=$1;shift
@@ -2288,7 +2288,7 @@ mysql_lease6_stat_test() {
22882288
# Test for address ::22, PD lease type
22892289
mysql_lease6_stat_per_type "::22" "::23" "::24" "1"
22902290

2291-
# Test for registered address ::33
2291+
# Test for registered addresses ::33, ::34 and ::35
22922292
mysql_lease6_stat_registered "::33" "::34" "::35"
22932293

22942294
# Let's wipe the whole database

src/bin/admin/tests/pgsql_tests.sh.in

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1753,7 +1753,7 @@ pgsql_lease6_stat_per_type() {
17531753
# insert a lease, update it, and delete checking the
17541754
# lease stat counts along the way. It assumes the
17551755
# database has been created but is empty.
1756-
# param addr - address to use to add to subnet 1
1756+
# param addr, addr1, addr2 - addresses to use to add to subnet 1
17571757
pgsql_lease6_stat_registered() {
17581758
addr=$1;shift
17591759
addr1=$1;shift
@@ -1841,7 +1841,7 @@ pgsql_lease6_stat_test() {
18411841
# Test for address 222, PD lease type
18421842
pgsql_lease6_stat_per_type "::22" "::23" "::24" "1"
18431843

1844-
# Test for registered address ::33
1844+
# Test for registered addresses ::33, ::34 and ::35
18451845
pgsql_lease6_stat_registered "::33" "::34" "::35"
18461846

18471847
# Let's wipe the whole database

src/bin/dhcp6/dhcp6_srv.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3384,7 +3384,7 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query,
33843384
Lease6Ptr lease = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
33853385
release_addr->getAddress());
33863386

3387-
if (!lease) {
3387+
if (!lease || (lease->state_ == Lease::STATE_REGISTERED)) {
33883388
// client releasing a lease that we don't know about.
33893389

33903390
// Insert status code NoBinding.

src/bin/dhcp6/tests/addr_reg_unittest.cc

Lines changed: 114 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,11 @@ class AddrRegTest : public Dhcpv6MessageTest {
181181

182182
/// @brief Test that the registered lease is updated even it
183183
/// belongs to another client.
184-
void testAnother();
184+
void testAnotherClient();
185+
186+
/// @brief Test that the registered lease is updated even it
187+
/// belongs to another subnet.
188+
void testAnotherSubnet();
185189

186190
/// @brief Common part of skip/drop callout.
187191
void commonSkipOrDrop();
@@ -904,7 +908,7 @@ TEST_F(AddrRegTest, renew) {
904908

905909
// Test that the registered lease is updated even it belongs to another client.
906910
void
907-
AddrRegTest::testAnother() {
911+
AddrRegTest::testAnotherClient() {
908912
// Create and add a lease for another client.
909913
IOAddress addr("2001:db8:1::1");
910914
DuidPtr duid(new DUID(vector<uint8_t>(8, 0x44)));
@@ -961,12 +965,75 @@ AddrRegTest::testAnother() {
961965
}
962966

963967
// Test that the registered lease is updated even it belongs to another client.
964-
TEST_F(AddrRegTest, another) {
968+
TEST_F(AddrRegTest, anotherClient) {
969+
IfaceMgrTestConfig test_config(true);
970+
971+
ASSERT_NO_THROW(configure(config_));
972+
973+
testAnotherClient();
974+
}
975+
976+
// Test that the registratered lease is updated even it belongs to
977+
// another subnet.
978+
void
979+
AddrRegTest::testAnotherSubnet() {
980+
// Create and add a lease.
981+
IOAddress addr("2001:db8:1::1");
982+
OptionPtr clientid = generateClientId();
983+
Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, 2345, 200, 300, 2));
984+
lease->state_ = Lease::STATE_REGISTERED;
985+
lease->cltt_ = 1234;
986+
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
987+
988+
addr_reg_inf_ = Pkt6Ptr(new Pkt6(DHCPV6_ADDR_REG_INFORM, 1234));
989+
addr_reg_inf_->setRemoteAddr(addr);
990+
addr_reg_inf_->setIface("eth0");
991+
addr_reg_inf_->setIndex(ETH0_INDEX);
992+
addr_reg_inf_->addOption(clientid);
993+
auto ia = generateIA(D6O_IA_NA, 234, 1500, 3000);
994+
ia->addOption(generateIAAddr(addr, 3000, 4000));
995+
addr_reg_inf_->addOption(ia);
996+
997+
// Pass it to the server.
998+
AllocEngine::ClientContext6 ctx;
999+
bool drop = !srv_.earlyGHRLookup(addr_reg_inf_, ctx);
1000+
ASSERT_FALSE(drop);
1001+
ctx.subnet_ = srv_.selectSubnet(addr_reg_inf_, drop);
1002+
ASSERT_FALSE(drop);
1003+
srv_.initContext(ctx, drop);
1004+
ASSERT_FALSE(drop);
1005+
ASSERT_TRUE(ctx.subnet_);
1006+
1007+
// Verify the response.
1008+
Pkt6Ptr response = srv_.processAddrRegInform(ctx);
1009+
ASSERT_TRUE(response);
1010+
1011+
// Verify the updated lease.
1012+
Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, addr);
1013+
ASSERT_TRUE(l);
1014+
EXPECT_EQ(Lease::STATE_REGISTERED, l->state_);
1015+
EXPECT_EQ(addr, l->addr_);
1016+
ASSERT_TRUE(l->duid_);
1017+
EXPECT_TRUE(*l->duid_ == *duid_);
1018+
EXPECT_EQ(ia->getIAID(), l->iaid_);
1019+
EXPECT_EQ(1, l->subnet_id_);
1020+
EXPECT_FALSE(l->fqdn_fwd_);
1021+
EXPECT_FALSE(l->fqdn_rev_);
1022+
1023+
string expected = "DHCPSRV_MEMFILE_UPDATE_ADDR6 ";
1024+
expected += "updating IPv6 lease for address 2001:db8:1::1";
1025+
EXPECT_EQ(1, countFile(expected));
1026+
expected = "DHCP6_ADDR_REG_INFORM_CLIENT_CHANGE";
1027+
EXPECT_EQ(0, countFile(expected));
1028+
}
1029+
1030+
// Test that the registered lease is updated even it belongs to another subnet.
1031+
TEST_F(AddrRegTest, anotherSubnet) {
9651032
IfaceMgrTestConfig test_config(true);
9661033

9671034
ASSERT_NO_THROW(configure(config_));
9681035

969-
testAnother();
1036+
testAnotherSubnet();
9701037
}
9711038

9721039
// Test that the FQDN option is handled.
@@ -1357,15 +1424,15 @@ TEST_F(AddrRegTest, calloutRenew) {
13571424
}
13581425

13591426
// Test the callout in the another scenario.
1360-
TEST_F(AddrRegTest, calloutAnother) {
1427+
TEST_F(AddrRegTest, calloutAnotherClient) {
13611428
IfaceMgrTestConfig test_config(true);
13621429

13631430
ASSERT_NO_THROW(configure(config_));
13641431

13651432
// Install addr6_register_callout.
13661433
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
13671434
"addr6_register", addr6_register_callout));
1368-
testAnother();
1435+
testAnotherClient();
13691436
EXPECT_TRUE(callout_errmsg_.empty()) << callout_errmsg_;
13701437
checkCalloutHandleReset();
13711438

@@ -1535,4 +1602,45 @@ TEST_F(AddrRegTest, statsRenew) {
15351602
EXPECT_EQ(20, stat->getInteger().first);
15361603
}
15371604

1605+
// Check the statictics for the another subnet scenario.
1606+
TEST_F(AddrRegTest, statsAnotherSubnet) {
1607+
IfaceMgrTestConfig test_config(true);
1608+
1609+
ASSERT_NO_THROW(configure(config_));
1610+
1611+
string registered_nas_name2 =
1612+
StatsMgr::generateName("subnet", 2, "registered-nas");
1613+
StatsMgr::instance().setValue(registered_nas_name2,
1614+
static_cast<int64_t>(3));
1615+
StatsMgr::instance().setValue(registered_nas_name_,
1616+
static_cast<int64_t>(5));
1617+
string cumulative_registered_nas_name2 =
1618+
StatsMgr::generateName("subnet", 2, "cumulative-registered-nas");
1619+
StatsMgr::instance().setValue(cumulative_registered_nas_name2,
1620+
static_cast<int64_t>(8));
1621+
StatsMgr::instance().setValue(cumulative_registered_nas_name_,
1622+
static_cast<int64_t>(10));
1623+
StatsMgr::instance().setValue("cumulative-registered-nas",
1624+
static_cast<int64_t>(20));
1625+
1626+
testAnotherSubnet();
1627+
1628+
// Statistics should have been not touched.
1629+
ObservationPtr stat;
1630+
stat = StatsMgr::instance().getObservation(registered_nas_name2);
1631+
ASSERT_TRUE(stat);
1632+
EXPECT_EQ(2, stat->getInteger().first);
1633+
stat = StatsMgr::instance().getObservation(registered_nas_name_);
1634+
ASSERT_TRUE(stat);
1635+
EXPECT_EQ(6, stat->getInteger().first);
1636+
stat = StatsMgr::instance().getObservation(cumulative_registered_nas_name2);
1637+
ASSERT_TRUE(stat);
1638+
EXPECT_EQ(8, stat->getInteger().first);
1639+
stat = StatsMgr::instance().getObservation(cumulative_registered_nas_name_);
1640+
ASSERT_TRUE(stat);
1641+
EXPECT_EQ(11, stat->getInteger().first);
1642+
stat = StatsMgr::instance().getObservation("cumulative-registered-nas");
1643+
EXPECT_EQ(20, stat->getInteger().first);
1644+
}
1645+
15381646
} // end of anonymous namespace

src/bin/dhcp6/tests/dhcp6_srv_unittest.cc

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2313,6 +2313,47 @@ TEST_F(Dhcpv6SrvTest, pdReleaseReject) {
23132313
testReleaseReject(Lease::TYPE_PD, IOAddress("2001:db8:1:2::"));
23142314
}
23152315

2316+
// This test verifies that RELEASE doesn't work on registered leases.
2317+
TEST_F(Dhcpv6SrvTest, ReleaseRegistered) {
2318+
NakedDhcpv6Srv srv(0);
2319+
2320+
const IOAddress addr("2001:db8:1:2::");
2321+
const uint32_t transid = 1234;
2322+
const uint32_t iaid = 234;
2323+
2324+
// GenerateClientId() also sets duid_
2325+
OptionPtr clientid = generateClientId();
2326+
2327+
// Create a registered lease.
2328+
Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid, 501, 502,
2329+
subnet_->getID(), HWAddrPtr()));
2330+
lease->state_ = Lease::STATE_REGISTERED;
2331+
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
2332+
2333+
// Let's create a RELEASE
2334+
Pkt6Ptr rel = createMessage(DHCPV6_RELEASE, Lease::TYPE_NA, addr, 128, iaid);
2335+
rel->addOption(clientid);
2336+
rel->addOption(srv.getServerID());
2337+
2338+
// Pass it to the server and hope for a REPLY
2339+
Pkt6Ptr reply = srv.processRelease(rel);
2340+
2341+
// Check if we get response at all
2342+
checkResponse(reply, DHCPV6_REPLY, transid);
2343+
OptionPtr tmp = reply->getOption(D6O_IA_NA);
2344+
ASSERT_TRUE(tmp);
2345+
// Check that IA_NA/IA_PD was returned and that there's status code in it
2346+
boost::shared_ptr<Option6IA> ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
2347+
ASSERT_TRUE(ia);
2348+
checkIA_NAStatusCode(ia, STATUS_NoBinding, 0, 0);
2349+
checkMsgStatusCode(reply, STATUS_NoBinding);
2350+
2351+
// Check that the lease is not there
2352+
Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, addr);
2353+
ASSERT_TRUE(l);
2354+
ASSERT_EQ(Lease::STATE_REGISTERED, l->state_);
2355+
}
2356+
23162357
// This test verifies if the sanityCheck() really checks options presence.
23172358
TEST_F(Dhcpv6SrvTest, sanityCheck) {
23182359
NakedDhcpv6Srv srv(0);

src/hooks/dhcp/run_script/tests/run_script_unittests.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,7 @@ TEST_F(RunScriptTest, lease6Decline) {
10761076
checkScriptResult();
10771077
}
10781078

1079+
// Check the addr6_register callout.
10791080
TEST_F(RunScriptTest, add6Register) {
10801081
impl.reset(new RunScriptImpl());
10811082
impl->setName(RUN_SCRIPT_TEST_SH);

src/lib/dhcpsrv/alloc_engine.cc

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -477,11 +477,12 @@ AllocEngine::allocateLeases6(ClientContext6& ctx) {
477477
ctx.currentIA().iaid_);
478478

479479
// Iterate over the leases and eliminate those that are outside of
480-
// our shared network.
480+
// our shared network or registered.
481481
Lease6Collection leases;
482482
while (subnet) {
483483
for (auto const& l : all_leases) {
484-
if ((l)->subnet_id_ == subnet->getID()) {
484+
if (((l)->state_ != Lease::STATE_REGISTERED) &&
485+
((l)->subnet_id_ == subnet->getID())) {
485486
leases.push_back(l);
486487
}
487488
}
@@ -2107,8 +2108,11 @@ AllocEngine::renewLeases6(ClientContext6& ctx) {
21072108
*ctx.duid_,
21082109
ctx.currentIA().iaid_,
21092110
subnet->getID());
2110-
leases.insert(leases.end(), leases_subnet.begin(), leases_subnet.end());
2111-
2111+
for (auto const& l : leases_subnet) {
2112+
if (l->state_ != Lease::STATE_REGISTERED) {
2113+
leases.push_back(l);
2114+
}
2115+
}
21122116
subnet = subnet->getNextSubnet(ctx.subnet_);
21132117
}
21142118

0 commit comments

Comments
 (0)