Parcourir la source

[3689] Added host renew and rebind tests

tests/dhcp6_client.cc
tests/dhcp6_client.h
    added Dhcp6Client::doRenew()

tests/host_unittest.cc
    added TEST_F(HostTest, sarrAndRenew)
    added TEST_F(HostTest, sarrAndRebind)
Thomas Markwalder il y a 10 ans
Parent
commit
2d290633db

+ 14 - 0
src/bin/dhcp6/tests/dhcp6_client.cc

@@ -339,6 +339,20 @@ Dhcp6Client::doInfRequest() {
 }
 }
 
 
 void
 void
+Dhcp6Client::doRenew() {
+    Pkt6Ptr query = createMsg(DHCPV6_RENEW);
+    query->addOption(context_.response_->getOption(D6O_SERVERID));
+    copyIAsFromLeases(query);
+    context_.query_ = query;
+    sendMsg(context_.query_);
+    context_.response_ = receiveOneMsg();
+    // Apply configuration only if the server has responded.
+    if (context_.response_) {
+        applyRcvdConfiguration(context_.response_);
+    }
+}
+
+void
 Dhcp6Client::doRebind() {
 Dhcp6Client::doRebind() {
     Pkt6Ptr query = createMsg(DHCPV6_REBIND);
     Pkt6Ptr query = createMsg(DHCPV6_REBIND);
     copyIAsFromLeases(query);
     copyIAsFromLeases(query);

+ 18 - 1
src/bin/dhcp6/tests/dhcp6_client.h

@@ -182,6 +182,21 @@ public:
     /// @todo Perform sanity checks on returned messages.
     /// @todo Perform sanity checks on returned messages.
     void doSolicit();
     void doSolicit();
 
 
+    /// @brief Sends a Renew to the server and receives the Reply.
+    ///
+    /// This function simulates sending the Renew message to the server and
+    /// receiving server's response (if any). The client uses existing leases
+    /// (either address or prefixes) and places them in the Renew message.
+    /// If the server responds to the Renew (and extends the lease lifetimes)
+    /// the current lease configuration is updated.
+    ///
+    /// @throw This function doesn't throw exceptions on its own, but it calls
+    /// functions that are not exception safe, so it may throw exceptions if
+    /// error occurs.
+    ///
+    /// @todo Perform sanity checks on returned messages.
+    void doRenew();
+
     /// @brief Sends a Rebind to the server and receives the Reply.
     /// @brief Sends a Rebind to the server and receives the Reply.
     ///
     ///
     /// This function simulates sending the Rebind message to the server and
     /// This function simulates sending the Rebind message to the server and
@@ -305,9 +320,11 @@ public:
     /// @brief Sets the client's DUID from a string value
     /// @brief Sets the client's DUID from a string value
     ///
     ///
     /// Replaces the client's DUID with one constructed from the given
     /// Replaces the client's DUID with one constructed from the given
-    /// string.  The string is expected to hexadecimal digits with or
+    /// string.  The string is expected to contain hexadecimal digits with or
     /// without ":" separators.
     /// without ":" separators.
     ///
     ///
+    /// @param str The string of digits from which to create the DUID
+    ///
     /// The DUID modification affects the value returned by the
     /// The DUID modification affects the value returned by the
     /// @c Dhcp6Client::getClientId
     /// @c Dhcp6Client::getClientId
     void setDUID(const std::string& duid_str);
     void setDUID(const std::string& duid_str);

+ 122 - 10
src/bin/dhcp6/tests/host_unittest.cc

@@ -26,10 +26,10 @@ namespace {
 
 
 /// @brief Set of JSON configurations used by the Host reservation unit tests.
 /// @brief Set of JSON configurations used by the Host reservation unit tests.
 ///
 ///
-/// - Configuration 0: 
+/// - Configuration 0:
 ///   Single subnet with two reservations, one with a hostname, one without
 ///   Single subnet with two reservations, one with a hostname, one without
 const char* CONFIGS[] = {
 const char* CONFIGS[] = {
-    // Configuration 0: 
+    // Configuration 0:
     "{ "
     "{ "
         "\"interfaces-config\": {"
         "\"interfaces-config\": {"
         "  \"interfaces\": [ \"*\" ]"
         "  \"interfaces\": [ \"*\" ]"
@@ -72,11 +72,23 @@ public:
     IfaceMgrTestConfig iface_mgr_test_config_;
     IfaceMgrTestConfig iface_mgr_test_config_;
 };
 };
 
 
-TEST_F(HostTest, basicSARRs) {
+// Test basic SARR scenarios against a server configured with one subnet
+// containing two reservations.  One reservation with a hostname, one
+// without a hostname. Scenarios:
+//
+// - Verify that a client when matched to a host reservation with a hostname
+// gets that reservation and the lease hostname matches the reserved hostname
+//
+// - Verify that a client when matched to a host reservation without a hostname
+// gets that reservation and the lease hostname is blank
+//
+// - Verify that a client that does not match a host reservation gets a dynamic
+// lease and the hostname for the lease is blank.
+//
+TEST_F(HostTest, basicSarrs) {
     Dhcp6Client client;
     Dhcp6Client client;
     configure(CONFIGS[0], *client.getServer());
     configure(CONFIGS[0], *client.getServer());
 
 
-    // Make sure we ended-up having expected number of subnets configured.
     const Subnet6Collection* subnets = CfgMgr::instance().getCurrentCfg()->
     const Subnet6Collection* subnets = CfgMgr::instance().getCurrentCfg()->
         getCfgSubnets6()->getAll();
         getCfgSubnets6()->getAll();
     ASSERT_EQ(1, subnets->size());
     ASSERT_EQ(1, subnets->size());
@@ -90,13 +102,13 @@ TEST_F(HostTest, basicSARRs) {
     // Perform 4-way exchange.
     // Perform 4-way exchange.
     ASSERT_NO_THROW(client.doSARR());
     ASSERT_NO_THROW(client.doSARR());
 
 
-    // Verify that the client we got the reserved address 
+    // Verify that the client we got the reserved address
     ASSERT_EQ(1, client.getLeaseNum());
     ASSERT_EQ(1, client.getLeaseNum());
     Lease6 lease_client = client.getLease(0);
     Lease6 lease_client = client.getLease(0);
     EXPECT_EQ("2001:db8:1:1::babe", lease_client.addr_.toText());
     EXPECT_EQ("2001:db8:1:1::babe", lease_client.addr_.toText());
 
 
     // Check that the server recorded the lease.
     // Check that the server recorded the lease.
-    // and lease has reserved hostname 
+    // and lease has reserved hostname
     Lease6Ptr lease_server = checkLease(lease_client);
     Lease6Ptr lease_server = checkLease(lease_client);
     ASSERT_TRUE(lease_server);
     ASSERT_TRUE(lease_server);
     EXPECT_EQ("alice", lease_server->hostname_);
     EXPECT_EQ("alice", lease_server->hostname_);
@@ -110,19 +122,19 @@ TEST_F(HostTest, basicSARRs) {
     // Perform 4-way exchange.
     // Perform 4-way exchange.
     ASSERT_NO_THROW(client.doSARR());
     ASSERT_NO_THROW(client.doSARR());
 
 
-    // Verify that the client we got the reserved address 
+    // Verify that the client we got the reserved address
     ASSERT_EQ(1, client.getLeaseNum());
     ASSERT_EQ(1, client.getLeaseNum());
     lease_client = client.getLease(0);
     lease_client = client.getLease(0);
     EXPECT_EQ("2001:db8:1:1::babf", lease_client.addr_.toText());
     EXPECT_EQ("2001:db8:1:1::babf", lease_client.addr_.toText());
 
 
     // Check that the server recorded the lease.
     // Check that the server recorded the lease.
-    // and that the server lease has NO hostname 
+    // and that the server lease has NO hostname
     lease_server = checkLease(lease_client);
     lease_server = checkLease(lease_client);
     ASSERT_TRUE(lease_server);
     ASSERT_TRUE(lease_server);
     EXPECT_EQ("", lease_server->hostname_);
     EXPECT_EQ("", lease_server->hostname_);
 
 
     // Now redo the client with yet another DUID and verify that
     // Now redo the client with yet another DUID and verify that
-    // we get a dynamic address. 
+    // we get a dynamic address.
     client.clearConfig();
     client.clearConfig();
     client.modifyDUID();
     client.modifyDUID();
     client.useNA();
     client.useNA();
@@ -137,10 +149,110 @@ TEST_F(HostTest, basicSARRs) {
     EXPECT_EQ("2001:db8:1:1::", lease_client.addr_.toText());
     EXPECT_EQ("2001:db8:1:1::", lease_client.addr_.toText());
 
 
     // Check that the server recorded the lease.
     // Check that the server recorded the lease.
-    // and that the server lease has NO hostname 
+    // and that the server lease has NO hostname
     lease_server = checkLease(lease_client);
     lease_server = checkLease(lease_client);
     ASSERT_TRUE(lease_server);
     ASSERT_TRUE(lease_server);
     EXPECT_EQ("", lease_server->hostname_);
     EXPECT_EQ("", lease_server->hostname_);
 }
 }
 
 
+// Test basic SARR and renew situation with a client that matches a host
+// reservation
+TEST_F(HostTest, sarrAndRenew) {
+    Dhcp6Client client;
+
+    configure(CONFIGS[0], *client.getServer());
+
+    // Configure client to request IA_NA.
+    client.useNA();
+
+    const Subnet6Collection* subnets = CfgMgr::instance().getCurrentCfg()->
+        getCfgSubnets6()->getAll();
+    ASSERT_EQ(1, subnets->size());
+
+    // Configure client to request IA_NA and aAppend IA_NA option
+    //  to the client's message.
+    client.setDUID("01:02:03:04");
+    client.useNA();
+    ASSERT_NO_THROW(client.useHint(100, 200, 64, "2001:db8:1:1::dead:beef"));
+
+    // Perform 4-way exchange.
+    ASSERT_NO_THROW(client.doSARR());
+
+    // Now play with time
+    client.fastFwdTime(1000);
+
+    // Verify that the client we got the reserved address
+    ASSERT_EQ(1, client.getLeaseNum());
+    Lease6 lease_client = client.getLease(0);
+    EXPECT_EQ("2001:db8:1:1::babe", lease_client.addr_.toText());
+
+    // Send Renew message to the server.
+    ASSERT_NO_THROW(client.doRenew());
+
+    // Verify that we got an extended lease back
+    ASSERT_EQ(1, client.getLeaseNum());
+    Lease6 lease_client2 = client.getLease(0);
+    EXPECT_EQ("2001:db8:1:1::babe", lease_client2.addr_.toText());
+
+    // The client's lease should have been extended. The client will
+    // update the cltt to current time when the lease gets extended.
+    ASSERT_GE(lease_client2.cltt_ - lease_client.cltt_, 1000);
+
+    // Make sure, that the client's lease matches the lease held by the
+    // server and that we have the reserved host name.
+    Lease6Ptr lease_server2 = checkLease(lease_client2);
+    EXPECT_TRUE(lease_server2);
+    EXPECT_EQ("alice", lease_server2->hostname_);
+}
+
+// Test basic SARR and rebind situation with a client that matches a host
+// reservation.
+TEST_F(HostTest, sarrAndRebind) {
+    Dhcp6Client client;
+
+    configure(CONFIGS[0], *client.getServer());
+
+    // Configure client to request IA_NA.
+    client.useNA();
+
+    const Subnet6Collection* subnets = CfgMgr::instance().getCurrentCfg()->
+        getCfgSubnets6()->getAll();
+    ASSERT_EQ(1, subnets->size());
+
+    // Configure client to request IA_NA and aAppend IA_NA option
+    //  to the client's message.
+    client.setDUID("01:02:03:04");
+    client.useNA();
+    ASSERT_NO_THROW(client.useHint(100, 200, 64, "2001:db8:1:1::dead:beef"));
+
+    // Perform 4-way exchange.
+    ASSERT_NO_THROW(client.doSARR());
+
+    // Now play with time
+    client.fastFwdTime(1000);
+
+    // Verify that the client we got the reserved address
+    ASSERT_EQ(1, client.getLeaseNum());
+    Lease6 lease_client = client.getLease(0);
+    EXPECT_EQ("2001:db8:1:1::babe", lease_client.addr_.toText());
+
+    // Send Rebind message to the server.
+    ASSERT_NO_THROW(client.doRebind());
+
+    // Verify that we got an extended lease back
+    ASSERT_EQ(1, client.getLeaseNum());
+    Lease6 lease_client2 = client.getLease(0);
+    EXPECT_EQ("2001:db8:1:1::babe", lease_client2.addr_.toText());
+
+    // The client's lease should have been extended. The client will
+    // update the cltt to current time when the lease gets extended.
+    ASSERT_GE(lease_client2.cltt_ - lease_client.cltt_, 1000);
+
+    // Make sure, that the client's lease matches the lease held by the
+    // server and that we have the reserved host name.
+    Lease6Ptr lease_server2 = checkLease(lease_client2);
+    EXPECT_TRUE(lease_server2);
+    EXPECT_EQ("alice", lease_server2->hostname_);
+}
+
 } // end of anonymous namespace
 } // end of anonymous namespace