From: Josh Date: Wed, 24 Sep 2014 14:46:26 +0000 (-0400) Subject: adding support for thread pinning X-Git-Tag: 3.0.0-233~1404^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ec056708c3efeca8ff5aa8830cd59efa13eb8901;p=thirdparty%2Fsnort3.git adding support for thread pinning --- diff --git a/lua/snort_defaults.lua b/lua/snort_defaults.lua index 1a1e83362..b5f020e35 100644 --- a/lua/snort_defaults.lua +++ b/lua/snort_defaults.lua @@ -285,4 +285,3 @@ default_wizard = to_server = telnet_commands, to_client = telnet_commands }, } } - diff --git a/src/helpers/markup.cc b/src/helpers/markup.cc index 5cdf04654..be463b365 100644 --- a/src/helpers/markup.cc +++ b/src/helpers/markup.cc @@ -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, "\\"); diff --git a/src/main/analyzer.cc b/src/main/analyzer.cc index fcca76daa..2ecc8c8e1 100644 --- a/src/main/analyzer.cc +++ b/src/main/analyzer.cc @@ -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(); diff --git a/src/main/modules.cc b/src/main/modules.cc index f4d6e1cd8..180cf6509 100644 --- a/src/main/modules.cc +++ b/src/main/modules.cc @@ -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 "}, + + { "thread", Parameter::PT_INT, "0:", nullptr, + "set cpu affinity for the 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 //------------------------------------------------------------------------- diff --git a/src/main/snort.h b/src/main/snort.h index 5beb26973..b0d3af184 100644 --- a/src/main/snort.h +++ b/src/main/snort.h @@ -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; diff --git a/src/main/snort_config.cc b/src/main/snort_config.cc index 984634eb5..af3e89c75 100644 --- a/src/main/snort_config.cc +++ b/src/main/snort_config.cc @@ -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; + sc->thread_affinity = new std::vector(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); } diff --git a/src/main/snort_config.h b/src/main/snort_config.h index 333d63050..15009c9b0 100644 --- a/src/main/snort_config.h +++ b/src/main/snort_config.h @@ -25,6 +25,8 @@ #include "config.h" #endif +#include +#include #include #include "detection/rules.h" #include "sfip/sfip_t.h" @@ -284,6 +286,10 @@ struct SnortConfig bool unit_test; #endif + + std::map* source_affinity; + std::vector* thread_affinity; + InspectionPolicy* get_inspection_policy() { return policy_map->inspection_policy[0]; }; diff --git a/src/main/thread.cc b/src/main/thread.cc index 8c5f95bf7..cb4dc3e81 100644 --- a/src/main/thread.cc +++ b/src/main/thread.cc @@ -18,11 +18,25 @@ */ // thread.cc author Russ Combs + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include "thread.h" +#ifdef LINUX +# include +#endif + #include #include -#include "snort.h" +#include + +#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& 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& 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& ta = *(snort_conf->thread_affinity); + std::map& 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 //------------------------------------------------------------------------- diff --git a/src/main/thread.h b/src/main/thread.h index caaad620b..9b6ab30f2 100644 --- a/src/main/thread.h +++ b/src/main/thread.h @@ -38,6 +38,12 @@ 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(); diff --git a/src/packet_io/trough.cc b/src/packet_io/trough.cc index 03e48083f..de0973e5f 100644 --- a/src/packet_io/trough.cc +++ b/src/packet_io/trough.cc @@ -31,13 +31,13 @@ #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;