Initially implement the new osmo-mgw and libosmo-mgcp
Leave the old osmo-bsc_mgcp and libosmo-legacy-mgcp as it is; on a copy thereof
(added by a previous commit), apply changes to initially implement the new
osmo-mgw.
Adjust build system and debian packaging to accomodate the new libosmo-mgcp and
osmo-mgw.
The main differences:
*) use a list to manage rtp connections.
Aggregate all rtp related information inside a single struct.
Use a linked list to manage the both connections (net and bts).
The idea behind using a list is that we might support conference
calls at some later point.
Store the linked list in struct mgcp_endpoint, have a private linked
list for each endpoint. The list contains connection items which are
implemented in struct mgcp_conn. A connection is allocated and freed
using the functions in mgcp_conn.c. A connection is allocated on the
reception of a CRCX command and freed with the reception of a DLCX
command.
*) remove external transcoder feature
Fortunatelly the external transcoder feature is not needed
anymore. This patch removes the related code.
*) vty: get rid of CONN_BTS and CONN_NET
Since the new connection model does not make a difference
between BTS and NET connections the VTY should not use
the fixed CONN_BTS and CONN_NET constants.
- Handle the conns list inside the endpoint directly
- introduce function to dump basic rtp connection info
- introduce human readable names for connections
Parts of the code adjusted to use generalized connections instead of explicit
BTS/NET ones:
- teach mgcp_send_dummy() to send dummy packets to any RTP connection
- network: generalize mgcp_bind_net/bts_rtp_port()
- network: generalize mgcp_send()
- tap: generalize call tapping feature
- stat: generalize statistics
- Replace rtp_data_net() and rtp_data_bts() with generalized rtp_data_rx()
*) mgcp_protocol.c fixes:
- check ci string before it is converted:
In case of missing ci, a nullpointer is delivered to strtoul().
Add a function that takes ci, checks it and converts it to an
uint32_t. Use the return code to react on missing ci.
- output error message on missing CI.
- when parsing the mode, print log message when mode is missing.
- use mode_orig when mode is missing.
- fix ptime formatstring to use %u rather than %d.
- cosmetic: log when connection is deleted on DLCX.
- change loglevels of CRCX, MDCX, DLCX events from DEBUG to NOTICE.
*) mgcp_test
- apply rename of strline_r() to mgcp_strline().
- MGCP command macros:
- Add 'I: 1' parameters.
- Use proper port numbers:
from m=audio 0 RTP/AVP 126
to m=audio 16002 RTP/AVP 128
- Change ptime to 'a=ptime:40' because this is what the MGW currently
returns. CRCX generally feed a ptime:40 and this is expected to be
returned.
- struct mgcp_test: Use only one ptype, there are no explicit BTS and NET
endpoints anymore.
Hence remove one column from tests[].
- test_messages():
- Enable: remove '#if 0'
- Remove concept of BTS and NET endpoints: test only one conn, as they are
now interchangeable anyway.
- remove endpoint init, now done internally.
- add false asserts in error cases.
- test_retransmission():
- remove endpoint init, now done internally.
- add false asserts in error cases.
- test_packet_error_detection():
- Remove concept of BTS and NET endpoints: test only one conn, as they are
now interchangeable anyway. Use arbitrary conn ids (e.g. 4711).
- remove endpoint init, now done internally.
- add false assert in error case.
- Assert that a conn really vanishes on DLCX, previously the conn would
remain and just be unused, now it is actually discarded.
- test_no_cycle()
- Remove concept of BTS and NET endpoints: test only one conn, as they are
now interchangeable anyway. Use arbitrary conn ids (e.g. 4711).
- test_no_name()
- Enable: remove '#if 0'.
- remove endpoint init, now done internally.
- add false assert in error case.
- mgcp_test.ok: adjust expected results to status quo:
- We now see two dummy packets instead of one, now sent to both sides because
we don't know of BTS or NET side. (maybe drop dummy packets later...)
- packet duration, conn mode: now sane defaults show instead of unset.
- various whitespace and formatting changes from lindent.
Change-Id: Ie008599136c7ed8a0dfbb0cf803188975a499fc5
diff --git a/src/libosmo-mgcp/mgcp_stat.c b/src/libosmo-mgcp/mgcp_stat.c
new file mode 100644
index 0000000..b84f5f2
--- /dev/null
+++ b/src/libosmo-mgcp/mgcp_stat.c
@@ -0,0 +1,128 @@
+/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
+/* The statistics generator */
+
+/*
+ * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2012 by On-Waves
+ * (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <osmocom/mgcp/mgcp_stat.h>
+#include <limits.h>
+
+/* Helper function for mgcp_format_stats_rtp() to calculate packet loss */
+void calc_loss(struct mgcp_rtp_state *state,
+ struct mgcp_rtp_end *end, uint32_t *expected,
+ int *loss)
+{
+ *expected = state->stats_cycles + state->stats_max_seq;
+ *expected = *expected - state->stats_base_seq + 1;
+
+ if (!state->stats_initialized) {
+ *expected = 0;
+ *loss = 0;
+ return;
+ }
+
+ /*
+ * Make sure the sign is correct and use the biggest
+ * positive/negative number that fits.
+ */
+ *loss = *expected - end->packets_rx;
+ if (*expected < end->packets_rx) {
+ if (*loss > 0)
+ *loss = INT_MIN;
+ } else {
+ if (*loss < 0)
+ *loss = INT_MAX;
+ }
+}
+
+/* Helper function for mgcp_format_stats_rtp() to calculate jitter */
+uint32_t calc_jitter(struct mgcp_rtp_state *state)
+{
+ if (!state->stats_initialized)
+ return 0;
+ return state->stats_jitter >> 4;
+}
+
+/* Generate statistics for an RTP connection */
+static void mgcp_format_stats_rtp(char *str, size_t str_len,
+ struct mgcp_conn_rtp *conn)
+{
+ uint32_t expected, jitter;
+ int ploss;
+ int nchars;
+
+ calc_loss(&conn->state, &conn->end, &expected, &ploss);
+ jitter = calc_jitter(&conn->state);
+
+ nchars = snprintf(str, str_len,
+ "\r\nP: PS=%u, OS=%u, PR=%u, OR=%u, PL=%d, JI=%u",
+ conn->end.packets_tx, conn->end.octets_tx,
+ conn->end.packets_rx, conn->end.octets_rx,
+ ploss, jitter);
+ if (nchars < 0 || nchars >= str_len)
+ goto truncate;
+
+ str += nchars;
+ str_len -= nchars;
+
+ /* Error Counter */
+ nchars = snprintf(str, str_len,
+ "\r\nX-Osmo-CP: EC TI=%u, TO=%u",
+ conn->state.in_stream.err_ts_counter,
+ conn->state.out_stream.err_ts_counter);
+ if (nchars < 0 || nchars >= str_len)
+ goto truncate;
+
+ str += nchars;
+ str_len -= nchars;
+
+ if (conn->osmux.state == OSMUX_STATE_ENABLED) {
+ snprintf(str, str_len,
+ "\r\nX-Osmux-ST: CR=%u, BR=%u",
+ conn->osmux.stats.chunks, conn->osmux.stats.octets);
+ }
+
+truncate:
+ str[str_len - 1] = '\0';
+}
+
+/*! format statistics into an mgcp parameter string.
+ * \param[out] str resulting string
+ * \param[in] str_len length of the string buffer
+ * \param[in] conn connection to evaluate */
+void mgcp_format_stats(char *str, size_t str_len, struct mgcp_conn *conn)
+{
+ memset(str, 0, str_len);
+ if (!conn)
+ return;
+
+ /* NOTE: At the moment we only support generating statistics for
+ * RTP connections. However, in the future we may also want to
+ * generate statistics for other connection types as well. Lets
+ * keep this option open: */
+ switch (conn->type) {
+ case MGCP_CONN_TYPE_RTP:
+ mgcp_format_stats_rtp(str, str_len, &conn->u.rtp);
+ break;
+ default:
+ break;
+ }
+}