Browse Source

[1959] Added generation of DUID prefix if it is not given by user.

Marcin Siodelski 12 years ago
parent
commit
967e3ec618

+ 38 - 0
tests/tools/perfdhcp/command_options.cc

@@ -20,8 +20,10 @@
 #include <boost/algorithm/string.hpp>
 #include <boost/foreach.hpp>
 #include <boost/lexical_cast.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
 
 #include <exceptions/exceptions.h>
+#include <dhcp/dhcp6.h>
 #include <dhcp/iface_mgr.h>
 #include "command_options.h"
 
@@ -367,6 +369,12 @@ CommandOptions::initialize(int argc, char** argv) {
         isc_throw(InvalidParameter,
                   "without an inteface server is required");
     }
+
+    // If DUID is not specified from command line we need to
+    // generate one.
+    if (duid_prefix_.size() == 0) {
+        generateDuidPrefix();
+    }
 }
 
 void
@@ -476,6 +484,36 @@ CommandOptions::decodeDuid(const std::string& base) {
     }
 }
 
+void
+CommandOptions::generateDuidPrefix() {
+    using namespace boost::posix_time;
+    // Duid prefix will be most likely generated only once but
+    // it is ok if it is called more then once so we simply
+    //  regenerate it and discard previous value.
+    duid_prefix_.clear();
+    const uint8_t duid_prefix_len = 14;
+    duid_prefix_.resize(duid_prefix_len);
+    // The first four octets consist of DUID LLT and hardware type.
+    duid_prefix_[0] = DUID_LLT >> 8;
+    duid_prefix_[1] = DUID_LLT & 0xff;
+    duid_prefix_[2] = HWTYPE_ETHERNET >> 8;
+    duid_prefix_[3] = HWTYPE_ETHERNET & 0xff;
+    
+    // As described in RFC3315: 'the time value is the time
+    // that the DUID is generated represented in seconds
+    // since midnight (UTC), January 1, 2000, modulo 2^32.'
+    ptime now = microsec_clock::universal_time();
+    ptime duid_epoch(from_iso_string("20000101T000000"));
+    time_period period(duid_epoch, now);
+    uint32_t duration_sec = htonl(period.length().total_seconds());
+    memcpy(&duid_prefix_[4], &duration_sec, 4);
+
+    // Set link layer address (6 octets). This value may be
+    // randomized before sending a packet to simulate different
+    // clients.
+    memcpy(&duid_prefix_[8], &mac_prefix_[0], 6);
+}
+
 uint8_t
 CommandOptions::convertHexString(const std::string& text) const {
     unsigned int ui = 0;

+ 6 - 0
tests/tools/perfdhcp/command_options.h

@@ -346,6 +346,12 @@ private:
     /// \param base Base string given as -b duid=0F1234
     /// \throws isc::InvalidParameter if DUID is invalid
     void decodeDuid(const std::string& base);
+    
+    /// \brief Generates DUID-LLT (based on link layer address).
+    ///
+    /// Function generates DUID based on link layer address and
+    /// initiates duid_prefix_ value with it.
+    void generateDuidPrefix();
 
     /// \brief Converts two-digit hexadecimal string to a byte
     ///

+ 15 - 1
tests/tools/perfdhcp/tests/command_options_unittest.cc

@@ -71,11 +71,25 @@ protected:
         EXPECT_EQ(0, opt.getClientsNum());
 
         // default mac
-        uint8_t mac[6] = { 0x00, 0x0C, 0x01, 0x02, 0x03, 0x04 };
+        const uint8_t mac[6] = { 0x00, 0x0C, 0x01, 0x02, 0x03, 0x04 };
         std::vector<uint8_t> v1 = opt.getMacPrefix();
         ASSERT_EQ(6, v1.size());
         EXPECT_TRUE(std::equal(v1.begin(), v1.end(), mac));
 
+        // Check if DUID is initialized. The DUID-LLT is expected
+        // to start with DUID_LLT value of 1 and hardware ethernet
+        // type equal to 1 (HWETHER_TYPE).
+        const uint8_t duid_llt_and_hw[4] = { 0x0, 0x1, 0x0, 0x1 };
+        // We assume DUID-LLT length 14. This includes 4 octets of
+        // DUID_LLT value, two octets of hardware type, 4 octets
+        // of time value and 6 octets of variable link layer (MAC)
+        // address.
+        const int duid_llt_size = 14; 
+        std::vector<uint8_t> v2 = opt.getDuidPrefix();
+        ASSERT_EQ(duid_llt_size, opt.getDuidPrefix().size());
+        EXPECT_TRUE(std::equal(v2.begin(), v2.begin() + 4,
+                               duid_llt_and_hw));
+
         EXPECT_EQ(0, opt.getBase().size());
         EXPECT_EQ(0, opt.getNumRequests().size());
         EXPECT_EQ(0, opt.getPeriod());