]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
adding support for thread pinning
authorJosh <jrosenba@cisco.com>
Wed, 24 Sep 2014 14:46:26 +0000 (10:46 -0400)
committerJosh <jrosenba@cisco.com>
Wed, 24 Sep 2014 14:46:26 +0000 (10:46 -0400)
lua/snort_defaults.lua
src/helpers/markup.cc
src/main/analyzer.cc
src/main/modules.cc
src/main/snort.h
src/main/snort_config.cc
src/main/snort_config.h
src/main/thread.cc
src/main/thread.h
src/packet_io/trough.cc

index 1a1e83362019cc6c1aa9e5d2a867a125a0c2feba..b5f020e35110e8c1b8ed3313400d76fa5e2feef6 100644 (file)
@@ -285,4 +285,3 @@ default_wizard =
           to_server = telnet_commands, to_client = telnet_commands },
     }
 }
-
index 5cdf04654979470705fdcae17ea1bb2a31c0fc05..be463b365c9632ce6c58b63f88b0581fb097ccf3 100644 (file)
@@ -48,20 +48,20 @@ const string& Markup::emphasis(const string& s)
     return m;
 }
 
-const std::string& Markup::sanitize(const char* const c)
-{ return sanitize(std::string(c)); }
+const string& Markup::sanitize(const char* const c)
+{ return sanitize(string(c)); }
 
-const std::string& Markup::sanitize(const std::string& s)
+const string& Markup::sanitize(const string& s)
 {
     const char* const asciidoc_chars = "~*<>^'";
-    static std::string m;
+    static string m;
     m.clear();
     m += s;
 
     if (enabled)
     {
-        for (std::size_t found = m.find_first_of(asciidoc_chars, 0);
-             found != std::string::npos;
+        for (size_t found = m.find_first_of(asciidoc_chars, 0);
+             found != string::npos;
              found = m.find_first_of(asciidoc_chars, found))
         {
             m.insert(found, "\\");
index fcca76daa06955348862fb578ad32f4862df9aff..2ecc8c8e12c5ba3a74388d26a9bb192dd065cf30 100644 (file)
@@ -53,6 +53,7 @@ void Analyzer::operator()(unsigned id, Swapper* ps)
     set_instance_id(id);
     ps->apply();
 
+    pin_thread_to_cpu(source);
     snort_thread_init(source);
 
     analyze();
index f4d6e1cd8866a783d8d6b733c733aa0a3b5ec51c..180cf65091049630be376f0923299a0259d58a6b 100644 (file)
@@ -55,6 +55,7 @@ using namespace std;
 #include "filters/detection_filter.h"
 #include "filters/sfthreshold.h"
 #include "sfip/sf_ip.h"
+#include "main/thread.h"
 
 #if defined(DEBUG_MSGS) || defined (REG_TEST)
 #include "file_api/file_api.h"
@@ -1152,11 +1153,26 @@ bool IpsModule::set(const char*, Value& v, SnortConfig*)
 // process module
 //-------------------------------------------------------------------------
 
+static const Parameter thread_pinning_params[] =
+{
+    { "cpu", Parameter::PT_INT, "0:127", nullptr,
+        "pin the associated source/thread to this cpu"},
+
+    { "source", Parameter::PT_STRING, nullptr, nullptr,
+        "set cpu affinity for this source (either pcap or <iface>"},
+
+    { "thread", Parameter::PT_INT, "0:", nullptr,
+        "set cpu affinity for the <cur_thread_num> thread that runs"},
+};
+
 static const Parameter process_params[] =
 {
     { "chroot", Parameter::PT_STRING, nullptr, nullptr,
       "set chroot directory (same as -t)" },
 
+    { "threads", Parameter::PT_LIST, thread_pinning_params, nullptr,
+        "thread pinning parameters"},
+
     { "daemon", Parameter::PT_BOOL, nullptr, "false",
       "fork as a daemon (same as -D)" },
 
@@ -1186,6 +1202,13 @@ class ProcessModule : public Module
 public:
     ProcessModule() : Module("process", process_help, process_params) { };
     bool set(const char*, Value&, SnortConfig*);
+    bool begin(const char*, int, SnortConfig*);
+    bool end(const char*, int, SnortConfig*);
+
+private:
+    std::string source;
+    int thread;
+    int cpu;
 };
 
 bool ProcessModule::set(const char*, Value& v, SnortConfig* sc)
@@ -1217,12 +1240,61 @@ bool ProcessModule::set(const char*, Value& v, SnortConfig* sc)
         if ( v.get_bool() )
             ConfigUtc(sc, "");
     }
+
+    else if (v.is("cpu"))
+        cpu = v.get_long();
+
+    else if (v.is("source"))
+        source = v.get_string();
+
+    else if (v.is("thread"))
+        thread = v.get_long();
+
     else
         return false;
 
     return true;
 }
 
+bool ProcessModule::begin(const char*, int, SnortConfig*)
+{
+    source.clear();
+    thread = -1;
+    cpu = -1;
+    return true;
+}
+
+bool ProcessModule::end(const char* fqn, int idx, SnortConfig* sc)
+{
+    if ( !idx )
+        return true;
+
+    if (!strcmp(fqn, "process.threads"))
+    {
+        if (cpu == -1)
+            ParseError("%s - cpu must be an integer in the range"
+                " of 0 < cpu < max_cpus", fqn, cpu);
+
+        else if (cpu >= CPU_SETSIZE)
+            ParseError("cpu must be between 0 and %d", INT8_MAX);
+
+        else if ((source.empty()) && (thread == -1))
+            ParseError("%s - must have either a source or a thread!", fqn);
+
+        else if ((!source.empty()) && (thread >= 0))
+            ParseError("%s - must have either a source or a thread!"
+                " Both thread(%d) and source(%s) are set", fqn, thread, source.c_str());
+
+        else if (!source.empty())
+            set_cpu_affinity(sc, source, cpu);
+
+        else 
+            set_cpu_affinity(sc, thread, cpu);
+    }
+
+    return true;
+}
+
 //-------------------------------------------------------------------------
 // file_id module
 //-------------------------------------------------------------------------
index 5beb2697365b0f58ddee212322454bb05f4f3374..b0d3af184797b654775e7b5b5c1c6b964df4425f 100644 (file)
@@ -87,7 +87,7 @@ void set_main_hook(MainHook_f);
 
 /*  D A T A  S T R U C T U R E S  *********************************************/
 
-typedef enum _RunFlag
+enum RunFlag
 {
     RUN_FLAG__READ                = 0x00000001,     /* -r --pcap-dir, etc. */
     RUN_FLAG__DAEMON              = 0x00000002,     /* -D */
@@ -123,9 +123,9 @@ typedef enum _RunFlag
     RUN_FLAG__SHELL               = 0x40000000,     /* --shell */
     RUN_FLAG__TEST                = 0x80000000      /* -T */
 
-} RunFlag;
+};
 
-typedef enum _OutputFlag
+enum OutputFlag
 {
     OUTPUT_FLAG__LINE_BUFFER       = 0x00000001,      /* -f */
     OUTPUT_FLAG__VERBOSE_DUMP      = 0x00000002,      /* -X */
@@ -145,22 +145,22 @@ typedef enum _OutputFlag
     OUTPUT_FLAG__NO_ALERT          = 0x00001000,      /* -A none */
     OUTPUT_FLAG__NO_LOG            = 0x00002000,      /* -K none */
 
-} OutputFlag;
+};
 
