]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #620 in SNORT/snort3 from tsc_clock to master
authorMichael Altizer (mialtize) <mialtize@cisco.com>
Tue, 13 Sep 2016 21:06:30 +0000 (17:06 -0400)
committerMichael Altizer (mialtize) <mialtize@cisco.com>
Tue, 13 Sep 2016 21:06:30 +0000 (17:06 -0400)
Squashed commit of the following:

commit e2bd893a5333968fe1899d2e67b19b98e2a65668
Author: Russ Combs <rucombs@cisco.com>
Date:   Tue Sep 13 16:00:05 2016 -0400

    add cmake support for --enable-tsc-clock

commit 170d01c6bbf086b2ea08dc26c96619a18a5eaf4b
Author: Russ Combs <rucombs@cisco.com>
Date:   Mon Sep 12 22:40:10 2016 -0400

    add --enable-tsc-clock to build/use TSC register
    tweak link order so time methods are found
    clean up some fp_detect cruft
    update latency to use ticks during runtime
    fix stream profile stats parents
    remove unused cpuclock.h

32 files changed:
cmake/configure_options.cmake
cmake/create_options.cmake
config.cmake.h.in
configure.ac
configure_cmake.sh
src/CMakeLists.txt
src/Makefile.am
src/detection/detect.cc
src/detection/fp_detect.cc
src/detection/fp_detect.h
src/latency/latency_module.cc
src/latency/packet_latency.cc
src/latency/rule_latency.cc
src/profiler/memory_profiler.cc
src/profiler/profiler_stats_table.cc
src/profiler/rule_profiler_defs.h
src/profiler/time_profiler.cc
src/profiler/time_profiler_defs.h
src/stream/icmp/icmp_module.cc
src/stream/icmp/icmp_module.h
src/stream/ip/ip_module.cc
src/stream/stream_api.cc
src/stream/tcp/tcp_module.cc
src/stream/udp/udp_module.cc
src/stream/udp/udp_module.h
src/time/CMakeLists.txt
src/time/Makefile.am
src/time/clock_defs.h
src/time/cpuclock.h [deleted file]
src/time/stopwatch_test.cc
src/time/tsc_clock.cc [new file with mode: 0644]
src/time/tsc_clock.h [new file with mode: 0644]

index b4ec0b5c5890d1b960332749fbd2d979da23822c..d116576384c3e650cb266837ae471fa2fb3aa198 100644 (file)
@@ -12,6 +12,7 @@ if ( NOT ENABLE_COREFILES )
 endif ( NOT ENABLE_COREFILES )
 
 set ( _LARGEFILE_SOURCE ${ENABLE_LARGE_PCAP} )
+set ( USE_TSC_CLOCK ${ENABLE_TSC_CLOCK} )
 
 if ( ENABLE_LARGE_PCAP )
     set ( _FILE_OFFSET_BITS 64 )
index 24b4d6b1879f91ec927500c64a65628be6074861..a7438f46211b34f4a0298f88d1195f80ec349974 100644 (file)
@@ -22,6 +22,7 @@ option ( ENABLE_PIGLET "enable piglet test harness" OFF )
 option ( ENABLE_COREFILES "Prevent Snort from generating core files" ON )
 option ( ENABLE_INTEL_SOFT_CPM "Enable Intel Soft CPM support" OFF )
 option ( ENABLE_LARGE_PCAP "Enable support for pcaps larger than 2 GB" OFF )
+option ( ENABLE_TSC_CLOCK "Use timestamp counter register clock (x86 only)" OFF )
 
 # documentation
 option ( MAKE_HTML_DOC "Create the HTML documentation" ON )
index 6d912c481222c1a91ae8097752b73427ded19ff0..9649829e8e6e7de76eca713b5cdd8d5d90bf66db 100644 (file)
 #cmakedefine _LARGEFILE_SOURCE 1
 #cmakedefine _FILE_OFFSET_BITS @_FILE_OFFSET_BITS@
 
+/* enable ha capable build */
+#cmakedefine USE_TSC_CLOCK 1
 
 
 /* platforms */
