blob: 8f3703fbe7b97f998bf267af712b882c54cb8e4b [file] [log] [blame]
Philipp Maierc66ab2c2020-06-02 20:55:34 +02001/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
2/* rate-counter implementation */
3
4/*
5 * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
6 * (C) 2009-2012 by On-Waves
7 * (C) 2017-2020 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 <errno.h>
26#include <osmocom/core/stats.h>
Philipp Maier993ea6b2020-08-04 18:26:50 +020027#include <osmocom/mgcp/mgcp_conn.h>
Philipp Maierc66ab2c2020-06-02 20:55:34 +020028#include <osmocom/mgcp/mgcp_ratectr.h>
29
30static const struct rate_ctr_desc mgcp_general_ctr_desc[] = {
31 /* rx_msgs = rx_msgs_retransmitted + rx_msgs_handled + rx_msgs_unhandled + err_rx_msg_parse + err_rx_no_endpoint */
32 [MGCP_GENERAL_RX_MSGS_TOTAL] = { "mgcp:rx_msgs", "total number of MGCP messages received." },
33 [MGCP_GENERAL_RX_MSGS_RETRANSMITTED] = { "mgcp:rx_msgs_retransmitted", "number of received retransmissions." },
34 [MGCP_GENERAL_RX_MSGS_HANDLED] = { "mgcp:rx_msgs_handled", "number of handled MGCP messages." },
35 [MGCP_GENERAL_RX_MSGS_UNHANDLED] = { "mgcp:rx_msgs_unhandled", "number of unhandled MGCP messages." },
36 [MGCP_GENERAL_RX_FAIL_MSG_PARSE] = { "mgcp:err_rx_msg_parse", "error parsing MGCP message." },
37 [MGCP_GENERAL_RX_FAIL_NO_ENDPOINT] =
38 { "mgcp:err_rx_no_endpoint", "can't find MGCP endpoint, probably we've used all allocated endpoints." },
39};
40
41const static struct rate_ctr_group_desc mgcp_general_ctr_group_desc = {
42 .group_name_prefix = "mgcp",
43 .group_description = "mgcp general statistics",
44 .class_id = OSMO_STATS_CLASS_GLOBAL,
45 .num_ctr = ARRAY_SIZE(mgcp_general_ctr_desc),
46 .ctr_desc = mgcp_general_ctr_desc
47};
48
49static const struct rate_ctr_desc mgcp_crcx_ctr_desc[] = {
50 [MGCP_CRCX_SUCCESS] = { "crcx:success", "CRCX command processed successfully." },
51 [MGCP_CRCX_FAIL_BAD_ACTION] = { "crcx:bad_action", "bad action in CRCX command." },
52 [MGCP_CRCX_FAIL_UNHANDLED_PARAM] = { "crcx:unhandled_param", "unhandled parameter in CRCX command." },
53 [MGCP_CRCX_FAIL_MISSING_CALLID] = { "crcx:missing_callid", "missing CallId in CRCX command." },
54 [MGCP_CRCX_FAIL_INVALID_MODE] = { "crcx:invalid_mode", "invalid connection mode in CRCX command." },
55 [MGCP_CRCX_FAIL_LIMIT_EXCEEDED] = { "crcx:limit_exceeded", "limit of concurrent connections was reached." },
56 [MGCP_CRCX_FAIL_UNKNOWN_CALLID] = { "crcx:unkown_callid", "unknown CallId in CRCX command." },
57 [MGCP_CRCX_FAIL_ALLOC_CONN] = { "crcx:alloc_conn_fail", "connection allocation failure." },
58 [MGCP_CRCX_FAIL_NO_REMOTE_CONN_DESC] =
59 { "crcx:no_remote_conn_desc", "no opposite end specified for connection." },
60 [MGCP_CRCX_FAIL_START_RTP] = { "crcx:start_rtp_failure", "failure to start RTP processing." },
61 [MGCP_CRCX_FAIL_REJECTED_BY_POLICY] = { "crcx:conn_rejected", "connection rejected by policy." },
62 [MGCP_CRCX_FAIL_NO_OSMUX] = { "crcx:no_osmux", "no osmux offered by peer." },
63 [MGCP_CRCX_FAIL_INVALID_CONN_OPTIONS] = { "crcx:conn_opt", "connection options invalid." },
64 [MGCP_CRCX_FAIL_CODEC_NEGOTIATION] = { "crcx:codec_nego", "codec negotiation failure." },
65 [MGCP_CRCX_FAIL_BIND_PORT] = { "crcx:bind_port", "port bind failure." },
Philipp Maier8d6a1932020-06-18 12:19:31 +020066 [MGCP_CRCX_FAIL_AVAIL] = { "crcx:unavailable", "endpoint unavailable." },
Philipp Maier889fe7f2020-07-06 17:44:12 +020067 [MGCP_CRCX_FAIL_CLAIM] = { "crcx:claim", "endpoint can not be claimed." },
Philipp Maierc66ab2c2020-06-02 20:55:34 +020068};
69
70const static struct rate_ctr_group_desc mgcp_crcx_ctr_group_desc = {
71 .group_name_prefix = "crcx",
72 .group_description = "crxc statistics",
73 .class_id = OSMO_STATS_CLASS_GLOBAL,
74 .num_ctr = ARRAY_SIZE(mgcp_crcx_ctr_desc),
75 .ctr_desc = mgcp_crcx_ctr_desc
76};
77
78static const struct rate_ctr_desc mgcp_mdcx_ctr_desc[] = {
79 [MGCP_MDCX_SUCCESS] = { "mdcx:success", "MDCX command processed successfully." },
80 [MGCP_MDCX_FAIL_WILDCARD] = { "mdcx:wildcard", "wildcard endpoint names in MDCX commands are unsupported." },
81 [MGCP_MDCX_FAIL_NO_CONN] = { "mdcx:no_conn", "endpoint specified in MDCX command has no active connections." },
82 [MGCP_MDCX_FAIL_INVALID_CALLID] = { "mdcx:callid", "invalid CallId specified in MDCX command." },
83 [MGCP_MDCX_FAIL_INVALID_CONNID] = { "mdcx:connid", "invalid connection ID specified in MDCX command." },
84 [MGCP_MDCX_FAIL_UNHANDLED_PARAM] = { "crcx:unhandled_param", "unhandled parameter in MDCX command." },
85 [MGCP_MDCX_FAIL_NO_CONNID] = { "mdcx:no_connid", "no connection ID specified in MDCX command." },
86 [MGCP_MDCX_FAIL_CONN_NOT_FOUND] =
87 { "mdcx:conn_not_found", "connection specified in MDCX command does not exist." },
88 [MGCP_MDCX_FAIL_INVALID_MODE] = { "mdcx:invalid_mode", "invalid connection mode in MDCX command." },
89 [MGCP_MDCX_FAIL_INVALID_CONN_OPTIONS] = { "mdcx:conn_opt", "connection options invalid." },
90 [MGCP_MDCX_FAIL_NO_REMOTE_CONN_DESC] =
91 { "mdcx:no_remote_conn_desc", "no opposite end specified for connection." },
92 [MGCP_MDCX_FAIL_START_RTP] = { "mdcx:start_rtp_failure", "failure to start RTP processing." },
93 [MGCP_MDCX_FAIL_REJECTED_BY_POLICY] = { "mdcx:conn_rejected", "connection rejected by policy." },
94 [MGCP_MDCX_DEFERRED_BY_POLICY] = { "mdcx:conn_deferred", "connection deferred by policy." },
Philipp Maier8d6a1932020-06-18 12:19:31 +020095 [MGCP_MDCX_FAIL_AVAIL] = { "mdcx:unavailable", "endpoint unavailable." },
Philipp Maierc66ab2c2020-06-02 20:55:34 +020096};
97
98const static struct rate_ctr_group_desc mgcp_mdcx_ctr_group_desc = {
99 .group_name_prefix = "mdcx",
100 .group_description = "mdcx statistics",
101 .class_id = OSMO_STATS_CLASS_GLOBAL,
102 .num_ctr = ARRAY_SIZE(mgcp_mdcx_ctr_desc),
103 .ctr_desc = mgcp_mdcx_ctr_desc
104};
105
106static const struct rate_ctr_desc mgcp_dlcx_ctr_desc[] = {
107 [MGCP_DLCX_SUCCESS] = { "dlcx:success", "DLCX command processed successfully." },
108 [MGCP_DLCX_FAIL_WILDCARD] = { "dlcx:wildcard", "wildcard names in DLCX commands are unsupported." },
109 [MGCP_DLCX_FAIL_NO_CONN] = { "dlcx:no_conn", "endpoint specified in DLCX command has no active connections." },
110 [MGCP_DLCX_FAIL_INVALID_CALLID] =
111 { "dlcx:callid", "CallId specified in DLCX command mismatches endpoint's CallId ." },
112 [MGCP_DLCX_FAIL_INVALID_CONNID] =
113 { "dlcx:connid", "connection ID specified in DLCX command does not exist on endpoint." },
114 [MGCP_DLCX_FAIL_UNHANDLED_PARAM] = { "dlcx:unhandled_param", "unhandled parameter in DLCX command." },
115 [MGCP_DLCX_FAIL_REJECTED_BY_POLICY] = { "dlcx:rejected", "connection deletion rejected by policy." },
116 [MGCP_DLCX_DEFERRED_BY_POLICY] = { "dlcx:deferred", "connection deletion deferred by policy." },
Philipp Maier8d6a1932020-06-18 12:19:31 +0200117 [MGCP_DLCX_FAIL_AVAIL] = { "dlcx:unavailable", "endpoint unavailable." },
Philipp Maierc66ab2c2020-06-02 20:55:34 +0200118};
119
120const static struct rate_ctr_group_desc mgcp_dlcx_ctr_group_desc = {
121 .group_name_prefix = "dlcx",
122 .group_description = "dlcx statistics",
123 .class_id = OSMO_STATS_CLASS_GLOBAL,
124 .num_ctr = ARRAY_SIZE(mgcp_dlcx_ctr_desc),
125 .ctr_desc = mgcp_dlcx_ctr_desc
126};
127
Philipp Maier889fe7f2020-07-06 17:44:12 +0200128static const struct rate_ctr_desc e1_rate_ctr_desc[] = {
Philipp Maier97cae472021-07-09 13:26:47 +0200129 [E1_I460_TRAU_RX_FAIL_CTR] = { "e1:rx_fail", "Inbound I.460 TRAU failures." },
130 [E1_I460_TRAU_TX_FAIL_CTR] = { "e1:tx_fail", "Outbound I.460 TRAU failures." },
131 [E1_I460_TRAU_MUX_EMPTY_CTR] = { "e1:i460", "Outbound I.460 MUX queue empty." }
Philipp Maier889fe7f2020-07-06 17:44:12 +0200132};
133
134const static struct rate_ctr_group_desc e1_rate_ctr_group_desc = {
135 .group_name_prefix = "e1",
136 .group_description = "e1 statistics",
137 .class_id = OSMO_STATS_CLASS_GLOBAL,
138 .num_ctr = ARRAY_SIZE(e1_rate_ctr_desc),
139 .ctr_desc = e1_rate_ctr_desc
140};
141
Philipp Maierc66ab2c2020-06-02 20:55:34 +0200142const static struct rate_ctr_group_desc all_rtp_conn_rate_ctr_group_desc = {
143 .group_name_prefix = "all_rtp_conn",
144 .group_description = "aggregated statistics for all rtp connections",
145 .class_id = 1,
146 .num_ctr = ARRAY_SIZE(all_rtp_conn_rate_ctr_desc),
147 .ctr_desc = all_rtp_conn_rate_ctr_desc
148};
149
150static int free_rate_counter_group(struct rate_ctr_group *rate_ctr_group)
151{
152 rate_ctr_group_free(rate_ctr_group);
153 return 0;
154}
155
156/*! allocate global rate counters into a given rate counter struct
157 * (called once at startup)
158 * \param[in] ctx talloc context.
159 * \param[out] ratectr struct that holds the counters
160 * \returns 0 on success, -EINVAL on failure */
161int mgcp_ratectr_global_alloc(void *ctx, struct mgcp_ratectr_global *ratectr)
162{
163 /* FIXME: Each new rate counter group requires a unique index. At the
164 * moment we generate an index using a counter, but perhaps there is
165 * a better way of assigning indices? */
166 static unsigned int general_rate_ctr_index = 0;
167
168 if (ratectr->mgcp_general_ctr_group == NULL) {
169 ratectr->mgcp_general_ctr_group =
170 rate_ctr_group_alloc(ctx, &mgcp_general_ctr_group_desc, general_rate_ctr_index);
171 if (!ratectr->mgcp_general_ctr_group)
172 return -EINVAL;
173 talloc_set_destructor(ratectr->mgcp_general_ctr_group, free_rate_counter_group);
174 general_rate_ctr_index++;
175 }
176 return 0;
177}
178
179/*! allocate trunk specific rate counters into a given rate counter struct
180 * (called once on trunk initialization)
181 * \param[in] ctx talloc context.
182 * \param[out] ratectr struct that holds the counters
183 * \returns 0 on success, -EINVAL on failure */
184int mgcp_ratectr_trunk_alloc(void *ctx, struct mgcp_ratectr_trunk *ratectr)
185{
186 /* FIXME: see comment in mgcp_ratectr_global_alloc() */
187 static unsigned int crcx_rate_ctr_index = 0;
188 static unsigned int mdcx_rate_ctr_index = 0;
189 static unsigned int dlcx_rate_ctr_index = 0;
190 static unsigned int all_rtp_conn_rate_ctr_index = 0;
191
192 if (ratectr->mgcp_crcx_ctr_group == NULL) {
193 ratectr->mgcp_crcx_ctr_group = rate_ctr_group_alloc(ctx, &mgcp_crcx_ctr_group_desc, crcx_rate_ctr_index);
194 if (!ratectr->mgcp_crcx_ctr_group)
195 return -EINVAL;
196 talloc_set_destructor(ratectr->mgcp_crcx_ctr_group, free_rate_counter_group);
197 crcx_rate_ctr_index++;
198 }
199 if (ratectr->mgcp_mdcx_ctr_group == NULL) {
200 ratectr->mgcp_mdcx_ctr_group = rate_ctr_group_alloc(ctx, &mgcp_mdcx_ctr_group_desc, mdcx_rate_ctr_index);
201 if (!ratectr->mgcp_mdcx_ctr_group)
202 return -EINVAL;
203 talloc_set_destructor(ratectr->mgcp_mdcx_ctr_group, free_rate_counter_group);
204 mdcx_rate_ctr_index++;
205 }
206 if (ratectr->mgcp_dlcx_ctr_group == NULL) {
207 ratectr->mgcp_dlcx_ctr_group = rate_ctr_group_alloc(ctx, &mgcp_dlcx_ctr_group_desc, dlcx_rate_ctr_index);
208 if (!ratectr->mgcp_dlcx_ctr_group)
209 return -EINVAL;
210 talloc_set_destructor(ratectr->mgcp_dlcx_ctr_group, free_rate_counter_group);
211 dlcx_rate_ctr_index++;
212 }
213 if (ratectr->all_rtp_conn_stats == NULL) {
214 ratectr->all_rtp_conn_stats = rate_ctr_group_alloc(ctx, &all_rtp_conn_rate_ctr_group_desc,
215 all_rtp_conn_rate_ctr_index);
216 if (!ratectr->all_rtp_conn_stats)
217 return -EINVAL;
218 talloc_set_destructor(ratectr->all_rtp_conn_stats, free_rate_counter_group);
219 all_rtp_conn_rate_ctr_index++;
220 }
Philipp Maier889fe7f2020-07-06 17:44:12 +0200221 if (ratectr->e1_stats == NULL) {
222 ratectr->e1_stats = rate_ctr_group_alloc(ctx, &e1_rate_ctr_group_desc, mdcx_rate_ctr_index);
223 if (!ratectr->e1_stats)
224 return -EINVAL;
225 talloc_set_destructor(ratectr->e1_stats, free_rate_counter_group);
226 mdcx_rate_ctr_index++;
227 }
Philipp Maierc66ab2c2020-06-02 20:55:34 +0200228 return 0;
229}