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