stats.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  1. /*
  2. * $Id$
  3. *
  4. * Stats reporting code. It reports through SIG_USR1 and if loaded
  5. * through the SNMP module
  6. *
  7. * Copyright (C) 2001-2003 Fhg Fokus
  8. *
  9. * This file is part of ser, a free SIP server.
  10. *
  11. * ser is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version
  15. *
  16. * For a license to use the ser software under conditions
  17. * other than those described here, or to purchase support for this
  18. * software, please contact iptel.org by e-mail at the following addresses:
  19. * [email protected]
  20. *
  21. * ser is distributed in the hope that it will be useful,
  22. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. * GNU General Public License for more details.
  25. *
  26. * You should have received a copy of the GNU General Public License
  27. * along with this program; if not, write to the Free Software
  28. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  29. */
  30. #ifdef STATS
  31. #include "stats.h"
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <time.h>
  36. #include <sys/types.h>
  37. #include <unistd.h>
  38. #include "dprint.h"
  39. #include "mem/shm_mem.h"
  40. #include "sr_module.h"
  41. /* SNMP includes */
  42. #include "modules/snmp/snmp_handler.h"
  43. #include "modules/snmp/sipCommonStatsMethod.h"
  44. #include "modules/snmp/sipCommonStatusCode.h"
  45. struct stats_s *stats; /* per process stats structure */
  46. char *stat_file = NULL; /* set by the parser */
  47. /* private variables */
  48. static struct stats_s *global_stats=NULL;
  49. static int stats_segments=-1; /*used also to determine if we've been init'ed*/
  50. /* adds up global statistics and puts them into passed struct.
  51. * -1 returned on failure */
  52. static int collect_stats(struct stats_s *s);
  53. /***********************8 SNMP Stuff **************************/
  54. /* a small structure we use to pass around the functions needed by
  55. * all the registration functions */
  56. struct stats_funcs {
  57. int (*reg_func)(const char *, struct sip_snmp_handler*);
  58. struct sip_snmp_handler* (*new_func)(size_t);
  59. void (*free_func)(struct sip_snmp_handler*);
  60. };
  61. /* SNMP Handler registration functions */
  62. static int sipSummaryStatsTable_register(const struct stats_funcs *f);
  63. static int sipMethodStatsTable_register(const struct stats_funcs *f);
  64. static int sipStatusCodesTable_register(const struct stats_funcs *f);
  65. /* the handlers */
  66. static int collect_InReqs(struct sip_snmp_obj *, enum handler_op);
  67. static int collect_OutReqs(struct sip_snmp_obj *, enum handler_op);
  68. static int collect_InResp(struct sip_snmp_obj *, enum handler_op);
  69. static int collect_OutResp(struct sip_snmp_obj *, enum handler_op);
  70. static int sipStatsMethod_handler(struct sip_snmp_obj *o, enum handler_op op);
  71. static int sipStatusCodes_handler(struct sip_snmp_obj *o, enum handler_op op);
  72. int init_stats(int nr_of_processes)
  73. {
  74. LOG(L_DBG,"init_stats(): initializing stats for %d processes\n",
  75. nr_of_processes);
  76. global_stats = shm_malloc(nr_of_processes*sizeof(struct stats_s));
  77. if(!global_stats) {
  78. LOG(L_ERR, "Out of memory\n");
  79. return -1;
  80. }
  81. stats_segments = nr_of_processes;
  82. if(stats_register() == -1)
  83. LOG(L_WARN, "init_stats(): Couldn't register stats"
  84. " with snmp module\n");
  85. return 0;
  86. }
  87. /* sets the stats pointer for the passed process */
  88. void setstats(int child_index)
  89. {
  90. if(stats_segments == -1 || !global_stats) {
  91. LOG(L_ERR, "Stats not initialized. Cannot set them\n");
  92. stats = NULL;
  93. return;
  94. }
  95. if(child_index < 0 || child_index >= stats_segments) {
  96. stats = NULL;
  97. LOG(L_ERR, "Invalid index %d while setting statistics. Only have "
  98. "space for %d processes\n", child_index, stats_segments);
  99. return;
  100. }
  101. stats = global_stats+child_index;
  102. stats->process_index = child_index;
  103. /* can't use pids[] because we may be called before the corresponding
  104. * slot in pids[] is initialized (chk main_loop()) */
  105. stats->pid = getpid();
  106. stats->start_time = time(NULL);
  107. }
  108. /* printheader is used to print pid, date and index */
  109. int dump_statistic(FILE *fp, struct stats_s *istats, int printheader)
  110. {
  111. struct tm res;
  112. char t[256];
  113. if(stats_segments == -1 || !global_stats) {
  114. LOG(L_ERR, "Stats \"engine\" not initialized\n");
  115. return -1;
  116. }
  117. if(printheader) {
  118. localtime_r(&istats->start_time, &res);
  119. strftime(t, 255, "%c", &res);
  120. fprintf(fp, "stats for process %d (pid %d) started at %s\n",
  121. istats->process_index, istats->pid, t);
  122. }
  123. fprintf(fp, "received requests:\ninv: %ld\tack: %ld\tcnc: %ld\t"
  124. "bye: %ld\tother: %ld\n",
  125. istats->received_requests_inv,
  126. istats->received_requests_ack,
  127. istats->received_requests_cnc,
  128. istats->received_requests_bye,
  129. istats->received_requests_other);
  130. fprintf(fp, "sent requests:\n"
  131. "inv: %ld\tack: %ld\tcnc: %ld\tbye: %ld\tother: %ld\n",
  132. istats->sent_requests_inv,
  133. istats->sent_requests_ack,
  134. istats->sent_requests_cnc,
  135. istats->sent_requests_bye,
  136. istats->sent_requests_other);
  137. fprintf(fp, "received responses:\n"
  138. "1: %ld\t2: %ld\t3: %ld\t4: %ld\t5: %ld\t6: %ld\tother: %ld\t"
  139. "drops: %ld\n",
  140. istats->received_responses_1,
  141. istats->received_responses_2,
  142. istats->received_responses_3,
  143. istats->received_responses_4,
  144. istats->received_responses_5,
  145. istats->received_responses_6,
  146. istats->received_responses_other,
  147. istats->received_drops);
  148. fprintf(fp, "sent responses:\n"
  149. "1: %ld\t2: %ld\t3: %ld\t4: %ld\t5: %ld\t6: %ld\n",
  150. istats->sent_responses_1,
  151. istats->sent_responses_2,
  152. istats->sent_responses_3,
  153. istats->sent_responses_4,
  154. istats->sent_responses_5,
  155. istats->sent_responses_6);
  156. fprintf(fp, "processed requests: %ld\t\tprocessed responses: %ld\n"
  157. "acc req time: %ld\t\t\tacc res time: %ld\nfailed on send: %ld\n\n",
  158. istats->processed_requests,
  159. istats->processed_responses,
  160. istats->acc_req_time,
  161. istats->acc_res_time,
  162. istats->failed_on_send);
  163. return 0;
  164. }
  165. int dump_all_statistic()
  166. {
  167. register int i;
  168. register struct stats_s *c;
  169. static struct stats_s *g = NULL;
  170. struct tm res;
  171. char t[256];
  172. time_t ts;
  173. FILE *stat_fp = NULL;
  174. if(stats_segments == -1 || !global_stats) {
  175. LOG(L_ERR, "%s: Can't dump statistics, not initialized!\n", __func__);
  176. return -1;
  177. }
  178. if(!stat_file) {
  179. LOG(L_ERR, "%s: Can't dump statistics, invalid stats file\n", __func__);
  180. return -1;
  181. }
  182. stat_fp = fopen(stat_file, "a");
  183. if(!stat_fp) {
  184. LOG(L_ERR, "%s: Couldn't open stats file %s: %s\n", __func__, stat_file,
  185. strerror(errno));
  186. return -1;
  187. }
  188. /* time stamp them since we're appending to the file */
  189. ts = time(NULL);
  190. localtime_r(&ts, &res);
  191. strftime(t, 255, "%c", &res);
  192. fprintf(stat_fp, "#### stats @ %s #####\n", t);
  193. c = global_stats;
  194. for(i=0; i<stats_segments; i++) {
  195. if(dump_statistic(stat_fp, c, 1) == -1) {
  196. LOG(L_ERR, "Error dumping statistics for process %d\n", i);
  197. goto end;
  198. }
  199. c++;
  200. }
  201. fprintf(stat_fp, "## Global Stats ##\n");
  202. if(!g)
  203. g = calloc(1, sizeof(struct stats_s));
  204. if(!g) {
  205. LOG(L_ERR, "Couldn't dump global stats: %s\n", strerror(errno));
  206. goto end;
  207. }
  208. if(collect_stats(g) == -1) {
  209. LOG(L_ERR, "%s: Couldn't dump global stats\n", __func__);
  210. goto end;
  211. }
  212. if(dump_statistic(stat_fp, g, 0) == -1) {
  213. LOG(L_ERR, "Couldn't dump global stats\n");
  214. goto end;
  215. }
  216. end:
  217. fprintf(stat_fp, "\n");
  218. fclose(stat_fp);
  219. return 0;
  220. }
  221. static int collect_stats(struct stats_s *s)
  222. {
  223. register int i;
  224. register struct stats_s *c;
  225. if(!s) {
  226. LOG(L_ERR, "collect_stats(): Invalid stats pointer passed\n");
  227. return -1;
  228. }
  229. if(!global_stats || stats_segments == -1) {
  230. LOG(L_ERR, "Can't collect statistics, not initalized!!\n");
  231. return -1;
  232. }
  233. c = global_stats;
  234. memset(s, '\0', sizeof(struct stats_s));
  235. for(i=0; i<stats_segments; i++) {
  236. s->received_requests_inv += c->received_requests_inv;
  237. s->received_requests_ack += c->received_requests_ack;
  238. s->received_requests_cnc += c->received_requests_cnc;
  239. s->received_requests_bye += c->received_requests_bye;
  240. s->received_requests_other += c->received_requests_other;
  241. s->received_responses_1 += c->received_responses_1;
  242. s->received_responses_2 += c->received_responses_2;
  243. s->received_responses_3 += c->received_responses_3;
  244. s->received_responses_4 += c->received_responses_4;
  245. s->received_responses_5 += c->received_responses_5;
  246. s->received_responses_6 += c->received_responses_6;
  247. s->received_responses_other += c->received_responses_other;
  248. s->received_drops += c->received_drops;
  249. s->sent_requests_inv += c->sent_requests_inv;
  250. s->sent_requests_ack += c->sent_requests_ack;
  251. s->sent_requests_cnc += c->sent_requests_cnc;
  252. s->sent_requests_bye += c->sent_requests_bye;
  253. s->sent_requests_other += c->sent_requests_other;
  254. s->sent_responses_1 += c->sent_responses_1;
  255. s->sent_responses_2 += c->sent_responses_2;
  256. s->sent_responses_3 += c->sent_responses_3;
  257. s->sent_responses_4 += c->sent_responses_4;
  258. s->sent_responses_5 += c->sent_responses_5;
  259. s->sent_responses_6 += c->sent_responses_6;
  260. s->processed_requests += c->processed_requests;
  261. s->processed_responses += c->processed_responses;
  262. s->acc_req_time += c->acc_req_time;
  263. s->acc_res_time += c->acc_res_time;
  264. s->failed_on_send += c->failed_on_send;
  265. c++; /* next, please... */
  266. }
  267. return 0;
  268. }
  269. /*************************** SNMP Stuff ***********************/
  270. /* ##### Registration Functions ####### */
  271. /* Registers the handlers for:
  272. * - sipSummaryStatsTable
  273. * - sipMethodStatsTable
  274. * - sipStatusCodesTable
  275. * - sipCommonStatusCodeTable
  276. *
  277. * Returns 0 if snmp module not present, -1 on error, 1 on successful
  278. * registration
  279. */
  280. #define reg(t) \
  281. if(t##_register(&f) == -1) { \
  282. LOG(L_ERR, "%s: Failed registering SNMP handlers\n", func); \
  283. return -1; \
  284. }
  285. int stats_register()
  286. {
  287. const char *func = __FUNCTION__;
  288. struct stats_funcs f;
  289. f.reg_func = (void*) find_export("snmp_register_handler", 2);
  290. f.new_func = (void*) find_export("snmp_new_handler", 1);
  291. f.free_func = (void*) find_export("snmp_free_handler", 1);
  292. if(!f.reg_func || !f.new_func || !f.free_func) {
  293. LOG(L_INFO, "%s: Couldn't find SNMP module\n", func);
  294. LOG(L_INFO, "%s: Not reporting stats through SNMP\n", func);
  295. return 0;
  296. }
  297. reg(sipSummaryStatsTable);
  298. reg(sipMethodStatsTable);
  299. reg(sipStatusCodesTable);
  300. return 0;
  301. }
  302. /* Receives the function used to register SNMP handlers. Returns 0
  303. * on success, -1 on error */
  304. /* Registers:
  305. * - sipSummaryInRequests
  306. * - sipSummaryOutRequests
  307. * - sipSummaryInResponses
  308. * - sipSummaryOutResponses
  309. * => sipSummaryTotalTransactions is handled by the tm module */
  310. static int sipSummaryStatsTable_register(const struct stats_funcs *f)
  311. {
  312. register struct sip_snmp_handler *h;
  313. register struct sip_snmp_obj *o;
  314. const char *func = __FUNCTION__;
  315. h = f->new_func(sizeof(unsigned long));
  316. if(!h) {
  317. LOG(L_ERR, "%s: Error creating handler\n", func);
  318. return -1;
  319. }
  320. o = h->sip_obj;
  321. /* this is the same for all of our objects */
  322. o->type = SER_COUNTER;
  323. *o->value.integer = 0; /* default value. The real one is computed on
  324. request */
  325. o->val_len = sizeof(unsigned long);
  326. /* sipSummaryInRequests */
  327. h->on_get = collect_InReqs;
  328. h->on_set = h->on_end = NULL;
  329. if(f->reg_func("sipSummaryInRequests", h) == -1) {
  330. LOG(L_ERR, "%s: Error registering sipSummaryInRequests\n", func);
  331. f->free_func(h);
  332. return -1;
  333. }
  334. /* sipSummaryOutRequests */
  335. h->on_get = collect_OutReqs;
  336. if(f->reg_func("sipSummaryOutRequests", h) == -1) {
  337. LOG(L_ERR, "%s: Error registering sipSummaryOutRequests\n", func);
  338. f->free_func(h);
  339. return -1;
  340. }
  341. /* sipSummaryInResponses */
  342. h->on_get = collect_InResp;
  343. if(f->reg_func("sipSummaryInResponses", h) == -1) {
  344. LOG(L_ERR, "%s: Error registering sipSummaryInResponses\n", func);
  345. f->free_func(h);
  346. return -1;
  347. }
  348. /* sipSummaryOutResponses */
  349. h->on_get = collect_OutResp;
  350. if(f->reg_func("sipSummaryOutResponses", h) == -1) {
  351. LOG(L_ERR, "%s: Error registering sipSummaryOutResponses\n", func);
  352. f->free_func(h);
  353. return -1;
  354. }
  355. f->free_func(h);
  356. return 0;
  357. }
  358. static int sipMethodStatsTable_register(const struct stats_funcs *f)
  359. {
  360. const char* objs[] = {
  361. "sipStatsInviteIns",
  362. "sipStatsInviteOuts",
  363. "sipStatsAckIns",
  364. "sipStatsAckOuts",
  365. "sipStatsByeIns",
  366. "sipStatsByeOuts",
  367. "sipStatsCancelIns",
  368. "sipStatsCancelOuts"
  369. #if 0 /* we don't know about these */
  370. "sipStatsOptionsIns",
  371. "sipStatsOptionsOuts",
  372. "sipStatsRegisterIns",
  373. "sipStatsRegisterOuts",
  374. "sipStatsInfoIns",
  375. "sipStatsInfoOuts"
  376. #endif
  377. };
  378. int i, num = 8;
  379. const char *func = __FUNCTION__;
  380. register struct sip_snmp_handler *h;
  381. register struct sip_snmp_obj *o;
  382. h = f->new_func(sizeof(unsigned long));
  383. if(!h) {
  384. LOG(L_ERR, "%s: Error creating handler\n", func);
  385. return -1;
  386. }
  387. o = h->sip_obj;
  388. o->type = SER_COUNTER;
  389. *o->value.integer = 0;
  390. o->val_len = sizeof(unsigned long);
  391. h->on_get = sipStatsMethod_handler;
  392. h->on_set = h->on_end = NULL;
  393. for(i=0; i<num; i++) {
  394. if(f->reg_func(objs[i], h) == -1) {
  395. LOG(L_ERR, "%s: Error registering %s\n", func, objs[i]);
  396. f->free_func(h);
  397. return -1;
  398. }
  399. }
  400. f->free_func(h);
  401. return 0;
  402. }
  403. static int sipStatusCodesTable_register(const struct stats_funcs *f)
  404. {
  405. const char *objs[] = {
  406. "sipStatsInfoClassIns",
  407. "sipStatsInfoClassOuts",
  408. "sipStatsSuccessClassIns",
  409. "sipStatsSuccessClassOuts",
  410. "sipStatsRedirClassIns",
  411. "sipStatsRedirClassOuts",
  412. "sipStatsReqFailClassIns",
  413. "sipStatsReqFailClassOuts",
  414. "sipStatsServerFailClassIns",
  415. "sipStatsServerFailClassOuts",
  416. "sipStatsGlobalFailClassIns",
  417. "sipStatsGlobalFailClassOuts",
  418. "sipStatsOtherClassesIns",
  419. "sipStatsOtherClassesOuts"
  420. };
  421. int i, num = 14;
  422. const char *func = __FUNCTION__;
  423. register struct sip_snmp_handler *h;
  424. register struct sip_snmp_obj *o;
  425. h = f->new_func(sizeof(unsigned long));
  426. if(!h) {
  427. LOG(L_ERR, "%s: Error creating handler\n", func);
  428. return -1;
  429. }
  430. o = h->sip_obj;
  431. o->type = SER_COUNTER;
  432. *o->value.integer = 0;
  433. o->val_len = sizeof(unsigned long);
  434. h->on_get = sipStatusCodes_handler;
  435. h->on_set = h->on_end = NULL;
  436. for(i=0; i<num; i++) {
  437. if(f->reg_func(objs[i], h) == -1) {
  438. LOG(L_ERR, "%s: Error registering %s\n", func, objs[i]);
  439. f->free_func(h);
  440. return -1;
  441. }
  442. }
  443. f->free_func(h);
  444. return 0;}
  445. /* ########################## SNMP Handlers ######################### */
  446. /*** Handlers for sipSummaryStatsTable */
  447. static int collect_InReqs(struct sip_snmp_obj *o, enum handler_op op)
  448. {
  449. register int i;
  450. register struct stats_s *c;
  451. register unsigned long t1, t2, t3, t4, t5;
  452. const char *func = __FUNCTION__;
  453. if(!global_stats || stats_segments == -1) {
  454. LOG(L_ERR, "%s: Can't collect stats, they have not been initialized."
  455. "Did you call init_stats()?\n", func);
  456. return -1;
  457. }
  458. if(op != SER_GET) {
  459. LOG(L_ERR, "%s: Invalid handler operation passed\n", func);
  460. return -1;
  461. }
  462. if(!o->value.integer) {
  463. o->value.integer = calloc(1, sizeof(unsigned long));
  464. if(!o->value.integer) {
  465. LOG(L_ERR, "%s: %s\n", func, strerror(errno));
  466. return -1;
  467. }
  468. }
  469. c = global_stats;
  470. t1 = t2 = t3 = t4 = t5 = 0;
  471. for(i=0; i<stats_segments; i++, c++) {
  472. t1 += c->received_requests_inv;
  473. t2 += c->received_requests_ack;
  474. t3 += c->received_requests_cnc;
  475. t4 += c->received_requests_bye;
  476. t5 += c->received_requests_other;
  477. }
  478. *o->value.integer = t1 + t2 + t3 + t4 + t5;
  479. o->val_len = sizeof(unsigned long);
  480. o->type = SER_COUNTER;
  481. return 0;
  482. }
  483. static int collect_OutReqs(struct sip_snmp_obj *o, enum handler_op op)
  484. {
  485. register int i;
  486. register struct stats_s *c;
  487. register unsigned long t1, t2, t3, t4, t5;
  488. const char *func = __FUNCTION__;
  489. if(!global_stats || stats_segments == -1) {
  490. LOG(L_ERR, "%s: Can't collect stats, they have not been initialized."
  491. "Did you call init_stats()?\n", func);
  492. return -1;
  493. }
  494. if(op != SER_GET) {
  495. LOG(L_ERR, "%s: Invalid handler operation passed\n", func);
  496. return -1;
  497. }
  498. if(!o->value.integer) {
  499. o->value.integer = calloc(1, sizeof(unsigned long));
  500. if(!o->value.integer) {
  501. LOG(L_ERR, "%s: %s\n", func, strerror(errno));
  502. return -1;
  503. }
  504. }
  505. c = global_stats;
  506. t1 = t2 = t3 = t4 = t5 = 0;
  507. for(i=0; i<stats_segments; i++, c++) {
  508. t1 += c->sent_requests_inv;
  509. t2 += c->sent_requests_ack;
  510. t3 += c->sent_requests_cnc;
  511. t4 += c->sent_requests_bye;
  512. t5 += c->sent_requests_other;
  513. }
  514. *o->value.integer = t1 + t2 + t3 + t4 + t5;
  515. o->val_len = sizeof(unsigned long);
  516. o->type = SER_COUNTER;
  517. return 0;
  518. }
  519. static int collect_InResp(struct sip_snmp_obj *o, enum handler_op op)
  520. {
  521. register int i;
  522. register struct stats_s *c;
  523. register unsigned long t1, t2, t3, t4, t5, t6, t7;
  524. const char *func = __FUNCTION__;
  525. if(!global_stats || stats_segments == -1) {
  526. LOG(L_ERR, "%s: Can't collect stats, they have not been initialized."
  527. "Did you call init_stats()?\n", func);
  528. return -1;
  529. }
  530. if(op != SER_GET) {
  531. LOG(L_ERR, "%s: Invalid handler operation passed\n", func);
  532. return -1;
  533. }
  534. if(!o->value.integer) {
  535. o->value.integer = calloc(1, sizeof(unsigned long));
  536. if(!o->value.integer) {
  537. LOG(L_ERR, "%s: %s\n", func, strerror(errno));
  538. return -1;
  539. }
  540. }
  541. c = global_stats;
  542. t1 = t2 = t3 = t4 = t5 = t6 = t7 = 0;
  543. for(i=0; i<stats_segments; i++, c++) {
  544. t1 += c->received_responses_1;
  545. t2 += c->received_responses_2;
  546. t3 += c->received_responses_3;
  547. t4 += c->received_responses_4;
  548. t5 += c->received_responses_5;
  549. t6 += c->received_responses_6;
  550. t7 += c->received_responses_other;
  551. }
  552. *o->value.integer = t1 + t2 + t3 + t4 + t5 + t6 + t7;
  553. o->val_len = sizeof(unsigned long);
  554. o->type = SER_COUNTER;
  555. return 0;
  556. }
  557. static int collect_OutResp(struct sip_snmp_obj *o, enum handler_op op)
  558. {
  559. register int i;
  560. register struct stats_s *c;
  561. register unsigned long t1, t2, t3, t4, t5, t6, t7;
  562. const char *func = __FUNCTION__;
  563. if(!global_stats || stats_segments == -1) {
  564. LOG(L_ERR, "%s: Can't collect stats, they have not been initialized\n",
  565. func);
  566. return -1;
  567. }
  568. if(op != SER_GET) {
  569. LOG(L_ERR, "%s: Invalid handler operation passed\n", func);
  570. return -1;
  571. }
  572. if(!o->value.integer) {
  573. o->value.integer = calloc(1, sizeof(unsigned long));
  574. if(!o->value.integer) {
  575. LOG(L_ERR, "%s: %s\n", func, strerror(errno));
  576. return -1;
  577. }
  578. }
  579. c = global_stats;
  580. t1 = t2 = t3 = t4 = t5 = t6 = t7 = 0;
  581. for(i=0; i<stats_segments; i++, c++) {
  582. t1 += c->sent_responses_1;
  583. t2 += c->sent_responses_2;
  584. t3 += c->sent_responses_3;
  585. t4 += c->sent_responses_4;
  586. t5 += c->sent_responses_5;
  587. t6 += c->sent_responses_6;
  588. /* XXX: Not in stats struct
  589. t7 += c->sent_responses_other;
  590. */
  591. }
  592. *o->value.integer = t1 + t2 + t3 + t4 + t5 + t6 + t7;
  593. o->val_len = sizeof(unsigned long);
  594. o->type = SER_COUNTER;
  595. return 0;
  596. }
  597. /***** Handlers for sipMethodStatsTable ******/
  598. /* Collects the specified stat and puts the result in total. s defines
  599. * the starting point in the stats array, normally global_stats */
  600. #define collect_this_stat(stat, total, s) \
  601. for(i=0; i<stats_segments; i++) \
  602. total += s++->stat;
  603. static int sipStatsMethod_handler(struct sip_snmp_obj *o, enum handler_op op)
  604. {
  605. register struct stats_s *c;
  606. register unsigned long total;
  607. register int i;
  608. const char *func = __FUNCTION__;
  609. if(!o) {
  610. LOG(L_ERR, "%s: Invalid sip SNMP object passed\n", func);
  611. return -1;
  612. }
  613. if(!global_stats || stats_segments == -1) {
  614. LOG(L_ERR, "%s: Can't collect stats, they have not been initialized\n",
  615. func);
  616. return -1;
  617. }
  618. if(op != SER_GET) {
  619. LOG(L_ERR, "%s: Invalid handler operation passed\n", func);
  620. return -1;
  621. }
  622. if(!o->value.integer) {
  623. o->value.integer = calloc(1, sizeof(unsigned long));
  624. if(!o->value.integer) {
  625. LOG(L_ERR, "%s: %s\n", func, strerror(errno));
  626. return -1;
  627. }
  628. }
  629. c = global_stats;
  630. total = 0;
  631. switch(o->col) {
  632. /* these definitions are taken from sipMethodStatsHandler */
  633. case COLUMN_SIPSTATSINVITEINS:
  634. collect_this_stat(received_requests_inv, total, c);
  635. break;
  636. case COLUMN_SIPSTATSINVITEOUTS:
  637. collect_this_stat(sent_requests_inv, total, c);
  638. break;
  639. case COLUMN_SIPSTATSACKINS:
  640. collect_this_stat(received_requests_ack, total, c);
  641. break;
  642. case COLUMN_SIPSTATSACKOUTS:
  643. collect_this_stat(sent_requests_ack, total, c);
  644. break;
  645. case COLUMN_SIPSTATSBYEINS:
  646. collect_this_stat(received_requests_bye, total, c);
  647. break;
  648. case COLUMN_SIPSTATSBYEOUTS:
  649. collect_this_stat(sent_requests_bye, total, c);
  650. break;
  651. case COLUMN_SIPSTATSCANCELINS:
  652. collect_this_stat(received_requests_cnc, total, c);
  653. break;
  654. case COLUMN_SIPSTATSCANCELOUTS:
  655. collect_this_stat(sent_requests_cnc, total, c);
  656. break;
  657. /* ser doesn't have notion for these. We don't
  658. * register them with snmp. Here just as remainder */
  659. #if 0
  660. case COLUMN_SIPSTATSOPTIONSINS:
  661. case COLUMN_SIPSTATSOPTIONSOUTS:
  662. case COLUMN_SIPSTATSREGISTERINS:
  663. case COLUMN_SIPSTATSREGISTEROUTS:
  664. case COLUMN_SIPSTATSINFOINS:
  665. case COLUMN_SIPSTATSINFOOUTS:
  666. break;
  667. #endif
  668. }
  669. *o->value.integer = total;
  670. o->val_len = sizeof(unsigned long);
  671. o->type = SER_COUNTER;
  672. return 0;
  673. }
  674. static int sipStatusCodes_handler(struct sip_snmp_obj *o, enum handler_op op)
  675. {
  676. register struct stats_s *c;
  677. register unsigned long total;
  678. register int i;
  679. const char *func = __FUNCTION__;
  680. if(!o) {
  681. LOG(L_ERR, "%s: Invalid sip SNMP object passed\n", func);
  682. return -1;
  683. }
  684. if(!global_stats || stats_segments == -1) {
  685. LOG(L_ERR, "%s: Can't collect stats, they have not been initialized\n",
  686. func);
  687. return -1;
  688. }
  689. if(op != SER_GET) {
  690. LOG(L_ERR, "%s: Invalid handler operation passed\n", func);
  691. return -1;
  692. }
  693. if(!o->value.integer) {
  694. o->value.integer = calloc(1, sizeof(unsigned long));
  695. if(!o->value.integer) {
  696. LOG(L_ERR, "%s: %s\n", func, strerror(errno));
  697. return -1;
  698. }
  699. }
  700. c = global_stats;
  701. total = 0;
  702. switch(o->col) {
  703. case COLUMN_SIPSTATSINFOCLASSINS:
  704. collect_this_stat(received_responses_1, total, c);
  705. break;
  706. case COLUMN_SIPSTATSINFOCLASSOUTS:
  707. collect_this_stat(sent_responses_1, total, c);
  708. break;
  709. case COLUMN_SIPSTATSSUCCESSCLASSINS:
  710. collect_this_stat(received_responses_2, total, c);
  711. break;
  712. case COLUMN_SIPSTATSSUCCESSCLASSOUTS:
  713. collect_this_stat(sent_responses_2, total, c);
  714. break;
  715. case COLUMN_SIPSTATSREDIRCLASSINS:
  716. collect_this_stat(received_responses_3, total, c);
  717. break;
  718. case COLUMN_SIPSTATSREDIRCLASSOUTS:
  719. collect_this_stat(sent_responses_3, total, c);
  720. break;
  721. case COLUMN_SIPSTATSREQFAILCLASSINS:
  722. collect_this_stat(received_responses_4, total, c);
  723. break;
  724. case COLUMN_SIPSTATSREQFAILCLASSOUTS:
  725. collect_this_stat(sent_responses_4, total, c);
  726. break;
  727. case COLUMN_SIPSTATSSERVERFAILCLASSINS:
  728. collect_this_stat(received_responses_5, total, c);
  729. break;
  730. case COLUMN_SIPSTATSSERVERFAILCLASSOUTS:
  731. collect_this_stat(sent_responses_5, total, c);
  732. break;
  733. case COLUMN_SIPSTATSGLOBALFAILCLASSINS:
  734. collect_this_stat(received_responses_6, total, c);
  735. break;
  736. case COLUMN_SIPSTATSGLOBALFAILCLASSOUTS:
  737. collect_this_stat(sent_responses_6, total, c);
  738. break;
  739. case COLUMN_SIPSTATSOTHERCLASSESINS:
  740. collect_this_stat(received_responses_other, total, c);
  741. break;
  742. case COLUMN_SIPSTATSOTHERCLASSESOUTS:
  743. /* FIXME: For some reason this is not defined in
  744. * struct stats_s... */
  745. /* collect_this_stat(sent_responses_other, total, c); */
  746. total = 0;
  747. break;
  748. }
  749. *o->value.integer = total;
  750. o->val_len = sizeof(unsigned long);
  751. o->type = SER_COUNTER;
  752. return 0;
  753. }
  754. #endif