Browse Source

[1955] Use PktTransform class for v6 packets.

Marcin Siodelski 13 years ago
parent
commit
53dfacddb5

+ 0 - 5
tests/tools/perfdhcp/perf_pkt4.h

@@ -136,11 +136,6 @@ public:
     /// \return false, if unpack operation failed.
     bool rawUnpack();
 
-    /// \brief Update packet timestamp with current time
-    ///
-    /// \throw isc::Unexpected if timestamp update failed
-    void updateTimestamp();
-
 private:
     size_t transid_offset_;      ///< transaction id offset
 

+ 25 - 145
tests/tools/perfdhcp/perf_pkt6.cc

@@ -18,6 +18,7 @@
 #include <dhcp/dhcp6.h>
 
 #include "perf_pkt6.h"
+#include "pkt_transform.h"
 
 using namespace std;
 using namespace isc;
@@ -26,165 +27,44 @@ using namespace dhcp;
 namespace isc {
 namespace perfdhcp {
 
-PerfPkt6::PerfPkt6(const uint8_t* buf, uint32_t len,
-                   uint32_t transid, const Offset& transid_offset) :
+PerfPkt6::PerfPkt6(const uint8_t* buf, size_t len) :
+    Pkt6(buf, len),
+    transid_offset_(1) {
+}
+
+PerfPkt6::PerfPkt6(const uint8_t* buf,
+                   size_t len,
+                   size_t transid_offset,
+                   uint32_t transid) :
     Pkt6(buf, len, Pkt6::UDP),
-    transid_offset_(transid_offset.get()) {
+    transid_offset_(transid_offset) {
     transid_ = transid;
 }
 
 PerfPkt6::PerfPkt6(const uint8_t* buf,
-                   uint32_t len,
-                   const Offset&
-                   transid_offset) :
+                   size_t len,
+                   size_t transid_offset) :
     Pkt6(buf, len, Pkt6::UDP),
-    transid_offset_(transid_offset.get()) {
+    transid_offset_(transid_offset) {
 }
 
 bool
 PerfPkt6::rawPack() {
-    // Always override the packet if function is called.
-    bufferOut_.clear();
-    // Write whole buffer to output buffer.
-    bufferOut_.writeData(&data_[0], data_.size());
-
-    if ((transid_offset_ + 4 > data_.size()) ||
-        (transid_offset_ == 0)) {
-        cout << "Failed to build packet: provided transaction id offset: "
-             << transid_offset_ <<  " is out of bounds (expected 1.."
-             << data_.size()-1 << ")." << endl;
-        return (false);
-    }
-
-    // Seek to the transaction id position in output buffer.
-    bufferOut_.clear();
-    bufferOut_.skip(transid_offset_);
-
-    try {
-        // Write 3 octets of transaction id
-        bufferOut_.writeUint8(transid_ >> 16 & 0xFF);
-        bufferOut_.writeUint8(transid_ >> 8 & 0xFF);
-        bufferOut_.writeUint8(transid_ & 0xFF);
-
-        // Buffer pointer is at the end of transaction id.
-        // We have to seek to the end of buffer so as data don't
-        // get truncated.
-        bufferOut_.skip(data_.size() - bufferOut_.getLength());
-
-        // We already have packet template stored in output buffer
-        // but still some options have to be updated if client
-        // specified them along with their offsets in the buffer.
-        rawPackOptions();
-    } catch (const isc::BadValue& e) {
-        cout << "Building packet failed: " << e.what() << endl;
-        return (false);
-    }
-    return (true);
+    return (PktTransform::pack(dhcp::Option::V6,
+                               data_,
+                               options_,
+                               transid_offset_,
+                               transid_,
+                               bufferOut_));
 }
 
 bool
 PerfPkt6::rawUnpack() {
-    // Validate transaction id offset.
-    if ((transid_offset_ + 4 > data_.size()) ||
-        (transid_offset_ == 0)) {
-        cout << "Failed to parse packet: provided transaction id offset: "
-             << transid_offset_ <<  " is out of bounds (expected 1.."
-             << data_.size()-1 << ")." << endl;
-        return (false);
-    }
-
-    // Read transaction id from the packet at the given offset.
-    transid_ = ( (data_[transid_offset_]) << 16 ) +
-        ((data_[transid_offset_ + 1]) << 8) + (data_[transid_offset_ + 2]);
-    transid_ = transid_ & 0xffffff;
-
-    // Get message type - assume it is first octet in the packet.
-    msg_type_ = data_[0];
-    try {
-        rawUnpackOptions();
-    } catch (const isc::BadValue& e) {
-        cout << "Packet parsing failed: " << e.what() << endl;
-        return (false);
-    }
-    return (true);
-}
-
-
-void
-PerfPkt6::rawPackOptions() {
-    try {
-        // If there are any options on the list, we will use provided
-        // options offsets to override them in the output buffer
-        // with new contents.
-        for (Option::OptionCollection::const_iterator it = options_.begin();
-             it != options_.end(); ++it) {
-            // Get options with their position (offset).
-            boost::shared_ptr<LocalizedOption> option =
-                boost::dynamic_pointer_cast<LocalizedOption>(it->second);
-            uint32_t offset = option->getOffset();
-            if ((offset == 0) ||
-                (offset + option->len() > data_.size())) {
-                isc_throw(isc::BadValue,
-                          "option offset for option: " << option->getType()
-                          << " is out of bounds (expected 1.."
-                          << data_.size() - option->len() << ")");
-            }
-            bufferOut_.clear();
-            bufferOut_.skip(offset);
-
-            // Replace existing option with new value.
-            option->pack(bufferOut_);
-        }
-        // Seek to the end of the buffer to make sure its size is correct.
-        bufferOut_.skip(data_.size() - bufferOut_.getLength());
-    }
-    catch (const Exception&) {
-        isc_throw(isc::BadValue, "failed to pack options into buffer.");
-    }
-}
-
-void
-PerfPkt6::rawUnpackOptions() {
-    for (Option::OptionCollection::const_iterator it = options_.begin();
-         it != options_.end(); ++it) {
-
-        LocalizedOptionPtr option =
-            boost::dynamic_pointer_cast<LocalizedOption>(it->second);
-        size_t opt_pos = option->getOffset();
-        if (opt_pos == 0) {
-            isc_throw(isc::BadValue, "failed to unpack packet from raw buffer "
-                      "(Option position not specified)");
-        } else if (opt_pos + 4 > data_.size()) {
-            isc_throw(isc::BadValue,
-                      "failed to unpack options from from raw buffer "
-                      "(Option position out of bounds)");
-        }
-
-        size_t offset = opt_pos;
-
-        // Get option type from first two octets.
-        uint16_t opt_type = data_[offset] * 256 + data_[offset + 1];
-        if (opt_type != option->getType()) {
-            isc_throw(isc::BadValue,
-                      "failed to unpack option from raw buffer "
-                      "(option type mismatch)");
-        }
-
-        // Get length from next two octets.
-        offset += 2;
-        uint16_t opt_len = data_[offset] * 256 + data_[offset + 1];
-
-        if (offset + opt_len > data_.size()) {
-            isc_throw(isc::BadValue,
-                      "failed to unpack option from raw buffer "
-                      "(option truncated)");
-        }
-
-        // Seek to actual option data and replace it.
-        offset += 2;
-        option->setData(data_.begin() + offset,
-                        data_.begin() + offset + opt_len);
-    }
+    return (PktTransform::unpack(dhcp::Option::V6,
+                                 data_,
+                                 options_,
+                                 transid_offset_,
+                                 transid_));
 }
 
 } // namespace perfdhcp

+ 50 - 114
tests/tools/perfdhcp/perf_pkt6.h

@@ -28,24 +28,18 @@ namespace perfdhcp {
 ///
 /// This class extends functionality of \ref isc::dhcp::Pkt6 by
 /// adding ability to specify options offset in DHCP message
-/// and override options' contents with new option.
-/// This approach is useful when we create paket object from
-/// raw template buffer from file and we want to use it as
-/// a base to create test packets to be sent to DHCP server.
-///
-/// Some of the contents of such a template packets always
-/// have to be replaced e.g. transaction id, IA_NA. Other
-/// contents (options) may be changed e.g. elapsed time,
-/// server id.
-///
-/// In order to create packet from raw template buffer
-/// we have to pass this buffer along with transaction id
-/// offset. Class will read transaction id from the buffer.
-/// Next, in order to replace contents of selected options
-/// in a template packet, we need to add these selected options
-/// to packet object using addOption() method. Please note
-/// that options must be of the
-/// \ref isc::perfdhcp::LocalizedOption type.
+/// and override options' contents.
+/// This is in particular useful when we create packet object using
+/// template file (do not build it dynamically). Client class
+/// should read data from template file and pass data to this class
+/// as buffer.
+/// Contents of such packet can be later partially replaced: preciselly
+/// selected options and transaction id can be replaced.
+/// Transaction id and its offset in template file is passed via
+/// constructor.
+/// In order to replace contents of options client class has to
+/// create collection of \ref LocalizedOption by adding them using
+/// \ref dhcp::Pkt6::addOption.
 ///
 /// \note: if you don't use template files simply use constructors
 /// inherited from parent class and isc::dhcp::Option type instead
@@ -53,77 +47,54 @@ namespace perfdhcp {
 class PerfPkt6 : public dhcp::Pkt6 {
 public:
 
-    /// \brief Represents offset value.
-    ///
-    /// This class represent offsets for DHCP message fields
-    /// like transaction id. Constructors of PerfPkt6 take
-    /// number of arguments of integer type so it is easy to
-    /// mess up arguments of constructors and for example
-    /// swap transaction id with its offset.
-    /// Use of this class implies that client class has to
-    /// explicitely use constructor of this class to pass
-    /// offset value. This should prevent mistakes and save some
-    /// time on debugging.
-    class Offset {
-    public:
-        /// \brief Default constructor
-        explicit Offset() :
-            offset_(1) { };
-
-        /// \brief Constructor
-        ///
-        /// \param offset offset value
-        explicit Offset(size_t offset) :
-            offset_(offset) { };
-
-        /// \brief Returns offset value.
-        ///
-        /// \return offset value.
-        size_t get() const { return offset_; };
-    private:
-        size_t offset_;    ///< offset value
-    };
-
     /// Localized option pointer type.
     typedef boost::shared_ptr<LocalizedOption> LocalizedOptionPtr;
 
+    /// \brief Constructor, used for outgoing and incoming messages
+    ///
+    /// This constructor initializes transaction id and
+    /// transaction id offset of the packet with default
+    /// values.
+    ///
+    /// \param buf buffer holding contents of the message.
+    /// \param len length of the data in the buffer.
+    PerfPkt6(const uint8_t* buf, size_t len);
+
     /// \brief Constructor, used for outgoing DHCP messages.
     ///
     /// Creates new DHCPv6 message using provided buffer.
-    /// Transaction id and its offset are specified through this
-    /// constructor so as they are stored in outgoing message
+    /// Transaction id and its offset are specified via this
+    /// constructor. Transaction id is stored in outgoing message
     /// when client class calls \ref PerfPkt6::rawPack.
     ///
     /// \note This constructor should be used only for outgoing
-    /// messages that are created from raw buffer (e.g. read from
-    /// template files).
+    /// messages that are created from template files.
     ///
-    /// \param buf buffer holiding contents of the message (this can
+    /// \param buf buffer holding contents of the message (this can
     /// be directly read from template file).
     /// \param len length of the data in the buffer.
-    /// \param transid transaction id to be stored in outgoing message.
     /// \param transid_offset transaction id offset in outgoing message.
+    /// \param transid transaction id to be stored in outgoing message.
     PerfPkt6(const uint8_t* buf,
-             uint32_t len,
-             uint32_t transid,
-             const Offset& transid_offset);
+             size_t len,
+             size_t transid_offset,
+             uint32_t transid);
 
     /// Constructor, used for incoming DHCP messages.
     ///
-    /// Creates new DHCPv6 message using provided buffer. New object
-    /// will keep copy of contents of provided buffer. If buffer contains
-    /// options at custom offsets (e.g. if packet was read from
-    /// template file) additional information about options'
-    /// offsets has to be provided - see
-    /// \ref isc::perfdhcp::LocalizedOption for details.
+    /// Creates new DHCPv6 message using provided buffer.
+    /// Client class may indicate which options are to be read
+    /// from the buffer. Such options should be added to
+    /// options collection using dhcp::Pkt4::addOption. Such
+    /// options should be of \ref LocalizedOption class.
     ///
-    /// Transaction id offset point to location of raw data where
+    /// Transaction id offset points to location where
     /// transaction id field is stored. The transaction id will
-    /// be read from this location when PerfPkt6::rawUnpack is
+    /// be read from this location when PerfPkt4::rawUnpack is
     /// called. The transid_ class member will be updated accordingly.
     ///
     /// \note use this constructor only in case you want to create
-    /// incoming DHCPv6 object from the raw buffer
+    /// incoming DHCPv4 object from the raw buffer
     /// and you know options offsets. Options offsets are
     /// specified from perfdhcp command line by the user.
     ///
@@ -131,19 +102,19 @@ public:
     /// \param len size of buffer of packet content.
     /// \param transid_offset transaction id offset in a message.
     PerfPkt6(const uint8_t* buf,
-             uint32_t len,
-             const Offset& transid_offset);
+             size_t len,
+             size_t transid_offset);
 
     /// \brief Returns transaction id offset in packet buffer
     ///
     /// return transaction id offset in packet buffer
     size_t getTransIdOffset() const { return transid_offset_; };
 
-    /// \brief Prepares on-wire format from raw buffer
+    /// \brief Prepares on-wire format from raw buffer.
     ///
-    /// The method copies user buffer to output buffer and
-    /// extracts transaction id from it based on transaction id
-    /// offset provided in constructor.
+    /// The method copies buffer provided in constructor to
+    /// output buffer and replaces transaction id and selected
+    /// options with new data.
     ///
     /// \note: Use this method to prepare on-wire DHCPv6 message
     /// when you use template packets that require replacement
@@ -155,52 +126,17 @@ public:
     /// \brief Handles limited binary packet parsing for packets with
     /// custom offsets of options and transaction id
     ///
-    /// Function handles reception of packets that have non-default values
-    /// of options or transaction id offsets. Use
-    /// \ref isc::dhcp::Pkt6::addOption to specify which options to parse.
-    /// Each option should be of the: isc::perfdhcp::LocalizedOption
-    /// type with offset value indicated.
+    /// Function handles parsing of packets that have custom offsets
+    /// of options or transaction id. Use
+    /// \ref isc::dhcp::Pkt4::addOption to specify which options to parse.
+    /// Options should be of the: isc::perfdhcp::LocalizedOption
+    /// type with offset values provided. Each added option will
+    /// be updated with actual data read from the binary packet buffer.
     ///
     /// \return false, if unpack operation failed.
     bool rawUnpack();
 
-    /// \brief Update packet timestamp with current time
-    ///
-    /// \throw isc::Unexpected if timestamp update failed
-    void updateTimestamp();
-
 private:
-
-    /// \brief Updates options in the output buffer
-    ///
-    /// The method uses options collection added to object
-    /// of this class with \ref dhcp::Pkt6::addOption to
-    /// on-wire data. Option objects has to be of
-    /// \ref perfdhcp::LocalizedOption type and should
-    /// have non-zero values of offsets specified.
-    /// This method will use these offsets to seek to
-    /// given position in output buffer and update option
-    /// on-wire data with contents of option's buffer.
-    ///
-    /// \throw isc::Unexpected if options update failed.
-    void rawPackOptions();
-
-    /// \brief Reads contents of specified options from buffer
-    ///
-    /// The method reads options data from the copy of the buffer
-    /// provided in constructor and stores data in options
-    /// objects that belong to options collection.
-    /// Client class that constructs this object has to create
-    /// options collection prior to calling \ref rawUnpack
-    /// method that in turn calls this method.
-    /// If option is not added to options collection, it will
-    /// not be added by this method. This method will rather
-    /// skip update of such an option even if it is present
-    /// in packet's buffer.
-    ///
-    /// \throw isc::Unexpected if options unpack failed.
-    void rawUnpackOptions();
-
     size_t transid_offset_;      ///< transaction id offset
 
 };

+ 12 - 26
tests/tools/perfdhcp/tests/perf_pkt6_unittest.cc

@@ -77,8 +77,7 @@ public:
         data[93] = 6;       data[94] = 0;     data[95] = 2;     data[96] = 0;
         data[97] = 23;
 
-        PerfPkt6* pkt = new PerfPkt6(data, sizeof(data),
-                                     0x1, PerfPkt6::Offset());
+        PerfPkt6* pkt = new PerfPkt6(data, sizeof(data));
 
         return (pkt);
     }
@@ -97,8 +96,7 @@ public:
         data[9]  = 1;       data[10] = 0;     data[11] = 1;     data[12] = 21;
         data[13] = 158;     data[14] = 60;    data[15] = 22;    data[16] = 0;
 
-        PerfPkt6* pkt = new PerfPkt6(data, sizeof(data),
-                                     0x1, PerfPkt6::Offset());
+        PerfPkt6* pkt = new PerfPkt6(data, sizeof(data));
 
         return (pkt);
     }
