Pcap::Diff() method added to compare PCAP traces packet-by-packet
authorPavel Boyko <boyko@iitp.ru>
Wed Oct 28 11:43:57 2009 +0300 (3 months ago)
changeset 5511917f7367691e
parent 5510 050630fcf15e
child 5512 c206a8ce5644
child 5779 26dfa683fc34
Pcap::Diff() method added to compare PCAP traces packet-by-packet
src/common/pcap-file-test-suite.cc
src/common/pcap-file.cc
src/common/pcap-file.h
     1.1 --- a/src/common/pcap-file-test-suite.cc	Tue Oct 27 18:43:45 2009 +0300
     1.2 +++ b/src/common/pcap-file-test-suite.cc	Wed Oct 28 11:43:57 2009 +0300
     1.3 @@ -12,6 +12,8 @@
     1.4   * You should have received a copy of the GNU General Public License
     1.5   * along with this program; if not, write to the Free Software
     1.6   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     1.7 + * 
     1.8 + * Author:  Craig Dowell (craigdo@ee.washington.edu)
     1.9   */
    1.10  
    1.11  #include <iostream>
    1.12 @@ -948,6 +950,62 @@
    1.13    return false;
    1.14  }
    1.15  
    1.16 +// ===========================================================================
    1.17 +// Test case to make sure that the Pcap::Diff method works as expected
    1.18 +// ===========================================================================
    1.19 +class DiffTestCase : public TestCase
    1.20 +{
    1.21 +public:
    1.22 +  DiffTestCase ();
    1.23 +
    1.24 +private:
    1.25 +  virtual bool DoRun (void);
    1.26 +};
    1.27 +
    1.28 +DiffTestCase::DiffTestCase ()
    1.29 +  : TestCase ("Check that PcapFile::Diff works as expected")
    1.30 +{
    1.31 +}
    1.32 +
    1.33 +bool
    1.34 +DiffTestCase::DoRun (void)
    1.35 +{
    1.36 +  //
    1.37 +  // Check that PcapDiff(file, file) is false
    1.38 +  //
    1.39 +  std::string filename = NS_TEST_SOURCEDIR + "known.pcap";
    1.40 +  uint32_t sec(0), usec(0);
    1.41 +  bool diff = PcapFile::Diff (filename, filename, sec, usec);
    1.42 +  NS_TEST_EXPECT_MSG_EQ (diff, false, "PcapDiff(file, file) must always be false");
    1.43 +
    1.44 +  //
    1.45 +  // Create different PCAP file (with the same timestamps, but different packets) and check that it is indeed different 
    1.46 +  //
    1.47 +  std::string filename2 = "different.pcap";
    1.48 +  PcapFile f;
    1.49 +  
    1.50 +  bool err = f.Open (filename2, "w");
    1.51 +  NS_TEST_ASSERT_MSG_EQ (err, false, "Open (" << filename2 << ", \"w\") returns error");
    1.52 +  err = f.Init (1, N_PACKET_BYTES);
    1.53 +  NS_TEST_ASSERT_MSG_EQ (err, false, "Init (1, " << N_PACKET_BYTES << ") returns error");
    1.54 +  
    1.55 +  for (uint32_t i = 0; i < N_KNOWN_PACKETS; ++i)
    1.56 +    {
    1.57 +      PacketEntry const & p = knownPackets[i];
    1.58 +      
    1.59 +      err = f.Write (p.tsSec, p.tsUsec, (uint8_t const *)p.data, p.origLen);
    1.60 +      NS_TEST_EXPECT_MSG_EQ (err, false, "Write must not fail");
    1.61 +    }
    1.62 +  f.Close ();
    1.63 +
    1.64 +  diff = PcapFile::Diff (filename, filename2, sec, usec);
    1.65 +  NS_TEST_EXPECT_MSG_EQ (diff, true, "PcapDiff(file, file2) must be true");
    1.66 +  NS_TEST_EXPECT_MSG_EQ (sec,  2, "Files are different from 2.3696 seconds");
    1.67 +  NS_TEST_EXPECT_MSG_EQ (usec, 3696, "Files are different from 2.3696 seconds");
    1.68 +  
    1.69 +  return GetErrorStatus();
    1.70 +}
    1.71 +
    1.72  class PcapFileTestSuite : public TestSuite
    1.73  {
    1.74  public:
    1.75 @@ -963,6 +1021,7 @@
    1.76    AddTestCase (new FileHeaderTestCase);
    1.77    AddTestCase (new RecordHeaderTestCase);
    1.78    AddTestCase (new ReadFileTestCase);
    1.79 +  AddTestCase (new DiffTestCase);
    1.80  }
    1.81  
    1.82  PcapFileTestSuite pcapFileTestSuite;
     2.1 --- a/src/common/pcap-file.cc	Tue Oct 27 18:43:45 2009 +0300
     2.2 +++ b/src/common/pcap-file.cc	Wed Oct 28 11:43:57 2009 +0300
     2.3 @@ -14,14 +14,16 @@
     2.4   * You should have received a copy of the GNU General Public License
     2.5   * along with this program; if not, write to the Free Software
     2.6   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     2.7 + * 
     2.8 + * Author:  Craig Dowell (craigdo@ee.washington.edu)
     2.9   */
    2.10  
    2.11  #include <iostream>
    2.12  #include <stdio.h>
    2.13  #include <stdlib.h>
    2.14 +#include <cstring>
    2.15  
    2.16  #include "pcap-file.h"
    2.17 -
    2.18  //
    2.19  // This file is used as part of the ns-3 test framework, so please refrain from 
    2.20  // adding any ns-3 specific constructs such as Packet to this file.
    2.21 @@ -516,4 +518,65 @@
    2.22    return false;
    2.23  }
    2.24  
    2.25 +bool
    2.26 +PcapFile::Diff (std::string const & f1, std::string const & f2, 
    2.27 +                uint32_t & sec, uint32_t & usec, 
    2.28 +                uint32_t snapLen)
    2.29 +{
    2.30 +  PcapFile pcap[2];
    2.31 +  for (int i = 0; i < 2; ++i)
    2.32 +    {
    2.33 +      std::string const & file = (i == 0) ? f1 : f2;
    2.34 +      bool err = pcap[i].Open (file, "r");
    2.35 +      if (err)
    2.36 +        {
    2.37 +          // Can't open file
    2.38 +          return true;
    2.39 +        }
    2.40 +    }
    2.41 +  
    2.42 +  uint8_t data[2][snapLen];
    2.43 +  uint32_t tsSec[2], tsUsec[2], inclLen[2], origLen[2], readLen[2];
    2.44 +  bool err[2];
    2.45 +  bool diff(false);
    2.46 +  
    2.47 +  while (1)
    2.48 +    {
    2.49 +      for (int i = 0; i < 2; ++i)
    2.50 +        err[i] = pcap[i].Read (data[i], snapLen, tsSec[i], tsUsec[i], inclLen[i], origLen[i], readLen[i]);
    2.51 +    
    2.52 +      sec = tsSec[0];
    2.53 +      usec = tsUsec[0];
    2.54 +      
    2.55 +      if (err[0] != err[1])
    2.56 +        {
    2.57 +          diff = true; // Read status doesn't match
    2.58 +          break;
    2.59 +        }
    2.60 +      
    2.61 +      if (err[0]) break; // nothing left
    2.62 +      
    2.63 +      if (tsSec[0] != tsSec[1] || tsUsec[0] != tsUsec[1])
    2.64 +        {
    2.65 +          diff = true; // Next packet timestamps do not match
    2.66 +          break;
    2.67 +        }
    2.68 +      
    2.69 +      if (readLen[0] != readLen[1])
    2.70 +        {
    2.71 +          diff = true; // Packet lengths do not match
    2.72 +          break;
    2.73 +        }
    2.74 +      
    2.75 +      if (std::memcmp(data[0], data[1], readLen[0]) != 0)
    2.76 +        {
    2.77 +          diff = true; // Packet data do not match
    2.78 +          break;
    2.79 +        }
    2.80 +    }  
    2.81 +  pcap[0].Close ();
    2.82 +  pcap[1].Close ();
    2.83 +  return diff;
    2.84 +}
    2.85 +
    2.86  } //namespace ns3
     3.1 --- a/src/common/pcap-file.h	Tue Oct 27 18:43:45 2009 +0300
     3.2 +++ b/src/common/pcap-file.h	Wed Oct 28 11:43:57 2009 +0300
     3.3 @@ -14,6 +14,8 @@
     3.4   * You should have received a copy of the GNU General Public License
     3.5   * along with this program; if not, write to the Free Software
     3.6   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     3.7 + * 
     3.8 + * Author:  Craig Dowell (craigdo@ee.washington.edu)
     3.9   */
    3.10  
    3.11  #ifndef PCAP_FILE_H
    3.12 @@ -125,7 +127,7 @@
    3.13     * time zone from UTC/GMT.  For example, Pacific Standard Time in the US is
    3.14     * GMT-8, so one would enter -8 for that correction.  Defaults to 0 (UTC).
    3.15     *
    3.16 -   * \returns false if the open succeeds, true otherwise.
    3.17 +   * \return false if the open succeeds, true otherwise.
    3.18     *
    3.19     * \warning Calling this method on an existing file will result in the loss
    3.20     * any existing data.
    3.21 @@ -135,8 +137,31 @@
    3.22               int32_t timeZoneCorrection = ZONE_DEFAULT,
    3.23               bool swapMode = false);
    3.24  
    3.25 +  /**
    3.26 +   * \brief Write next packet to file
    3.27 +   * 
    3.28 +   * \param tsSec       Packet timestamp, seconds 
    3.29 +   * \param tsUsec      Packet timestamp, microseconds
    3.30 +   * \param data        Data buffer
    3.31 +   * \param totalLen    Total packet length
    3.32 +   * 
    3.33 +   * \return true on error, false otherwise
    3.34 +   */
    3.35    bool Write (uint32_t tsSec, uint32_t tsUsec, uint8_t const * const data, uint32_t totalLen);
    3.36  
    3.37 +  /**
    3.38 +   * \brief Read next packet from file
    3.39 +   * 
    3.40 +   * \param data        [out] Data buffer
    3.41 +   * \param maxBytes    Allocated data buffer size
    3.42 +   * \param tsSec       [out] Packet timestamp, seconds
    3.43 +   * \param tsUsec      [out] Packet timestamp, microseconds
    3.44 +   * \param inclLen     [out] Included length
    3.45 +   * \param origLen     [out] Original length
    3.46 +   * \param readLen     [out] Number of bytes read
    3.47 +   * 
    3.48 +   * \return true if read failed, false otherwise
    3.49 +   */
    3.50    bool Read (uint8_t * const data, 
    3.51               uint32_t maxBytes,
    3.52               uint32_t &tsSec, 
    3.53 @@ -154,6 +179,21 @@
    3.54    uint32_t GetSigFigs (void);
    3.55    uint32_t GetSnapLen (void);
    3.56    uint32_t GetDataLinkType (void);
    3.57 +  
    3.58 +  /**
    3.59 +   * \brief Compare two PCAP files packet-by-packet
    3.60 +   * 
    3.61 +   * \return true if files are different, false otherwise
    3.62 +   * 
    3.63 +   * \param  f1         First PCAP file name
    3.64 +   * \param  f2         Second PCAP file name
    3.65 +   * \param  sec        [out] Time stamp of first different packet, seconds. Undefined if files doesn't differ.
    3.66 +   * \param  uses       [out] Time stamp of first different packet, microseconds. Undefined if files doesn't differ.
    3.67 +   * \param  snapLen    Snap length (if used)
    3.68 +   */
    3.69 +  static bool Diff (std::string const & f1, std::string const & f2, 
    3.70 +                    uint32_t & sec, uint32_t & usec, 
    3.71 +                    uint32_t snapLen = SNAPLEN_DEFAULT);
    3.72  
    3.73  private:
    3.74    typedef struct {