diff options
author | Marcin Siodelski <marcin@isc.org> | 2015-07-10 17:04:31 +0200 |
---|---|---|
committer | Marcin Siodelski <marcin@isc.org> | 2015-07-10 17:04:31 +0200 |
commit | fc345a3a34c987e3677752cb272a5389d6852ee5 (patch) | |
tree | 3e1742d0f168ec18619988be28129b58dbf002aa /src | |
parent | [3947] Added git ignore for stats mgr tests. (diff) | |
download | kea-fc345a3a34c987e3677752cb272a5389d6852ee5.tar.xz kea-fc345a3a34c987e3677752cb272a5389d6852ee5.zip |
[3947] Implemented test for acqusition of the address in Renew.
Diffstat (limited to 'src')
-rw-r--r-- | src/bin/dhcp6/dhcp6_srv.cc | 13 | ||||
-rw-r--r-- | src/bin/dhcp6/tests/dhcp6_client.cc | 29 | ||||
-rw-r--r-- | src/bin/dhcp6/tests/dhcp6_client.h | 11 | ||||
-rw-r--r-- | src/bin/dhcp6/tests/renew_unittest.cc | 102 |
4 files changed, 122 insertions, 33 deletions
diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc index 9ec0376287..18860b9901 100644 --- a/src/bin/dhcp6/dhcp6_srv.cc +++ b/src/bin/dhcp6/dhcp6_srv.cc @@ -482,7 +482,7 @@ bool Dhcpv6Srv::run() { LOG_DEBUG(packet_logger, DBG_DHCP6_BASIC_DATA, DHCP6_PACKET_RECEIVED) .arg(query->getLabel()) .arg(query->getName()) - .arg(query->getType()) + .arg(static_cast<int>(query->getType())) .arg(query->getRemoteAddr()) .arg(query->getLocalAddr()) .arg(query->getIface()); @@ -1721,6 +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; // Extract the addresses that the client is trying to obtain. OptionCollection addrs = ia->getOptions(); @@ -1746,15 +1747,6 @@ Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer, // we extend, cancel or otherwise deal with the leases. bool hints_present = !ctx.hints_.empty(); - /// @todo: This was clarified in draft-ietf-dhc-dhcpv6-stateful-issues that - /// the server is allowed to assign new leases in both Renew and Rebind. For - /// now, we only support it in Renew, because it breaks a lot of Rebind - /// unit-tests. Ultimately, whether we allow it or not, should be exposed - /// as configurable policy. See ticket #3717. - if (query->getType() == DHCPV6_RENEW) { - ctx.allow_new_leases_in_renewals_ = true; - } - Lease6Collection leases = alloc_engine_->renewLeases6(ctx); // Ok, now we have the leases extended. We have: @@ -1897,6 +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; // Extract prefixes that the client is trying to renew. OptionCollection addrs = ia->getOptions(); diff --git a/src/bin/dhcp6/tests/dhcp6_client.cc b/src/bin/dhcp6/tests/dhcp6_client.cc index d8b985fb72..740a4cc546 100644 --- a/src/bin/dhcp6/tests/dhcp6_client.cc +++ b/src/bin/dhcp6/tests/dhcp6_client.cc @@ -80,8 +80,6 @@ Dhcp6Client::applyRcvdConfiguration(const Pkt6Ptr& reply) { // Let's try to get a MAC HWAddrPtr hwaddr = reply->getMAC(HWAddr::HWADDR_SOURCE_ANY); - // Set the global status code to default: success and not received. - config_.resetGlobalStatusCode(); for (Opts::const_iterator opt = opts.begin(); opt != opts.end(); ++opt) { Option6IAPtr ia = boost::dynamic_pointer_cast<Option6IA>(opt->second); if (!ia) { @@ -94,7 +92,9 @@ Dhcp6Client::applyRcvdConfiguration(const Pkt6Ptr& reply) { for (Opts::const_iterator iter_ia_opt = ia_opts.begin(); iter_ia_opt != ia_opts.end(); ++iter_ia_opt) { OptionPtr ia_opt = iter_ia_opt->second; - LeaseInfo lease_info; + LeaseInfo lease_info(ia->getType()); + lease_info.lease_.iaid_ = ia->getIAID(); + switch (ia_opt->getType()) { case D6O_IAADDR: { @@ -107,7 +107,6 @@ Dhcp6Client::applyRcvdConfiguration(const Pkt6Ptr& reply) { // lease and keep IAID around. lease_info.lease_ = Lease6(); lease_info.lease_.type_ = Lease::TYPE_NA; - lease_info.lease_.iaid_ = ia->getIAID(); break; } @@ -132,7 +131,6 @@ Dhcp6Client::applyRcvdConfiguration(const Pkt6Ptr& reply) { // lease and keep IAID around. lease_info.lease_ = Lease6(); lease_info.lease_.type_ = Lease::TYPE_PD; - lease_info.lease_.iaid_ = ia->getIAID(); break; } lease_info.lease_ = Lease6(Lease::TYPE_PD, @@ -193,12 +191,15 @@ Dhcp6Client::applyLease(const LeaseInfo& lease_info) { config_.leases_[i] = lease_info; return; - } else if (lease_info.lease_.addr_ == asiolink::IOAddress("::")) { + } else if ((existing_lease.iaid_ == lease_info.lease_.iaid_) && + (lease_info.lease_.addr_ == asiolink::IOAddress("::"))) { + config_.leases_[i] = lease_info; config_.leases_[i].status_code_ = lease_info.status_code_; return; } } + // It is a new lease. Add it. config_.leases_.push_back(lease_info); } @@ -286,6 +287,11 @@ Dhcp6Client::copyIAsFromLeases(const Pkt6Ptr& dest) const { for (std::set<uint32_t>::const_iterator iaid = iaids.begin(); iaid != iaids.end(); ++iaid) { std::vector<Lease6> leases = getLeasesByIAID(*iaid); + // Only a valid lease should be included. If we have received an + // error status code, it should not be copied. + if (leases[0].valid_lft_ == 0) { + continue; + } Option6IAPtr opt(new Option6IA(leases[0].type_ == Lease::TYPE_NA ? D6O_IA_NA : D6O_IA_PD, *iaid)); opt->setT1(leases[0].t1_); @@ -370,6 +376,7 @@ Dhcp6Client::doSolicit() { // let's apply received configuration. if (use_rapid_commit_ && context_.response_ && context_.response_->getType() == DHCPV6_REPLY) { + config_.clear(); applyRcvdConfiguration(context_.response_); } } @@ -396,6 +403,7 @@ Dhcp6Client::doRequest() { // Apply new configuration only if the server has responded. if (context_.response_) { + config_.clear(); applyRcvdConfiguration(context_.response_); } } @@ -444,6 +452,7 @@ Dhcp6Client::doRenew() { context_.response_ = receiveOneMsg(); // Apply configuration only if the server has responded. if (context_.response_) { + config_.clear(); applyRcvdConfiguration(context_.response_); } } @@ -465,6 +474,7 @@ Dhcp6Client::doRebind() { context_.response_ = receiveOneMsg(); // Apply configuration only if the server has responded. if (context_.response_) { + config_.clear(); applyRcvdConfiguration(context_.response_); } } @@ -478,6 +488,7 @@ Dhcp6Client::doConfirm() { // Set the global status code to default: success and not received. config_.resetGlobalStatusCode(); if (context_.response_) { + config_.resetGlobalStatusCode(); applyRcvdConfiguration(context_.response_); } } @@ -543,13 +554,13 @@ Dhcp6Client::getLeasesByIAID(const uint32_t iaid) const { return (leases); } -std::vector<Lease6> +std::vector<Dhcp6Client::LeaseInfo> Dhcp6Client::getLeasesByType(const Lease::Type& lease_type) const { - std::vector<Lease6> leases; + std::vector<Dhcp6Client::LeaseInfo> leases; LeaseInfo lease_info; BOOST_FOREACH(lease_info, config_.leases_) { if (lease_info.lease_.type_ == lease_type) { - leases.push_back(lease_info.lease_); + leases.push_back(lease_info); } } return (leases); diff --git a/src/bin/dhcp6/tests/dhcp6_client.h b/src/bin/dhcp6/tests/dhcp6_client.h index a6171861f8..fb1c23fcc4 100644 --- a/src/bin/dhcp6/tests/dhcp6_client.h +++ b/src/bin/dhcp6/tests/dhcp6_client.h @@ -70,6 +70,15 @@ public: /// @brief Default constructor for the structure. LeaseInfo() : lease_(), status_code_(0) { } + + /// @brief Constructor which sets the lease type. + /// + /// @param lease_type One of the D6O_IA_NA or D6O_IA_PD. + LeaseInfo(const uint16_t lease_type) : + lease_(), status_code_(0) { + lease_.type_ = lease_type == D6O_IA_NA ? Lease::TYPE_NA : + Lease::TYPE_PD; + } }; /// @brief Holds the current client configuration obtained from the @@ -317,7 +326,7 @@ public: /// @param type Lease type: D6O_IA_NA or D6O_IA_PD. /// /// @return Vector containing leases of the specified type. - std::vector<Lease6> getLeasesByType(const Lease::Type& lease_type) const; + std::vector<LeaseInfo> getLeasesByType(const Lease::Type& lease_type) const; /// @brief Returns the value of the global status code for the last /// transaction. diff --git a/src/bin/dhcp6/tests/renew_unittest.cc b/src/bin/dhcp6/tests/renew_unittest.cc index 91f058980d..29a1e1f2ff 100644 --- a/src/bin/dhcp6/tests/renew_unittest.cc +++ b/src/bin/dhcp6/tests/renew_unittest.cc @@ -32,17 +32,17 @@ namespace { /// /// - Configuration 0: /// - only addresses (no prefixes) -/// - 2 subnets with 2001:db8:1::/64 and 2001:db8:2::64 -/// - 1 subnet for eth0 and 1 subnet for eth1 +/// - 1 subnet with 2001:db8:1::/64 pool /// /// - Configuration 1: -/// - similar to Configuration 0 but different subnets -/// - pools configured: 2001:db8:3::/64 and 2001:db8:4::/64 +/// - only prefixes (no addresses) +/// - prefix pool: 3000::/72 /// /// - Configuration 2: -/// - similar to Configuration 0 and Configuration 1 -/// - pools configured: 3000:1::/64 and 3000:2::/64 -/// - this specific configuration is used by tests using relays +/// - addresses and prefixes +/// - 1 subnet with one address pool and one prefix pool +/// - address pool: 2001:db8:1::/64 +/// - prefix pool: 3000::/72 /// const char* RENEW_CONFIGS[] = { // Configuration 0 @@ -68,6 +68,25 @@ const char* RENEW_CONFIGS[] = { "\"rebind-timer\": 2000, " "\"renew-timer\": 1000, " "\"subnet6\": [ { " + " \"pd-pools\": [" + " { \"prefix\": \"3000::\", " + " \"prefix-len\": 72, " + " \"delegated-len\": 80" + " } ]," + " \"subnet\": \"2001:db8:1::/48\", " + " \"interface-id\": \"\"," + " \"interface\": \"eth0\"" + " } ]," + "\"valid-lifetime\": 4000 }", + +// Configuration 2 + "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ]" + "}," + "\"preferred-lifetime\": 3000," + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"subnet6\": [ { " " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ]," " \"pd-pools\": [" " { \"prefix\": \"3000::\", " @@ -112,29 +131,86 @@ TEST_F(RenewTest, requestPrefixInRenew) { client.fastFwdTime(1000); // Make sure that the client has acquired NA lease. - std::vector<Lease6> leases_client_na = client.getLeasesByType(Lease::TYPE_NA); + std::vector<Dhcp6Client::LeaseInfo> leases_client_na = + client.getLeasesByType(Lease::TYPE_NA); ASSERT_EQ(1, leases_client_na.size()); // The client should not acquire a PD lease. - std::vector<Lease6> leases_client_pd = client.getLeasesByType(Lease::TYPE_PD); - ASSERT_TRUE(leases_client_pd.empty()); + std::vector<Dhcp6Client::LeaseInfo> leases_client_pd = + client.getLeasesByType(Lease::TYPE_PD); + ASSERT_EQ(1, leases_client_pd.size()); + ASSERT_EQ(STATUS_NoPrefixAvail, leases_client_pd[0].status_code_); // Reconfigure the server to use both NA and PD pools. - configure(RENEW_CONFIGS[1], *client.getServer()); + configure(RENEW_CONFIGS[2], *client.getServer()); // Send Renew message to the server, including IA_NA and requesting IA_PD. ASSERT_NO_THROW(client.doRenew()); // Make sure that the client has acquired NA lease. - std::vector<Lease6> leases_client_na_renewed = client.getLeasesByType(Lease::TYPE_NA); + std::vector<Dhcp6Client::LeaseInfo> leases_client_na_renewed = + client.getLeasesByType(Lease::TYPE_NA); ASSERT_EQ(1, leases_client_na_renewed.size()); + EXPECT_EQ(STATUS_Success, leases_client_na_renewed[0].status_code_); // The lease should have been renewed. - EXPECT_EQ(1000, leases_client_na_renewed[0].cltt_ - leases_client_na[0].cltt_); + EXPECT_EQ(1000, leases_client_na_renewed[0].lease_.cltt_ - + leases_client_na[0].lease_.cltt_); // The client should now also acquire a PD lease. leases_client_pd = client.getLeasesByType(Lease::TYPE_PD); ASSERT_EQ(1, leases_client_pd.size()); + EXPECT_EQ(STATUS_Success, leases_client_pd[0].status_code_); +} + +// This test verifies that the client can request the prefix delegation +// while it is renewing an address lease. +TEST_F(RenewTest, requestAddressInRenew) { + Dhcp6Client client; + + // Configure client to request IA_NA and IA_PD. + client.useNA(); + client.usePD(); + + // Configure the server with PD pools only. + ASSERT_NO_THROW(configure(RENEW_CONFIGS[1], *client.getServer())); + + // Perform 4-way exchange. + ASSERT_NO_THROW(client.doSARR()); + + // Simulate aging of leases. + client.fastFwdTime(1000); + + // Make sure that the client has acquired PD lease. + std::vector<Dhcp6Client::LeaseInfo> leases_client_pd = + client.getLeasesByType(Lease::TYPE_PD); + ASSERT_EQ(1, leases_client_pd.size()); + EXPECT_EQ(STATUS_Success, leases_client_pd[0].status_code_); + + // The client should not acquire a NA lease. + std::vector<Dhcp6Client::LeaseInfo> leases_client_na = + client.getLeasesByType(Lease::TYPE_NA); + ASSERT_EQ(1, leases_client_na.size()); + ASSERT_EQ(STATUS_NoAddrsAvail, leases_client_na[0].status_code_); + + // Reconfigure the server to use both NA and PD pools. + configure(RENEW_CONFIGS[2], *client.getServer()); + + // Send Renew message to the server, including IA_PD and requesting IA_NA. + ASSERT_NO_THROW(client.doRenew()); + + // Make sure that the client has renewed PD lease. + std::vector<Dhcp6Client::LeaseInfo> leases_client_pd_renewed = + client.getLeasesByType(Lease::TYPE_PD); + ASSERT_EQ(1, leases_client_pd_renewed.size()); + EXPECT_EQ(STATUS_Success, leases_client_pd_renewed[0].status_code_); + EXPECT_EQ(1000, leases_client_pd_renewed[0].lease_.cltt_ - + leases_client_pd[0].lease_.cltt_); + + // The client should now also acquire a NA lease. + leases_client_na = client.getLeasesByType(Lease::TYPE_NA); + ASSERT_EQ(1, leases_client_na.size()); + EXPECT_EQ(STATUS_Success, leases_client_na[0].status_code_); } |