@@ -110,28 +108,17 @@ TEST_F(PerfPkt6Test, Constructor) {
     // Data to be used to create packet.
     uint8_t data[] = { 0, 1, 2, 3, 4, 5 };
 
-    // Test constructors of Offset class.
-    PerfPkt6::Offset of1(0);
-    EXPECT_EQ(0, of1.get());
-
-    PerfPkt6::Offset of2;
-    EXPECT_EQ(1, of2.get());
-
-    PerfPkt6::Offset of3(10);
-    EXPECT_EQ(10, of3.get());
-
     // Test constructor to be used for incoming messages.
     // Use default (1) offset value and don't specify transaction id.
-    boost::scoped_ptr<PerfPkt6> pkt1(new PerfPkt6(data, sizeof(data),
-                                                  PerfPkt6::Offset()));
+    boost::scoped_ptr<PerfPkt6> pkt1(new PerfPkt6(data, sizeof(data)));
     EXPECT_EQ(6, pkt1->getData().size());
     EXPECT_EQ(0, memcmp(&pkt1->getData()[0], data, sizeof(data)));
     EXPECT_EQ(1, pkt1->getTransIdOffset());
 
     // Test constructor to be used for outgoing messages.
     // Use non-zero offset and specify transaction id.
-    boost::scoped_ptr<PerfPkt6> pkt2(new PerfPkt6(data, sizeof(data), 0x010203,
-                                                  PerfPkt6::Offset(10)));
+    boost::scoped_ptr<PerfPkt6> pkt2(new PerfPkt6(data, sizeof(data),
+                                                  10, 0x010203));
     EXPECT_EQ(6, pkt2->getData().size());
     EXPECT_EQ(0, memcmp(&pkt2->getData()[0], data, sizeof(data)));
     EXPECT_EQ(0x010203, pkt2->getTransid());
@@ -175,8 +162,7 @@ TEST_F(PerfPkt6Test, RawPackUnpack) {
     const uint8_t* pkt1_output_data = static_cast<const uint8_t*>
         (pkt1_output.getData());
     boost::scoped_ptr<PerfPkt6> pkt2(new PerfPkt6(pkt1_output_data,
-                                                  pkt1_output.getLength(),
-                                                  PerfPkt6::Offset()));
+                                                  pkt1_output.getLength()));
 
     // Create objects specifying options offset in a packet.
     // Offsets will inform pkt2 object where to read data from.
