blob: 581130c4c003033c2a4ee448c88be66e3081eb34 [file] [log] [blame]
Philipp Maier87bd9be2017-08-22 16:35:41 +02001/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
2/* The statistics generator */
3
4/*
5 * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
6 * (C) 2009-2012 by On-Waves
7 * (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
8 * All Rights Reserved
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Affero General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Affero General Public License for more details.
19 *
20 * You should have received a copy of the GNU Affero General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 *
23 */
24
25#include <osmocom/mgcp/mgcp_stat.h>
Pau Espin Pedrol2da99a22018-02-20 13:11:17 +010026#include <osmocom/mgcp/mgcp_endp.h>
Philipp Maier87bd9be2017-08-22 16:35:41 +020027#include <limits.h>
28
29/* Helper function for mgcp_format_stats_rtp() to calculate packet loss */
30void calc_loss(struct mgcp_rtp_state *state,
31 struct mgcp_rtp_end *end, uint32_t *expected,
32 int *loss)
33{
Harald Welte49e3d5a2017-12-25 09:47:57 +010034 *expected = state->stats.cycles + state->stats.max_seq;
35 *expected = *expected - state->stats.base_seq + 1;
Philipp Maier87bd9be2017-08-22 16:35:41 +020036
Harald Welte49e3d5a2017-12-25 09:47:57 +010037 if (!state->stats.initialized) {
Philipp Maier87bd9be2017-08-22 16:35:41 +020038 *expected = 0;
39 *loss = 0;
40 return;
41 }
42
43 /*
44 * Make sure the sign is correct and use the biggest
45 * positive/negative number that fits.
46 */
Harald Weltea0ac30f2017-12-25 09:52:30 +010047 *loss = *expected - end->stats.packets_rx;
48 if (*expected < end->stats.packets_rx) {
Philipp Maier87bd9be2017-08-22 16:35:41 +020049 if (*loss > 0)
50 *loss = INT_MIN;
51 } else {
52 if (*loss < 0)
53 *loss = INT_MAX;
54 }
55}
56
57/* Helper function for mgcp_format_stats_rtp() to calculate jitter */
58uint32_t calc_jitter(struct mgcp_rtp_state *state)
59{
Harald Welte49e3d5a2017-12-25 09:47:57 +010060 if (!state->stats.initialized)
Philipp Maier87bd9be2017-08-22 16:35:41 +020061 return 0;
Harald Welte49e3d5a2017-12-25 09:47:57 +010062 return state->stats.jitter >> 4;
Philipp Maier87bd9be2017-08-22 16:35:41 +020063}
64
65/* Generate statistics for an RTP connection */
66static void mgcp_format_stats_rtp(char *str, size_t str_len,
67 struct mgcp_conn_rtp *conn)
68{
69 uint32_t expected, jitter;
70 int ploss;
71 int nchars;
72
73 calc_loss(&conn->state, &conn->end, &expected, &ploss);
74 jitter = calc_jitter(&conn->state);
75
76 nchars = snprintf(str, str_len,
77 "\r\nP: PS=%u, OS=%u, PR=%u, OR=%u, PL=%d, JI=%u",
Harald Weltea0ac30f2017-12-25 09:52:30 +010078 conn->end.stats.packets_tx, conn->end.stats.octets_tx,
79 conn->end.stats.packets_rx, conn->end.stats.octets_rx,
Philipp Maier87bd9be2017-08-22 16:35:41 +020080 ploss, jitter);
81 if (nchars < 0 || nchars >= str_len)
82 goto truncate;
83
84 str += nchars;
85 str_len -= nchars;
86
Pau Espin Pedrol2da99a22018-02-20 13:11:17 +010087 if (conn->conn->endp->cfg->osmux != OSMUX_USAGE_OFF) {
88 /* Error Counter */
89 nchars = snprintf(str, str_len,
90 "\r\nX-Osmo-CP: EC TI=%u, TO=%u",
91 conn->state.in_stream.err_ts_counter,
92 conn->state.out_stream.err_ts_counter);
93 if (nchars < 0 || nchars >= str_len)
94 goto truncate;
Philipp Maier87bd9be2017-08-22 16:35:41 +020095
Pau Espin Pedrol2da99a22018-02-20 13:11:17 +010096 str += nchars;
97 str_len -= nchars;
Philipp Maier87bd9be2017-08-22 16:35:41 +020098
Pau Espin Pedrol2da99a22018-02-20 13:11:17 +010099 if (conn->osmux.state == OSMUX_STATE_ENABLED) {
100 snprintf(str, str_len,
101 "\r\nX-Osmux-ST: CR=%u, BR=%u",
102 conn->osmux.stats.chunks, conn->osmux.stats.octets);
103 }
Philipp Maier87bd9be2017-08-22 16:35:41 +0200104 }
105
106truncate:
107 str[str_len - 1] = '\0';
108}
109
110/*! format statistics into an mgcp parameter string.
111 * \param[out] str resulting string
112 * \param[in] str_len length of the string buffer
113 * \param[in] conn connection to evaluate */
114void mgcp_format_stats(char *str, size_t str_len, struct mgcp_conn *conn)
115{
116 memset(str, 0, str_len);
117 if (!conn)
118 return;
119
120 /* NOTE: At the moment we only support generating statistics for
121 * RTP connections. However, in the future we may also want to
122 * generate statistics for other connection types as well. Lets
123 * keep this option open: */
124 switch (conn->type) {
125 case MGCP_CONN_TYPE_RTP:
126 mgcp_format_stats_rtp(str, str_len, &conn->u.rtp);
127 break;
128 default:
129 break;
130 }
131}