index 53eaef708138e6b17f0a028f1c44f111f179c330..c50576c7714a26fa5cc28b7ae0eca284dfedacf9 100644 (file)
@@ -377,6 +377,14 @@ if test "x$enable_shell" = "xyes"; then
     AC_DEFINE(SHELL, [1], [enable shell support])
 fi
 
+AC_ARG_ENABLE(tsc-clock,
+    AS_HELP_STRING([--enable-tsc-clock],[use timestamp counter register clock (x86 only)]),
+    enable_tsc_clock="$enableval", enable_tsc_clock="no")
+
+if test "x$enable_tsc_clock" = "xyes"; then
+    AC_DEFINE(USE_TSC_CLOCK, [1], [enable tsc clock])
+fi
+
 AC_ARG_ENABLE(large-pcap,
     AS_HELP_STRING([--enable-large-pcap],[enable support for pcaps larger than 2 GB]),
     enable_large_pcap="$enableval", enable_large_pcap="no")
index fabb5f307c949214cf87758645f07ff33608a0fa..bf47415bd40704c03631e6c43f2b2b918604c81d 100755 (executable)
@@ -40,6 +40,7 @@ Optional Features:
     --disable-static-codecs do not include codecs in binary
     --enable-shell          enable command line shell support
     --enable-large-pcap     enable support for pcaps larger than 2 GB
+    --enable-tsc-clock      use timestamp counter register clock (x86 only)
     --enable-debug-msgs     enable debug printing options (bugreports and
                             developers only)
     --enable-debug          enable debugging options (bugreports and developers
@@ -217,6 +218,9 @@ while [ $# -ne 0 ]; do
         --enable-large-pcap)
             append_cache_entry ENABLE_LARGE_PCAP        BOOL true
             ;;
+        --enable-tsc-clock)
+            append_cache_entry ENABLE_TSC_CLOCK         BOOL true
+            ;;
         --disable-large-pcap)
             append_cache_entry ENABLE_LARGE_PCAP        BOOL false
             ;;
