Browse Source

[3173] Add IA_PD option to solicit and request messages.

Marcin Siodelski 11 years ago
parent
commit
b6c658d2fd

+ 62 - 8
tests/tools/perfdhcp/test_control.cc

@@ -97,6 +97,31 @@ TestControl::TestControl() {
     reset();
 }
 
+void
+TestControl::copyIaOptions(const Pkt6Ptr& pkt_from, Pkt6Ptr& pkt_to) {
+    if (!pkt_from || !pkt_to) {
+        isc_throw(BadValue, "NULL pointers must not be specified as arguments"
+                  " for the copyIaOptions function");
+    }
+    OptionPtr option;
+    if (CommandOptions::instance().getLeaseType() ==
+        CommandOptions::ADDRESS_ONLY) {
+        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);
+        if (!option) {
+            isc_throw(OptionNotFound, "IA_PD option not found in the"
+                      " server's response");
+        }
+    }
+    pkt_to->addOption(option);
+
+}
+
 std::string
 TestControl::byte2Hex(const uint8_t b) const {
     const int b1 = b / 16;
@@ -290,6 +315,22 @@ TestControl::factoryIana6(Option::Universe, uint16_t,
 }
 
 OptionPtr
+TestControl::factoryIapd6(Option::Universe, uint16_t,
+                          const OptionBuffer& buf) {
+    // @todo allow different values of T1, T2 and IAID.
+    static const uint8_t buf_array[] = {
+        0, 0, 0, 1,                     // IAID = 1
+        0, 0, 3600 >> 8, 3600 & 0xff,   // T1 = 3600
+        0, 0, 5400 >> 8, 5400 & 0xff,   // T2 = 5400
+    };
+    OptionBuffer buf_ia_pd(buf_array, buf_array + sizeof(buf_array));
+    // Append sub-options to IA_PD.
+    buf_ia_pd.insert(buf_ia_pd.end(), buf.begin(), buf.end());
+    return (OptionPtr(new Option(Option::V6, D6O_IA_PD, buf_ia_pd)));
+}
+
+
+OptionPtr
 TestControl::factoryRapidCommit6(Option::Universe, uint16_t,
                                  const OptionBuffer&) {
     return (OptionPtr(new Option(Option::V6, D6O_RAPID_COMMIT, OptionBuffer())));
@@ -1079,6 +1120,11 @@ TestControl::registerOptionFactories6() const {
                                        D6O_IA_NA,
                                        &TestControl::factoryIana6);
 
+        // D6O_IA_PD option factory.
+        LibDHCP::OptionFactoryRegister(Option::V6,
+                                       D6O_IA_PD,
+                                       &TestControl::factoryIapd6);
+
 
     }
     factories_registered = true;
@@ -1577,13 +1623,13 @@ TestControl::sendRequest6(const TestControlSocket& socket,
         }
         pkt6->addOption(opt_serverid);
     }
-    // Set IA_NA option.
-    OptionPtr opt_ia_na = advertise_pkt6->getOption(D6O_IA_NA);
-    if (!opt_ia_na) {
-        isc_throw(Unexpected, "DHCPv6 IA_NA option not found in received "
-                  "packet");
-    }
-    pkt6->addOption(opt_ia_na);
+
+    // Copy IA_NA or IA_PD option from the Advertise message to the Request
+    // message being sent to the server. This will throw exception if the
+    // option to be copied is not found. Note that this function will copy
+    // one of IA_NA or IA_PD options, depending on the lease-type value
+    // specified in the command line.
+    copyIaOptions(advertise_pkt6, pkt6);
 
     // Set default packet data.
     setDefaults6(socket, pkt6);
@@ -1732,7 +1778,15 @@ TestControl::sendSolicit6(const TestControlSocket& socket,
     }
     pkt6->addOption(Option::factory(Option::V6, D6O_CLIENTID, duid));
     pkt6->addOption(Option::factory(Option::V6, D6O_ORO));
-    pkt6->addOption(Option::factory(Option::V6, D6O_IA_NA));
+
+    // Depending on the lease-type option specified, we should request
+    // IPv6 address (with IA_NA) or IPv6 prefix (IA_PD).
+    if (CommandOptions::instance().getLeaseType() ==
+        CommandOptions::ADDRESS_ONLY) {
+        pkt6->addOption(Option::factory(Option::V6, D6O_IA_NA));
+    } else {
+        pkt6->addOption(Option::factory(Option::V6, D6O_IA_PD));
+    }
 
     setDefaults6(socket, pkt6);
     pkt6->pack();

