|
@@ -1,4 +1,4 @@
|
|
|
-// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
|
|
|
+// Copyright (C) 2012-2016 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
|
|
@@ -95,6 +95,7 @@ public:
|
|
|
|
|
|
using TestControl::checkExitConditions;
|
|
|
using TestControl::createMessageFromReply;
|
|
|
+ using TestControl::createRequestFromAck;
|
|
|
using TestControl::factoryElapsedTime6;
|
|
|
using TestControl::factoryGeneric;
|
|
|
using TestControl::factoryIana6;
|
|
@@ -114,6 +115,7 @@ public:
|
|
|
using TestControl::reset;
|
|
|
using TestControl::sendDiscover4;
|
|
|
using TestControl::sendPackets;
|
|
|
+ using TestControl::sendMultipleRequests;
|
|
|
using TestControl::sendMultipleMessages6;
|
|
|
using TestControl::sendRequest6;
|
|
|
using TestControl::sendSolicit6;
|
|
@@ -650,7 +652,134 @@ public:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /// \brief Test that the DHCPv4 Release or Renew message is created
|
|
|
+ /// \brief Test sending DHCPv4 renews.
|
|
|
+ ///
|
|
|
+ /// This function simulates acquiring 10 leases from the server. Returned
|
|
|
+ /// DHCPACK messages are cached and used to send renew messages.
|
|
|
+ /// The maxmimal number of messages which can be sent is equal to the
|
|
|
+ /// number of leases acquired (10). This function also checks that an
|
|
|
+ /// attempt to send more renew messages than the number of leases acquired
|
|
|
+ /// will fail.
|
|
|
+ void testSendRenew4() {
|
|
|
+ std::string loopback_iface(getLocalLoopback());
|
|
|
+ if (loopback_iface.empty()) {
|
|
|
+ std::cout << "Skipping the test because loopback interface could"
|
|
|
+ " not be detected" << std::endl;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // Build a command line. Depending on the message type, we will use
|
|
|
+ // -f<renew-rate> or -F<release-rate> parameter.
|
|
|
+ std::ostringstream s;
|
|
|
+ s << "perfdhcp -4 -l " << loopback_iface << " -r 10 -f";
|
|
|
+ s << " 10 -R 10 -L 10067 -n 10 127.0.0.1";
|
|
|
+ ASSERT_NO_THROW(processCmdLine(s.str()));
|
|
|
+ // Create a test controller class.
|
|
|
+ NakedTestControl tc;
|
|
|
+ tc.initializeStatsMgr();
|
|
|
+ // Set the transaction id generator to sequential to control to
|
|
|
+ // guarantee that transaction ids are predictable.
|
|
|
+ boost::shared_ptr<NakedTestControl::IncrementalGenerator>
|
|
|
+ generator(new NakedTestControl::IncrementalGenerator());
|
|
|
+ tc.setTransidGenerator(generator);
|
|
|
+ // Socket has to be created so as we can actually send packets.
|
|
|
+ int sock_handle = 0;
|
|
|
+ ASSERT_NO_THROW(sock_handle = tc.openSocket());
|
|
|
+ TestControl::TestControlSocket sock(sock_handle);
|
|
|
+
|
|
|
+ // Send a number of DHCPDISCOVER messages. Each generated message will
|
|
|
+ // be assigned a different transaction id, starting from 1 to 10.
|
|
|
+ tc.sendPackets(sock, 10);
|
|
|
+
|
|
|
+ // Simulate DHCPOFFER responses from the server. Each DHCPOFFER is
|
|
|
+ // assigned a transaction id from the range of 1 to 10, so as they
|
|
|
+ // match the transaction ids from the DHCPDISCOVER messages.
|
|
|
+ for (unsigned i = generator->getNext() - 10;
|
|
|
+ i < generator->getNext(); ++i) {
|
|
|
+ Pkt4Ptr offer(createOfferPkt4(i));
|
|
|
+ // If DHCPOFFER is matched with the DHCPDISCOVER the call below
|
|
|
+ // will trigger a corresponding DHCPREQUEST. They will be assigned
|
|
|
+ // transaction ids from the range from 11 to 20 (the range of
|
|
|
+ // 1 to 10 has been used by DHCPDISCOVER-DHCPOFFER).
|
|
|
+ ASSERT_NO_THROW(tc.processReceivedPacket4(sock, offer));
|
|
|
+ }
|
|
|
+
|
|
|
+ // Requests have been sent, so now let's simulate responses from the
|
|
|
+ // server. Generate corresponding DHCPACK messages with the transaction
|
|
|
+ // ids from the range from 11 to 20.
|
|
|
+ for (unsigned i = generator->getNext() - 10;
|
|
|
+ i < generator->getNext(); ++i) {
|
|
|
+ Pkt4Ptr ack(createAckPkt4(i));
|
|
|
+ // Each DHCPACK packet corresponds to the new lease acquired. Since
|
|
|
+ // -f<renew-rate> option has been specified, received Reply
|
|
|
+ // messages are held so as renew messages can be sent for
|
|
|
+ // existing leases.
|
|
|
+ ASSERT_NO_THROW(tc.processReceivedPacket4(sock, ack));
|
|
|
+ }
|
|
|
+
|
|
|
+ uint64_t msg_num;
|
|
|
+ // Try to send 5 messages. It should be successful because 10
|
|
|
+ // DHCPREQUEST messages has been received. For each of them we
|
|
|
+ // should be able to send renewal.
|
|
|
+ ASSERT_NO_THROW(
|
|
|
+ msg_num = tc.sendMultipleRequests(sock, 5)
|
|
|
+ );
|
|
|
+ // Make sure that we have sent 5 messages.
|
|
|
+ EXPECT_EQ(5, msg_num);
|
|
|
+
|
|
|
+ // Try to do it again. We should still have 5 Reply packets for
|
|
|
+ // which renews haven't been sent yet.
|
|
|
+ ASSERT_NO_THROW(
|
|
|
+ msg_num = tc.sendMultipleRequests(sock, 5)
|
|
|
+ );
|
|
|
+ EXPECT_EQ(5, msg_num);
|
|
|
+
|
|
|
+ // We used all the DHCPACK packets (we sent renew or release for each of
|
|
|
+ // them already). Therefore, no further renew messages should be sent
|
|
|
+ // before we acquire new leases.
|
|
|
+ ASSERT_NO_THROW(
|
|
|
+ msg_num = tc.sendMultipleRequests(sock, 5)
|
|
|
+ );
|
|
|
+ // Make sure that no message has been sent.
|
|
|
+ EXPECT_EQ(0, msg_num);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// \brief Test that the DHCPREQUEST message is created correctly and
|
|
|
+ /// comprises expected values.
|
|
|
+ void testCreateRequest() {
|
|
|
+ // This command line specifies that the Release/Renew messages should
|
|
|
+ // be sent with the same rate as the Solicit messages.
|
|
|
+ std::ostringstream s;
|
|
|
+ s << "perfdhcp -4 -l lo -r 10 -f 10";
|
|
|
+ s << " -R 10 -L 10067 -n 10 127.0.0.1";
|
|
|
+ ASSERT_NO_THROW(processCmdLine(s.str()));
|
|
|
+ // Create a test controller class.
|
|
|
+ NakedTestControl tc;
|
|
|
+ // Set the transaction id generator which will be used by the
|
|
|
+ // createRenew or createRelease function to generate transaction id.
|
|
|
+ boost::shared_ptr<NakedTestControl::IncrementalGenerator>
|
|
|
+ generator(new NakedTestControl::IncrementalGenerator());
|
|
|
+ tc.setTransidGenerator(generator);
|
|
|
+
|
|
|
+ Pkt4Ptr ack = createAckPkt4(1);
|
|
|
+
|
|
|
+ // Create DHCPREQUST from DHCPACK.
|
|
|
+ Pkt4Ptr request;
|
|
|
+ ASSERT_NO_THROW(request = tc.createRequestFromAck(ack));
|
|
|
+
|
|
|
+ // Make sure that the DHCPACK has been successfully created and that
|
|
|
+ // it holds expected data.
|
|
|
+ ASSERT_TRUE(request);
|
|
|
+ EXPECT_EQ("127.0.0.1", request->getCiaddr().toText());
|
|
|
+
|
|
|
+ // HW address.
|
|
|
+ HWAddrPtr hwaddr_ack = ack->getHWAddr();
|
|
|
+ ASSERT_TRUE(hwaddr_ack);
|
|
|
+ HWAddrPtr hwaddr_req = request->getHWAddr();
|
|
|
+ ASSERT_TRUE(hwaddr_req);
|
|
|
+ EXPECT_TRUE(hwaddr_ack->hwaddr_ == hwaddr_req->hwaddr_);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// \brief Test that the DHCPv6 Release or Renew message is created
|
|
|
/// correctly and comprises expected options.
|
|
|
///
|
|
|
/// \param msg_type A type of the message to be tested: DHCPV6_RELEASE
|
|
@@ -822,20 +951,41 @@ public:
|
|
|
CommandOptionsHelper::process(cmdline);
|
|
|
}
|
|
|
|
|
|
+ /// \brief Create DHCPOFFER or DHCPACK packet.
|
|
|
+ ///
|
|
|
+ /// \param pkt_type DHCPOFFER or DHCPACK.
|
|
|
+ /// \param transid Transaction id.
|
|
|
+ ///
|
|
|
+ /// \return Instance of the packet.
|
|
|
+ Pkt4Ptr
|
|
|
+ createResponsePkt4(const uint8_t pkt_type,
|
|
|
+ const uint32_t transid) const {
|
|
|
+ Pkt4Ptr pkt(new Pkt4(pkt_type, transid));
|
|
|
+ OptionPtr opt_serverid = Option::factory(Option::V4,
|
|
|
+ DHO_DHCP_SERVER_IDENTIFIER,
|
|
|
+ OptionBuffer(4, 1));
|
|
|
+ pkt->setYiaddr(asiolink::IOAddress("127.0.0.1"));
|
|
|
+ pkt->addOption(opt_serverid);
|
|
|
+ pkt->updateTimestamp();
|
|
|
+ return (pkt);
|
|
|
+ }
|
|
|
+
|
|
|
/// \brief Create DHCPv4 OFFER packet.
|
|
|
///
|
|
|
/// \param transid transaction id.
|
|
|
/// \return instance of the packet.
|
|
|
- boost::shared_ptr<Pkt4>
|
|
|
+ Pkt4Ptr
|
|
|
createOfferPkt4(uint32_t transid) const {
|
|
|
- boost::shared_ptr<Pkt4> offer(new Pkt4(DHCPOFFER, transid));
|
|
|
- OptionPtr opt_serverid = Option::factory(Option::V4,
|
|
|
- DHO_DHCP_SERVER_IDENTIFIER,
|
|
|
- OptionBuffer(4, 1));
|
|
|
- offer->setYiaddr(asiolink::IOAddress("127.0.0.1"));
|
|
|
- offer->addOption(opt_serverid);
|
|
|
- offer->updateTimestamp();
|
|
|
- return (offer);
|
|
|
+ return (createResponsePkt4(DHCPOFFER, transid));
|
|
|
+ }
|
|
|
+
|
|
|
+ /// \brief Create DHCPACK packet.
|
|
|
+ ///
|
|
|
+ /// \param transid transaction id.
|
|
|
+ /// \return instance of the packet.
|
|
|
+ Pkt4Ptr
|
|
|
+ createAckPkt4(const uint32_t transid) const {
|
|
|
+ return (createResponsePkt4(DHCPACK, transid));
|
|
|
}
|
|
|
|
|
|
/// \brief Create DHCPv6 ADVERTISE packet.
|
|
@@ -1432,14 +1582,30 @@ TEST_F(TestControlTest, PacketTemplates) {
|
|
|
EXPECT_THROW(tc.initPacketTemplates(), isc::BadValue);
|
|
|
}
|
|
|
|
|
|
-TEST_F(TestControlTest, processRenew) {
|
|
|
+// This test verifies that DHCPv4 renew (DHCPREQUEST) messages can be
|
|
|
+// sent for acquired leases.
|
|
|
+TEST_F(TestControlTest, processRenew4) {
|
|
|
+ testSendRenew4();
|
|
|
+}
|
|
|
+
|
|
|
+// This test verifies that DHCPv6 Renew messages can be sent for acquired
|
|
|
+// leases.
|
|
|
+TEST_F(TestControlTest, processRenew6) {
|
|
|
testSendRenewRelease(DHCPV6_RENEW);
|
|
|
}
|
|
|
|
|
|
-TEST_F(TestControlTest, processRelease) {
|
|
|
+// This test verifies that DHCPv6 Release messages can be sent for acquired
|
|
|
+// leases.
|
|
|
+TEST_F(TestControlTest, processRelease6) {
|
|
|
testSendRenewRelease(DHCPV6_RELEASE);
|
|
|
}
|
|
|
|
|
|
+// This test verifies that DHCPREQUEST is created correctly from the
|
|
|
+// DHCPACK message.
|
|
|
+TEST_F(TestControlTest, createRequest) {
|
|
|
+ testCreateRequest();
|
|
|
+}
|
|
|
+
|
|
|
// This test verifies that the DHCPV6 Renew message is created correctly
|
|
|
// and that it comprises all required options.
|
|
|
TEST_F(TestControlTest, createRenew) {
|