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/include/osmocom/mgcp/mgcp_internal.h b/include/osmocom/mgcp/mgcp_internal.h
index dcc75f1..3a22d51 100644
--- a/include/osmocom/mgcp/mgcp_internal.h
+++ b/include/osmocom/mgcp/mgcp_internal.h
@@ -23,11 +23,16 @@
#pragma once
#include <string.h>
-
+#include <inttypes.h>
#include <osmocom/core/select.h>
+#include <osmocom/mgcp/mgcp.h>
+#include <osmocom/core/linuxlist.h>
#define CI_UNUSED 0
+#define CONN_ID_BTS 0
+#define CONN_ID_NET 1
+
enum mgcp_trunk_type {
MGCP_TRUNK_VIRTUAL,
MGCP_TRUNK_E1,
@@ -80,8 +85,10 @@
struct mgcp_rtp_end {
/* statistics */
- unsigned int packets;
- unsigned int octets;
+ unsigned int packets_rx;
+ unsigned int octets_rx;
+ unsigned int packets_tx;
+ unsigned int octets_tx;
unsigned int dropped_packets;
struct in_addr addr;
@@ -104,24 +111,11 @@
int force_aligned_timing;
void *rtp_process_data;
- /*
- * Each end has a socket...
- */
+ /* Each end has a separate socket for RTP and RTCP */
struct osmo_fd rtp;
struct osmo_fd rtcp;
int local_port;
- int local_alloc;
-};
-
-enum {
- MGCP_TAP_BTS_IN,
- MGCP_TAP_BTS_OUT,
- MGCP_TAP_NET_IN,
- MGCP_TAP_NET_OUT,
-
- /* last element */
- MGCP_TAP_COUNT
};
struct mgcp_rtp_tap {
@@ -136,51 +130,36 @@
int pkt_period_max; /* time in ms */
};
-enum mgcp_type {
+/* Specific rtp connection type (see struct mgcp_conn_rtp) */
+enum mgcp_conn_rtp_type {
MGCP_RTP_DEFAULT = 0,
- MGCP_RTP_TRANSCODED,
MGCP_OSMUX_BSC,
MGCP_OSMUX_BSC_NAT,
};
-#include <osmocom/legacy_mgcp/osmux.h>
+#include <osmocom/mgcp/osmux.h>
+struct mgcp_conn;
-struct mgcp_endpoint {
- int allocated;
- uint32_t ci;
- char *callid;
- struct mgcp_lco local_options;
- int conn_mode;
- int orig_mode;
+/* MGCP connection (RTP) */
+struct mgcp_conn_rtp {
- /* backpointer */
- struct mgcp_config *cfg;
- struct mgcp_trunk_config *tcfg;
+ /* Backpointer to conn struct */
+ struct mgcp_conn *conn;
- /* port status for bts/net */
- struct mgcp_rtp_end bts_end;
- struct mgcp_rtp_end net_end;
+ /* Specific connection type */
+ enum mgcp_conn_rtp_type type;
- /*
- * For transcoding we will send from the local_port
- * of trans_bts and it will arrive at trans_net from
- * where we will forward it to the network.
- */
- struct mgcp_rtp_end trans_bts;
- struct mgcp_rtp_end trans_net;
- enum mgcp_type type;
+ /* Port status */
+ struct mgcp_rtp_end end;
- /* sequence bits */
- struct mgcp_rtp_state net_state;
- struct mgcp_rtp_state bts_state;
+ /* Sequence bits */
+ struct mgcp_rtp_state state;
- /* fields for re-transmission */
- char *last_trans;
- char *last_response;
+ /* taps for the rtp connection */
+ struct mgcp_rtp_tap tap_in;
+ struct mgcp_rtp_tap tap_out;
- /* tap for the endpoint */
- struct mgcp_rtp_tap taps[MGCP_TAP_COUNT];
-
+ /* Osmux states (optional) */
struct {
/* Osmux state: disabled, activating, active */
enum osmux_state state;
@@ -200,38 +179,64 @@
} osmux;
};
-#define for_each_line(line, save) \
- for (line = strline_r(NULL, &save); line;\
- line = strline_r(NULL, &save))
+/*! Connection type, specifies which member of the union "u" in mgcp_conn
+ * contains a useful connection description (currently only RTP) */
+enum mgcp_conn_type {
+ MGCP_CONN_TYPE_RTP,
+};
-static inline char *strline_r(char *str, char **saveptr)
-{
- char *result;
+/*! MGCP connection (untyped) */
+struct mgcp_conn {
+ /*!< list head */
+ struct llist_head entry;
- if (str)
- *saveptr = str;
+ /*!< Backpointer to the endpoint where the conn belongs to */
+ struct mgcp_endpoint *endp;
- result = *saveptr;
+ /*!< type of the connection (union) */
+ enum mgcp_conn_type type;
- if (*saveptr != NULL) {
- *saveptr = strpbrk(*saveptr, "\r\n");
+ /*!< mode of the connection */
+ enum mgcp_connection_mode mode;
- if (*saveptr != NULL) {
- char *eos = *saveptr;
+ /*!< copy of the mode to restore the original setting (VTY) */
+ enum mgcp_connection_mode mode_orig;
- if ((*saveptr)[0] == '\r' && (*saveptr)[1] == '\n')
- (*saveptr)++;
- (*saveptr)++;
- if ((*saveptr)[0] == '\0')
- *saveptr = NULL;
+ /*!< connection id to identify the conntion */
+ uint32_t id;
- *eos = '\0';
- }
- }
+ /*!< human readable name (vty, logging) */
+ char name[256];
- return result;
-}
+ /*!< union with connection description */
+ union {
+ struct mgcp_conn_rtp rtp;
+ } u;
+ /*!< pointer to optional private data */
+ void *priv;
+};
+
+#include <osmocom/mgcp/mgcp_conn.h>
+
+struct mgcp_endpoint_type;
+
+struct mgcp_endpoint {
+ char *callid;
+ struct mgcp_lco local_options;
+
+ struct llist_head conns;
+
+ /* backpointer */
+ struct mgcp_config *cfg;
+ struct mgcp_trunk_config *tcfg;
+
+ const struct mgcp_endpoint_type *type;
+
+ /* fields for re-transmission */
+ char *last_trans;
+ char *last_response;
+};
#define ENDPOINT_NUMBER(endp) abs((int)(endp - endp->tcfg->endpoints))
@@ -247,12 +252,15 @@
int found;
};
-int mgcp_send_dummy(struct mgcp_endpoint *endp);
-int mgcp_bind_bts_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
-int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
-int mgcp_bind_trans_bts_rtp_port(struct mgcp_endpoint *enp, int rtp_port);
-int mgcp_bind_trans_net_rtp_port(struct mgcp_endpoint *enp, int rtp_port);
-int mgcp_free_rtp_port(struct mgcp_rtp_end *end);
+int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
+ char *buf, int rc, struct mgcp_conn_rtp *conn_src,
+ struct mgcp_conn_rtp *conn_dst);
+int mgcp_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn);
+int mgcp_dispatch_rtp_bridge_cb(int proto, struct sockaddr_in *addr, char *buf,
+ unsigned int buf_size, struct mgcp_conn *conn);
+int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port,
+ struct mgcp_conn_rtp *conn);
+void mgcp_free_rtp_port(struct mgcp_rtp_end *end);
/* For transcoding we need to manage an in and an output that are connected */
static inline int endp_back_channel(int endpoint)
@@ -268,10 +276,6 @@
uint32_t mgcp_rtp_packet_duration(struct mgcp_endpoint *endp,
struct mgcp_rtp_end *rtp);
-void mgcp_state_calc_loss(struct mgcp_rtp_state *s, struct mgcp_rtp_end *,
- uint32_t *expected, int *loss);
-uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *);
-
/* payload processing default functions */
int mgcp_rtp_processing_default(struct mgcp_endpoint *endp, struct mgcp_rtp_end *dst_end,
char *data, int *len, int buf_size);
@@ -282,8 +286,9 @@
void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp,
int *payload_type,
- const char**subtype_name,
- const char**fmtp_extra);
+ const char**audio_name,
+ const char**fmtp_extra,
+ struct mgcp_conn_rtp *conn);
/* internal RTP Annex A counting */
void mgcp_rtp_annex_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
@@ -316,10 +321,9 @@
int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
int payload_type, const char *audio_name);
-
-/**
- * Internal network related
- */
+/*! get the ip-address where the mgw application is bound on.
+ * \param[in] endp mgcp endpoint, that holds a copy of the VTY parameters
+ * \returns pointer to a string that contains the source ip-address */
static inline const char *mgcp_net_src_addr(struct mgcp_endpoint *endp)
{
if (endp->cfg->net_ports.bind_addr)
@@ -327,11 +331,4 @@
return endp->cfg->source_addr;
}
-static inline const char *mgcp_bts_src_addr(struct mgcp_endpoint *endp)
-{
- if (endp->cfg->bts_ports.bind_addr)
- return endp->cfg->bts_ports.bind_addr;
- return endp->cfg->source_addr;
-}
-
int mgcp_msg_terminate_nul(struct msgb *msg);