Browse Source

[1956] Added timestamp update mechanism to pkt6 and pkt4 classes.

Marcin Siodelski 13 years ago
parent
commit
9cd5b8d800

+ 1 - 0
src/lib/dhcp/Makefile.am

@@ -31,3 +31,4 @@ libdhcp___la_CPPFLAGS = $(AM_CPPFLAGS) $(LOG4CPLUS_INCLUDES)
 libdhcp___la_LIBADD   = $(top_builddir)/src/lib/asiolink/libasiolink.la
 libdhcp___la_LIBADD  += $(top_builddir)/src/lib/util/libutil.la
 libdhcp___la_LDFLAGS  = -no-undefined -version-info 1:0:0
+libdhcp___la_LDFLAGS += $(CLOCK_GETTIME_LDFLAGS)

+ 8 - 0
src/lib/dhcp/iface_mgr.cc

@@ -597,6 +597,8 @@ IfaceMgr::send(const Pkt6Ptr& pkt) {
     pktinfo->ipi6_ifindex = pkt->getIndex();
     m.msg_controllen = cmsg->cmsg_len;
 
+    pkt->updateTimestamp();
+
     result = sendmsg(getSocket(*pkt), &m, 0);
     if (result < 0) {
         isc_throw(Unexpected, "Pkt6 send failed: sendmsg() returned " << result);
@@ -656,6 +658,8 @@ IfaceMgr::send(const Pkt4Ptr& pkt)
          << " over socket " << getSocket(*pkt) << " on interface "
          << getIface(pkt->getIface())->getFullName() << endl;
 
+    pkt->updateTimestamp();
+
     int result = sendmsg(getSocket(*pkt), &m, 0);
     if (result < 0) {
         isc_throw(Unexpected, "Pkt4 send failed.");
@@ -746,6 +750,8 @@ IfaceMgr::receive4() {
     // We have all data let's create Pkt4 object.
     Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(buf, result));
 
+    pkt->updateTimestamp();
+
     unsigned int ifindex = iface->getIndex();
 
     IOAddress from(htonl(from_addr.sin_addr.s_addr));
@@ -890,6 +896,8 @@ Pkt6Ptr IfaceMgr::receive6() {
         return (Pkt6Ptr()); // NULL
     }
 
+    pkt->updateTimestamp();
+
     pkt->setLocalAddr(IOAddress::from_bytes(AF_INET6,
                       reinterpret_cast<const uint8_t*>(&to_addr)));
     pkt->setRemoteAddr(IOAddress::from_bytes(AF_INET6,

+ 9 - 0
src/lib/dhcp/pkt4.cc

@@ -53,6 +53,7 @@ Pkt4::Pkt4(uint8_t msg_type, uint32_t transid)
     memset(chaddr_, 0, MAX_CHADDR_LEN);
     memset(sname_, 0, MAX_SNAME_LEN);
     memset(file_, 0, MAX_FILE_LEN);
+    memset(&timestamp_, 0, sizeof(timestamp_));
 }
 
 Pkt4::Pkt4(const uint8_t* data, size_t len)
@@ -81,6 +82,7 @@ Pkt4::Pkt4(const uint8_t* data, size_t len)
 
     data_.resize(len);
     memcpy(&data_[0], data, len);
+    memset(&timestamp_, 0, sizeof(timestamp_));
 }
 
 size_t
@@ -305,6 +307,13 @@ Pkt4::getOption(uint8_t type) {
     return boost::shared_ptr<isc::dhcp::Option>(); // NULL
 }
 
+void
+Pkt4::updateTimestamp() {
+    if (clock_gettime(CLOCK_REALTIME, &timestamp_) < 0) {
+        isc_throw(isc::Unexpected, "Failed to get timestamp for packet");
+    }
+}
+
 } // end of namespace isc::dhcp
 
 } // end of namespace isc

+ 20 - 0
src/lib/dhcp/pkt4.h

@@ -16,6 +16,7 @@
 #define PKT4_H
 
 #include <iostream>
+#include <time.h>
 #include <vector>
 #include <boost/shared_ptr.hpp>
 #include "asiolink/io_address.h"
@@ -321,6 +322,14 @@ public:
     /// @return interface name
     std::string getIface() const { return iface_; };
 
+    /// @brief Returns packet timestamp.
+    ///
+    /// Returns packet timestamp value updated when
+    /// packet is received or send.
+    ///
+    /// @return packet timestamp.
+    timespec getTimestamp() const { return timestamp_; }
+
     /// @brief Sets interface name.
     ///
     /// Sets interface name over which packet was received or is
@@ -387,6 +396,14 @@ public:
     /// @return remote port
     uint16_t getRemotePort() { return (remote_port_); }
 
+    /// @brief Update packet timestamp.
+    ///
+    /// Updates packet timestamp. This method is invoked
+    /// by interface manager just before sending or
+    /// just after receiving it.
+    /// @throw isc::Unexpected if timestamp update failed
+    void updateTimestamp();
+
 protected:
 
     /// converts DHCP message type to BOOTP op type
@@ -485,6 +502,9 @@ protected:
 
     /// collection of options present in this message
     isc::dhcp::Option::OptionCollection options_;
+
+    /// packet timestamp
+    timespec timestamp_;
 }; // Pkt4 class
 
 typedef boost::shared_ptr<Pkt4> Pkt4Ptr;