index 769c5fe985ed39e9645560c2a9c780779ca247ef..fc78cf39e531f231976edc9a6af468744c877776 100644 (file)
@@ -133,9 +133,9 @@ target_link_libraries( snort
     detection
     framework
     file_api
-    time
     latency
     profiler
+    time
     ips_actions
     events
     hash
index a9227f301b9e978c84205fa9c7d75c1d0cfebeff..a2e3ca2af5aa9cdef5228e2e1de420ac01180292 100644 (file)
@@ -90,9 +90,9 @@ filters/libfilter.a \
 detection/libdetection.a \
 framework/libframework.a \
 file_api/libfile_api.a \
-time/libtime.a \
 latency/liblatency.a \
 profiler/libprofiler.a \
+time/libtime.a \
 actions/libips_actions.a \
 events/libevents.a \
 hash/libhash.a \
index 1ba081b0999ff2069f26a4d86cee179b0ad7b9cd..4aec779b3b459ffb9aa70991c1eafccc55906202 100644 (file)
@@ -71,7 +71,6 @@ void snort_inspect(Packet* p)
 {
     {
         PacketLatency::Context pkt_latency_ctx { p };
-
         bool inspected = false;
 
         // If the packet has errors, we won't analyze it.
index 8f66153a957e1f36112c4ed7d8383d82f13e6d62..edaf00780532c02c246f59aba2e85ec426e37ea0 100644 (file)
@@ -88,7 +88,7 @@ THREAD_LOCAL ProfileStats ruleNFPEvalPerfStats;
 
 THREAD_LOCAL uint64_t rule_eval_pkt_count = 0;
 
-THREAD_LOCAL OTNX_MATCH_DATA t_omd;
+static THREAD_LOCAL OTNX_MATCH_DATA t_omd;
 
 /* initialize the global OTNX_MATCH_DATA variable */
 void otnx_match_data_init(int num_rule_types)
@@ -111,14 +111,10 @@ void otnx_match_data_term()
 
 static inline void InitMatchInfo(OTNX_MATCH_DATA* o)
 {
-    int i = 0;
+    for ( int i = 0; i < o->iMatchInfoArraySize; i++ )
+        o->matchInfo[i].iMatchCount = 0;
 
-    for (i = 0; i < o->iMatchInfoArraySize; i++)
-    {
-        o->matchInfo[i].iMatchCount  = 0;
-        o->matchInfo[i].iMatchIndex  = 0;
-        o->matchInfo[i].iMatchMaxLen = 0;
-    }
+    o->have_match = false;
 }
 
 // called by fpLogEvent(), which does the filtering etc.
@@ -270,14 +266,10 @@ int fpLogEvent(const RuleTreeNode* rtn, const OptTreeNode* otn, Packet* p)
 **    int - 1 max_events variable hit, 0 successful.
 **
 */
-int fpAddMatch(OTNX_MATCH_DATA* omd_local, int pLen, const OptTreeNode* otn)
+int fpAddMatch(OTNX_MATCH_DATA* omd_local, int /*pLen*/, const OptTreeNode* otn)
 {
-    MATCH_INFO* pmi;
-    int evalIndex;
-    int i;
     RuleTreeNode* rtn = getRuntimeRtnFromOtn(otn);
-
-    evalIndex = rtn->listhead->ruleListNode->evalIndex;
+    int evalIndex = rtn->listhead->ruleListNode->evalIndex;
 
     /* bounds check index */
     if ( evalIndex >= omd_local->iMatchInfoArraySize )
@@ -285,7 +277,7 @@ int fpAddMatch(OTNX_MATCH_DATA* omd_local, int pLen, const OptTreeNode* otn)
         pc.match_limit++;
         return 1;
     }
-    pmi = &omd_local->matchInfo[evalIndex];
+    MATCH_INFO* pmi = &omd_local->matchInfo[evalIndex];
 
     /*
     **  If we hit the max number of unique events for any rule type alert,
@@ -298,43 +290,18 @@ int fpAddMatch(OTNX_MATCH_DATA* omd_local, int pLen, const OptTreeNode* otn)
         return 1;
     }
 
-    /* Check that we are not storing the same otn again */
-    for ( i=0; i< pmi->iMatchCount; i++ )
+    // don't store the same otn again
+    for ( int i=0; i< pmi->iMatchCount; i++ )
     {
         if ( pmi->MatchArray[ i  ] == otn )
-        {
-            //LogMessage("fpAddMatch: storing the same otn...\n");
             return 0;
-        }
     }
 
-    /*
-    **  Add the event to the appropriate list
-    */
+    //  add the event to the appropriate list
     pmi->MatchArray[ pmi->iMatchCount ] = otn;
 
-    /*
-    **  This means that we are adding a NC rule
-    **  and we only set the index to this rule
-    **  if there is no content rules in the
-    **  same array.
-    */
-    if (pLen > 0)
-    {
-        /*
-        **  Event Comparison Function
-        **  Here the largest content match is the
-        **  priority
-        */
-        if ( pmi->iMatchMaxLen < pLen )
-        {
-            pmi->iMatchMaxLen = pLen;
-            pmi->iMatchIndex  = pmi->iMatchCount;
-        }
-    }
-
     pmi->iMatchCount++;
-
+    omd_local->have_match = true;
     return 0;
 }
 
@@ -702,6 +669,9 @@ static inline int fpSessionAlerted(Packet* p, const OptTreeNode* otn)
 */
 static inline int fpFinalSelectEvent(OTNX_MATCH_DATA* o, Packet* p)
 {
+    if ( !o->have_match )
+        return 0;
+
     int i;
     int j;
     int k;
index 6efd95614804c5d65a8502a709942dcc5228bf6e..da9236f830f3b8822cb655b0975fec3900ca25df 100644 (file)
@@ -96,6 +96,7 @@ struct OTNX_MATCH_DATA
     unsigned size;
 
     int check_ports;
+    bool have_match;
 
     MATCH_INFO* matchInfo;
     int iMatchInfoArraySize;
index 3b7092fd89bbae5ddc32c0501fd6bf2d5c26cdd6..c38c30ff3a4a4a13aa7e219d49ccbd1fcda8eb8a 100644 (file)
@@ -113,8 +113,10 @@ static inline bool latency_set(Value& v, PacketLatencyConfig& config)
     using std::chrono::microseconds;
 
     if ( v.is("max_time") )
-        config.max_time =
-            duration_cast<decltype(config.max_time)>(microseconds(v.get_long()));
+    {
+        long t = clock_ticks(v.get_long());
+        config.max_time = duration_cast<decltype(config.max_time)>(microseconds(t));
+    }
 
     else if ( v.is("fastpath") )
         config.fastpath = v.get_bool();
@@ -136,9 +138,10 @@ static inline bool latency_set(Value& v, RuleLatencyConfig& config)
     using std::chrono::milliseconds;
 
     if ( v.is("max_time") )
-        config.max_time =
-            duration_cast<decltype(config.max_time)>(microseconds(v.get_long()));
-
+    {
+        long t = clock_ticks(v.get_long());
+        config.max_time = duration_cast<decltype(config.max_time)>(microseconds(t));
+    }
     else if ( v.is("suspend") )
         config.suspend = v.get_bool();
 
@@ -146,9 +149,10 @@ static inline bool latency_set(Value& v, RuleLatencyConfig& config)
         config.suspend_threshold = v.get_long();
 
     else if ( v.is("max_suspend_time") )
-        config.max_suspend_time =
-            duration_cast<decltype(config.max_time)>(milliseconds(v.get_long()));
-
+    {
+        long t = clock_ticks(v.get_long());
+        config.max_suspend_time = duration_cast<decltype(config.max_time)>(milliseconds(t));
+    }
     else if ( v.is("action") )
         config.action =
             static_cast<decltype(config.action)>(v.get_long());
index 2e7f4087ea0e0dcf4d99124ea5659aa91cb4819a..e770dca85e501325b6d6a2e313968b38a4ec9d8f 100644 (file)
@@ -29,6 +29,7 @@
 #include "protocols/packet.h"
 #include "sfip/sf_ip.h"
 #include "time/clock_defs.h"
+
 #include "latency_config.h"
 #include "latency_timer.h"
 #include "latency_util.h"
@@ -49,13 +50,11 @@ namespace packet_latency
 // helpers
 // -----------------------------------------------------------------------------
 
-using DefaultClock = hr_clock;
-
 struct Event
 {
     const Packet* packet;
     bool fastpathed;
-    typename DefaultClock::duration elapsed;
+    typename SnortClock::duration elapsed;
 };
 
 template<typename Clock>
@@ -91,7 +90,7 @@ static inline std::ostream& operator<<(std::ostream& os, const Event& e)
 
     os << ": ";
 
-    os << duration_cast<microseconds>(e.elapsed).count() << " usec, [";
+    os << clock_usecs(duration_cast<microseconds>(e.elapsed).count()) << " usec, [";
     os << e.packet->ptrs.ip_api.get_src() << " -> " <<
         e.packet->ptrs.ip_api.get_dst() << "]";
 
@@ -102,7 +101,7 @@ static inline std::ostream& operator<<(std::ostream& os, const Event& e)
 // implementation
 // -----------------------------------------------------------------------------
 
-template<typename Clock = DefaultClock>
+template<typename Clock = SnortClock>
 class Impl
 {
 public:
@@ -152,7 +151,7 @@ inline bool Impl<Clock>::pop(const Packet* p)
         if ( config->action & PacketLatencyConfig::LOG )
             log_handler.handle(e);
 
-        if ( timer.marked_as_fastpathed and (config->action & PacketLatencyConfig::ALERT) )
+        if ( config->action & PacketLatencyConfig::ALERT )
             event_handler.handle(e);
     }
 
index 3cdc883c62dc9565c6ab820774fe4b7f38c0144c..a9a1aab4d8b8adb9ddabb8b6b23879397b4fabdd 100644 (file)
@@ -32,6 +32,7 @@
 #include "events/event_queue.h"
 #include "log/messages.h"
 #include "main/snort_config.h"
+
 #include "latency_config.h"
 #include "latency_rules.h"
 #include "latency_stats.h"
@@ -49,8 +50,6 @@ namespace rule_latency
 // helpers
 // -----------------------------------------------------------------------------
 
-using DefaultClock = hr_clock;
-
 struct Event
 {
     enum Type
@@ -61,7 +60,7 @@ struct Event
     };
 
     Type type;
-    typename DefaultClock::duration elapsed;
+    typename SnortClock::duration elapsed;
     detection_option_tree_root_t* root;
 };
 
@@ -96,7 +95,7 @@ static inline std::ostream& operator<<(std::ostream& os, const Event& e)
 
         os << ": ";
 
-        os << duration_cast<microseconds>(e.elapsed).count() << " usec, ";
+        os << clock_usecs(duration_cast<microseconds>(e.elapsed).count()) << " usec, ";
     }
 
     // FIXIT-L clean up rule latency logging; delete or make useful
@@ -175,7 +174,7 @@ struct DefaultRuleInterface
 // implementation
 // -----------------------------------------------------------------------------
 
-template<typename Clock = DefaultClock, typename RuleTree = DefaultRuleInterface>
+template<typename Clock = SnortClock, typename RuleTree = DefaultRuleInterface>
 class Impl
 {
 public:
index 82e950171b3797c5c1a8c07a569e3c8f611fc475..a8059d7c99e706c6550cb5c18af5109eeb571bdf 100644 (file)
@@ -40,7 +40,7 @@
 // show statistics
 // -----------------------------------------------------------------------------
 
-#define s_memory_table_title "Memory Profile Statistics"
+#define s_memory_table_title "memory profile"
 
 namespace memory_stats
 {
index e8020e4893a7afc24fb22e41be1086bca371e620..f1dff874f960f100113c794513ba5baf386b8e01 100644 (file)
@@ -32,7 +32,7 @@
 #include "catch/catch.hpp"
 #endif
 
-static constexpr unsigned WIDTH = 40;
+static constexpr unsigned WIDTH = 50;
 static constexpr char ENDL = '\n';
 
 const StatsTable::Header StatsTable::HEADER { '=' };
index d2aa9b469b718834a99a14eb1a56cd82b708d2d9..515dca8334ebda70461ca2bfdc86ad504410244d 100644 (file)
@@ -67,7 +67,7 @@ public:
 
 private:
     dot_node_state_t& stats;
-    Stopwatch<hr_clock> sw;
+    Stopwatch<SnortClock> sw;
     bool finished = false;
 };
 
index 77a5ff7bc8e4681636e3b3a9593f750b24eb00aa..fdcd693dbd58573482404485746f2b47f8aaa503 100644 (file)
@@ -38,7 +38,7 @@
 #include "catch/catch.hpp"
 #endif
 
-#define s_time_table_title "Module Profile Statistics"
+#define s_time_table_title "module profile"
 
 namespace time_stats
 {
@@ -131,7 +131,7 @@ static void print_fn(StatsTable& t, const View& v)
     t << v.checks();
 
     // total time
-    t << duration_cast<microseconds>(v.elapsed()).count();
+    t << clock_usecs(duration_cast<microseconds>(v.elapsed()).count());
 
     // avg/check
     t << duration_cast<microseconds>(v.avg_check()).count();
index 372a3d60709e748cd65125197c3fb5e0dbab4915..eaeaff7b2b5853e1398f3a9a20e2399f4096639a 100644 (file)
@@ -113,7 +113,7 @@ public:
 
 private:
     TimeProfilerStats& stats;
-    Stopwatch<hr_clock> sw;
+    Stopwatch<SnortClock> sw;
     bool stopped_once = false;
 };
 
index 33cbaefe0f9f72a7d06ffe7e4e15940e9a0a1c75..9d9205e0b5df8479f2bdb4639455606c30d3f045 100644 (file)
@@ -43,8 +43,16 @@ StreamIcmpModule::StreamIcmpModule() :
     config = nullptr;
 }
 
-ProfileStats* StreamIcmpModule::get_profile() const
-{ return &icmp_perf_stats; }
+ProfileStats* StreamIcmpModule::get_profile(
+    unsigned index, const char*& name, const char*& parent) const
+{
+    if ( index )
+        return nullptr;
+
+    name = MOD_NAME;
+    parent = "stream";
+    return &icmp_perf_stats;
+}
 
 StreamIcmpConfig* StreamIcmpModule::get_data()
 {
index 447bdf51f7ecbc8a28f388bb2508859d15bc2e5e..712d2f5369a00c42238acaf82de60e42eca7d9e2 100644 (file)
@@ -54,7 +54,7 @@ public:
     bool begin(const char*, int, SnortConfig*) override;
     bool end(const char*, int, SnortConfig*) override;
 
-    ProfileStats* get_profile() const override;
+    ProfileStats* get_profile(unsigned, const char*&, const char*&) const override;
     const PegInfo* get_pegs() const override;
     PegCount* get_counts() const override;
 
index 13dbb4dd2cb5c79b079046ba1db7ddfd5bb57fcf..352d63abd5b86af77796b3d98a68fc9ffede0a1e 100644 (file)
@@ -140,7 +140,7 @@ ProfileStats* StreamIpModule::get_profile(
     {
     case 0:
         name = "stream_ip";
-        parent = nullptr;
+        parent = "stream";
         return &ip_perf_stats;
 
     case 1:
index e50dc80d00b38c55f80d611aee883903b36f0266..e735bfb436934ed5143e7f0588ba5e1106b368c5 100644 (file)
@@ -160,7 +160,7 @@ void Stream::check_session_closed(Packet* p)
 {
     Flow* flow = p->flow;
 
-    if (!p || !flow)
+    if ( !flow )
         return;
 
     if (flow->session_state & STREAM_STATE_CLOSED)
index 39250f92a4dc175d36038f1d3c924f026ac3a9ea..c8beec63b333b8236e518ca61c4cde7def60b9f6 100644 (file)
@@ -228,8 +228,8 @@ ProfileStats* StreamTcpModule::get_profile(
     switch ( index )
     {
     case 0:
-        name = "stream_tcp";
-        parent = nullptr;
+        name = MOD_NAME;
+        parent = "stream";
         return &s5TcpPerfStats;
 
     case 1:
index 952817e7a116b51f0ae0dfae62a11041fa653072..f8062ad71cc8f4df6dd397ad3f68fe9ab7ed30a6 100644 (file)
@@ -46,8 +46,14 @@ StreamUdpModule::StreamUdpModule() :
     config = nullptr;
 }
 
-ProfileStats* StreamUdpModule::get_profile() const
+ProfileStats* StreamUdpModule::get_profile(
+    unsigned index, const char*& name, const char*& parent) const
 {
+    if ( index )
+        return nullptr;
+
+    name = MOD_NAME;
+    parent = "stream";
     return &udp_perf_stats;
 }
 
index 8f4c96566a596f7afebe773047649696c7b45072..31847c0f889c0dbd09b7434f23903c9c9467c089 100644 (file)
@@ -57,7 +57,7 @@ public:
     bool begin(const char*, int, SnortConfig*) override;
     bool end(const char*, int, SnortConfig*) override;
 
-    ProfileStats* get_profile() const override;
+    ProfileStats* get_profile(unsigned, const char*&, const char*&) const override;
     const PegInfo* get_pegs() const override;
     PegCount* get_counts() const override;
     StreamUdpConfig* get_data();
index ec5dd24a5a5e74cab702aaa5eb3d177ecf2cda0c..db8e2e06e73cc964d02d9d354ab999e25be94c93 100644 (file)
@@ -4,6 +4,7 @@ set ( TIME_INTERNAL_SOURCES
     periodic.cc
     periodic.h
     timersub.h
+    tsc_clock.cc
     )
 
 if ( ENABLE_UNIT_TESTS )
@@ -11,9 +12,9 @@ if ( ENABLE_UNIT_TESTS )
 endif ( ENABLE_UNIT_TESTS )
 
 set ( TIME_INCLUDES
-    cpuclock.h
     clock_defs.h
     stopwatch.h
+    tsc_clock.h
     )
 
 add_library ( time STATIC
index b2f89a36451e6bd2eca467feb04c9735b8a7c8f8..b32475d0761df10e871e644422325cdeb587422d 100644 (file)
@@ -3,18 +3,19 @@ noinst_LIBRARIES = libtime.a
 x_includedir = $(pkgincludedir)/time
 
 x_include_HEADERS = \
-cpuclock.h \
 clock_defs.h \
-stopwatch.h
+stopwatch.h \
+tsc_clock.h
 
 libtime_a_SOURCES = \
+clock_defs.h \
 packet_time.cc \
 packet_time.h \
 periodic.cc \
 periodic.h \
-timersub.h \
-clock_defs.h \
-stopwatch.h
+stopwatch.h \
+timersub.h  \
+tsc_clock.cc
 
 if ENABLE_UNIT_TESTS
 libtime_a_SOURCES += stopwatch_test.cc
index f0f17f5f8eea78663f4024f38d891d0f0f09de8b..23b1e60de33e1d8ac0d3c6794833851055c4c41f 100644 (file)
 #ifndef CLOCK_DEFS_H
 #define CLOCK_DEFS_H
 
-#include <chrono>
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef USE_TSC_CLOCK
+#include "time/tsc_clock.h"
+using SnortClock = TscClock;
 
+#else
+#include <chrono>
 using hr_clock = std::chrono::high_resolution_clock;
-using hr_duration = hr_clock::duration;
-using hr_time = hr_clock::time_point;
+using SnortClock = hr_clock;
+inline long clock_scale() { return 1.0; }
+#endif
+
+using hr_duration = SnortClock::duration;
+using hr_time = SnortClock::time_point;
 
 inline constexpr hr_duration operator "" _ticks (unsigned long long int v)
 { return hr_duration(v); }
@@ -39,4 +51,11 @@ struct ClockTraits
     using time_point = TimePoint;
     using rep = Rep;
 };
+
+inline long clock_usecs(long ticks)
+{ return ticks / clock_scale(); }
+
+inline long clock_ticks(long usecs)
+{ return usecs * clock_scale(); }
+
 #endif
diff --git a/src/time/cpuclock.h b/src/time/cpuclock.h
deleted file mode 100644 (file)
index 91e3609..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2014-2016 Cisco and/or its affiliates. All rights reserved.
-// Copyright (C) 2006-2013 Sourcefire, Inc.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-#ifndef CPUCLOCK_H
-#define CPUCLOCK_H
-
-// Assembly to find clock ticks
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <unistd.h>
-
-// INTEL LINUX/BSD/..
-#if (defined(__i386) || defined(__amd64) || defined(__x86_64__))
-#define get_clockticks(val) \
-{ \
-    uint32_t a, d; \
-    __asm__ __volatile__ ("rdtsc" : "=a" (a), "=d" (d));  \
-    val = ((uint64_t)a) | (((uint64_t)d) << 32);  \
-}
-#else
-#if (defined(__ia64) && defined(__GNUC__) )
-#define get_clockticks(val) \
-{ \
-    __asm__ __volatile__ ("mov %0=ar.itc" : "=r" (val)); \
-}
-#else
-#if (defined(__ia64) && defined(__hpux))
-#include <machine/sys/inline.h>
-#define get_clockticks(val) \
-{ \
-    val = _Asm_mov_from_ar (_AREG_ITC); \
-}
-#else
-// POWER PC
-#if (defined(__GNUC__) && (defined(__powerpc__) || (defined(__ppc__))))
-#define get_clockticks(val) \
-{ \
-    uint32_t tbu0, tbu1, tbl; \
-    do \
-    { \
-        __asm__ __volatile__ ("mftbu %0" : "=r" (tbu0)); \
-        __asm__ __volatile__ ("mftb  %0" : "=r" (tbl)); \
-        __asm__ __volatile__ ("mftbu %0" : "=r" (tbu1)); \
-    } while (tbu0 != tbu1); \
-    val = ((uint64_t)tbl) | (((uint64_t)tbu0) << 32);  \
-}
-#else
-// SPARC
-#ifdef SPARCV9
-#ifdef _LP64
-#define get_clockticks(val) \
-{ \
-    __asm__ __volatile__ ("rd %%tick, %0" : "=r" (val)); \
-}
-#else
-#define get_clockticks(val) \
-{ \
-    uint32_t a, b; \
-    __asm__ __volatile__ ("rd %%tick, %0\n" \
-        "srlx %0, 32, %1" \
-        : "=r" (a), "=r" (b)); \
-    val = ((uint64_t)a) | (((uint64_t)b) << 32); \
-}
-#endif // _LP64
-#else
-#define get_clockticks(val)
-#endif // SPARCV9
-#endif // __GNUC__ && __powerpc__ || __ppc__
-#endif // __ia64 && __hpux
-#endif // __ia64 && __GNUC__
-#endif // __i386 || __amd64 || __x86_64__
-
-inline double get_ticks_per_usec()
-{
-    uint64_t start = 0, end = 0;
-    get_clockticks(start);
-
-    sleep(1);
-    get_clockticks(end);
-
-    return (double)(end-start)/1e6;
-}
-
-#endif
-
index b986ec0fa1fe3f486c2326511ec4874bde5e975c..cad2c27e6bf9b61181bef958ce44bb5b22e055b2 100644 (file)
@@ -25,7 +25,7 @@
 namespace t_stopwatch
 {
 
-struct Clock : public ClockTraits<hr_clock>
+struct Clock : public ClockTraits<SnortClock>
 {
     static time_point now()
     { return time; }
diff --git a/src/time/tsc_clock.cc b/src/time/tsc_clock.cc
new file mode 100644 (file)
index 0000000..9fcad20
--- /dev/null
@@ -0,0 +1,37 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2016-2016 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+// tsc_clock.cc author Russ Combs <rucombs@cisco.com>
+
+#include "tsc_clock.h"
+#include <time.h>
+
+long clock_scale()
+{
+    static long tpus = 0;  // ticks / usec
+
+    if ( !tpus )
+    {
+        struct timespec one_sec = { 1, 0 };
+        uint64_t start = TscClock::counter();
+        nanosleep(&one_sec, nullptr);
+        uint64_t end = TscClock::counter();
+        tpus = (long)((end - start)/1e6);
+    }
+    return tpus;
+}
+
diff --git a/src/time/tsc_clock.h b/src/time/tsc_clock.h
new file mode 100644 (file)
index 0000000..848649f
--- /dev/null
@@ -0,0 +1,65 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2016-2016 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+// tsc_clock.h author Russ Combs <rucombs@cisco.com>
+
+#ifndef TSC_CLOCK_H
+#define TSC_CLOCK_H
+
+// the STL chrono clocks are kinda heavy so we use the time stamp counter
+// where available (x86 with rdtsc support).  this wasn't always a good
+// choice on multi-core systems but most now have rdtscp, constant_tsc,
+// tsc_reliable, and nonstop_tsc.  note that we don't worry about exact
+// instruction sequencing.
+//
+// references:
+// http://stackoverflow.com/questions/275004/timer-function-to-provide-time-in-nano-seconds-using-c
+// http://stackoverflow.com/questions/7935518/is-clock-gettime-adequate-for-submicrosecond-timing
+//
+// this clock stores ticks, not actual time values.  use ticks during runtime
+// convert from/to usecs at startup/shutdown.  see clock_defs.h.
+
+#include <chrono>
+
+struct TscClock
+{
+    // this has to be const so we use a nice round number and scale it later
+    typedef std::ratio<1, 1000000> period;
+
+    typedef uint64_t rep;
+    typedef std::chrono::duration<rep, period> duration;
+    typedef std::chrono::time_point<TscClock> time_point;
+
+    static const bool is_steady = true;
+
+    static uint64_t counter()
+    {
+        uint32_t lo, hi;
+        asm volatile("rdtsc" : "=a" (lo), "=d" (hi));
+        return ((uint64_t)hi << 32) | lo;
+    }
+
+    static time_point now() noexcept
+    {
+        return time_point(duration(counter()));
+    }
+};
+
+long clock_scale();
+
+#endif
+