blob: b84f5f252ddb7cac387fbef93c8085449b2072d1 [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>
26#include <limits.h>
27
28/* Helper function for mgcp_format_stats_rtp() to calculate packet loss */
29void calc_loss(struct mgcp_rtp_state *state,
30 struct mgcp_rtp_end *end, uint32_t *expected,
31 int *loss)
32{
33 *expected = state->stats_cycles + state->stats_max_seq;
34 *expected = *expected - state->stats_base_seq + 1;
35
36 if (!state->stats_initialized) {
37 *expected = 0;
38 *loss = 0;
39 return;
40 }
41
42 /*
43 * Make sure the sign is correct and use the biggest
44 * positive/negative number that fits.
45 */
46 *loss = *expected - end->packets_rx;
47 if (*expected < end->packets_rx) {
48 if (*loss > 0)
49 *loss = INT_MIN;
50 } else {
51 if (*loss < 0)
52 *loss = INT_MAX;
53 }
54}
55
56/* Helper function for mgcp_format_stats_rtp() to calculate jitter */
57uint32_t calc_jitter(struct mgcp_rtp_state *state)
58{
59 if (!state->stats_initialized)
60 return 0;
61 return state->stats_jitter >> 4;
62}
63
64/* Generate statistics for an RTP connection */
65static void mgcp_format_stats_rtp(char *str, size_t str_len,
66 struct mgcp_conn_rtp *conn)
67{
68 uint32_t expected, jitter;
69 int ploss;
70 int nchars;
71
72 calc_loss(&conn->state, &conn->end, &expected, &ploss);
73 jitter = calc_jitter(&conn->state);
74
75 nchars = snprintf(str, str_len,
76 "\r\nP: PS=%u, OS=%u, PR=%u, OR=%u, PL=%d, JI=%u",
77 conn->end.packets_tx, conn->end.octets_tx,
78 conn->end.packets_rx, conn->end.octets_rx,
79 ploss, jitter);
80 if (nchars < 0 || nchars >= str_len)
81 goto truncate;
82
83 str += nchars;
84 str_len -= nchars;
85
86 /* Error Counter */
87 nchars = snprintf(str, str_len,
88 "\r\nX-Osmo-CP: EC TI=%u, TO=%u",
89 conn->state.in_stream.err_ts_counter,
90 conn->state.out_stream.err_ts_counter);
91 if (nchars < 0 || nchars >= str_len)
92 goto truncate;
93
94 str += nchars;
95 str_len -= nchars;
96
97 if (conn->osmux.state == OSMUX_STATE_ENABLED) {
98 snprintf(str, str_len,
99 "\r\nX-Osmux-ST: CR=%u, BR=%u",
100 conn->osmux.stats.chunks, conn->osmux.stats.octets);
101 }
102
103truncate:
104 str[str_len - 1] = '\0';
105}
106
107/*! format statistics into an mgcp parameter string.
108 * \param[out] str resulting string
109 * \param[in] str_len length of the string buffer
110 * \param[in] conn connection to evaluate */
111void mgcp_format_stats(char *str, size_t str_len, struct mgcp_conn *conn)
112{
113 memset(str, 0, str_len);
114 if (!conn)
115 return;
116
117 /* NOTE: At the moment we only support generating statistics for
118 * RTP connections. However, in the future we may also want to
119 * generate statistics for other connection types as well. Lets
120 * keep this option open: */
121 switch (conn->type) {
122 case MGCP_CONN_TYPE_RTP:
123 mgcp_format_stats_rtp(str, str_len, &conn->u.rtp);
124 break;
125 default:
126 break;
127 }
128}