stats.c 23 KB

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