-typedef enum _LoggingFlag
+enum LoggingFlag
 {
     LOGGING_FLAG__VERBOSE         = 0x00000001,      /* -v */
     LOGGING_FLAG__QUIET           = 0x00000002,      /* -q */
     LOGGING_FLAG__SYSLOG          = 0x00000004       /* -M */
 
-} LoggingFlag;
+};
 
-typedef enum {
+enum TunnelFlags{
     TUNNEL_GTP    = 0x01,
     TUNNEL_TEREDO = 0x02,
     TUNNEL_6IN4   = 0x04,
     TUNNEL_4IN6   = 0x08
-} TunnelFlags;
+};
 
 /*  E X T E R N S  ************************************************************/
 SO_PUBLIC extern THREAD_LOCAL SnortConfig* snort_conf;
index 984634eb5252b66631da77300c8e0717fc5d9ff7..af3e89c75e228d6ee9c32e6cdb096675f1a2167c 100644 (file)
@@ -196,6 +196,11 @@ SnortConfig * SnortConfNew(void)
     set_inspection_policy(sc->get_inspection_policy());
     set_ips_policy(sc->get_ips_policy());
     set_network_policy(sc->get_network_policy());
+
+
+    sc->source_affinity = new std::map<const std::string, int>;
+    sc->thread_affinity = new std::vector<int>(32, -1);
+
     return sc;
 }
 
@@ -292,6 +297,13 @@ void SnortConfFree(SnortConfig *sc)
     delete sc->policy_map;
 
     free(sc->state);
+
+    if (sc->source_affinity)
+        delete sc->source_affinity;
+
+    if (sc->thread_affinity)
+        delete sc->thread_affinity;
+
     free(sc);
 }
 
index 333d630504fb6afce2a98d09bbc7961d2049adac..15009c9b0b2b1431a8d67019c7ccd10df569278d 100644 (file)
@@ -25,6 +25,8 @@
 #include "config.h"
 #endif
 
+#include <vector>
+#include <map>
 #include <sys/stat.h>
 #include "detection/rules.h"
 #include "sfip/sfip_t.h"
@@ -284,6 +286,10 @@ struct SnortConfig
     bool unit_test;
 #endif
 
