Browse Source

[3173] It is possible to request IA_NA and IA_PD in a single message.

Marcin Siodelski 11 years ago
parent
commit
ef4ae0b32f

+ 18 - 4
tests/tools/perfdhcp/command_options.cc

@@ -45,6 +45,11 @@ CommandOptions::LeaseType::is(const Type lease_type) const {
     return (lease_type == type_);
 }
 
+bool
+CommandOptions::LeaseType::includes(const Type lease_type) const {
+    return (is(ADDRESS_AND_PREFIX) || (lease_type == type_));
+}
+
 void
 CommandOptions::LeaseType::set(const Type lease_type) {
     type_ = lease_type;
@@ -58,6 +63,9 @@ CommandOptions::LeaseType::fromCommandLine(const std::string& cmd_line_arg) {
     } else if (cmd_line_arg == "prefix-only") {
         type_ = PREFIX_ONLY;
 
+    } else if (cmd_line_arg == "address-and-prefix") {
+        type_ = ADDRESS_AND_PREFIX;
+
     } else {
         isc_throw(isc::InvalidParameter, "value of lease-type: -e<lease-type>,"
                   " must be one of the following: 'address-only' or"
@@ -72,6 +80,9 @@ CommandOptions::LeaseType::toText() const {
         return ("address-only (IA_NA option added to the client's request)");
     case PREFIX_ONLY:
         return ("prefix-only (IA_PD option added to the client's request)");
+    case ADDRESS_AND_PREFIX:
+        return ("address-and-prefix (Both IA_NA and IA_PD options added to the"
+                " client's request)");
     default:
         isc_throw(Unexpected, "internal error: undefined lease type code when"
                   " returning textual representation of the lease type");
@@ -903,10 +914,13 @@ CommandOptions::usage() const {
         "    having been lost.  The value is given in seconds and may contain a\n"
         "    fractional component.  The default is 1 second.\n"
         "-e<lease-type>: A type of lease being requested from the server. It\n"
-        "    may be one of the following: address-only or prefix-only. The\n"
-        "    former indicates that the regular IP (v4 or v6) will be requested,\n"
-        "    the latter indicates that the IPv6 prefixes will be requested. The\n"
-        "    '-e prefix-only' must not be used with -4.\n"
+        "    may be one of the following: address-only, prefix-only or\n"
+        "    address-and-prefix. The address-only indicates that the regular\n"
+        "    address (v4 or v6) will be requested. The prefix-only indicates\n"
+        "    that the IPv6 prefix will be requested. The address-and-prefix\n"
+        "    indicates that both IPv6 address and prefix will be requested.\n"
+        "    The '-e prefix-only' and -'e address-and-prefix' must not be\n"
+        "    used with -4.\n"
         "-E<time-offset>: Offset of the (DHCPv4) secs field / (DHCPv6)\n"
         "    elapsed-time option in the (second/request) template.\n"
         "    The value 0 disables it.\n"

+ 19 - 1
tests/tools/perfdhcp/command_options.h

@@ -43,7 +43,8 @@ public:
         /// The lease type code.
         enum Type {
             ADDRESS_ONLY,
-            PREFIX_ONLY
+            PREFIX_ONLY,
+            ADDRESS_AND_PREFIX
         };
 
         LeaseType();
@@ -60,6 +61,23 @@ public:
         /// \return true if lease type is matched with the specified code.
         bool is(const Type lease_type) const;
 
+        /// \brief Checks if lease type implies request for the address,
+        /// prefix (or both) as specified by the function argument.
+        ///
+        /// This is a convenience function to check that, for the lease type
+        /// specified from the command line, the address or prefix
+        /// (IA_NA or IA_PD) option should be sent to the server.
+        /// For example, if user specified '-e address-and-prefix' in the
+        /// command line this function will return true for both ADDRESS_ONLY
+        /// and PREFIX_ONLY, because both address and prefix is requested from
+        /// the server.
+        ///
+        /// \param lease_type A lease type.
+        ///
+        /// \return true if the lease type implies creation of the address,
+        /// prefix or both as specified by the argument.
+        bool includes(const Type lease_type) const;
+
         /// \brief Sets the lease type code.
         ///
         /// \param lease_type A lease type code.

+ 24 - 14
tests/tools/perfdhcp/test_control.cc

@@ -103,22 +103,27 @@ TestControl::copyIaOptions(const Pkt6Ptr& pkt_from, Pkt6Ptr& pkt_to) {
         isc_throw(BadValue, "NULL pointers must not be specified as arguments"
                   " for the copyIaOptions function");
     }
-    OptionPtr option;
+    // IA_NA
     if (CommandOptions::instance().getLeaseType()
-        .is(CommandOptions::LeaseType::ADDRESS_ONLY)) {
-        option = pkt_from->getOption(D6O_IA_NA);
+        .includes(CommandOptions::LeaseType::ADDRESS_ONLY)) {
+        OptionPtr option = pkt_from->getOption(D6O_IA_NA);
         if (!option) {
             isc_throw(OptionNotFound, "IA_NA option not found in the"
                       " server's response");
         }
-    } else {
-        option = pkt_from->getOption(D6O_IA_PD);
+        pkt_to->addOption(option);
+    }
+    // IA_PD
+    if (CommandOptions::instance().getLeaseType()
+        .includes(CommandOptions::LeaseType::PREFIX_ONLY)) {
+        OptionPtr option = pkt_from->getOption(D6O_IA_PD);
         if (!option) {
             isc_throw(OptionNotFound, "IA_PD option not found in the"
                       " server's response");
         }
+        pkt_to->addOption(option);
     }
-    pkt_to->addOption(option);
+
 
 }
 
@@ -635,15 +640,15 @@ TestControl::openSocket() const {
     uint16_t port = options.getLocalPort();
     int sock = 0;
 
-    uint8_t family = (options.getIpVersion() == 6) ? AF_INET6 : AF_INET; 
+    uint8_t family = (options.getIpVersion() == 6) ? AF_INET6 : AF_INET;
     IOAddress remoteaddr(servername);
-    
+
     // Check for mismatch between IP option and server address
     if (family != remoteaddr.getFamily()) {
-        isc_throw(InvalidParameter, 
-                  "Values for IP version: " <<  
+        isc_throw(InvalidParameter,
+                  "Values for IP version: " <<
                   static_cast<unsigned int>(options.getIpVersion()) <<
-                  " and server address: " << servername << " are mismatched."); 
+                  " and server address: " << servername << " are mismatched.");
     }
 
     if (port == 0) {
@@ -1780,11 +1785,16 @@ TestControl::sendSolicit6(const TestControlSocket& socket,
     pkt6->addOption(Option::factory(Option::V6, D6O_ORO));
 
     // Depending on the lease-type option specified, we should request
-    // IPv6 address (with IA_NA) or IPv6 prefix (IA_PD).
+    // IPv6 address (with IA_NA) or IPv6 prefix (IA_PD) or both.
+
+    // IA_NA
     if (CommandOptions::instance().getLeaseType()
-        .is(CommandOptions::LeaseType::ADDRESS_ONLY)) {
+        .includes(CommandOptions::LeaseType::ADDRESS_ONLY)) {
         pkt6->addOption(Option::factory(Option::V6, D6O_IA_NA));
-    } else {
+    }
+    // IA_PD
+    if (CommandOptions::instance().getLeaseType()
+        .includes(CommandOptions::LeaseType::PREFIX_ONLY)) {
         pkt6->addOption(Option::factory(Option::V6, D6O_IA_PD));
     }
 

+ 27 - 0
tests/tools/perfdhcp/tests/command_options_unittest.cc

@@ -52,6 +52,33 @@ TEST(LeaseTypeTest, set) {
     EXPECT_TRUE(lease_type.is(CommandOptions::LeaseType::PREFIX_ONLY));
 }
 
+TEST(LeaseTypeTest, includes) {
+    CommandOptions::LeaseType
+        lease_type(CommandOptions::LeaseType::ADDRESS_ONLY);
+    ASSERT_TRUE(lease_type.is(CommandOptions::LeaseType::ADDRESS_ONLY));
+    EXPECT_TRUE(lease_type.includes(CommandOptions::LeaseType::ADDRESS_ONLY));
+    EXPECT_FALSE(lease_type.includes(CommandOptions::LeaseType::PREFIX_ONLY));
+    EXPECT_FALSE(
+        lease_type.includes(CommandOptions::LeaseType::ADDRESS_AND_PREFIX)
+    );
+
+    lease_type.set(CommandOptions::LeaseType::PREFIX_ONLY);
+    EXPECT_FALSE(lease_type.includes(CommandOptions::LeaseType::ADDRESS_ONLY));
+    EXPECT_TRUE(lease_type.includes(CommandOptions::LeaseType::PREFIX_ONLY));
+    EXPECT_FALSE(
+        lease_type.includes(CommandOptions::LeaseType::ADDRESS_AND_PREFIX)
+    );
+
+    lease_type.set(CommandOptions::LeaseType::ADDRESS_AND_PREFIX);
+    EXPECT_TRUE(lease_type.includes(CommandOptions::LeaseType::ADDRESS_ONLY));
+    EXPECT_TRUE(lease_type.includes(CommandOptions::LeaseType::PREFIX_ONLY));
+    EXPECT_TRUE(
+        lease_type.includes(CommandOptions::LeaseType::ADDRESS_AND_PREFIX)
+    );
+
+}
+
+
 TEST(LeaseTypeTest, fromCommandLine) {
     CommandOptions::LeaseType
         lease_type(CommandOptions::LeaseType::ADDRESS_ONLY);

+ 39 - 8
tests/tools/perfdhcp/tests/test_control_unittest.cc

@@ -524,7 +524,8 @@ public:
                 /*                ASSERT_NO_THROW(tc.processReceivedPacket6(sock,
                                   advertise_pkt6)); */
                 try {
-                    tc.processReceivedPacket6(sock, advertise_pkt6);
+                    tc.processReceivedPacket6(sock,
+                                              advertise_pkt6);
                 } catch (const Exception& ex) {
                     std::cout << ex.what() << std::endl;
                 }
@@ -652,20 +653,24 @@ private:
     /// \return instance of the packet.
     boost::shared_ptr<Pkt6>
     createAdvertisePkt6(uint32_t transid) const {
-        OptionPtr opt_ia;
+        boost::shared_ptr<Pkt6> advertise(new Pkt6(DHCPV6_ADVERTISE, transid));
+        // Add IA_NA if requested by the client.
+        if (CommandOptions::instance().getLeaseType()
+            .includes(CommandOptions::LeaseType::ADDRESS_ONLY)) {
+            OptionPtr opt_ia_na = Option::factory(Option::V6, D6O_IA_NA);
+            advertise->addOption(opt_ia_na);
+        }
+        // Add IA_PD if requested by the client.
         if (CommandOptions::instance().getLeaseType()
-            .is(CommandOptions::LeaseType::ADDRESS_ONLY)) {
-            opt_ia = Option::factory(Option::V6, D6O_IA_NA);
-        } else {
-            opt_ia = Option::factory(Option::V6, D6O_IA_PD);
+            .includes(CommandOptions::LeaseType::PREFIX_ONLY)) {
+            OptionPtr opt_ia_pd = Option::factory(Option::V6, D6O_IA_PD);
+            advertise->addOption(opt_ia_pd);
         }
         OptionPtr opt_serverid(new Option(Option::V6, D6O_SERVERID));
         NakedTestControl tc;
         uint8_t randomized = 0;
         std::vector<uint8_t> duid(tc.generateDuid(randomized));
         OptionPtr opt_clientid(Option::factory(Option::V6, D6O_CLIENTID, duid));
-        boost::shared_ptr<Pkt6> advertise(new Pkt6(DHCPV6_ADVERTISE, transid));
-        advertise->addOption(opt_ia);
         advertise->addOption(opt_serverid);
         advertise->addOption(opt_clientid);
         advertise->updateTimestamp();
@@ -1041,6 +1046,32 @@ TEST_F(TestControlTest, Packet6ExchangePrefixDelegation) {
     EXPECT_EQ(10, iterations_performed);
 }
 
+TEST_F(TestControlTest, Packet6ExchangeAddressAndPrefix) {
+    // Get the local loopback interface to open socket on
+    // it and test packets exchanges. We don't want to fail
+    // the test if interface is not available.
+    std::string loopback_iface(getLocalLoopback());
+    if (loopback_iface.empty()) {
+        std::cout << "Unable to find the loopback interface. Skip test."
+                  << std::endl;
+        return;
+    }
+
+    const int iterations_num = 100;
+    // Set number of iterations to 10.
+    processCmdLine("perfdhcp -l " + loopback_iface
+                   + " -e address-and-prefix"
+                   + " -6 -r 100 -n 10 -R 20 -L 10547 ::1");
+    int iterations_performed = 0;
+    // Set number of received packets equal to number of iterations.
+    // This simulates no packet drops.
+    bool use_templates = false;
+    testPkt6Exchange(iterations_num, iterations_num, use_templates,
+                     iterations_performed);
+    // Actual number of iterations should be 10.
+    EXPECT_EQ(10, iterations_performed);
+}
+
 TEST_F(TestControlTest, PacketTemplates) {
     std::vector<uint8_t> template1(256);
     std::string file1("test1.hex");