@@ -268,8 +254,8 @@ TEST_F(PerfPkt6Test, PackTransactionId) {
     // Create dummy packet that is simply filled with zeros.
     boost::scoped_ptr<PerfPkt6> pkt1(new PerfPkt6(data,
                                                   sizeof(data),
-                                                  0x010203,
-                                                  PerfPkt6::Offset(50)));
+                                                  50,
+                                                  0x010203));
 
     // Reference data are non zero so we can detect them in dummy packet.
     uint8_t ref_data[3] = { 1, 2, 3 };
@@ -290,8 +276,8 @@ TEST_F(PerfPkt6Test, PackTransactionId) {
     // Out of bounds transaction id offset.
     boost::scoped_ptr<PerfPkt6> pkt2(new PerfPkt6(data,
                                                   sizeof(data),
-                                                  0x010202,
-                                                  PerfPkt6::Offset(100)));
+                                                  100,
+                                                  0x010202));
     cout << "Testing out of bounds offset. "
         "This may produce spurious errors ..." << endl;
     EXPECT_FALSE(pkt2->rawPack());
@@ -308,7 +294,7 @@ TEST_F(PerfPkt6Test, UnpackTransactionId) {
     // Create packet and point out that transaction id is at offset 50.
     boost::scoped_ptr<PerfPkt6> pkt1(new PerfPkt6(data,
                                                   sizeof(data),
-                                                  PerfPkt6::Offset(50)));
+                                                  50));
 
     // Get transaction id out of buffer and store in class member.
     ASSERT_TRUE(pkt1->rawUnpack());
@@ -318,7 +304,7 @@ TEST_F(PerfPkt6Test, UnpackTransactionId) {
     // Out of bounds transaction id offset.
     boost::scoped_ptr<PerfPkt6> pkt2(new PerfPkt6(data,
                                                   sizeof(data),
-                                                  PerfPkt6::Offset(300)));
+                                                  300));
     cout << "Testing out of bounds offset. "
         "This may produce spurious errors ..." << endl;
     EXPECT_FALSE(pkt2->rawUnpack());