+
+    std::map<const std::string, int>* source_affinity;
+    std::vector<int>* thread_affinity;
+
     InspectionPolicy* get_inspection_policy()
     { return policy_map->inspection_policy[0]; };
 
index 8c5f95bf74d7d342a601af6e2a80e869a96021a7..cb4dc3e818a122b3d7bbc75195fb1ae5bdd40987 100644 (file)
 */
 // thread.cc author Russ Combs <rucombs@cisco.com>
 
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
 #include "thread.h"
 
+#ifdef LINUX
+# include <sched.h>
+#endif
+
 #include <sys/stat.h>
 #include <thread>
-#include "snort.h"
+#include <vector>
+
+#include "main/snort.h"
+#include "parser/parser.h"
+
+
 
 //-------------------------------------------------------------------------
 // FIXIT-L instance_id zero indicates main thread during parse time and the
@@ -33,6 +47,9 @@
 static unsigned instance_max = 1;
 static THREAD_LOCAL unsigned instance_id = 0;
 
+static THREAD_LOCAL cpu_set_t cpu_set;
+
+
 void set_instance_id(unsigned id)
 {
     instance_id = id;
@@ -56,6 +73,92 @@ unsigned get_instance_max()
     return instance_max;
 }
 
+
+
+
+bool set_cpu_affinity(SnortConfig* sc, const std::string& str, int cpu)
+{
+    std::map<const std::string, int>& sa = *(sc->source_affinity);
+
+    auto search = sa.find(str);
+    if(search != sa.end())
+        ParseError("Multiple CPU's set for interface %s", str.c_str());
+
+    sa[std::string(str)] = cpu;
+    return false;
+}
+
+bool set_cpu_affinity(SnortConfig* sc, int thread, int cpu)
+{
+    std::vector<int>& ta = *(sc->thread_affinity);
+
+    if (ta.size() <= (unsigned)thread)
+    {
+        const std::size_t curr_size = ta.size();
+        const std::size_t new_size = curr_size * 2;
+        ta.resize(new_size);
+
+        for (std::size_t i = curr_size; i < new_size; ++i)
+            ta[i] = -1;
+    }
+
+    if (ta[thread] >= 0)
+        ParseError("Multiple CPU's set for thread %d", thread);
+
+    ta[thread] = cpu;
+    return true;
+}
+
+void pin_thread_to_cpu(const char* source)
+{
+    std::vector<int>& ta = *(snort_conf->thread_affinity);
+    std::map<const std::string, int>& sa = *(snort_conf->source_affinity);
+    const std::string src = source;
+    int cpu = -1;
+
+    ta.shrink_to_fit();
+    auto search = sa.find(src);
+
+    if(search != sa.end())
+    {
+        cpu = sa[src];
+    }
+    else if (ta[instance_id] != -1)
+    {
+        cpu = ta[instance_id];
+    }
+
+
+    if (cpu != -1)
+    {
+// PREPROCESSOR MACROS -- these are not actually if statements!
+#       if LINUX
+        {
+            CPU_ZERO(&cpu_set);
+            if (cpu >= CPU_SETSIZE)
+            {
+                FatalError("Maximum CPU value for this Operating System is %d",
+                    CPU_SETSIZE);
+            }
+
+            CPU_SET(cpu, &cpu_set);
+            sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
+
+        }
+#       else
+        {
+            static bool warning_printed = false;
+            if (!warning_printed)
+            {
+                LogWarning("Thread Pinning / CPU affinity support is currently"
+                    " unsupported for this Operating System");
+                warning_printed = true;
+            }
+        }
+#       endif
+    }
+}
+
 //-------------------------------------------------------------------------
 // union rules - breaks are mandatory and must be taken in daq thread
 //-------------------------------------------------------------------------
index caaad620ba40a92097d6af6ee3932bbea842d83c..9b6ab30f20677ed98e2fd29fd4152324cddd2cd5 100644 (file)
 void set_instance_id(unsigned);
 void set_instance_max(unsigned);
 
+
+struct SnortConfig;
+bool set_cpu_affinity(SnortConfig*, const std::string&, int cpu);
+bool set_cpu_affinity(SnortConfig*, int thread, int cpu);
+void pin_thread_to_cpu(const char* source);
+
 SO_PUBLIC unsigned get_instance_id();
 SO_PUBLIC unsigned get_instance_max();
 
index 03e48083fca47a33f0da94edfb716c6f50540066..de0973e5fd337fd0d506ec77b03364f68221d390 100644 (file)
 #include "sfdaq.h"
 #include "utils/util.h"
 
-typedef struct _PcapReadObject
+struct PcapReadObject
 {
     SourceType type;
     char *arg;
     char *filter;
 
-} PcapReadObject;
+};
 
 static SF_LIST *pcap_object_list = NULL;
 static SF_QUEUE *pcap_queue = NULL;