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 33 GetMTCPManager(mctx_t mctx) 34 { 35 return &mtcp; 36 } 37 38 u_int 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 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 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 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 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 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 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