|
|
@ -97,7 +97,16 @@ enum {
|
|
|
|
SC_PROFILING_RULES_SORT_BY_AVG_TICKS_MATCH,
|
|
|
|
SC_PROFILING_RULES_SORT_BY_AVG_TICKS_MATCH,
|
|
|
|
SC_PROFILING_RULES_SORT_BY_AVG_TICKS_NO_MATCH,
|
|
|
|
SC_PROFILING_RULES_SORT_BY_AVG_TICKS_NO_MATCH,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
static int profiling_rules_sort_order = SC_PROFILING_RULES_SORT_BY_TICKS;
|
|
|
|
|
|
|
|
|
|
|
|
static int profiling_rules_sort_orders[8] = {
|
|
|
|
|
|
|
|
SC_PROFILING_RULES_SORT_BY_TICKS,
|
|
|
|
|
|
|
|
SC_PROFILING_RULES_SORT_BY_AVG_TICKS,
|
|
|
|
|
|
|
|
SC_PROFILING_RULES_SORT_BY_AVG_TICKS_MATCH,
|
|
|
|
|
|
|
|
SC_PROFILING_RULES_SORT_BY_AVG_TICKS_NO_MATCH,
|
|
|
|
|
|
|
|
SC_PROFILING_RULES_SORT_BY_CHECKS,
|
|
|
|
|
|
|
|
SC_PROFILING_RULES_SORT_BY_MATCHES,
|
|
|
|
|
|
|
|
SC_PROFILING_RULES_SORT_BY_MAX_TICKS,
|
|
|
|
|
|
|
|
-1 };
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Maximum number of rules to dump.
|
|
|
|
* Maximum number of rules to dump.
|
|
|
@ -106,6 +115,11 @@ static uint32_t profiling_rules_limit = UINT32_MAX;
|
|
|
|
|
|
|
|
|
|
|
|
void SCProfilingRulesGlobalInit(void)
|
|
|
|
void SCProfilingRulesGlobalInit(void)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
#define SET_ONE(x) { \
|
|
|
|
|
|
|
|
profiling_rules_sort_orders[0] = (x); \
|
|
|
|
|
|
|
|
profiling_rules_sort_orders[1] = -1; \
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ConfNode *conf;
|
|
|
|
ConfNode *conf;
|
|
|
|
const char *val;
|
|
|
|
const char *val;
|
|
|
|
|
|
|
|
|
|
|
@ -117,32 +131,25 @@ void SCProfilingRulesGlobalInit(void)
|
|
|
|
val = ConfNodeLookupChildValue(conf, "sort");
|
|
|
|
val = ConfNodeLookupChildValue(conf, "sort");
|
|
|
|
if (val != NULL) {
|
|
|
|
if (val != NULL) {
|
|
|
|
if (strcmp(val, "ticks") == 0) {
|
|
|
|
if (strcmp(val, "ticks") == 0) {
|
|
|
|
profiling_rules_sort_order =
|
|
|
|
SET_ONE(SC_PROFILING_RULES_SORT_BY_TICKS);
|
|
|
|
SC_PROFILING_RULES_SORT_BY_TICKS;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (strcmp(val, "avgticks") == 0) {
|
|
|
|
else if (strcmp(val, "avgticks") == 0) {
|
|
|
|
profiling_rules_sort_order =
|
|
|
|
SET_ONE(SC_PROFILING_RULES_SORT_BY_AVG_TICKS);
|
|
|
|
SC_PROFILING_RULES_SORT_BY_AVG_TICKS;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (strcmp(val, "avgticks_match") == 0) {
|
|
|
|
else if (strcmp(val, "avgticks_match") == 0) {
|
|
|
|
profiling_rules_sort_order =
|
|
|
|
SET_ONE(SC_PROFILING_RULES_SORT_BY_AVG_TICKS_MATCH);
|
|
|
|
SC_PROFILING_RULES_SORT_BY_AVG_TICKS_MATCH;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (strcmp(val, "avgticks_no_match") == 0) {
|
|
|
|
else if (strcmp(val, "avgticks_no_match") == 0) {
|
|
|
|
profiling_rules_sort_order =
|
|
|
|
SET_ONE(SC_PROFILING_RULES_SORT_BY_AVG_TICKS_NO_MATCH);
|
|
|
|
SC_PROFILING_RULES_SORT_BY_AVG_TICKS_NO_MATCH;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (strcmp(val, "checks") == 0) {
|
|
|
|
else if (strcmp(val, "checks") == 0) {
|
|
|
|
profiling_rules_sort_order =
|
|
|
|
SET_ONE(SC_PROFILING_RULES_SORT_BY_CHECKS);
|
|
|
|
SC_PROFILING_RULES_SORT_BY_CHECKS;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (strcmp(val, "matches") == 0) {
|
|
|
|
else if (strcmp(val, "matches") == 0) {
|
|
|
|
profiling_rules_sort_order =
|
|
|
|
SET_ONE(SC_PROFILING_RULES_SORT_BY_MATCHES);
|
|
|
|
SC_PROFILING_RULES_SORT_BY_MATCHES;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (strcmp(val, "maxticks") == 0) {
|
|
|
|
else if (strcmp(val, "maxticks") == 0) {
|
|
|
|
profiling_rules_sort_order =
|
|
|
|
SET_ONE(SC_PROFILING_RULES_SORT_BY_MAX_TICKS);
|
|
|
|
SC_PROFILING_RULES_SORT_BY_MAX_TICKS;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
SCLogError(SC_ERR_INVALID_ARGUMENT,
|
|
|
|
SCLogError(SC_ERR_INVALID_ARGUMENT,
|
|
|
@ -186,6 +193,7 @@ void SCProfilingRulesGlobalInit(void)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef SET_ONE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -288,7 +296,9 @@ SCProfileSummarySortByMaxTicks(const void *a, const void *b)
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_LIBJANSSON
|
|
|
|
#ifdef HAVE_LIBJANSSON
|
|
|
|
|
|
|
|
|
|
|
|
static void DumpJson(FILE *fp, SCProfileSummary *summary, uint32_t count, uint64_t total_ticks)
|
|
|
|
static void DumpJson(FILE *fp, SCProfileSummary *summary,
|
|
|
|
|
|
|
|
uint32_t count, uint64_t total_ticks,
|
|
|
|
|
|
|
|
const char *sort_desc)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
char timebuf[64];
|
|
|
|
char timebuf[64];
|
|
|
|
uint32_t i;
|
|
|
|
uint32_t i;
|
|
|
@ -306,6 +316,7 @@ static void DumpJson(FILE *fp, SCProfileSummary *summary, uint32_t count, uint64
|
|
|
|
gettimeofday(&tval, NULL);
|
|
|
|
gettimeofday(&tval, NULL);
|
|
|
|
CreateIsoTimeString(&tval, timebuf, sizeof(timebuf));
|
|
|
|
CreateIsoTimeString(&tval, timebuf, sizeof(timebuf));
|
|
|
|
json_object_set_new(js, "timestamp", json_string(timebuf));
|
|
|
|
json_object_set_new(js, "timestamp", json_string(timebuf));
|
|
|
|
|
|
|
|
json_object_set_new(js, "sort", json_string(sort_desc));
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < MIN(count, profiling_rules_limit); i++) {
|
|
|
|
for (i = 0; i < MIN(count, profiling_rules_limit); i++) {
|
|
|
|
/* Stop dumping when we hit our first rule with 0 checks. Due
|
|
|
|
/* Stop dumping when we hit our first rule with 0 checks. Due
|
|
|
@ -350,7 +361,9 @@ static void DumpJson(FILE *fp, SCProfileSummary *summary, uint32_t count, uint64
|
|
|
|
|
|
|
|
|
|
|
|
#endif /* HAVE_LIBJANSSON */
|
|
|
|
#endif /* HAVE_LIBJANSSON */
|
|
|
|
|
|
|
|
|
|
|
|
static void DumpText(FILE *fp, SCProfileSummary *summary, uint32_t count, uint64_t total_ticks)
|
|
|
|
static void DumpText(FILE *fp, SCProfileSummary *summary,
|
|
|
|
|
|
|
|
uint32_t count, uint64_t total_ticks,
|
|
|
|
|
|
|
|
const char *sort_desc)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
uint32_t i;
|
|
|
|
uint32_t i;
|
|
|
|
struct timeval tval;
|
|
|
|
struct timeval tval;
|
|
|
@ -362,8 +375,9 @@ static void DumpText(FILE *fp, SCProfileSummary *summary, uint32_t count, uint64
|
|
|
|
fprintf(fp, " ----------------------------------------------"
|
|
|
|
fprintf(fp, " ----------------------------------------------"
|
|
|
|
"----------------------------\n");
|
|
|
|
"----------------------------\n");
|
|
|
|
fprintf(fp, " Date: %" PRId32 "/%" PRId32 "/%04d -- "
|
|
|
|
fprintf(fp, " Date: %" PRId32 "/%" PRId32 "/%04d -- "
|
|
|
|
"%02d:%02d:%02d\n", tms->tm_mon + 1, tms->tm_mday, tms->tm_year + 1900,
|
|
|
|
"%02d:%02d:%02d.", tms->tm_mon + 1, tms->tm_mday, tms->tm_year + 1900,
|
|
|
|
tms->tm_hour,tms->tm_min, tms->tm_sec);
|
|
|
|
tms->tm_hour,tms->tm_min, tms->tm_sec);
|
|
|
|
|
|
|
|
fprintf(fp, " Sorted by: %s.\n", sort_desc);
|
|
|
|
fprintf(fp, " ----------------------------------------------"
|
|
|
|
fprintf(fp, " ----------------------------------------------"
|
|
|
|
"----------------------------\n");
|
|
|
|
"----------------------------\n");
|
|
|
|
fprintf(fp, " %-8s %-12s %-8s %-8s %-12s %-6s %-8s %-8s %-11s %-11s %-11s %-11s\n", "Num", "Rule", "Gid", "Rev", "Ticks", "%", "Checks", "Matches", "Max Ticks", "Avg Ticks", "Avg Match", "Avg No Match");
|
|
|
|
fprintf(fp, " %-8s %-12s %-8s %-8s %-12s %-6s %-8s %-8s %-11s %-11s %-11s %-11s\n", "Num", "Rule", "Gid", "Rev", "Ticks", "%", "Checks", "Matches", "Max Ticks", "Avg Ticks", "Avg Match", "Avg No Match");
|
|
|
@ -476,43 +490,55 @@ SCProfilingRuleDump(SCProfileDetectCtx *rules_ctx)
|
|
|
|
total_ticks += summary[i].ticks;
|
|
|
|
total_ticks += summary[i].ticks;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch (profiling_rules_sort_order) {
|
|
|
|
int *order = profiling_rules_sort_orders;
|
|
|
|
case SC_PROFILING_RULES_SORT_BY_TICKS:
|
|
|
|
while (*order != -1) {
|
|
|
|
qsort(summary, count, sizeof(SCProfileSummary),
|
|
|
|
const char *sort_desc = NULL;
|
|
|
|
SCProfileSummarySortByTicks);
|
|
|
|
switch (*order) {
|
|
|
|
break;
|
|
|
|
case SC_PROFILING_RULES_SORT_BY_TICKS:
|
|
|
|
case SC_PROFILING_RULES_SORT_BY_AVG_TICKS:
|
|
|
|
qsort(summary, count, sizeof(SCProfileSummary),
|
|
|
|
qsort(summary, count, sizeof(SCProfileSummary),
|
|
|
|
SCProfileSummarySortByTicks);
|
|
|
|
SCProfileSummarySortByAvgTicks);
|
|
|
|
sort_desc = "ticks";
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case SC_PROFILING_RULES_SORT_BY_CHECKS:
|
|
|
|
case SC_PROFILING_RULES_SORT_BY_AVG_TICKS:
|
|
|
|
qsort(summary, count, sizeof(SCProfileSummary),
|
|
|
|
qsort(summary, count, sizeof(SCProfileSummary),
|
|
|
|
SCProfileSummarySortByChecks);
|
|
|
|
SCProfileSummarySortByAvgTicks);
|
|
|
|
break;
|
|
|
|
sort_desc = "average ticks";
|
|
|
|
case SC_PROFILING_RULES_SORT_BY_MATCHES:
|
|
|
|
break;
|
|
|
|
qsort(summary, count, sizeof(SCProfileSummary),
|
|
|
|
case SC_PROFILING_RULES_SORT_BY_CHECKS:
|
|
|
|
SCProfileSummarySortByMatches);
|
|
|
|
qsort(summary, count, sizeof(SCProfileSummary),
|
|
|
|
break;
|
|
|
|
SCProfileSummarySortByChecks);
|
|
|
|
case SC_PROFILING_RULES_SORT_BY_MAX_TICKS:
|
|
|
|
sort_desc = "number of checks";
|
|
|
|
qsort(summary, count, sizeof(SCProfileSummary),
|
|
|
|
break;
|
|
|
|
SCProfileSummarySortByMaxTicks);
|
|
|
|
case SC_PROFILING_RULES_SORT_BY_MATCHES:
|
|
|
|
break;
|
|
|
|
qsort(summary, count, sizeof(SCProfileSummary),
|
|
|
|
case SC_PROFILING_RULES_SORT_BY_AVG_TICKS_MATCH:
|
|
|
|
SCProfileSummarySortByMatches);
|
|
|
|
qsort(summary, count, sizeof(SCProfileSummary),
|
|
|
|
sort_desc = "number of matches";
|
|
|
|
SCProfileSummarySortByAvgTicksMatch);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case SC_PROFILING_RULES_SORT_BY_MAX_TICKS:
|
|
|
|
case SC_PROFILING_RULES_SORT_BY_AVG_TICKS_NO_MATCH:
|
|
|
|
qsort(summary, count, sizeof(SCProfileSummary),
|
|
|
|
qsort(summary, count, sizeof(SCProfileSummary),
|
|
|
|
SCProfileSummarySortByMaxTicks);
|
|
|
|
SCProfileSummarySortByAvgTicksNoMatch);
|
|
|
|
sort_desc = "max ticks";
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SC_PROFILING_RULES_SORT_BY_AVG_TICKS_MATCH:
|
|
|
|
|
|
|
|
qsort(summary, count, sizeof(SCProfileSummary),
|
|
|
|
|
|
|
|
SCProfileSummarySortByAvgTicksMatch);
|
|
|
|
|
|
|
|
sort_desc = "average ticks (match)";
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SC_PROFILING_RULES_SORT_BY_AVG_TICKS_NO_MATCH:
|
|
|
|
|
|
|
|
qsort(summary, count, sizeof(SCProfileSummary),
|
|
|
|
|
|
|
|
SCProfileSummarySortByAvgTicksNoMatch);
|
|
|
|
|
|
|
|
sort_desc = "average ticks (no match)";
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
#ifdef HAVE_LIBJANSSON
|
|
|
|
#ifdef HAVE_LIBJANSSON
|
|
|
|
if (profiling_rule_json) {
|
|
|
|
if (profiling_rule_json) {
|
|
|
|
DumpJson(fp, summary, count, total_ticks);
|
|
|
|
DumpJson(fp, summary, count, total_ticks, sort_desc);
|
|
|
|
} else
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
{
|
|
|
|
DumpText(fp, summary, count, total_ticks);
|
|
|
|
DumpText(fp, summary, count, total_ticks, sort_desc);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
order++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (fp != stdout)
|
|
|
|
if (fp != stdout)
|
|
|
|