1 /* 2 ** Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved. 3 ** Copyright (C) 2005-2013 Sourcefire, Inc. 4 ** Author: Steven Sturges <ssturges@sourcefire.com> 5 ** 6 ** This program is free software; you can redistribute it and/or modify 7 ** it under the terms of the GNU General Public License Version 2 as 8 ** published by the Free Software Foundation. You may not use, modify or 9 ** distribute this program under any other version of the GNU General 10 ** Public License. 11 ** 12 ** This program is distributed in the hope that it will be useful, 13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 ** GNU General Public License for more details. 16 ** 17 ** You should have received a copy of the GNU General Public License 18 ** along with this program; if not, write to the Free Software 19 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 */ 21 22 /* $Id$ */ 23 24 #ifndef __PROFILER_H__ 25 #define __PROFILER_H__ 26 27 #ifdef PERF_PROFILING 28 29 #include "cpuclock.h" 30 31 /* Sort preferences for rule profiling */ 32 #define PROFILE_SORT_CHECKS 1 33 #define PROFILE_SORT_MATCHES 2 34 #define PROFILE_SORT_NOMATCHES 3 35 #define PROFILE_SORT_AVG_TICKS 4 36 #define PROFILE_SORT_AVG_TICKS_PER_MATCH 5 37 #define PROFILE_SORT_AVG_TICKS_PER_NOMATCH 6 38 #define PROFILE_SORT_TOTAL_TICKS 7 39 40 /* MACROS that handle profiling of rules and preprocessors */ 41 #define PROFILE_VARS_NAMED(name) uint64_t name##_ticks_start, name##_ticks_end 42 #define PROFILE_VARS PROFILE_VARS_NAMED(snort) 43 44 #define PROFILE_START_NAMED(name) \ 45 get_clockticks(name##_ticks_start) 46 47 #define PROFILE_END_NAMED(name) \ 48 get_clockticks(name##_ticks_end) 49 50 #define NODE_PROFILE_END \ 51 PROFILE_END_NAMED(node); \ 52 node_ticks_delta = node_ticks_end - node_ticks_start 53 54 #ifndef PROFILING_RULES 55 #define PROFILING_RULES ScProfileRules() 56 #endif 57 58 #define NODE_PROFILE_VARS uint64_t node_ticks_start = 0, node_ticks_end = 0, node_ticks_delta = 0, node_deltas = 0 59 60 #define NODE_PROFILE_START(node) \ 61 if (PROFILING_RULES) { \ 62 node->checks++; \ 63 PROFILE_START_NAMED(node); \ 64 } 65 66 #define NODE_PROFILE_END_MATCH(node) \ 67 if (PROFILING_RULES) { \ 68 NODE_PROFILE_END; \ 69 node->ticks += node_ticks_delta + node_deltas; \ 70 node->ticks_match += node_ticks_delta + node_deltas; \ 71 } 72 73 #define NODE_PROFILE_END_NOMATCH(node) \ 74 if (PROFILING_RULES) { \ 75 NODE_PROFILE_END; \ 76 node->ticks += node_ticks_delta + node_deltas; \ 77 node->ticks_no_match += node_ticks_delta + node_deltas; \ 78 } 79 80 #define NODE_PROFILE_TMPSTART(node) \ 81 if (PROFILING_RULES) { \ 82 PROFILE_START_NAMED(node); \ 83 } 84 85 #define NODE_PROFILE_TMPEND(node) \ 86 if (PROFILING_RULES) { \ 87 NODE_PROFILE_END; \ 88 node_deltas += node_ticks_delta; \ 89 } 90 91 #define OTN_PROFILE_ALERT(otn) otn->alerts++; 92 93 #ifndef PROFILING_PREPROCS 94 #define PROFILING_PREPROCS ScProfilePreprocs() 95 #endif 96 97 #define PREPROC_PROFILE_START_NAMED(name, ppstat) \ 98 if (PROFILING_PREPROCS) { \ 99 ppstat.checks++; \ 100 PROFILE_START_NAMED(name); \ 101 ppstat.ticks_start = name##_ticks_start; \ 102 } 103 #define PREPROC_PROFILE_START(ppstat) PREPROC_PROFILE_START_NAMED(snort, ppstat) 104 105 #define PREPROC_PROFILE_START_NAMED_PI(name, ppstat) \ 106 { \ 107 ppstat.checks++; \ 108 PROFILE_START_NAMED(name); \ 109 ppstat.ticks_start = name##_ticks_start; \ 110 } 111 #define PREPROC_PROFILE_START_PI(ppstat) PREPROC_PROFILE_START_NAMED_PI(snort, ppstat) 112 113 #define PREPROC_PROFILE_REENTER_START_NAMED(name, ppstat) \ 114 if (PROFILING_PREPROCS) { \ 115 PROFILE_START_NAMED(name); \ 116 ppstat.ticks_start = name##_ticks_start; \ 117 } 118 #define PREPROC_PROFILE_REENTER_START(ppstat) PREPROC_PROFILE_REENTER_START_NAMED(snort, ppstat) 119 120 #define PREPROC_PROFILE_TMPSTART_NAMED(name, ppstat) \ 121 if (PROFILING_PREPROCS) { \ 122 PROFILE_START_NAMED(name); \ 123 ppstat.ticks_start = name##_ticks_start; \ 124 } 125 #define PREPROC_PROFILE_TMPSTART(ppstat) PREPROC_PROFILE_TMPSTART_NAMED(snort, ppstat) 126 127 #define PREPROC_PROFILE_END_NAMED(name, ppstat) \ 128 if (PROFILING_PREPROCS) { \ 129 PROFILE_END_NAMED(name); \ 130 ppstat.exits++; \ 131 ppstat.ticks += name##_ticks_end - ppstat.ticks_start; \ 132 } 133 #define PREPROC_PROFILE_END(ppstat) PREPROC_PROFILE_END_NAMED(snort, ppstat) 134 135 #define PREPROC_PROFILE_END_NAMED_PI(name, ppstat) \ 136 { \ 137 PROFILE_END_NAMED(name); \ 138 ppstat.exits++; \ 139 ppstat.ticks += name##_ticks_end - ppstat.ticks_start; \ 140 } 141 #define PREPROC_PROFILE_END_PI(ppstat) PREPROC_PROFILE_END_NAMED_PI(snort, ppstat) 142 143 #define PREPROC_PROFILE_REENTER_END_NAMED(name, ppstat) \ 144 if (PROFILING_PREPROCS) { \ 145 PROFILE_END_NAMED(name); \ 146 ppstat.ticks += name##_ticks_end - ppstat.ticks_start; \ 147 } 148 #define PREPROC_PROFILE_REENTER_END(ppstat) PREPROC_PROFILE_REENTER_END_NAMED(snort, ppstat) 149 150 #define PREPROC_PROFILE_TMPEND_NAMED(name, ppstat) \ 151 if (PROFILING_PREPROCS) { \ 152 PROFILE_END_NAMED(name); \ 153 ppstat.ticks += name##_ticks_end - ppstat.ticks_start; \ 154 } 155 #define PREPROC_PROFILE_TMPEND(ppstat) PREPROC_PROFILE_TMPEND_NAMED(snort, ppstat) 156 157 /************** Profiling API ******************/ 158 void ShowRuleProfiles(void); 159 160 /* Preprocessor stats info */ 161 typedef struct _PreprocStats 162 { 163 uint64_t ticks, ticks_start; 164 uint64_t checks; 165 uint64_t exits; 166 } PreprocStats; 167 168 typedef void (*FreeFunc)(PreprocStats *stats); 169 170 typedef struct _PreprocStatsNode 171 { 172 PreprocStats *stats; 173 char *name; 174 int layer; 175 FreeFunc freefn; 176 PreprocStats *parent; 177 178 struct _PreprocStatsNode *next; 179 } PreprocStatsNode; 180 181 typedef struct _ProfileConfig 182 { 183 int num; 184 int sort; 185 int append; 186 char *filename; 187 188 } ProfileConfig; 189 190 typedef void (*StatsNodeFreeFunc)(PreprocStats *stats); 191 void RegisterPreprocessorProfile(const char *keyword, PreprocStats *stats, int layer, PreprocStats *parent, StatsNodeFreeFunc freefn); 192 void ShowPreprocProfiles(void); 193 void ResetRuleProfiling(void); 194 void ResetPreprocProfiling(void); 195 void CleanupPreprocStatsNodeList(void); 196 extern PreprocStats totalPerfStats; 197 #else 198 #define PROFILE_VARS 199 #define PROFILE_VARS_NAMED(name) 200 #define NODE_PROFILE_VARS 201 #define NODE_PROFILE_START(node) 202 #define NODE_PROFILE_END_MATCH(node) 203 #define NODE_PROFILE_END_NOMATCH(node) 204 #define NODE_PROFILE_TMPSTART(node) 205 #define NODE_PROFILE_TMPEND(node) 206 #define OTN_PROFILE_ALERT(otn) 207 #define PREPROC_PROFILE_START(ppstat) 208 #define PREPROC_PROFILE_START_NAMED(name, ppstat) 209 #define PREPROC_PROFILE_START_PI(ppstat) 210 #define PREPROC_PROFILE_REENTER_START(ppstat) 211 #define PREPROC_PROFILE_REENTER_START_NAMED(name, ppstat) 212 #define PREPROC_PROFILE_TMPSTART(ppstat) 213 #define PREPROC_PROFILE_TMPSTART_NAMED(name, ppstat) 214 #define PREPROC_PROFILE_END(ppstat) 215 #define PREPROC_PROFILE_END_NAMED(name, ppstat) 216 #define PREPROC_PROFILE_END_PI(ppstat) 217 #define PREPROC_PROFILE_REENTER_END(ppstat) 218 #define PREPROC_PROFILE_REENTER_END_NAMED(name, ppstat) 219 #define PREPROC_PROFILE_TMPEND(ppstat) 220 #define PREPROC_PROFILE_TMPEND_NAMED(name, ppstat) 221 #endif 222 223 #endif /* __PROFILER_H__ */ 224