1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <unistd.h>
5 #include <time.h>
6
7 #include "mtcp.h"
8 #include "mos_api.h"
9 #include "memory_mgt.h"
10 #include "scalable_event.h"
11
12 #define PROFILE_ON
13 #include "profile.h"
14
15 event_t g_first_ev = MOS_NULL_EVENT, g_last_ev = MOS_NULL_EVENT;
16 int g_depth = 0;
17 float g_prob = 0;
18 int g_threshold = 0;
19
20 int ft_counter = 0, cb_counter = 0;
21 struct mtcp_manager mtcp;
22
23 extern inline int
24 ModCb(kvs_t *store, stree_t **pstree, event_t ev, callback_t cb);
25
26 extern void
27 HandleCb(mctx_t mctx, int sock, int side, stree_t *stree, event_t events);
28
29 extern int
30 RaiseEv(kvs_t *store, event_t event);
31
32 mtcp_manager_t
GetMTCPManager(mctx_t mctx)33 GetMTCPManager(mctx_t mctx)
34 {
35 return &mtcp;
36 }
37
38 u_int
sfbpf_filter(const struct sfbpf_insn * pc,const u_char * p,u_int wirelen,u_int buflen)39 sfbpf_filter(const struct sfbpf_insn *pc, const u_char *p, u_int wirelen,
40 u_int buflen)
41 {
42 return 0;
43 }
44
45 static void
cb(mctx_t mctx,int sock,int side,event_t ev,filter_arg_t * arg)46 cb(mctx_t mctx, int sock, int side, event_t ev, filter_arg_t *arg)
47 {
48 //printf("cb: %ld\n", ev);
49 cb_counter++;
50 }
51
52 static bool
ft(mctx_t mctx,int sock,int side,event_t ev,filter_arg_t * arg)53 ft(mctx_t mctx, int sock, int side, event_t ev, filter_arg_t *arg)
54 {
55 //printf("ft: %ld\n", ev);
56 return true;
57 }
58
59 static bool
ft_prob(mctx_t mctx,int sockid,int side,uint64_t events,filter_arg_t * arg)60 ft_prob(mctx_t mctx, int sockid, int side, uint64_t events, filter_arg_t *arg)
61 {
62 static __thread unsigned int seed = 0;
63 if (seed == 0)
64 seed = time(NULL) + getpid();
65 bool ret = rand_r(&seed) < g_threshold;
66 //printf("ft: %ld returns %s\n", events, ret ? "true" : "false");
67 ft_counter++;
68 return ret;
69 }
70
71 static int
power(base,exponent)72 power(base, exponent)
73 {
74 int i, ret = 1;
75
76 assert(exponent >= 0);
77
78 for (i = 0; i < exponent; i++)
79 ret *= base;
80
81 return ret;
82 }
83
84 event_t g_ac_events[5000];
85 event_t g_r_events[5000];
86
87 static bool
ft_ac_match(mctx_t mctx,int sock,int side,uint64_t ev,filter_arg_t * arg)88 ft_ac_match(mctx_t mctx, int sock, int side, uint64_t ev, filter_arg_t *arg)
89 {
90 event_t ev_matched;
91 static __thread unsigned int seed = 0;
92 if (seed == 0)
93 seed = time(NULL) + getpid();
94 ev_matched = g_ac_events[rand_r(&seed) % *((int *)arg->arg)];
95
96 RaiseEv(mtcp.ev_store, ev_matched);
97
98 return true;
99 }
100
main(int argc,char ** argv)101 int main(int argc, char **argv)
102 {
103 stree_t *stree[10] = {NULL};
104
105 GlobInitEvent();
106 InitEvent(&mtcp);
107
108 ModCb(mtcp.ev_store, &stree[0], 1, cb);
109 ModCb(mtcp.ev_store, &stree[1], 1, cb);
110 ModCb(mtcp.ev_store, &stree[0], 2, cb);
111
112 printf("HandleCb(0)\n");
113 HandleCb(NULL, 0, 0, stree[0], 3);
114 printf("HandleCb(1)\n");
115 HandleCb(NULL, 0, 0, stree[1], 3);
116
117 event_t ude1 = mtcp_define_event(1, ft, NULL);
118 assert(ude1);
119 ModCb(mtcp.ev_store, &stree[2], ude1, cb);
120
121 printf("HandleCb(2)\n");
122 HandleCb(NULL, 0, 0, stree[2], 3);
123
124 event_t ude2 = mtcp_define_event(ude1, ft, NULL);
125 assert(ude2);
126 ModCb(mtcp.ev_store, &stree[1], ude2, cb);
127
128 printf("HandleCb(1)\n");
129 HandleCb(NULL, 0, 0, stree[1], 1);
130
131 ModCb(mtcp.ev_store, &stree[1], ude2, NULL);
132
133 printf("HandleCb(1)\n");
134 HandleCb(NULL, 0, 0, stree[1], 1);
135
136 /* Random tree test */
137 #define BEV4 4
138 event_t ev;
139 int opt, i;
140 float numcb = 1, numft = 0, p;
141
142 while ((opt = getopt(argc, argv, "d:p:")) > 0) {
143 if (opt == 'd')
144 g_depth = atoi(optarg);
145 else if (opt == 'p')
146 sscanf(optarg, "%f", &g_prob);
147 else {
148 fprintf(stderr, "Unknown option '%c'\n", opt);
149 exit(0);
150 }
151 }
152
153 g_threshold = (int)((float)RAND_MAX * g_prob);
154
155 if (g_depth < 0)
156 return -1;
157
158 PROFILE_INIT();
159 PROFILE_VAR(define_event);
160 PROFILE_VAR(register_event);
161 PROFILE_VAR(trigger_event);
162
163 PROFILE_START();
164
165 PROFILE_FROM(define_event);
166
167 g_first_ev = mtcp_define_event(BEV4, ft_prob, NULL);
168 //printf("%d -> %ld\n", BEV4, g_first_ev);
169 ev = mtcp_define_event(BEV4, ft_prob, NULL);
170 //printf("%d -> %ld\n", BEV4, ev);
171 g_last_ev = g_first_ev + power(2, g_depth + 1) - 3;
172
173 for (ev = g_first_ev; g_depth != 1 && ev != MOS_NULL_EVENT; ev++) {
174 event_t nev;
175 /* Call define_event() twice since it is full binary tree */
176 nev = mtcp_define_event(ev, ft_prob, NULL);
177 //printf("%ld -> %ld\n", ev, nev);
178 nev = mtcp_define_event(ev, ft_prob, NULL);
179 //printf("%ld -> %ld\n", ev, nev);
180 if (nev == g_last_ev)
181 break;
182 else if (nev == MOS_NULL_EVENT) {
183 fprintf(stderr, "Failed to define child event of event %ld\n", ev);
184 exit(0);
185 }
186 }
187 if (ev == MOS_NULL_EVENT) {
188 fprintf(stderr, "Failed to define child event of event %ld\n", ev);
189 exit(0);
190 }
191
192 PROFILE_TO(define_event);
193
194 for (p = g_prob, i = 0; i < g_depth; p *= g_prob, i++) {
195 numft = 2*numcb;
196 numcb += p * power(2, i+1);
197 }
198
199 printf("\x1b[33m"
200 "Tree depth: %d, Defined total events: %d\n"
201 "Theoritical average function call: %.2f callbacks, %.2f filters"
202 "\x1b[0m\n",
203 g_depth, power(2, g_depth) + 1, numcb, numft);
204
205 /* Test random tree */
206
207 PROFILE_FROM(register_event);
208
209 ModCb(mtcp.ev_store, &stree[3], BEV4, cb);
210 for (ev = g_first_ev; ev != g_last_ev; ev++)
211 ModCb(mtcp.ev_store, &stree[3], ev, cb);
212
213 PROFILE_TO(register_event);
214
215 #if 0
216 mtcp_register_callback(mctx, msock, BEV4, MOS_PRE_RCV, cb_void);
217
218 for (ev = g_first_ev; ev != g_last_ev; ev++)
219 mtcp_register_callback(mctx, msock, ev, MOS_PRE_RCV, cb_void);
220 #endif
221
222 PROFILE_FROM(trigger_event);
223 #define LCOUNT 1000000
224 int j;
225 for (j=0; j<LCOUNT;j++)
226 HandleCb(NULL, 0, 0, stree[3], BEV4);
227
228 PROFILE_TO(trigger_event);
229
230 PROFILE_END();
231
232 PROFILE_PRINT(stdout);
233 printf("Avg CB %f Avg FT %f\n", cb_counter*1.000000/LCOUNT, ft_counter*1.0/LCOUNT);
234
235 #ifdef DO_SNORT_SIM
236 /*--------------------------------------------------------------------*/
237 /* selective event invocation test */
238 /*--------------------------------------------------------------------*/
239
240 /* 1. Snort simulation */
241 {
242 printf("SNORT SIMULATION TEST\n");
243 stree_t *s = NULL;
244 const event_t BEV8 = 8;
245 const int REPEAT = 10;
246 const int RULES = 4000;
247 const int RULE_CONDS = 4;
248 filter_arg_t arg = {&RULES, sizeof(RULES)};
249 int percent = 0;
250
251 int i, j;
252
253 const event_t EV_AC_MATCH = mtcp_define_event(BEV8, ft_ac_match, &arg);
254
255 for (i = 0; i < RULES; i++) {
256 event_t e = g_ac_events[i] = mtcp_alloc_event(EV_AC_MATCH);
257
258 for (j = 0; j < RULE_CONDS; j++)
259 e = mtcp_define_event(e, ft, NULL);
260
261 g_r_events[i] = e;
262
263 if ((i * 100) / RULES > percent) {
264 percent = (i * 100) / RULES;
265 printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
266 printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
267 printf(" %d%% (%d / %d)", percent, i, RULES);
268 }
269 }
270 printf("\n");
271
272 percent = 0;
273 for (i = 0; i < RULES; i++) {
274 ModCb(mtcp.ev_store, &s, g_r_events[i], cb);
275
276 if ((i * 100) / RULES > percent) {
277 percent = (i * 100) / RULES;
278 printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
279 printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
280 printf(" %d%% (%d / %d)", percent, i, RULES);
281 }
282 }
283 printf("\n");
284
285 cb_counter = 0;
286 for (i = 0; i < REPEAT; i++)
287 HandleCb(NULL, 0, 0, s, BEV8);
288 printf("%d / %d callbacks are called; %s\n",
289 cb_counter, REPEAT, cb_counter == REPEAT ? "SUCCESS" : "FAILURE");
290 }
291 #endif
292
293 return 0;
294 }
295