00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef PHY_TIMETRACKER_HXX_
00023 # define PHY_TIMETRACKER_HXX_
00024
00025 # include <boost/optional.hpp>
00026
00027 # include <wipal/tool/gmp_64_wrapper.hh>
00028
00029 # include "timetracker.hh"
00030
00031 namespace wpl
00032 {
00033
00034 namespace phy
00035 {
00036
00037 template <class B>
00038 timetracker<B>::timetracker(bool force_pcap): last_stamp_ (0),
00039 ms_count_ (0),
00040 force_pcap_ (force_pcap)
00041 {
00042 }
00043
00044 template <class B>
00045 template <class UIntType>
00046 void
00047 timetracker<B>::tick_uint(UIntType ts)
00048 {
00049 const UIntType half_range (UIntType (1)
00050 << (sizeof (ts) * 8 - 1));
00051 const tool::microseconds ms_ts (ts);
00052 const tool::microseconds ms_last_stamp (last_stamp_);
00053
00054 ms_count_ += ms_ts - ms_last_stamp;
00055 if (ts < last_stamp_ and last_stamp_ - ts > half_range)
00056 {
00057 static boost::optional<tool::microseconds> range;
00058
00059 if (not range)
00060 {
00061 range = 1;
00062 *range <<= sizeof (ts) * 8;
00063 }
00064
00065 ms_count_ += *range;
00066 }
00067 last_stamp_ = ts;
00068 }
00069
00070 template <class B>
00071 void
00072 timetracker<B>::tick_tv(const struct timeval& tv)
00073 {
00074 ms_count_ = tool::microseconds (tv);
00075 }
00076
00077 namespace internals
00078 {
00079
00080 template <class I, class B>
00081 struct tick_switch
00082 {
00083 template <class S>
00084 static void tick(timetracker<B>& trk,
00085 const pkt::packet<S>& p,
00086 const I& )
00087 {
00088 trk.tick_tv(p.meta().ts);
00089 }
00090 };
00091
00092 template <class B>
00093 struct tick_switch<uint32_t, B>
00094 {
00095 template <class S>
00096 static void tick(timetracker<B>& trk,
00097 const pkt::packet<S>& ,
00098 uint32_t ts)
00099 {
00100 trk.tick_uint(ts);
00101 }
00102 };
00103
00104 template <class B>
00105 struct tick_switch<uint64_t, B>
00106 {
00107 template <class S>
00108 static void tick(timetracker<B>& trk,
00109 const pkt::packet<S>& ,
00110 uint64_t ts)
00111 {
00112 trk.tick_uint(ts);
00113 }
00114 };
00115
00116 template <class B>
00117 struct tick_switch<struct timeval, B>
00118 {
00119 template <class S>
00120 static void tick(timetracker<B>& trk,
00121 const pkt::packet<S>& ,
00122 const struct timeval& tv)
00123 {
00124 trk.tick_tv(tv);
00125 }
00126 };
00127
00128 }
00129
00130 template <class B>
00131 template <class HT, class S>
00132 void
00133 timetracker<B>::tick(const pkt::packet<S>& frame,
00134 tool::end::endianness phy_end)
00135 {
00136 const pkt::metadata& m = frame.meta();
00137
00138 if (force_pcap_)
00139 {
00140 tick_tv(m.ts);
00141 return;
00142 }
00143
00144 const bool swap = tool::need_swap(phy_end, frame.swapped());
00145 const HT* const bytes = static_cast<const HT*> (frame.bytes());
00146
00147 if (m.caplen < bytes->len(m.caplen, swap))
00148 return;
00149
00150 internals::tick_switch<typename HT::time_type::impl_type, B>::
00151 tick(*this, frame, bytes->time_get(swap).get());
00152 }
00153
00154 template <class B>
00155 tool::microseconds
00156 timetracker<B>::microseconds() const
00157 {
00158 return ms_count_;
00159 }
00160
00161 }
00162
00163 }
00164
00165 #endif // ! PHY_TIMETRACKER_HXX_