blob: 4072ac06710d89dc04b4fe16aa0cdfa6ad2acba9 [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 */
Philipp Maiercede2a42018-07-03 14:14:21 +020030void calc_loss(struct mgcp_conn_rtp *conn, uint32_t *expected, int *loss)
Philipp Maier87bd9be2017-08-22 16:35:41 +020031{
Philipp Maiercede2a42018-07-03 14:14:21 +020032 struct mgcp_rtp_state *state = &conn->state;
33 struct rate_ctr *packets_rx = &conn->rate_ctr_group->ctr[RTP_PACKETS_RX_CTR];
34
Harald Welte49e3d5a2017-12-25 09:47:57 +010035 *expected = state->stats.cycles + state->stats.max_seq;
36 *expected = *expected - state->stats.base_seq + 1;
Philipp Maier87bd9be2017-08-22 16:35:41 +020037
Harald Welte49e3d5a2017-12-25 09:47:57 +010038 if (!state->stats.initialized) {
Philipp Maier87bd9be2017-08-22 16:35:41 +020039 *expected = 0;
40 *loss = 0;
41 return;
42 }
43
44 /*
45 * Make sure the sign is correct and use the biggest
46 * positive/negative number that fits.
47 */
Philipp Maiercede2a42018-07-03 14:14:21 +020048 *loss = *expected - packets_rx->current;
49 if (*expected < packets_rx->current) {
Philipp Maier87bd9be2017-08-22 16:35:41 +020050 if (*loss > 0)
51 *loss = INT_MIN;
52 } else {
53 if (*loss < 0)
54 *loss = INT_MAX;
55 }
56}
57
58/* Helper function for mgcp_format_stats_rtp() to calculate jitter */
59uint32_t calc_jitter(struct mgcp_rtp_state *state)
60{
Harald Welte49e3d5a2017-12-25 09:47:57 +010061 if (!state->stats.initialized)
Philipp Maier87bd9be2017-08-22 16:35:41 +020062 return 0;
Harald Welte49e3d5a2017-12-25 09:47:57 +010063 return state->stats.jitter >> 4;
Philipp Maier87bd9be2017-08-22 16:35:41 +020064}
65
66/* Generate statistics for an RTP connection */
67static void mgcp_format_stats_rtp(char *str, size_t str_len,
68 struct mgcp_conn_rtp *conn)
69{
70 uint32_t expected, jitter;
71 int ploss;
72 int nchars;
73
Philipp Maiercede2a42018-07-03 14:14:21 +020074 struct rate_ctr *packets_rx = &conn->rate_ctr_group->ctr[RTP_PACKETS_RX_CTR];
75 struct rate_ctr *octets_rx = &conn->rate_ctr_group->ctr[RTP_OCTETS_RX_CTR];
76 struct rate_ctr *packets_tx = &conn->rate_ctr_group->ctr[RTP_PACKETS_TX_CTR];
77 struct rate_ctr *octets_tx = &conn->rate_ctr_group->ctr[RTP_OCTETS_TX_CTR];
78
79 calc_loss(conn, &expected, &ploss);
Philipp Maier87bd9be2017-08-22 16:35:41 +020080 jitter = calc_jitter(&conn->state);
81
82 nchars = snprintf(str, str_len,
Philipp Maiercede2a42018-07-03 14:14:21 +020083 "\r\nP: PS=%lu, OS=%lu, PR=%lu, OR=%lu, PL=%d, JI=%u",
84 packets_tx->current, octets_tx->current,
85 packets_rx->current, octets_rx->current,
Philipp Maier87bd9be2017-08-22 16:35:41 +020086 ploss, jitter);
87 if (nchars < 0 || nchars >= str_len)
88 goto truncate;
89
90 str += nchars;
91 str_len -= nchars;
92
Pau Espin Pedrol2da99a22018-02-20 13:11:17 +010093 if (conn->conn->endp->cfg->osmux != OSMUX_USAGE_OFF) {
94 /* Error Counter */
95 nchars = snprintf(str, str_len,
Philipp Maier9e1d1642018-05-09 16:26:34 +020096 "\r\nX-Osmo-CP: EC TI=%lu, TO=%lu",
97 conn->state.in_stream.err_ts_ctr->current,
98 conn->state.out_stream.err_ts_ctr->current);
Pau Espin Pedrol2da99a22018-02-20 13:11:17 +010099 if (nchars < 0 || nchars >= str_len)
100 goto truncate;
Philipp Maier87bd9be2017-08-22 16:35:41 +0200101
Pau Espin Pedrol2da99a22018-02-20 13:11:17 +0100102 str += nchars;
103 str_len -= nchars;
Philipp Maier87bd9be2017-08-22 16:35:41 +0200104
Pau Espin Pedrol2da99a22018-02-20 13:11:17 +0100105 if (conn->osmux.state == OSMUX_STATE_ENABLED) {
106 snprintf(str, str_len,
107 "\r\nX-Osmux-ST: CR=%u, BR=%u",
108 conn->osmux.stats.chunks, conn->osmux.stats.octets);
109 }
Philipp Maier87bd9be2017-08-22 16:35:41 +0200110 }
111
112truncate:
113 str[str_len - 1] = '\0';
114}
115
116/*! format statistics into an mgcp parameter string.
117 * \param[out] str resulting string
118 * \param[in] str_len length of the string buffer
119 * \param[in] conn connection to evaluate */
120void mgcp_format_stats(char *str, size_t str_len, struct mgcp_conn *conn)
121{
122 memset(str, 0, str_len);
123 if (!conn)
124 return;
125
126 /* NOTE: At the moment we only support generating statistics for
127 * RTP connections. However, in the future we may also want to
128 * generate statistics for other connection types as well. Lets
129 * keep this option open: */
130 switch (conn->type) {
131 case MGCP_CONN_TYPE_RTP:
132 mgcp_format_stats_rtp(str, str_len, &conn->u.rtp);
133 break;
134 default:
135 break;
136 }
137}