+ 44 - 1
tests/tools/perfdhcp/test_control.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -55,6 +55,13 @@ static const size_t DHCPV6_SERVERID_OFFSET = 22;
 /// Default DHCPV6 IA_NA offset in the packet template.
 static const size_t DHCPV6_IA_NA_OFFSET = 40;
 
+/// @brief Exception thrown when the required option is not found in a packet.
+class OptionNotFound : public Exception {
+public:
+    OptionNotFound(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) { };
+};
+
 /// \brief Test Control class.
 ///
 /// This singleton class is used to run the performance test with
@@ -338,6 +345,17 @@ protected:
                                         uint16_t type,
                                         const dhcp::OptionBuffer& buf);
 
+    /// \brief Factory function to create IA_PD option.
+    ///
+    /// this factory function creates DHCPv6 IA_PD option instance.
+    ///
+    /// \param u universe (ignored).
+    /// \param type option-type (ignored).
+    /// \param buf option-buffer carrying sub-options.
+    static dhcp::OptionPtr factoryIapd6(dhcp::Option::Universe u,
+                                        uint16_t type,
+                                        const dhcp::OptionBuffer& buf);
+
     /// \brief Factory function to create DHCPv6 ORO option.
     ///
     /// This factory function creates DHCPv6 Option Request Option instance.
@@ -834,6 +852,31 @@ protected:
 
 private:
 
+    /// \brief Copies IA_NA or IA_PD option from one packet to another.
+    ///
+    /// This function checks the lease-type specified in the command line
+    /// with option -e<lease-type>. If 'address-only' value has been specified
+    /// this function expects that IA_NA option is present in the packet
+    /// encapsulated by pkt_from object. If 'prefix-only' value has been
+    /// specified, this function expects that IA_PD option is present in the
+    /// packet encapsulated by pkt_to object.
+    ///
+    /// \todo In the future it is planned to add support for the perfdhcp to
+    /// request address and prefix in the same DHCP message (request both
+    /// IA_NA and IA_PD options). In this case, this function will have to
+    /// be extended to copy both IA_NA and IA_PD options.
+    ///
+    /// \warning
+    ///
+    /// \param [in] pkt_from A packet from which options should be copied.
+    /// \parma [out] pkt_to A packet to which options should be copied.
+    ///
+    /// \throw isc::perfdhcp::OptionNotFound if a required option is not
+    /// found in the packet from which options should be copied.
+    /// \throw isc::BadValue if any of the specified pointers to packets
+    /// is NULL.
+    void copyIaOptions(const dhcp::Pkt6Ptr& pkt_from, dhcp::Pkt6Ptr& pkt_to);
+
     /// \brief Convert binary value to hex string.
     ///
     /// \todo Consider moving this function to src/lib/util.

+ 41 - 3
tests/tools/perfdhcp/tests/test_control_unittest.cc

@@ -521,7 +521,13 @@ public:
                 boost::shared_ptr<Pkt6>
                     advertise_pkt6(createAdvertisePkt6(transid));
                 // Receive ADVERTISE and send REQUEST.
-                ASSERT_NO_THROW(tc.processReceivedPacket6(sock, advertise_pkt6));
+                /*                ASSERT_NO_THROW(tc.processReceivedPacket6(sock,
+                                  advertise_pkt6)); */
+                try {
+                    tc.processReceivedPacket6(sock, advertise_pkt6);
+                } catch (const Exception& ex) {
+                    std::cout << ex.what() << std::endl;
+                }
                 ++transid;
             }
             if (tc.checkExitConditions()) {
@@ -646,14 +652,20 @@ private:
     /// \return instance of the packet.
     boost::shared_ptr<Pkt6>
     createAdvertisePkt6(uint32_t transid) const {
-        OptionPtr opt_ia_na = Option::factory(Option::V6, D6O_IA_NA);
+        OptionPtr opt_ia;
+        if (CommandOptions::instance().getLeaseType() ==
+            CommandOptions::ADDRESS_ONLY) {
+            opt_ia = Option::factory(Option::V6, D6O_IA_NA);
+        } else {
+            opt_ia = Option::factory(Option::V6, D6O_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_na);
+        advertise->addOption(opt_ia);
         advertise->addOption(opt_serverid);
         advertise->addOption(opt_clientid);
         advertise->updateTimestamp();
@@ -1003,6 +1015,32 @@ TEST_F(TestControlTest, Packet6Exchange) {
     EXPECT_EQ(6, iterations_performed);
 }
 
+TEST_F(TestControlTest, Packet6ExchangePrefixDelegation) {
+    // 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 prefix-only"
+                   + " -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");