+ 10 - 0
src/lib/dhcp/pkt6.cc

@@ -38,6 +38,7 @@ Pkt6::Pkt6(const uint8_t* buf, uint32_t buf_len, DHCPv6Proto proto /* = UDP */)
     bufferOut_(0) {
     data_.resize(buf_len);
     memcpy(&data_[0], buf, buf_len);
+    memset(&timestamp_, 0, sizeof(timestamp_));
 }
 
 Pkt6::Pkt6(uint8_t msg_type, uint32_t transid, DHCPv6Proto proto /*= UDP*/) :
@@ -51,6 +52,7 @@ Pkt6::Pkt6(uint8_t msg_type, uint32_t transid, DHCPv6Proto proto /*= UDP*/) :
     local_port_(0),
     remote_port_(0),
     bufferOut_(0) {
+    memset(&timestamp_, 0, sizeof(timestamp_));
 }
 
 uint16_t Pkt6::len() {
@@ -202,5 +204,13 @@ void Pkt6::repack() {
     bufferOut_.writeData(&data_[0], data_.size());
 }
 
+void
+Pkt6::updateTimestamp() {
+    if (clock_gettime(CLOCK_REALTIME, &timestamp_) < 0) {
+        isc_throw(isc::Unexpected, "Failed to get timestamp for packet");
+    }
+}
+
+
 } // end of isc::dhcp namespace
 } // end of isc namespace

+ 20 - 0
src/lib/dhcp/pkt6.h

@@ -16,6 +16,7 @@
 #define PKT6_H
 
 #include <iostream>
+#include <time.h>
 #include <boost/shared_ptr.hpp>
 #include <boost/shared_array.hpp>
 #include "asiolink/io_address.h"
@@ -220,6 +221,14 @@ public:
     /// @return interface name
     std::string getIface() const { return iface_; };
 
+    /// @brief Returns packet timestamp.
+    ///
+    /// Returns packet timestamp value updated when
+    /// packet is received or send.
+    ///
+    /// @return packet timestamp.
+    timespec getTimestamp() const { return timestamp_; }
+
     /// @brief Sets interface name.
     ///
     /// Sets interface name over which packet was received or is
@@ -233,6 +242,14 @@ public:
     /// collection of options present in this message
     isc::dhcp::Option::OptionCollection options_;
 
+    /// @brief Update packet timestamp.
+    ///
+    /// Updates packet timestamp. This method is invoked
+    /// by interface manager just before sending or
+    /// just after receiving it.
+    /// @throw isc::Unexpected if timestamp update failed
+    void updateTimestamp();
+
 protected:
     /// Builds on wire packet for TCP transmission.
     ///
@@ -305,6 +322,9 @@ protected:
 
     /// output buffer (used during message transmission)
     isc::util::OutputBuffer bufferOut_;
+
+    /// packet timestamp
+    timespec timestamp_;
 }; // Pkt6 class
 
 typedef boost::shared_ptr<Pkt6> Pkt6Ptr;

+ 1 - 1
src/lib/dhcp/tests/Makefile.am

@@ -33,7 +33,7 @@ libdhcp___unittests_SOURCES += ../pkt6.h ../pkt6.cc pkt6_unittest.cc
 libdhcp___unittests_SOURCES += ../pkt4.h ../pkt4.cc pkt4_unittest.cc
 
 libdhcp___unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES)
-libdhcp___unittests_LDFLAGS  = $(AM_LDFLAGS)  $(GTEST_LDFLAGS)
+libdhcp___unittests_LDFLAGS  = $(AM_LDFLAGS)  $(GTEST_LDFLAGS) $(CLOCK_GETTIME_LDFLAGS)
 
 libdhcp___unittests_CXXFLAGS = $(AM_CXXFLAGS)
 

+ 12 - 0
src/lib/dhcp/tests/pkt4_unittest.cc

@@ -598,4 +598,16 @@ TEST(Pkt4Test, metaFields) {
     delete pkt;
 }
 
+TEST(Pkt4Test, Timestamp) {
+    Pkt4* pkt = new Pkt4(DHCPOFFER, 1234);
+    ASSERT_NO_THROW(pkt->updateTimestamp());
+    timespec ts_packet = pkt->getTimestamp();
+    timespec ts_now;
+    ASSERT_FALSE(clock_gettime(CLOCK_REALTIME, &ts_now) < 0);
+    EXPECT_TRUE(ts_packet.tv_sec >= ts_now.tv_sec);
+
+    delete pkt;
+}
+
+
 } // end of anonymous namespace

+ 9 - 0
src/lib/dhcp/tests/pkt6_unittest.cc

@@ -204,4 +204,13 @@ TEST_F(Pkt6Test, addGetDelOptions) {
     delete parent;
 }
 
+TEST_F(Pkt6Test, Timestamp) {
+    Pkt6* pkt = new Pkt6(DHCPV6_SOLICIT, 0x020304);
+    ASSERT_NO_THROW(pkt->updateTimestamp());
+    timespec ts_packet = pkt->getTimestamp();
+    timespec ts_now;
+    ASSERT_FALSE(clock_gettime(CLOCK_REALTIME, &ts_now) < 0);
+    EXPECT_TRUE(ts_packet.tv_sec >= ts_now.tv_sec);
+}
+
 }