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