<p>dexter <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-mgw/+/18644">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Jenkins Builder: Verified
pespin: Looks good to me, but someone else must approve
laforge: Looks good to me, approved
neels: Looks good to me, approved
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">osmo-mgw: refactor endpoint and trunk handling<br><br>The trunk and endpoint handling in osmo-mgw is still very complex and<br>implemented in various places (mostly mgcp_protocol.c). Also we use<br>still integers for endpoint identification, which is not flexible enough<br>to address timeslots/subslots on an E1 trunk. Some refactoring is needed.<br><br> - get rid of integers as endpoint identifiers, use strings instead and<br> find the endpoint based on its string name on the trunk.<br><br> - identify the trunk based on the trunk prefix given in the endpoint<br> name.<br><br> - refactor trunk and endpoint allocation. Aggregate functionality in<br> in mgcp_endp.c and mgcp_trunk.c. Also remove non-reusable code that<br> relates to the still exisiting, but unfinished E1 trunk support.<br><br> - refactor rate counters, put them into a separate module and do no<br> longer allocate them per trunk. Allocate them globally instead.<br><br>Change-Id: Ia8cf4d6caf05a4e13f1f507dc68cbabb7e6239aa<br>Related: OS#2659<br>---<br>M include/osmocom/mgcp/Makefile.am<br>M include/osmocom/mgcp/mgcp.h<br>M include/osmocom/mgcp/mgcp_common.h<br>M include/osmocom/mgcp/mgcp_endp.h<br>M include/osmocom/mgcp/mgcp_internal.h<br>A include/osmocom/mgcp/mgcp_ratectr.h<br>A include/osmocom/mgcp/mgcp_trunk.h<br>M src/libosmo-mgcp/Makefile.am<br>M src/libosmo-mgcp/mgcp_codec.c<br>M src/libosmo-mgcp/mgcp_conn.c<br>M src/libosmo-mgcp/mgcp_endp.c<br>M src/libosmo-mgcp/mgcp_msg.c<br>M src/libosmo-mgcp/mgcp_network.c<br>M src/libosmo-mgcp/mgcp_osmux.c<br>M src/libosmo-mgcp/mgcp_protocol.c<br>A src/libosmo-mgcp/mgcp_ratectr.c<br>M src/libosmo-mgcp/mgcp_sdp.c<br>A src/libosmo-mgcp/mgcp_trunk.c<br>M src/libosmo-mgcp/mgcp_vty.c<br>M src/osmo-mgw/mgw_main.c<br>M tests/mgcp/mgcp_test.c<br>21 files changed, 938 insertions(+), 628 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/mgcp/Makefile.am b/include/osmocom/mgcp/Makefile.am</span><br><span>index 036b4ca..fb7654f 100644</span><br><span>--- a/include/osmocom/mgcp/Makefile.am</span><br><span>+++ b/include/osmocom/mgcp/Makefile.am</span><br><span>@@ -7,5 +7,7 @@</span><br><span> mgcp_sdp.h \</span><br><span> mgcp_codec.h \</span><br><span> mgcp_ctrl.h \</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_trunk.h \</span><br><span> debug.h \</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_ratectr.h \</span><br><span> $(NULL)</span><br><span>diff --git a/include/osmocom/mgcp/mgcp.h b/include/osmocom/mgcp/mgcp.h</span><br><span>index 538c907..3811991 100644</span><br><span>--- a/include/osmocom/mgcp/mgcp.h</span><br><span>+++ b/include/osmocom/mgcp/mgcp.h</span><br><span>@@ -34,6 +34,8 @@</span><br><span> #include <sys/socket.h></span><br><span> #include <netinet/in.h></span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#include "mgcp_ratectr.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #define RTP_PORT_DEFAULT_RANGE_START 16002</span><br><span> #define RTP_PORT_DEFAULT_RANGE_END RTP_PORT_DEFAULT_RANGE_START + 64</span><br><span> </span><br><span>@@ -59,8 +61,8 @@</span><br><span> #define MGCP_POLICY_REJECT 5</span><br><span> #define MGCP_POLICY_DEFER 6</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-typedef int (*mgcp_change)(struct mgcp_trunk *cfg, int endpoint, int state);</span><br><span style="color: hsl(0, 100%, 40%);">-typedef int (*mgcp_policy)(struct mgcp_trunk *cfg, int endpoint, int state, const char *transactio_id);</span><br><span style="color: hsl(120, 100%, 40%);">+typedef int (*mgcp_change)(struct mgcp_endpoint *endp, int state);</span><br><span style="color: hsl(120, 100%, 40%);">+typedef int (*mgcp_policy)(struct mgcp_endpoint *endp, int state, const char *transaction_id);</span><br><span> typedef int (*mgcp_reset)(struct mgcp_trunk *cfg);</span><br><span> typedef int (*mgcp_rqnt)(struct mgcp_endpoint *endp, char tone);</span><br><span> </span><br><span>@@ -177,57 +179,6 @@</span><br><span> MGCP_DLCX_DEFERRED_BY_POLICY,</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct mgcp_trunk {</span><br><span style="color: hsl(0, 100%, 40%);">- struct llist_head entry;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- struct mgcp_config *cfg;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- int trunk_nr;</span><br><span style="color: hsl(0, 100%, 40%);">- int trunk_type;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- char *audio_fmtp_extra;</span><br><span style="color: hsl(0, 100%, 40%);">- char *audio_name;</span><br><span style="color: hsl(0, 100%, 40%);">- int audio_payload;</span><br><span style="color: hsl(0, 100%, 40%);">- int audio_send_ptime;</span><br><span style="color: hsl(0, 100%, 40%);">- int audio_send_name;</span><br><span style="color: hsl(0, 100%, 40%);">- int audio_loop;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- int no_audio_transcoding;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- int omit_rtcp;</span><br><span style="color: hsl(0, 100%, 40%);">- int keepalive_interval;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* RTP patching */</span><br><span style="color: hsl(0, 100%, 40%);">- int force_constant_ssrc; /* 0: don't, 1: once */</span><br><span style="color: hsl(0, 100%, 40%);">- int force_aligned_timing;</span><br><span style="color: hsl(0, 100%, 40%);">- bool rfc5993_hr_convert;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* spec handling */</span><br><span style="color: hsl(0, 100%, 40%);">- int force_realloc;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* timer */</span><br><span style="color: hsl(0, 100%, 40%);">- struct osmo_timer_list keepalive_timer;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* When set, incoming RTP packets are not filtered</span><br><span style="color: hsl(0, 100%, 40%);">- * when ports and ip-address do not match (debug) */</span><br><span style="color: hsl(0, 100%, 40%);">- int rtp_accept_all;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned int number_endpoints;</span><br><span style="color: hsl(0, 100%, 40%);">- int vty_number_endpoints;</span><br><span style="color: hsl(0, 100%, 40%);">- struct mgcp_endpoint *endpoints;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Rate counter group which contains stats for generic MGCP events. */</span><br><span style="color: hsl(0, 100%, 40%);">- struct rate_ctr_group *mgcp_general_ctr_group;</span><br><span style="color: hsl(0, 100%, 40%);">- /* Rate counter group which contains stats for processed CRCX commands. */</span><br><span style="color: hsl(0, 100%, 40%);">- struct rate_ctr_group *mgcp_crcx_ctr_group;</span><br><span style="color: hsl(0, 100%, 40%);">- /* Rate counter group which contains stats for processed MDCX commands. */</span><br><span style="color: hsl(0, 100%, 40%);">- struct rate_ctr_group *mgcp_mdcx_ctr_group;</span><br><span style="color: hsl(0, 100%, 40%);">- /* Rate counter group which contains stats for processed DLCX commands. */</span><br><span style="color: hsl(0, 100%, 40%);">- struct rate_ctr_group *mgcp_dlcx_ctr_group;</span><br><span style="color: hsl(0, 100%, 40%);">- /* Rate counter group which aggregates stats of individual RTP connections. */</span><br><span style="color: hsl(0, 100%, 40%);">- struct rate_ctr_group *all_rtp_conn_stats;</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> enum mgcp_role {</span><br><span> MGCP_BSC = 0,</span><br><span> MGCP_BSC_NAT,</span><br><span>@@ -295,6 +246,10 @@</span><br><span> </span><br><span> /* osmocom CTRL interface */</span><br><span> struct ctrl_handle *ctrl;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* global rate counters to measure the MGWs overall performance and</span><br><span style="color: hsl(120, 100%, 40%);">+ * health */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_ratectr_global ratectr;</span><br><span> };</span><br><span> </span><br><span> /* config management */</span><br><span>@@ -302,7 +257,6 @@</span><br><span> int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,</span><br><span> enum mgcp_role role);</span><br><span> int mgcp_vty_init(void);</span><br><span style="color: hsl(0, 100%, 40%);">-int mgcp_endpoints_allocate(struct mgcp_trunk *cfg);</span><br><span> void mgcp_trunk_set_keepalive(struct mgcp_trunk *trunk, int interval);</span><br><span> </span><br><span> /*</span><br><span>@@ -311,7 +265,7 @@</span><br><span> struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg);</span><br><span> </span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-int mgcp_send_reset_ep(struct mgcp_endpoint *endp, int endpoint);</span><br><span style="color: hsl(120, 100%, 40%);">+int mgcp_send_reset_ep(struct mgcp_endpoint *endp);</span><br><span> int mgcp_send_reset_all(struct mgcp_config *cfg);</span><br><span> </span><br><span> </span><br><span>diff --git a/include/osmocom/mgcp/mgcp_common.h b/include/osmocom/mgcp/mgcp_common.h</span><br><span>index a1bbb19..07d8d37 100644</span><br><span>--- a/include/osmocom/mgcp/mgcp_common.h</span><br><span>+++ b/include/osmocom/mgcp/mgcp_common.h</span><br><span>@@ -100,6 +100,10 @@</span><br><span> /* A prefix to denote the virtual trunk (RTP on both ends) */</span><br><span> #define MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK "rtpbridge/"</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* A prefix to denote the e1 trunk</span><br><span style="color: hsl(120, 100%, 40%);">+ * (see also RFC3435 section E.2) */</span><br><span style="color: hsl(120, 100%, 40%);">+#define MGCP_ENDPOINT_PREFIX_E1_TRUNK "ds/e1-"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Maximal number of payload types / codecs that can be negotiated via SDP at</span><br><span> * at once. */</span><br><span> #define MGCP_MAX_CODECS 10</span><br><span>diff --git a/include/osmocom/mgcp/mgcp_endp.h b/include/osmocom/mgcp/mgcp_endp.h</span><br><span>index 8fa8390..5737cd2 100644</span><br><span>--- a/include/osmocom/mgcp/mgcp_endp.h</span><br><span>+++ b/include/osmocom/mgcp/mgcp_endp.h</span><br><span>@@ -28,8 +28,8 @@</span><br><span> struct mgcp_endpoint;</span><br><span> </span><br><span> #define LOGPENDP(endp, cat, level, fmt, args...) \</span><br><span style="color: hsl(0, 100%, 40%);">-LOGP(cat, level, "endpoint:0x%x " fmt, \</span><br><span style="color: hsl(0, 100%, 40%);">- endp ? ENDPOINT_NUMBER(endp) : -1, \</span><br><span style="color: hsl(120, 100%, 40%);">+LOGP(cat, level, "endpoint:%s " fmt, \</span><br><span style="color: hsl(120, 100%, 40%);">+ endp ? endp->name : "none", \</span><br><span> ## args)</span><br><span> </span><br><span> /* Callback type for RTP dispatcher functions</span><br><span>@@ -68,6 +68,9 @@</span><br><span> /*! MGCP endpoint model */</span><br><span> struct mgcp_endpoint {</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /*! Unique endpoint name, used for addressing via MGCP */</span><br><span style="color: hsl(120, 100%, 40%);">+ char *name;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Call identifier string (as supplied by the call agant) */</span><br><span> char *callid;</span><br><span> </span><br><span>@@ -80,7 +83,7 @@</span><br><span> /*! Backpointer to the MGW configuration */</span><br><span> struct mgcp_config *cfg;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /*! Backpointer to the Trunk specific configuration */</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! Backpointer to the trunk this endpoint belongs to */</span><br><span> struct mgcp_trunk *trunk;</span><br><span> </span><br><span> /*! Endpoint properties (see above) */</span><br><span>@@ -100,7 +103,9 @@</span><br><span> uint32_t x_osmo_ign;</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*! Extract endpoint number for a given endpoint */</span><br><span style="color: hsl(0, 100%, 40%);">-#define ENDPOINT_NUMBER(endp) abs((int)(endp - endp->trunk->endpoints))</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+struct mgcp_endpoint *mgcp_endp_alloc(struct mgcp_trunk *trunk, char *name);</span><br><span> void mgcp_endp_release(struct mgcp_endpoint *endp);</span><br><span style="color: hsl(120, 100%, 40%);">+struct mgcp_endpoint *mgcp_endp_by_name_trunk(int *cause, const char *epname,</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct mgcp_trunk *trunk);</span><br><span style="color: hsl(120, 100%, 40%);">+struct mgcp_endpoint *mgcp_endp_by_name(int *cause, const char *epname,</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_config *cfg);</span><br><span>diff --git a/include/osmocom/mgcp/mgcp_internal.h b/include/osmocom/mgcp/mgcp_internal.h</span><br><span>index b2e2210..174bfd9 100644</span><br><span>--- a/include/osmocom/mgcp/mgcp_internal.h</span><br><span>+++ b/include/osmocom/mgcp/mgcp_internal.h</span><br><span>@@ -282,9 +282,6 @@</span><br><span> return endpoint + 60;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct mgcp_trunk *mgcp_trunk_alloc(struct mgcp_config *cfg, enum mgcp_trunk_type ttype, int index);</span><br><span style="color: hsl(0, 100%, 40%);">-struct mgcp_trunk *mgcp_trunk_num(struct mgcp_config *cfg, int index);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> char *get_lco_identifier(const char *options);</span><br><span> int check_local_cx_options(void *ctx, const char *options);</span><br><span> void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change,</span><br><span>diff --git a/include/osmocom/mgcp/mgcp_ratectr.h b/include/osmocom/mgcp/mgcp_ratectr.h</span><br><span>new file mode 100644</span><br><span>index 0000000..e05b70c</span><br><span>--- /dev/null</span><br><span>+++ b/include/osmocom/mgcp/mgcp_ratectr.h</span><br><span>@@ -0,0 +1,22 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* NOTE: When adding counters, also the dump_ratectr_* routines in vty.c must be updated. */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct mgcp_ratectr_global {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Rate counter group which contains stats for generic MGCP events. */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct rate_ctr_group *mgcp_general_ctr_group;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct mgcp_ratectr_trunk {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Rate counter group which contains stats for processed CRCX commands. */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct rate_ctr_group *mgcp_crcx_ctr_group;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Rate counter group which contains stats for processed MDCX commands. */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct rate_ctr_group *mgcp_mdcx_ctr_group;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Rate counter group which contains stats for processed DLCX commands. */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct rate_ctr_group *mgcp_dlcx_ctr_group;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Rate counter group which aggregates stats of individual RTP connections. */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct rate_ctr_group *all_rtp_conn_stats;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int mgcp_ratectr_global_alloc(void *ctx, struct mgcp_ratectr_global *ratectr);</span><br><span style="color: hsl(120, 100%, 40%);">+int mgcp_ratectr_trunk_alloc(void *ctx, struct mgcp_ratectr_trunk *ratectr);</span><br><span>diff --git a/include/osmocom/mgcp/mgcp_trunk.h b/include/osmocom/mgcp/mgcp_trunk.h</span><br><span>new file mode 100644</span><br><span>index 0000000..436e39a</span><br><span>--- /dev/null</span><br><span>+++ b/include/osmocom/mgcp/mgcp_trunk.h</span><br><span>@@ -0,0 +1,49 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct mgcp_trunk {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct llist_head entry;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_config *cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ int trunk_nr;</span><br><span style="color: hsl(120, 100%, 40%);">+ int trunk_type;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ char *audio_fmtp_extra;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *audio_name;</span><br><span style="color: hsl(120, 100%, 40%);">+ int audio_payload;</span><br><span style="color: hsl(120, 100%, 40%);">+ int audio_send_ptime;</span><br><span style="color: hsl(120, 100%, 40%);">+ int audio_send_name;</span><br><span style="color: hsl(120, 100%, 40%);">+ int audio_loop;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ int no_audio_transcoding;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ int omit_rtcp;</span><br><span style="color: hsl(120, 100%, 40%);">+ int keepalive_interval;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* RTP patching */</span><br><span style="color: hsl(120, 100%, 40%);">+ int force_constant_ssrc; /* 0: don't, 1: once */</span><br><span style="color: hsl(120, 100%, 40%);">+ int force_aligned_timing;</span><br><span style="color: hsl(120, 100%, 40%);">+ bool rfc5993_hr_convert;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* spec handling */</span><br><span style="color: hsl(120, 100%, 40%);">+ int force_realloc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* timer */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_timer_list keepalive_timer;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* When set, incoming RTP packets are not filtered</span><br><span style="color: hsl(120, 100%, 40%);">+ * when ports and ip-address do not match (debug) */</span><br><span style="color: hsl(120, 100%, 40%);">+ int rtp_accept_all;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int number_endpoints;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int vty_number_endpoints;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_endpoint **endpoints;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* global rate counters to measure the trunks overall performance and health */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_ratectr_trunk ratectr;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct mgcp_trunk *mgcp_trunk_alloc(struct mgcp_config *cfg, enum mgcp_trunk_type ttype, int nr);</span><br><span style="color: hsl(120, 100%, 40%);">+int mgcp_trunk_alloc_endpts(struct mgcp_trunk *tcfg);</span><br><span style="color: hsl(120, 100%, 40%);">+struct mgcp_trunk *mgcp_trunk_by_num(const struct mgcp_config *cfg, int index);</span><br><span style="color: hsl(120, 100%, 40%);">+struct mgcp_trunk *mgcp_trunk_by_name(const struct mgcp_config *cfg, const char *epname);</span><br><span>diff --git a/src/libosmo-mgcp/Makefile.am b/src/libosmo-mgcp/Makefile.am</span><br><span>index a0c015b..77d0cdf 100644</span><br><span>--- a/src/libosmo-mgcp/Makefile.am</span><br><span>+++ b/src/libosmo-mgcp/Makefile.am</span><br><span>@@ -40,5 +40,7 @@</span><br><span> mgcp_conn.c \</span><br><span> mgcp_stat.c \</span><br><span> mgcp_endp.c \</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_trunk.c \</span><br><span> mgcp_ctrl.c \</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_ratectr.c \</span><br><span> $(NULL)</span><br><span>diff --git a/src/libosmo-mgcp/mgcp_codec.c b/src/libosmo-mgcp/mgcp_codec.c</span><br><span>index 3cea495..c251317 100644</span><br><span>--- a/src/libosmo-mgcp/mgcp_codec.c</span><br><span>+++ b/src/libosmo-mgcp/mgcp_codec.c</span><br><span>@@ -19,6 +19,7 @@</span><br><span> */</span><br><span> #include <osmocom/mgcp/mgcp_internal.h></span><br><span> #include <osmocom/mgcp/mgcp_endp.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/mgcp/mgcp_trunk.h></span><br><span> #include <errno.h></span><br><span> </span><br><span> /* Helper function to dump codec information of a specified codec to a printable</span><br><span>diff --git a/src/libosmo-mgcp/mgcp_conn.c b/src/libosmo-mgcp/mgcp_conn.c</span><br><span>index 0b499b4..6802b91 100644</span><br><span>--- a/src/libosmo-mgcp/mgcp_conn.c</span><br><span>+++ b/src/libosmo-mgcp/mgcp_conn.c</span><br><span>@@ -25,6 +25,7 @@</span><br><span> #include <osmocom/mgcp/mgcp_internal.h></span><br><span> #include <osmocom/mgcp/mgcp_common.h></span><br><span> #include <osmocom/mgcp/mgcp_endp.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/mgcp/mgcp_trunk.h></span><br><span> #include <osmocom/mgcp/mgcp_sdp.h></span><br><span> #include <osmocom/mgcp/mgcp_codec.h></span><br><span> #include <osmocom/gsm/gsm_utils.h></span><br><span>@@ -254,10 +255,9 @@</span><br><span> return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void</span><br><span style="color: hsl(0, 100%, 40%);">-aggregate_rtp_conn_stats(struct mgcp_trunk *trunk, struct mgcp_conn_rtp *conn_rtp)</span><br><span style="color: hsl(120, 100%, 40%);">+static void aggregate_rtp_conn_stats(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn_rtp)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct rate_ctr_group *all_stats = trunk->all_rtp_conn_stats;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct rate_ctr_group *all_stats = endp->trunk->ratectr.all_rtp_conn_stats;</span><br><span> struct rate_ctr_group *conn_stats = conn_rtp->rate_ctr_group;</span><br><span> </span><br><span> if (all_stats == NULL || conn_stats == NULL)</span><br><span>@@ -296,7 +296,7 @@</span><br><span> </span><br><span> switch (conn->type) {</span><br><span> case MGCP_CONN_TYPE_RTP:</span><br><span style="color: hsl(0, 100%, 40%);">- aggregate_rtp_conn_stats(endp->trunk, &conn->u.rtp);</span><br><span style="color: hsl(120, 100%, 40%);">+ aggregate_rtp_conn_stats(endp, &conn->u.rtp);</span><br><span> mgcp_rtp_conn_cleanup(&conn->u.rtp);</span><br><span> break;</span><br><span> default:</span><br><span>diff --git a/src/libosmo-mgcp/mgcp_endp.c b/src/libosmo-mgcp/mgcp_endp.c</span><br><span>index eec46bf..6c78de2 100644</span><br><span>--- a/src/libosmo-mgcp/mgcp_endp.c</span><br><span>+++ b/src/libosmo-mgcp/mgcp_endp.c</span><br><span>@@ -1,7 +1,7 @@</span><br><span> /* Endpoint types */</span><br><span> </span><br><span> /*</span><br><span style="color: hsl(0, 100%, 40%);">- * (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2017-2020 by sysmocom s.f.m.c. GmbH <info@sysmocom.de></span><br><span> * All Rights Reserved</span><br><span> *</span><br><span> * Author: Philipp Maier</span><br><span>@@ -23,6 +23,7 @@</span><br><span> </span><br><span> #include <osmocom/mgcp/mgcp_internal.h></span><br><span> #include <osmocom/mgcp/mgcp_endp.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/mgcp/mgcp_trunk.h></span><br><span> </span><br><span> /* Endpoint typeset definition */</span><br><span> const struct mgcp_endpoint_typeset ep_typeset = {</span><br><span>@@ -32,6 +33,39 @@</span><br><span> .rtp.cleanup_cb = mgcp_cleanup_rtp_bridge_cb</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! allocate an endpoint and set default values.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] trunk configuration.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] name endpoint name.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns endpoint on success, NULL on failure. */</span><br><span style="color: hsl(120, 100%, 40%);">+struct mgcp_endpoint *mgcp_endp_alloc(struct mgcp_trunk *trunk, char *name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_endpoint *endp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = talloc_zero(trunk->endpoints, struct mgcp_endpoint);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!endp)</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ INIT_LLIST_HEAD(&endp->conns);</span><br><span style="color: hsl(120, 100%, 40%);">+ endp->cfg = trunk->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ endp->trunk = trunk;</span><br><span style="color: hsl(120, 100%, 40%);">+ endp->name = talloc_strdup(endp, name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (trunk->trunk_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case MGCP_TRUNK_VIRTUAL:</span><br><span style="color: hsl(120, 100%, 40%);">+ endp->type = &ep_typeset.rtp;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case MGCP_TRUNK_E1:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* FIXME: Implement E1 allocation */</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DLMGCP, LOGL_FATAL, "E1 trunks not implemented!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_panic("Cannot allocate unimplemented trunk type %d! %s:%d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk->trunk_type, __FILE__, __LINE__);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return endp;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! release endpoint, all open connections are closed.</span><br><span> * \param[in] endp endpoint to release */</span><br><span> void mgcp_endp_release(struct mgcp_endpoint *endp)</span><br><span>@@ -53,3 +87,223 @@</span><br><span> endp->local_options.codec = NULL;</span><br><span> endp->wildcarded_req = false;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Check if the endpoint name contains the prefix (e.g. "rtpbridge/" or</span><br><span style="color: hsl(120, 100%, 40%);">+ * "ds/e1-") and write the epname without the prefix back to the memory</span><br><span style="color: hsl(120, 100%, 40%);">+ * pointed at by epname. (per trunk the prefix is the same for all endpoints,</span><br><span style="color: hsl(120, 100%, 40%);">+ * so no ambiguity is introduced) */</span><br><span style="color: hsl(120, 100%, 40%);">+static void chop_epname_prefix(char *epname, const struct mgcp_trunk *trunk)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t prefix_len;</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (trunk->trunk_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case MGCP_TRUNK_VIRTUAL:</span><br><span style="color: hsl(120, 100%, 40%);">+ prefix_len = sizeof(MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK) - 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strncmp</span><br><span style="color: hsl(120, 100%, 40%);">+ (epname, MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK,</span><br><span style="color: hsl(120, 100%, 40%);">+ prefix_len) == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ memmove(epname, epname + prefix_len,</span><br><span style="color: hsl(120, 100%, 40%);">+ strlen(epname) - prefix_len + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ case MGCP_TRUNK_E1:</span><br><span style="color: hsl(120, 100%, 40%);">+ prefix_len = sizeof(MGCP_ENDPOINT_PREFIX_E1_TRUNK) - 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strncmp</span><br><span style="color: hsl(120, 100%, 40%);">+ (epname, MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK,</span><br><span style="color: hsl(120, 100%, 40%);">+ prefix_len) == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ memmove(epname, epname + prefix_len,</span><br><span style="color: hsl(120, 100%, 40%);">+ strlen(epname) - prefix_len + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(false);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Check if the endpoint name contains a suffix (e.g. "@mgw") and truncate</span><br><span style="color: hsl(120, 100%, 40%);">+ * epname by writing a '\0' char where the suffix starts. */</span><br><span style="color: hsl(120, 100%, 40%);">+static void chop_epname_suffix(char *epname, const struct mgcp_trunk *trunk)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *suffix_begin;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Endpoints on the virtual trunk may have a domain name that is</span><br><span style="color: hsl(120, 100%, 40%);">+ * followed after an @ character, this can be chopped off. All</span><br><span style="color: hsl(120, 100%, 40%);">+ * other supported trunk types do not have any suffixes that may</span><br><span style="color: hsl(120, 100%, 40%);">+ * be chopped off */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (trunk->trunk_type == MGCP_TRUNK_VIRTUAL) {</span><br><span style="color: hsl(120, 100%, 40%);">+ suffix_begin = strchr(epname, '@');</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!suffix_begin)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ *suffix_begin = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Convert all characters in epname to lowercase and strip trunk prefix and</span><br><span style="color: hsl(120, 100%, 40%);">+ * endpoint name suffix (domain name) from epname. The result is written to</span><br><span style="color: hsl(120, 100%, 40%);">+ * to the memory pointed at by epname_stripped. The expected size of the</span><br><span style="color: hsl(120, 100%, 40%);">+ * result is either equal or lower then the length of the input string</span><br><span style="color: hsl(120, 100%, 40%);">+ * (epname) */</span><br><span style="color: hsl(120, 100%, 40%);">+static void strip_epname(char *epname_stripped, const char *epname,</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct mgcp_trunk *trunk)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_str_tolower_buf(epname_stripped, MGCP_ENDPOINT_MAXLEN, epname);</span><br><span style="color: hsl(120, 100%, 40%);">+ chop_epname_prefix(epname_stripped, trunk);</span><br><span style="color: hsl(120, 100%, 40%);">+ chop_epname_suffix(epname_stripped, trunk);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Go through the trunk and find a random free (no active calls) endpoint,</span><br><span style="color: hsl(120, 100%, 40%);">+ * this function is called when a wildcarded request is carried out, which</span><br><span style="color: hsl(120, 100%, 40%);">+ * means that it is up to the MGW to choose a random free endpoint. */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct mgcp_endpoint *find_free_endpoint(const struct mgcp_trunk *trunk)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_endpoint *endp;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < trunk->number_endpoints; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = trunk->endpoints[i];</span><br><span style="color: hsl(120, 100%, 40%);">+ if (endp->callid == NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+ return endp;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Find an endpoint specified by its name. If the endpoint can not be found,</span><br><span style="color: hsl(120, 100%, 40%);">+ * return NULL */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct mgcp_endpoint *find_specific_endpoint(const char *epname,</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct mgcp_trunk *trunk)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char epname_stripped[MGCP_ENDPOINT_MAXLEN];</span><br><span style="color: hsl(120, 100%, 40%);">+ char epname_stripped_endp[MGCP_ENDPOINT_MAXLEN];</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_endpoint *endp;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Strip irrelevant information from the endpoint name */</span><br><span style="color: hsl(120, 100%, 40%);">+ strip_epname(epname_stripped, epname, trunk);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < trunk->number_endpoints; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = trunk->endpoints[i];</span><br><span style="color: hsl(120, 100%, 40%);">+ strip_epname(epname_stripped_endp, endp->name, trunk);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strcmp(epname_stripped_endp, epname_stripped) == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ return endp;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Find an endpoint by its name on a specified trunk.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] cause pointer to store cause code, can be NULL.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] epname endpoint name to lookup.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] trunk where the endpoint is located.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns endpoint or NULL if endpoint was not found. */</span><br><span style="color: hsl(120, 100%, 40%);">+struct mgcp_endpoint *mgcp_endp_by_name_trunk(int *cause, const char *epname,</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct mgcp_trunk *trunk)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_endpoint *endp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cause)</span><br><span style="color: hsl(120, 100%, 40%);">+ *cause = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* At the moment we only support a primitive ('*'-only) method of</span><br><span style="color: hsl(120, 100%, 40%);">+ * wildcarded endpoint searches that picks the next free endpoint on</span><br><span style="color: hsl(120, 100%, 40%);">+ * a trunk. */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strstr(epname, "*")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = find_free_endpoint(trunk);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (endp) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPENDP(endp, DLMGCP, LOGL_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+ "(trunk:%d) found free endpoint: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk->trunk_nr, endp->name);</span><br><span style="color: hsl(120, 100%, 40%);">+ endp->wildcarded_req = true;</span><br><span style="color: hsl(120, 100%, 40%);">+ return endp;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DLMGCP, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+ "(trunk:%d) Not able to find a free endpoint\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk->trunk_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cause)</span><br><span style="color: hsl(120, 100%, 40%);">+ *cause = -403;</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Find an endpoint by its name (if wildcarded request is not</span><br><span style="color: hsl(120, 100%, 40%);">+ * applicable) */</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = find_specific_endpoint(epname, trunk);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (endp) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPENDP(endp, DLMGCP, LOGL_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+ "(trunk:%d) found endpoint: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk->trunk_nr, endp->name);</span><br><span style="color: hsl(120, 100%, 40%);">+ endp->wildcarded_req = false;</span><br><span style="color: hsl(120, 100%, 40%);">+ return endp;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DLMGCP, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+ "(trunk:%d) Not able to find specified endpoint: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk->trunk_nr, epname);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cause)</span><br><span style="color: hsl(120, 100%, 40%);">+ *cause = -500;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Check if the domain name, which is supplied with the endpoint name</span><br><span style="color: hsl(120, 100%, 40%);">+ * matches the configuration. */</span><br><span style="color: hsl(120, 100%, 40%);">+static int check_domain_name(const char *epname, struct mgcp_config *cfg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *domain_to_check;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ domain_to_check = strstr(epname, "@");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!domain_to_check) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DLMGCP, LOGL_ERROR, "missing domain name in endpoint name \"%s\", expecting \"%s\"\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ epname, cfg->domain);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Accept any domain if configured as "*" */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strcmp(cfg->domain, "*"))</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strcmp(domain_to_check+1, cfg->domain) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DLMGCP, LOGL_ERROR, "wrong domain name in endpoint name \"%s\", expecting \"%s\"\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ epname, cfg->domain);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Find an endpoint by its name, search at all trunks.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] cause, pointer to store cause code, can be NULL.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] epname, must contain trunk prefix.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] cfg, mgcp configuration (trunks).</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns endpoint or NULL if endpoint was not found. */</span><br><span style="color: hsl(120, 100%, 40%);">+struct mgcp_endpoint *mgcp_endp_by_name(int *cause, const char *epname,</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_config *cfg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_trunk *trunk;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_endpoint *endp;</span><br><span style="color: hsl(120, 100%, 40%);">+ char epname_lc[MGCP_ENDPOINT_MAXLEN];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_str_tolower_buf(epname_lc, sizeof(epname_lc), epname);</span><br><span style="color: hsl(120, 100%, 40%);">+ epname = epname_lc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cause)</span><br><span style="color: hsl(120, 100%, 40%);">+ *cause = -500;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Identify the trunk where the endpoint is located */</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk = mgcp_trunk_by_name(cfg, epname);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!trunk)</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Virtual endpoints require a domain name (see RFC3435, section E.3) */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (trunk->trunk_type == MGCP_TRUNK_VIRTUAL) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (check_domain_name(epname, cfg))</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Identify the endpoint on the trunk */</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = mgcp_endp_by_name_trunk(cause, epname, trunk);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!endp) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cause)</span><br><span style="color: hsl(120, 100%, 40%);">+ *cause = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ return endp;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/libosmo-mgcp/mgcp_msg.c b/src/libosmo-mgcp/mgcp_msg.c</span><br><span>index 7124a39..019466e 100644</span><br><span>--- a/src/libosmo-mgcp/mgcp_msg.c</span><br><span>+++ b/src/libosmo-mgcp/mgcp_msg.c</span><br><span>@@ -129,167 +129,6 @@</span><br><span> return ret;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* We have a null terminated string with the endpoint name here. We only</span><br><span style="color: hsl(0, 100%, 40%);">- * support two kinds. Simple ones as seen on the BSC level and the ones</span><br><span style="color: hsl(0, 100%, 40%);">- * seen on the trunk side. (helper function for find_endpoint()) */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct mgcp_endpoint *find_e1_endpoint(struct mgcp_config *cfg,</span><br><span style="color: hsl(0, 100%, 40%);">- const char *mgcp)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- char *rest = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- struct mgcp_trunk *trunk;</span><br><span style="color: hsl(0, 100%, 40%);">- int trunk_index, endp;</span><br><span style="color: hsl(0, 100%, 40%);">- struct mgcp_endpoint *endp_ptr;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- trunk_index = strtoul(mgcp + 6, &rest, 10);</span><br><span style="color: hsl(0, 100%, 40%);">- if (rest == NULL || rest[0] != '/' || trunk_index < 1) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DLMGCP, LOGL_ERROR, "Wrong trunk name '%s'\n", mgcp);</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- endp = strtoul(rest + 1, &rest, 10);</span><br><span style="color: hsl(0, 100%, 40%);">- if (rest == NULL || rest[0] != '@') {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DLMGCP, LOGL_ERROR, "Wrong endpoint name '%s'\n", mgcp);</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* signalling is on timeslot 1 */</span><br><span style="color: hsl(0, 100%, 40%);">- if (endp == 1)</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- trunk = mgcp_trunk_num(cfg, trunk_index);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!trunk) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DLMGCP, LOGL_ERROR, "The trunk %d is not declared.\n",</span><br><span style="color: hsl(0, 100%, 40%);">- trunk_index);</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!trunk->endpoints) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DLMGCP, LOGL_ERROR,</span><br><span style="color: hsl(0, 100%, 40%);">- "Endpoints of trunk %d not allocated.\n", trunk_index);</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (endp < 1 || endp >= trunk->number_endpoints) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DLMGCP, LOGL_ERROR, "Failed to find endpoint '%s'\n",</span><br><span style="color: hsl(0, 100%, 40%);">- mgcp);</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- endp_ptr = &trunk->endpoints[endp];</span><br><span style="color: hsl(0, 100%, 40%);">- endp_ptr->wildcarded_req = false;</span><br><span style="color: hsl(0, 100%, 40%);">- return endp_ptr;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Find an endpoint that is not in use. Do this by going through the endpoint</span><br><span style="color: hsl(0, 100%, 40%);">- * array, check the callid. A callid nullpointer indicates that the endpoint</span><br><span style="color: hsl(0, 100%, 40%);">- * is free */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct mgcp_endpoint *find_free_endpoint(struct mgcp_endpoint *endpoints,</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned int number_endpoints)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct mgcp_endpoint *endp;</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned int i;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- for (i = 0; i < number_endpoints; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (endpoints[i].callid == NULL) {</span><br><span style="color: hsl(0, 100%, 40%);">- endp = &endpoints[i];</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPENDP(endp, DLMGCP, LOGL_DEBUG,</span><br><span style="color: hsl(0, 100%, 40%);">- "found free endpoint\n");</span><br><span style="color: hsl(0, 100%, 40%);">- endp->wildcarded_req = true;</span><br><span style="color: hsl(0, 100%, 40%);">- return endp;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DLMGCP, LOGL_ERROR, "Not able to find a free endpoint\n");</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Check if the domain name, which is supplied with the endpoint name</span><br><span style="color: hsl(0, 100%, 40%);">- * matches the configuration. */</span><br><span style="color: hsl(0, 100%, 40%);">-static int check_domain_name(struct mgcp_config *cfg, const char *mgcp)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- char *domain_to_check;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- domain_to_check = strstr(mgcp, "@");</span><br><span style="color: hsl(0, 100%, 40%);">- if (!domain_to_check)</span><br><span style="color: hsl(0, 100%, 40%);">- return -EINVAL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Accept any domain if configured as "*" */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!strcmp(cfg->domain, "*"))</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (strcmp(domain_to_check+1, cfg->domain) != 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DLMGCP, LOGL_ERROR, "Wrong domain name '%s', expecting '%s'\n", mgcp, cfg->domain);</span><br><span style="color: hsl(0, 100%, 40%);">- return -EINVAL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Search the endpoint pool for the endpoint that had been selected via the</span><br><span style="color: hsl(0, 100%, 40%);">- * MGCP message (helper function for mgcp_analyze_header()) */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct mgcp_endpoint *find_endpoint(struct mgcp_config *cfg,</span><br><span style="color: hsl(0, 100%, 40%);">- const char *mgcp,</span><br><span style="color: hsl(0, 100%, 40%);">- int *cause)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- char *endptr = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned int gw = INT_MAX;</span><br><span style="color: hsl(0, 100%, 40%);">- const char *endpoint_number_str;</span><br><span style="color: hsl(0, 100%, 40%);">- struct mgcp_endpoint *endp;</span><br><span style="color: hsl(0, 100%, 40%);">- struct mgcp_trunk *virt_trunk = cfg->virt_trunk;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- *cause = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Check if the domainname in the request is correct */</span><br><span style="color: hsl(0, 100%, 40%);">- if (check_domain_name(cfg, mgcp)) {</span><br><span style="color: hsl(0, 100%, 40%);">- *cause = -500;</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Check if the E1 trunk is requested */</span><br><span style="color: hsl(0, 100%, 40%);">- if (strncmp(mgcp, "ds/e1", 5) == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- endp = find_e1_endpoint(cfg, mgcp);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!endp)</span><br><span style="color: hsl(0, 100%, 40%);">- *cause = -500;</span><br><span style="color: hsl(0, 100%, 40%);">- return endp;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Check if the virtual trunk is addressed (new, correct way with prefix) */</span><br><span style="color: hsl(0, 100%, 40%);">- if (strncmp</span><br><span style="color: hsl(0, 100%, 40%);">- (mgcp, MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK,</span><br><span style="color: hsl(0, 100%, 40%);">- strlen(MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK)) == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- endpoint_number_str =</span><br><span style="color: hsl(0, 100%, 40%);">- mgcp + strlen(MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK);</span><br><span style="color: hsl(0, 100%, 40%);">- if (endpoint_number_str[0] == '*') {</span><br><span style="color: hsl(0, 100%, 40%);">- endp = find_free_endpoint(virt_trunk->endpoints,</span><br><span style="color: hsl(0, 100%, 40%);">- virt_trunk->number_endpoints);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!endp)</span><br><span style="color: hsl(0, 100%, 40%);">- *cause = -403;</span><br><span style="color: hsl(0, 100%, 40%);">- return endp;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- gw = strtoul(endpoint_number_str, &endptr, 16);</span><br><span style="color: hsl(0, 100%, 40%);">- if (gw < virt_trunk->number_endpoints && endptr[0] == '@') {</span><br><span style="color: hsl(0, 100%, 40%);">- endp = &virt_trunk->endpoints[gw];</span><br><span style="color: hsl(0, 100%, 40%);">- endp->wildcarded_req = false;</span><br><span style="color: hsl(0, 100%, 40%);">- return endp;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Deprecated method without prefix */</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DLMGCP, LOGL_NOTICE,</span><br><span style="color: hsl(0, 100%, 40%);">- "Addressing virtual trunk without prefix (deprecated), please use %s: '%s'\n",</span><br><span style="color: hsl(0, 100%, 40%);">- MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK, mgcp);</span><br><span style="color: hsl(0, 100%, 40%);">- gw = strtoul(mgcp, &endptr, 16);</span><br><span style="color: hsl(0, 100%, 40%);">- if (gw < virt_trunk->number_endpoints && endptr[0] == '@') {</span><br><span style="color: hsl(0, 100%, 40%);">- endp = &virt_trunk->endpoints[gw];</span><br><span style="color: hsl(0, 100%, 40%);">- endp->wildcarded_req = false;</span><br><span style="color: hsl(0, 100%, 40%);">- return endp;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DLMGCP, LOGL_ERROR, "Not able to find the endpoint: '%s'\n", mgcp);</span><br><span style="color: hsl(0, 100%, 40%);">- *cause = -500;</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> /*! Analyze and parse the the hader of an MGCP messeage string.</span><br><span> * \param[out] pdata caller provided memory to store the parsing results</span><br><span> * \param[in] data mgcp message string</span><br><span>@@ -317,7 +156,7 @@</span><br><span> pdata->trans = elem;</span><br><span> break;</span><br><span> case 1:</span><br><span style="color: hsl(0, 100%, 40%);">- pdata->endp = find_endpoint(pdata->cfg, elem, &cause);</span><br><span style="color: hsl(120, 100%, 40%);">+ pdata->endp = mgcp_endp_by_name(&cause, elem, pdata->cfg);</span><br><span> if (!pdata->endp) {</span><br><span> LOGP(DLMGCP, LOGL_ERROR,</span><br><span> "Unable to find Endpoint `%s'\n", elem);</span><br><span>@@ -391,8 +230,8 @@</span><br><span> const size_t line_len = strlen(line);</span><br><span> if (line[0] != '\0' && line_len < 2) {</span><br><span> LOGP(DLMGCP, LOGL_ERROR,</span><br><span style="color: hsl(0, 100%, 40%);">- "Wrong MGCP option format: '%s' on 0x%x\n",</span><br><span style="color: hsl(0, 100%, 40%);">- line, ENDPOINT_NUMBER(endp));</span><br><span style="color: hsl(120, 100%, 40%);">+ "Wrong MGCP option format: '%s' on %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ line, endp->name);</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span>diff --git a/src/libosmo-mgcp/mgcp_network.c b/src/libosmo-mgcp/mgcp_network.c</span><br><span>index 2d3fdc3..8efc6b7 100644</span><br><span>--- a/src/libosmo-mgcp/mgcp_network.c</span><br><span>+++ b/src/libosmo-mgcp/mgcp_network.c</span><br><span>@@ -42,6 +42,7 @@</span><br><span> #include <osmocom/mgcp/osmux.h></span><br><span> #include <osmocom/mgcp/mgcp_conn.h></span><br><span> #include <osmocom/mgcp/mgcp_endp.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/mgcp/mgcp_trunk.h></span><br><span> #include <osmocom/mgcp/mgcp_codec.h></span><br><span> #include <osmocom/mgcp/debug.h></span><br><span> #include <osmocom/codec/codec.h></span><br><span>@@ -61,11 +62,11 @@</span><br><span> int id, int inc)</span><br><span> {</span><br><span> struct rate_ctr_group *conn_stats = conn_rtp->rate_ctr_group;</span><br><span style="color: hsl(0, 100%, 40%);">- struct rate_ctr_group *trunk_stats = endp->trunk->all_rtp_conn_stats;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct rate_ctr_group *mgw_stats = endp->trunk->ratectr.all_rtp_conn_stats;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* add to both the per-connection and the per-trunk global stats */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* add to both the per-connection and the global stats */</span><br><span> rate_ctr_add(&conn_stats->ctr[id], inc);</span><br><span style="color: hsl(0, 100%, 40%);">- rate_ctr_add(&trunk_stats->ctr[id], inc);</span><br><span style="color: hsl(120, 100%, 40%);">+ rate_ctr_add(&mgw_stats->ctr[id], inc);</span><br><span> }</span><br><span> </span><br><span> static void rtpconn_rate_ctr_inc(struct mgcp_conn_rtp *conn_rtp, struct mgcp_endpoint *endp, int id)</span><br><span>@@ -648,9 +649,8 @@</span><br><span> return;</span><br><span> </span><br><span> #if 0</span><br><span style="color: hsl(0, 100%, 40%);">- DEBUGP(DRTP,</span><br><span style="color: hsl(0, 100%, 40%);">- "endpoint:0x%x payload hdr payload %u -> endp payload %u\n",</span><br><span style="color: hsl(0, 100%, 40%);">- ENDPOINT_NUMBER(endp), rtp_hdr->payload_type, payload);</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPENDP(endp, DRTP, LOGL_DEBUG, "payload hdr payload %u -> endp payload %u\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ rtp_hdr->payload_type, payload);</span><br><span> rtp_hdr->payload_type = payload;</span><br><span> #endif</span><br><span> }</span><br><span>@@ -1436,11 +1436,10 @@</span><br><span> </span><br><span> /* Bind RTP and RTCP port (helper function for mgcp_bind_net_rtp_port()) */</span><br><span> static int bind_rtp(struct mgcp_config *cfg, const char *source_addr,</span><br><span style="color: hsl(0, 100%, 40%);">- struct mgcp_rtp_end *rtp_end, int endpno)</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_rtp_end *rtp_end, struct mgcp_endpoint *endp)</span><br><span> {</span><br><span> /* NOTE: The port that is used for RTCP is the RTP port incremented by one</span><br><span> * (e.g. RTP-Port = 16000 ==> RTCP-Port = 16001) */</span><br><span style="color: hsl(0, 100%, 40%);">- struct mgcp_endpoint *endp = &cfg->virt_trunk->endpoints[endpno];</span><br><span> </span><br><span> if (mgcp_create_bind(source_addr, &rtp_end->rtp,</span><br><span> rtp_end->local_port) != 0) {</span><br><span>@@ -1527,8 +1526,7 @@</span><br><span> </span><br><span> mgcp_get_local_addr(local_ip_addr, conn);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- return bind_rtp(endp->cfg, local_ip_addr, end,</span><br><span style="color: hsl(0, 100%, 40%);">- ENDPOINT_NUMBER(endp));</span><br><span style="color: hsl(120, 100%, 40%);">+ return bind_rtp(endp->cfg, local_ip_addr, end, endp);</span><br><span> }</span><br><span> </span><br><span> /*! free allocated RTP and RTCP ports.</span><br><span>diff --git a/src/libosmo-mgcp/mgcp_osmux.c b/src/libosmo-mgcp/mgcp_osmux.c</span><br><span>index 8da7361..ca8b5f0 100644</span><br><span>--- a/src/libosmo-mgcp/mgcp_osmux.c</span><br><span>+++ b/src/libosmo-mgcp/mgcp_osmux.c</span><br><span>@@ -27,6 +27,7 @@</span><br><span> #include <osmocom/mgcp/osmux.h></span><br><span> #include <osmocom/mgcp/mgcp_conn.h></span><br><span> #include <osmocom/mgcp/mgcp_endp.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/mgcp/mgcp_trunk.h></span><br><span> </span><br><span> static struct osmo_fd osmux_fd;</span><br><span> </span><br><span>@@ -204,7 +205,7 @@</span><br><span> </span><br><span> for (i=0; i<cfg->virt_trunk->number_endpoints; i++) {</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- endp = &cfg->virt_trunk->endpoints[i];</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = cfg->virt_trunk->endpoints[i];</span><br><span> </span><br><span> llist_for_each_entry(conn, &endp->conns, entry) {</span><br><span> if (conn->type != MGCP_CONN_TYPE_RTP)</span><br><span>diff --git a/src/libosmo-mgcp/mgcp_protocol.c b/src/libosmo-mgcp/mgcp_protocol.c</span><br><span>index 4d77a4c..1d25c45 100644</span><br><span>--- a/src/libosmo-mgcp/mgcp_protocol.c</span><br><span>+++ b/src/libosmo-mgcp/mgcp_protocol.c</span><br><span>@@ -32,7 +32,6 @@</span><br><span> #include <osmocom/core/msgb.h></span><br><span> #include <osmocom/core/talloc.h></span><br><span> #include <osmocom/core/select.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/core/stats.h></span><br><span> </span><br><span> #include <osmocom/mgcp/mgcp.h></span><br><span> #include <osmocom/mgcp/mgcp_common.h></span><br><span>@@ -40,6 +39,7 @@</span><br><span> #include <osmocom/mgcp/mgcp_stat.h></span><br><span> #include <osmocom/mgcp/mgcp_msg.h></span><br><span> #include <osmocom/mgcp/mgcp_endp.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/mgcp/mgcp_trunk.h></span><br><span> #include <osmocom/mgcp/mgcp_sdp.h></span><br><span> #include <osmocom/mgcp/mgcp_codec.h></span><br><span> #include <osmocom/mgcp/mgcp_conn.h></span><br><span>@@ -53,101 +53,6 @@</span><br><span> #define MGCP_REQUEST(NAME, REQ, DEBUG_NAME) \</span><br><span> { .name = NAME, .handle_request = REQ, .debug_name = DEBUG_NAME },</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static const struct rate_ctr_desc mgcp_general_ctr_desc[] = {</span><br><span style="color: hsl(0, 100%, 40%);">- /* rx_msgs = rx_msgs_retransmitted + rx_msgs_handled + rx_msgs_unhandled + err_rx_msg_parse + err_rx_no_endpoint */</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_GENERAL_RX_MSGS_TOTAL] = {"mgcp:rx_msgs", "total number of MGCP messages received."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_GENERAL_RX_MSGS_RETRANSMITTED] = {"mgcp:rx_msgs_retransmitted", "number of received retransmissions."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_GENERAL_RX_MSGS_HANDLED] = {"mgcp:rx_msgs_handled", "number of handled MGCP messages."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_GENERAL_RX_MSGS_UNHANDLED] = {"mgcp:rx_msgs_unhandled", "number of unhandled MGCP messages."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_GENERAL_RX_FAIL_MSG_PARSE] = {"mgcp:err_rx_msg_parse", "error parsing MGCP message."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_GENERAL_RX_FAIL_NO_ENDPOINT] = {"mgcp:err_rx_no_endpoint", "can't find MGCP endpoint, probably we've used all allocated endpoints."},</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-const static struct rate_ctr_group_desc mgcp_general_ctr_group_desc = {</span><br><span style="color: hsl(0, 100%, 40%);">- .group_name_prefix = "mgcp",</span><br><span style="color: hsl(0, 100%, 40%);">- .group_description = "mgcp general statistics",</span><br><span style="color: hsl(0, 100%, 40%);">- .class_id = OSMO_STATS_CLASS_GLOBAL,</span><br><span style="color: hsl(0, 100%, 40%);">- .num_ctr = ARRAY_SIZE(mgcp_general_ctr_desc),</span><br><span style="color: hsl(0, 100%, 40%);">- .ctr_desc = mgcp_general_ctr_desc</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static const struct rate_ctr_desc mgcp_crcx_ctr_desc[] = {</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_CRCX_SUCCESS] = {"crcx:success", "CRCX command processed successfully."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_CRCX_FAIL_BAD_ACTION] = {"crcx:bad_action", "bad action in CRCX command."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_CRCX_FAIL_UNHANDLED_PARAM] = {"crcx:unhandled_param", "unhandled parameter in CRCX command."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_CRCX_FAIL_MISSING_CALLID] = {"crcx:missing_callid", "missing CallId in CRCX command."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_CRCX_FAIL_INVALID_MODE] = {"crcx:invalid_mode", "invalid connection mode in CRCX command."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_CRCX_FAIL_LIMIT_EXCEEDED] = {"crcx:limit_exceeded", "limit of concurrent connections was reached."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_CRCX_FAIL_UNKNOWN_CALLID] = {"crcx:unkown_callid", "unknown CallId in CRCX command."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_CRCX_FAIL_ALLOC_CONN] = {"crcx:alloc_conn_fail", "connection allocation failure."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_CRCX_FAIL_NO_REMOTE_CONN_DESC] = {"crcx:no_remote_conn_desc", "no opposite end specified for connection."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_CRCX_FAIL_START_RTP] = {"crcx:start_rtp_failure", "failure to start RTP processing."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_CRCX_FAIL_REJECTED_BY_POLICY] = {"crcx:conn_rejected", "connection rejected by policy."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_CRCX_FAIL_NO_OSMUX] = {"crcx:no_osmux", "no osmux offered by peer."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_CRCX_FAIL_INVALID_CONN_OPTIONS] = {"crcx:conn_opt", "connection options invalid."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_CRCX_FAIL_CODEC_NEGOTIATION] = {"crcx:codec_nego", "codec negotiation failure."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_CRCX_FAIL_BIND_PORT] = {"crcx:bind_port", "port bind failure."},</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-const static struct rate_ctr_group_desc mgcp_crcx_ctr_group_desc = {</span><br><span style="color: hsl(0, 100%, 40%);">- .group_name_prefix = "crcx",</span><br><span style="color: hsl(0, 100%, 40%);">- .group_description = "crxc statistics",</span><br><span style="color: hsl(0, 100%, 40%);">- .class_id = OSMO_STATS_CLASS_GLOBAL,</span><br><span style="color: hsl(0, 100%, 40%);">- .num_ctr = ARRAY_SIZE(mgcp_crcx_ctr_desc),</span><br><span style="color: hsl(0, 100%, 40%);">- .ctr_desc = mgcp_crcx_ctr_desc</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static const struct rate_ctr_desc mgcp_mdcx_ctr_desc[] = {</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_MDCX_SUCCESS] = {"mdcx:success", "MDCX command processed successfully."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_MDCX_FAIL_WILDCARD] = {"mdcx:wildcard", "wildcard endpoint names in MDCX commands are unsupported."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_MDCX_FAIL_NO_CONN] = {"mdcx:no_conn", "endpoint specified in MDCX command has no active connections."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_MDCX_FAIL_INVALID_CALLID] = {"mdcx:callid", "invalid CallId specified in MDCX command."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_MDCX_FAIL_INVALID_CONNID] = {"mdcx:connid", "invalid connection ID specified in MDCX command."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_MDCX_FAIL_UNHANDLED_PARAM] = {"crcx:unhandled_param", "unhandled parameter in MDCX command."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_MDCX_FAIL_NO_CONNID] = {"mdcx:no_connid", "no connection ID specified in MDCX command."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_MDCX_FAIL_CONN_NOT_FOUND] = {"mdcx:conn_not_found", "connection specified in MDCX command does not exist."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_MDCX_FAIL_INVALID_MODE] = {"mdcx:invalid_mode", "invalid connection mode in MDCX command."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_MDCX_FAIL_INVALID_CONN_OPTIONS] = {"mdcx:conn_opt", "connection options invalid."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_MDCX_FAIL_NO_REMOTE_CONN_DESC] = {"mdcx:no_remote_conn_desc", "no opposite end specified for connection."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_MDCX_FAIL_START_RTP] = {"mdcx:start_rtp_failure", "failure to start RTP processing."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_MDCX_FAIL_REJECTED_BY_POLICY] = {"mdcx:conn_rejected", "connection rejected by policy."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_MDCX_DEFERRED_BY_POLICY] = {"mdcx:conn_deferred", "connection deferred by policy."},</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-const static struct rate_ctr_group_desc mgcp_mdcx_ctr_group_desc = {</span><br><span style="color: hsl(0, 100%, 40%);">- .group_name_prefix = "mdcx",</span><br><span style="color: hsl(0, 100%, 40%);">- .group_description = "mdcx statistics",</span><br><span style="color: hsl(0, 100%, 40%);">- .class_id = OSMO_STATS_CLASS_GLOBAL,</span><br><span style="color: hsl(0, 100%, 40%);">- .num_ctr = ARRAY_SIZE(mgcp_mdcx_ctr_desc),</span><br><span style="color: hsl(0, 100%, 40%);">- .ctr_desc = mgcp_mdcx_ctr_desc</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static const struct rate_ctr_desc mgcp_dlcx_ctr_desc[] = {</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_DLCX_SUCCESS] = {"dlcx:success", "DLCX command processed successfully."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_DLCX_FAIL_WILDCARD] = {"dlcx:wildcard", "wildcard names in DLCX commands are unsupported."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_DLCX_FAIL_NO_CONN] = {"dlcx:no_conn", "endpoint specified in DLCX command has no active connections."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_DLCX_FAIL_INVALID_CALLID] = {"dlcx:callid", "CallId specified in DLCX command mismatches endpoint's CallId ."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_DLCX_FAIL_INVALID_CONNID] = {"dlcx:connid", "connection ID specified in DLCX command does not exist on endpoint."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_DLCX_FAIL_UNHANDLED_PARAM] = {"dlcx:unhandled_param", "unhandled parameter in DLCX command."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_DLCX_FAIL_REJECTED_BY_POLICY] = {"dlcx:rejected", "connection deletion rejected by policy."},</span><br><span style="color: hsl(0, 100%, 40%);">- [MGCP_DLCX_DEFERRED_BY_POLICY] = {"dlcx:deferred", "connection deletion deferred by policy."},</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-const static struct rate_ctr_group_desc mgcp_dlcx_ctr_group_desc = {</span><br><span style="color: hsl(0, 100%, 40%);">- .group_name_prefix = "dlcx",</span><br><span style="color: hsl(0, 100%, 40%);">- .group_description = "dlcx statistics",</span><br><span style="color: hsl(0, 100%, 40%);">- .class_id = OSMO_STATS_CLASS_GLOBAL,</span><br><span style="color: hsl(0, 100%, 40%);">- .num_ctr = ARRAY_SIZE(mgcp_dlcx_ctr_desc),</span><br><span style="color: hsl(0, 100%, 40%);">- .ctr_desc = mgcp_dlcx_ctr_desc</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-const static struct rate_ctr_group_desc all_rtp_conn_rate_ctr_group_desc = {</span><br><span style="color: hsl(0, 100%, 40%);">- .group_name_prefix = "all_rtp_conn",</span><br><span style="color: hsl(0, 100%, 40%);">- .group_description = "aggregated statistics for all rtp connections",</span><br><span style="color: hsl(0, 100%, 40%);">- .class_id = 1,</span><br><span style="color: hsl(0, 100%, 40%);">- .num_ctr = ARRAY_SIZE(all_rtp_conn_rate_ctr_desc),</span><br><span style="color: hsl(0, 100%, 40%);">- .ctr_desc = all_rtp_conn_rate_ctr_desc</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span> </span><br><span> static struct msgb *handle_audit_endpoint(struct mgcp_parse_data *data);</span><br><span> static struct msgb *handle_create_con(struct mgcp_parse_data *data);</span><br><span>@@ -297,9 +202,7 @@</span><br><span> /* NOTE: Only in the virtual trunk we allow dynamic endpoint names */</span><br><span> if (endp->wildcarded_req</span><br><span> && endp->trunk->trunk_type == MGCP_TRUNK_VIRTUAL) {</span><br><span style="color: hsl(0, 100%, 40%);">- rc = msgb_printf(msg, "Z: %s%x@%s\r\n",</span><br><span style="color: hsl(0, 100%, 40%);">- MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK,</span><br><span style="color: hsl(0, 100%, 40%);">- ENDPOINT_NUMBER(endp), endp->cfg->domain);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = msgb_printf(msg, "Z: %s\r\n", endp->name);</span><br><span> if (rc < 0)</span><br><span> return -EINVAL;</span><br><span> }</span><br><span>@@ -379,8 +282,7 @@</span><br><span> * - or a response (three numbers, space, transaction id) */</span><br><span> struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct mgcp_trunk *trunk = cfg->virt_trunk;</span><br><span style="color: hsl(0, 100%, 40%);">- struct rate_ctr_group *rate_ctrs = trunk->mgcp_general_ctr_group;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct rate_ctr_group *rate_ctrs = cfg->ratectr.mgcp_general_ctr_group;</span><br><span> struct mgcp_parse_data pdata;</span><br><span> int rc, i, code, handled = 0;</span><br><span> struct msgb *resp = NULL;</span><br><span>@@ -832,7 +734,7 @@</span><br><span> {</span><br><span> struct mgcp_trunk *trunk = p->endp->trunk;</span><br><span> struct mgcp_endpoint *endp = p->endp;</span><br><span style="color: hsl(0, 100%, 40%);">- struct rate_ctr_group *rate_ctrs = trunk->mgcp_crcx_ctr_group;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct rate_ctr_group *rate_ctrs = trunk->ratectr.mgcp_crcx_ctr_group;</span><br><span> int error_code = 400;</span><br><span> const char *local_options = NULL;</span><br><span> const char *callid = NULL;</span><br><span>@@ -1043,8 +945,7 @@</span><br><span> /* policy CB */</span><br><span> if (p->cfg->policy_cb) {</span><br><span> int rc;</span><br><span style="color: hsl(0, 100%, 40%);">- rc = p->cfg->policy_cb(trunk, ENDPOINT_NUMBER(endp),</span><br><span style="color: hsl(0, 100%, 40%);">- MGCP_ENDP_CRCX, p->trans);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = p->cfg->policy_cb(endp, MGCP_ENDP_CRCX, p->trans);</span><br><span> switch (rc) {</span><br><span> case MGCP_POLICY_REJECT:</span><br><span> LOGPCONN(_conn, DLMGCP, LOGL_NOTICE,</span><br><span>@@ -1066,7 +967,7 @@</span><br><span> LOGPCONN(conn->conn, DLMGCP, LOGL_DEBUG,</span><br><span> "CRCX: Creating connection: port: %u\n", conn->end.local_port);</span><br><span> if (p->cfg->change_cb)</span><br><span style="color: hsl(0, 100%, 40%);">- p->cfg->change_cb(trunk, ENDPOINT_NUMBER(endp), MGCP_ENDP_CRCX);</span><br><span style="color: hsl(120, 100%, 40%);">+ p->cfg->change_cb(endp, MGCP_ENDP_CRCX);</span><br><span> </span><br><span> /* Send dummy packet, see also comments in mgcp_keepalive_timer_cb() */</span><br><span> OSMO_ASSERT(trunk->keepalive_interval >= MGCP_KEEPALIVE_ONCE);</span><br><span>@@ -1088,9 +989,8 @@</span><br><span> /* MDCX command handler, processes the received command */</span><br><span> static struct msgb *handle_modify_con(struct mgcp_parse_data *p)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct mgcp_trunk *trunk = p->endp->trunk;</span><br><span> struct mgcp_endpoint *endp = p->endp;</span><br><span style="color: hsl(0, 100%, 40%);">- struct rate_ctr_group *rate_ctrs = trunk->mgcp_mdcx_ctr_group;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct rate_ctr_group *rate_ctrs = endp->trunk->ratectr.mgcp_mdcx_ctr_group;</span><br><span> int error_code = 500;</span><br><span> int silent = 0;</span><br><span> int have_sdp = 0;</span><br><span>@@ -1257,8 +1157,7 @@</span><br><span> /* policy CB */</span><br><span> if (p->cfg->policy_cb) {</span><br><span> int rc;</span><br><span style="color: hsl(0, 100%, 40%);">- rc = p->cfg->policy_cb(endp->trunk, ENDPOINT_NUMBER(endp),</span><br><span style="color: hsl(0, 100%, 40%);">- MGCP_ENDP_MDCX, p->trans);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = p->cfg->policy_cb(endp, MGCP_ENDP_MDCX, p->trans);</span><br><span> switch (rc) {</span><br><span> case MGCP_POLICY_REJECT:</span><br><span> LOGPCONN(conn->conn, DLMGCP, LOGL_NOTICE,</span><br><span>@@ -1287,8 +1186,7 @@</span><br><span> LOGPCONN(conn->conn, DLMGCP, LOGL_DEBUG,</span><br><span> "MDCX: modified conn:%s\n", mgcp_conn_dump(conn->conn));</span><br><span> if (p->cfg->change_cb)</span><br><span style="color: hsl(0, 100%, 40%);">- p->cfg->change_cb(endp->trunk, ENDPOINT_NUMBER(endp),</span><br><span style="color: hsl(0, 100%, 40%);">- MGCP_ENDP_MDCX);</span><br><span style="color: hsl(120, 100%, 40%);">+ p->cfg->change_cb(endp, MGCP_ENDP_MDCX);</span><br><span> </span><br><span> /* Send dummy packet, see also comments in mgcp_keepalive_timer_cb() */</span><br><span> OSMO_ASSERT(endp->trunk->keepalive_interval >= MGCP_KEEPALIVE_ONCE);</span><br><span>@@ -1314,9 +1212,8 @@</span><br><span> /* DLCX command handler, processes the received command */</span><br><span> static struct msgb *handle_delete_con(struct mgcp_parse_data *p)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct mgcp_trunk *trunk = p->endp->trunk;</span><br><span> struct mgcp_endpoint *endp = p->endp;</span><br><span style="color: hsl(0, 100%, 40%);">- struct rate_ctr_group *rate_ctrs = trunk->mgcp_dlcx_ctr_group;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct rate_ctr_group *rate_ctrs = endp->trunk->ratectr.mgcp_dlcx_ctr_group;</span><br><span> int error_code = 400;</span><br><span> int silent = 0;</span><br><span> char *line;</span><br><span>@@ -1377,8 +1274,7 @@</span><br><span> /* policy CB */</span><br><span> if (p->cfg->policy_cb) {</span><br><span> int rc;</span><br><span style="color: hsl(0, 100%, 40%);">- rc = p->cfg->policy_cb(endp->trunk, ENDPOINT_NUMBER(endp),</span><br><span style="color: hsl(0, 100%, 40%);">- MGCP_ENDP_DLCX, p->trans);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = p->cfg->policy_cb(endp, MGCP_ENDP_DLCX, p->trans);</span><br><span> switch (rc) {</span><br><span> case MGCP_POLICY_REJECT:</span><br><span> LOGPENDP(endp, DLMGCP, LOGL_NOTICE, "DLCX: rejected by policy\n");</span><br><span>@@ -1442,8 +1338,7 @@</span><br><span> }</span><br><span> </span><br><span> if (p->cfg->change_cb)</span><br><span style="color: hsl(0, 100%, 40%);">- p->cfg->change_cb(endp->trunk, ENDPOINT_NUMBER(endp),</span><br><span style="color: hsl(0, 100%, 40%);">- MGCP_ENDP_DLCX);</span><br><span style="color: hsl(120, 100%, 40%);">+ p->cfg->change_cb(endp, MGCP_ENDP_DLCX);</span><br><span> </span><br><span> rate_ctr_inc(&rate_ctrs->ctr[MGCP_DLCX_SUCCESS]);</span><br><span> if (silent)</span><br><span>@@ -1548,7 +1443,7 @@</span><br><span> /* Send walk over all endpoints and send out dummy packets through</span><br><span> * every connection present on each endpoint */</span><br><span> for (i = 1; i < trunk->number_endpoints; ++i) {</span><br><span style="color: hsl(0, 100%, 40%);">- struct mgcp_endpoint *endp = &trunk->endpoints[i];</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_endpoint *endp = trunk->endpoints[i];</span><br><span> llist_for_each_entry(conn, &endp->conns, entry) {</span><br><span> if (conn->mode == MGCP_CONN_RECV_ONLY)</span><br><span> send_dummy(endp, &conn->u.rtp);</span><br><span>@@ -1574,66 +1469,12 @@</span><br><span> trunk->keepalive_interval, 0);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int free_rate_counter_group(struct rate_ctr_group *rate_ctr_group)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- rate_ctr_group_free(rate_ctr_group);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int alloc_mgcp_rate_counters(struct mgcp_trunk *trunk, void *ctx)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- /* FIXME: Each new rate counter group requires a unique index. At the</span><br><span style="color: hsl(0, 100%, 40%);">- * moment we generate an index using a counter, but perhaps there is</span><br><span style="color: hsl(0, 100%, 40%);">- * a better way of assigning indices? */</span><br><span style="color: hsl(0, 100%, 40%);">- static unsigned int general_rate_ctr_index = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- static unsigned int crcx_rate_ctr_index = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- static unsigned int mdcx_rate_ctr_index = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- static unsigned int dlcx_rate_ctr_index = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- static unsigned int all_rtp_conn_rate_ctr_index = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (trunk->mgcp_general_ctr_group == NULL) {</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->mgcp_general_ctr_group = rate_ctr_group_alloc(ctx, &mgcp_general_ctr_group_desc, general_rate_ctr_index);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!trunk->mgcp_general_ctr_group)</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- talloc_set_destructor(trunk->mgcp_general_ctr_group, free_rate_counter_group);</span><br><span style="color: hsl(0, 100%, 40%);">- general_rate_ctr_index++;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (trunk->mgcp_crcx_ctr_group == NULL) {</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->mgcp_crcx_ctr_group = rate_ctr_group_alloc(ctx, &mgcp_crcx_ctr_group_desc, crcx_rate_ctr_index);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!trunk->mgcp_crcx_ctr_group)</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- talloc_set_destructor(trunk->mgcp_crcx_ctr_group, free_rate_counter_group);</span><br><span style="color: hsl(0, 100%, 40%);">- crcx_rate_ctr_index++;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (trunk->mgcp_mdcx_ctr_group == NULL) {</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->mgcp_mdcx_ctr_group = rate_ctr_group_alloc(ctx, &mgcp_mdcx_ctr_group_desc, mdcx_rate_ctr_index);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!trunk->mgcp_mdcx_ctr_group)</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- talloc_set_destructor(trunk->mgcp_mdcx_ctr_group, free_rate_counter_group);</span><br><span style="color: hsl(0, 100%, 40%);">- mdcx_rate_ctr_index++;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (trunk->mgcp_dlcx_ctr_group == NULL) {</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->mgcp_dlcx_ctr_group = rate_ctr_group_alloc(ctx, &mgcp_dlcx_ctr_group_desc, dlcx_rate_ctr_index);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!trunk->mgcp_dlcx_ctr_group)</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- talloc_set_destructor(trunk->mgcp_dlcx_ctr_group, free_rate_counter_group);</span><br><span style="color: hsl(0, 100%, 40%);">- dlcx_rate_ctr_index++;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (trunk->all_rtp_conn_stats == NULL) {</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->all_rtp_conn_stats = rate_ctr_group_alloc(ctx, &all_rtp_conn_rate_ctr_group_desc,</span><br><span style="color: hsl(0, 100%, 40%);">- all_rtp_conn_rate_ctr_index);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!trunk->all_rtp_conn_stats)</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- talloc_set_destructor(trunk->all_rtp_conn_stats, free_rate_counter_group);</span><br><span style="color: hsl(0, 100%, 40%);">- all_rtp_conn_rate_ctr_index++;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> /*! allocate configuration with default values.</span><br><span> * (called once at startup by main function) */</span><br><span> struct mgcp_config *mgcp_config_alloc(void)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* FIXME: This is unrelated to the protocol, put this in some</span><br><span style="color: hsl(120, 100%, 40%);">+ * appropiate place! */</span><br><span> struct mgcp_config *cfg;</span><br><span> </span><br><span> cfg = talloc_zero(NULL, struct mgcp_config);</span><br><span>@@ -1657,109 +1498,21 @@</span><br><span> </span><br><span> cfg->get_net_downlink_format_cb = &mgcp_get_net_downlink_format_default;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- INIT_LLIST_HEAD(&cfg->trunks);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* default trunk handling */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Allocate virtual trunk */</span><br><span> cfg->virt_trunk = mgcp_trunk_alloc(cfg, MGCP_TRUNK_VIRTUAL, 0);</span><br><span> if (!cfg->virt_trunk) {</span><br><span> talloc_free(cfg);</span><br><span> return NULL;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- /* virtual trunk is not part of the list! */</span><br><span style="color: hsl(0, 100%, 40%);">- llist_del(&cfg->virt_trunk->entry);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Initalize list head for user configurable trunks */</span><br><span style="color: hsl(120, 100%, 40%);">+ INIT_LLIST_HEAD(&cfg->trunks);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_ratectr_global_alloc(cfg, &cfg->ratectr);</span><br><span> </span><br><span> return cfg;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*! allocate configuration with default values. Do not link it into global list yet!</span><br><span style="color: hsl(0, 100%, 40%);">- * (called once at startup by VTY)</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] cfg mgcp configuration</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] nr trunk number</span><br><span style="color: hsl(0, 100%, 40%);">- * \returns pointer to allocated trunk configuration */</span><br><span style="color: hsl(0, 100%, 40%);">-struct mgcp_trunk *mgcp_trunk_alloc(struct mgcp_config *cfg, enum mgcp_trunk_type ttype, int nr)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct mgcp_trunk *trunk;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- trunk = talloc_zero(cfg, struct mgcp_trunk);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!trunk) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DLMGCP, LOGL_ERROR, "Failed to allocate.\n");</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->cfg = cfg;</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->trunk_type = ttype;</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->trunk_nr = nr;</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->audio_name = talloc_strdup(trunk, "AMR/8000");</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->audio_payload = 126;</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->audio_send_ptime = 1;</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->audio_send_name = 1;</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->vty_number_endpoints = 33;</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->omit_rtcp = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);</span><br><span style="color: hsl(0, 100%, 40%);">- if (alloc_mgcp_rate_counters(trunk, trunk) < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- talloc_free(trunk);</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- llist_add_tail(&trunk->entry, &cfg->trunks);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return trunk;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! get trunk configuration by trunk number (index).</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] cfg mgcp configuration</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] index trunk number</span><br><span style="color: hsl(0, 100%, 40%);">- * \returns pointer to trunk configuration, NULL on error */</span><br><span style="color: hsl(0, 100%, 40%);">-struct mgcp_trunk *mgcp_trunk_num(struct mgcp_config *cfg, int index)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct mgcp_trunk *trunk;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry(trunk, &cfg->trunks, entry)</span><br><span style="color: hsl(0, 100%, 40%);">- if (trunk->trunk_nr == index)</span><br><span style="color: hsl(0, 100%, 40%);">- return trunk;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! allocate endpoints and set default values.</span><br><span style="color: hsl(0, 100%, 40%);">- * (called once at startup by VTY)</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] trunk trunk configuration</span><br><span style="color: hsl(0, 100%, 40%);">- * \returns 0 on success, -1 on failure */</span><br><span style="color: hsl(0, 100%, 40%);">-int mgcp_endpoints_allocate(struct mgcp_trunk *trunk)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- int i;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->endpoints = _talloc_zero_array(trunk->cfg,</span><br><span style="color: hsl(0, 100%, 40%);">- sizeof(struct mgcp_endpoint),</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->vty_number_endpoints,</span><br><span style="color: hsl(0, 100%, 40%);">- "endpoints");</span><br><span style="color: hsl(0, 100%, 40%);">- if (!trunk->endpoints)</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- for (i = 0; i < trunk->vty_number_endpoints; ++i) {</span><br><span style="color: hsl(0, 100%, 40%);">- INIT_LLIST_HEAD(&trunk->endpoints[i].conns);</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->endpoints[i].cfg = trunk->cfg;</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->endpoints[i].trunk = trunk;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- switch (trunk->trunk_type) {</span><br><span style="color: hsl(0, 100%, 40%);">- case MGCP_TRUNK_VIRTUAL:</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->endpoints[i].type = &ep_typeset.rtp;</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case MGCP_TRUNK_E1:</span><br><span style="color: hsl(0, 100%, 40%);">- /* FIXME: Implement E1 allocation */</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DLMGCP, LOGL_FATAL, "E1 trunks not implemented!\n");</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- default:</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_panic("Cannot allocate unimplemented trunk type %d! %s:%d\n",</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->trunk_type, __FILE__, __LINE__);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- trunk->number_endpoints = trunk->vty_number_endpoints;</span><br><span style="color: hsl(0, 100%, 40%);">- alloc_mgcp_rate_counters(trunk, trunk->cfg);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> static int send_agent(struct mgcp_config *cfg, const char *buf, int len)</span><br><span> {</span><br><span> return write(cfg->gw_fd.bfd.fd, buf, len);</span><br><span>@@ -1790,17 +1543,16 @@</span><br><span> </span><br><span> /*! Reset a single endpoint by sending RSIP message to self.</span><br><span> * (called by VTY)</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] endp trunk endpoint</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] endpoint number</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] endp to reset</span><br><span> * \returns 0 on success, -1 on error */</span><br><span style="color: hsl(0, 100%, 40%);">-int mgcp_send_reset_ep(struct mgcp_endpoint *endp, int endpoint)</span><br><span style="color: hsl(120, 100%, 40%);">+int mgcp_send_reset_ep(struct mgcp_endpoint *endp)</span><br><span> {</span><br><span> char buf[MGCP_ENDPOINT_MAXLEN + 128];</span><br><span> int len;</span><br><span> int rc;</span><br><span> </span><br><span> len = snprintf(buf, sizeof(buf),</span><br><span style="color: hsl(0, 100%, 40%);">- "RSIP 39 %x@%s MGCP 1.0\r\n", endpoint, endp->cfg->domain);</span><br><span style="color: hsl(120, 100%, 40%);">+ "RSIP 39 %s MGCP 1.0\r\n", endp->name);</span><br><span> if (len < 0)</span><br><span> return -1;</span><br><span> </span><br><span>diff --git a/src/libosmo-mgcp/mgcp_ratectr.c b/src/libosmo-mgcp/mgcp_ratectr.c</span><br><span>new file mode 100644</span><br><span>index 0000000..302786f</span><br><span>--- /dev/null</span><br><span>+++ b/src/libosmo-mgcp/mgcp_ratectr.c</span><br><span>@@ -0,0 +1,204 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */</span><br><span style="color: hsl(120, 100%, 40%);">+/* rate-counter implementation */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org></span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2009-2012 by On-Waves</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2017-2020 by sysmocom s.f.m.c. GmbH <info@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU Affero General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 3 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU Affero General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU Affero General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program. If not, see <http://www.gnu.org/licenses/>.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/stats.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/mgcp/mgcp_internal.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/mgcp/mgcp_ratectr.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct rate_ctr_desc mgcp_general_ctr_desc[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* rx_msgs = rx_msgs_retransmitted + rx_msgs_handled + rx_msgs_unhandled + err_rx_msg_parse + err_rx_no_endpoint */</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_GENERAL_RX_MSGS_TOTAL] = { "mgcp:rx_msgs", "total number of MGCP messages received." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_GENERAL_RX_MSGS_RETRANSMITTED] = { "mgcp:rx_msgs_retransmitted", "number of received retransmissions." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_GENERAL_RX_MSGS_HANDLED] = { "mgcp:rx_msgs_handled", "number of handled MGCP messages." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_GENERAL_RX_MSGS_UNHANDLED] = { "mgcp:rx_msgs_unhandled", "number of unhandled MGCP messages." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_GENERAL_RX_FAIL_MSG_PARSE] = { "mgcp:err_rx_msg_parse", "error parsing MGCP message." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_GENERAL_RX_FAIL_NO_ENDPOINT] =</span><br><span style="color: hsl(120, 100%, 40%);">+ { "mgcp:err_rx_no_endpoint", "can't find MGCP endpoint, probably we've used all allocated endpoints." },</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const static struct rate_ctr_group_desc mgcp_general_ctr_group_desc = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .group_name_prefix = "mgcp",</span><br><span style="color: hsl(120, 100%, 40%);">+ .group_description = "mgcp general statistics",</span><br><span style="color: hsl(120, 100%, 40%);">+ .class_id = OSMO_STATS_CLASS_GLOBAL,</span><br><span style="color: hsl(120, 100%, 40%);">+ .num_ctr = ARRAY_SIZE(mgcp_general_ctr_desc),</span><br><span style="color: hsl(120, 100%, 40%);">+ .ctr_desc = mgcp_general_ctr_desc</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct rate_ctr_desc mgcp_crcx_ctr_desc[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_CRCX_SUCCESS] = { "crcx:success", "CRCX command processed successfully." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_CRCX_FAIL_BAD_ACTION] = { "crcx:bad_action", "bad action in CRCX command." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_CRCX_FAIL_UNHANDLED_PARAM] = { "crcx:unhandled_param", "unhandled parameter in CRCX command." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_CRCX_FAIL_MISSING_CALLID] = { "crcx:missing_callid", "missing CallId in CRCX command." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_CRCX_FAIL_INVALID_MODE] = { "crcx:invalid_mode", "invalid connection mode in CRCX command." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_CRCX_FAIL_LIMIT_EXCEEDED] = { "crcx:limit_exceeded", "limit of concurrent connections was reached." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_CRCX_FAIL_UNKNOWN_CALLID] = { "crcx:unkown_callid", "unknown CallId in CRCX command." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_CRCX_FAIL_ALLOC_CONN] = { "crcx:alloc_conn_fail", "connection allocation failure." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_CRCX_FAIL_NO_REMOTE_CONN_DESC] =</span><br><span style="color: hsl(120, 100%, 40%);">+ { "crcx:no_remote_conn_desc", "no opposite end specified for connection." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_CRCX_FAIL_START_RTP] = { "crcx:start_rtp_failure", "failure to start RTP processing." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_CRCX_FAIL_REJECTED_BY_POLICY] = { "crcx:conn_rejected", "connection rejected by policy." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_CRCX_FAIL_NO_OSMUX] = { "crcx:no_osmux", "no osmux offered by peer." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_CRCX_FAIL_INVALID_CONN_OPTIONS] = { "crcx:conn_opt", "connection options invalid." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_CRCX_FAIL_CODEC_NEGOTIATION] = { "crcx:codec_nego", "codec negotiation failure." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_CRCX_FAIL_BIND_PORT] = { "crcx:bind_port", "port bind failure." },</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const static struct rate_ctr_group_desc mgcp_crcx_ctr_group_desc = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .group_name_prefix = "crcx",</span><br><span style="color: hsl(120, 100%, 40%);">+ .group_description = "crxc statistics",</span><br><span style="color: hsl(120, 100%, 40%);">+ .class_id = OSMO_STATS_CLASS_GLOBAL,</span><br><span style="color: hsl(120, 100%, 40%);">+ .num_ctr = ARRAY_SIZE(mgcp_crcx_ctr_desc),</span><br><span style="color: hsl(120, 100%, 40%);">+ .ctr_desc = mgcp_crcx_ctr_desc</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct rate_ctr_desc mgcp_mdcx_ctr_desc[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_MDCX_SUCCESS] = { "mdcx:success", "MDCX command processed successfully." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_MDCX_FAIL_WILDCARD] = { "mdcx:wildcard", "wildcard endpoint names in MDCX commands are unsupported." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_MDCX_FAIL_NO_CONN] = { "mdcx:no_conn", "endpoint specified in MDCX command has no active connections." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_MDCX_FAIL_INVALID_CALLID] = { "mdcx:callid", "invalid CallId specified in MDCX command." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_MDCX_FAIL_INVALID_CONNID] = { "mdcx:connid", "invalid connection ID specified in MDCX command." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_MDCX_FAIL_UNHANDLED_PARAM] = { "crcx:unhandled_param", "unhandled parameter in MDCX command." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_MDCX_FAIL_NO_CONNID] = { "mdcx:no_connid", "no connection ID specified in MDCX command." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_MDCX_FAIL_CONN_NOT_FOUND] =</span><br><span style="color: hsl(120, 100%, 40%);">+ { "mdcx:conn_not_found", "connection specified in MDCX command does not exist." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_MDCX_FAIL_INVALID_MODE] = { "mdcx:invalid_mode", "invalid connection mode in MDCX command." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_MDCX_FAIL_INVALID_CONN_OPTIONS] = { "mdcx:conn_opt", "connection options invalid." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_MDCX_FAIL_NO_REMOTE_CONN_DESC] =</span><br><span style="color: hsl(120, 100%, 40%);">+ { "mdcx:no_remote_conn_desc", "no opposite end specified for connection." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_MDCX_FAIL_START_RTP] = { "mdcx:start_rtp_failure", "failure to start RTP processing." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_MDCX_FAIL_REJECTED_BY_POLICY] = { "mdcx:conn_rejected", "connection rejected by policy." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_MDCX_DEFERRED_BY_POLICY] = { "mdcx:conn_deferred", "connection deferred by policy." },</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const static struct rate_ctr_group_desc mgcp_mdcx_ctr_group_desc = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .group_name_prefix = "mdcx",</span><br><span style="color: hsl(120, 100%, 40%);">+ .group_description = "mdcx statistics",</span><br><span style="color: hsl(120, 100%, 40%);">+ .class_id = OSMO_STATS_CLASS_GLOBAL,</span><br><span style="color: hsl(120, 100%, 40%);">+ .num_ctr = ARRAY_SIZE(mgcp_mdcx_ctr_desc),</span><br><span style="color: hsl(120, 100%, 40%);">+ .ctr_desc = mgcp_mdcx_ctr_desc</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct rate_ctr_desc mgcp_dlcx_ctr_desc[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_DLCX_SUCCESS] = { "dlcx:success", "DLCX command processed successfully." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_DLCX_FAIL_WILDCARD] = { "dlcx:wildcard", "wildcard names in DLCX commands are unsupported." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_DLCX_FAIL_NO_CONN] = { "dlcx:no_conn", "endpoint specified in DLCX command has no active connections." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_DLCX_FAIL_INVALID_CALLID] =</span><br><span style="color: hsl(120, 100%, 40%);">+ { "dlcx:callid", "CallId specified in DLCX command mismatches endpoint's CallId ." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_DLCX_FAIL_INVALID_CONNID] =</span><br><span style="color: hsl(120, 100%, 40%);">+ { "dlcx:connid", "connection ID specified in DLCX command does not exist on endpoint." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_DLCX_FAIL_UNHANDLED_PARAM] = { "dlcx:unhandled_param", "unhandled parameter in DLCX command." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_DLCX_FAIL_REJECTED_BY_POLICY] = { "dlcx:rejected", "connection deletion rejected by policy." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_DLCX_DEFERRED_BY_POLICY] = { "dlcx:deferred", "connection deletion deferred by policy." },</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const static struct rate_ctr_group_desc mgcp_dlcx_ctr_group_desc = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .group_name_prefix = "dlcx",</span><br><span style="color: hsl(120, 100%, 40%);">+ .group_description = "dlcx statistics",</span><br><span style="color: hsl(120, 100%, 40%);">+ .class_id = OSMO_STATS_CLASS_GLOBAL,</span><br><span style="color: hsl(120, 100%, 40%);">+ .num_ctr = ARRAY_SIZE(mgcp_dlcx_ctr_desc),</span><br><span style="color: hsl(120, 100%, 40%);">+ .ctr_desc = mgcp_dlcx_ctr_desc</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const static struct rate_ctr_group_desc all_rtp_conn_rate_ctr_group_desc = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .group_name_prefix = "all_rtp_conn",</span><br><span style="color: hsl(120, 100%, 40%);">+ .group_description = "aggregated statistics for all rtp connections",</span><br><span style="color: hsl(120, 100%, 40%);">+ .class_id = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+ .num_ctr = ARRAY_SIZE(all_rtp_conn_rate_ctr_desc),</span><br><span style="color: hsl(120, 100%, 40%);">+ .ctr_desc = all_rtp_conn_rate_ctr_desc</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int free_rate_counter_group(struct rate_ctr_group *rate_ctr_group)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ rate_ctr_group_free(rate_ctr_group);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! allocate global rate counters into a given rate counter struct</span><br><span style="color: hsl(120, 100%, 40%);">+ * (called once at startup)</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ctx talloc context.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] ratectr struct that holds the counters</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns 0 on success, -EINVAL on failure */</span><br><span style="color: hsl(120, 100%, 40%);">+int mgcp_ratectr_global_alloc(void *ctx, struct mgcp_ratectr_global *ratectr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ /* FIXME: Each new rate counter group requires a unique index. At the</span><br><span style="color: hsl(120, 100%, 40%);">+ * moment we generate an index using a counter, but perhaps there is</span><br><span style="color: hsl(120, 100%, 40%);">+ * a better way of assigning indices? */</span><br><span style="color: hsl(120, 100%, 40%);">+ static unsigned int general_rate_ctr_index = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ratectr->mgcp_general_ctr_group == NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ratectr->mgcp_general_ctr_group =</span><br><span style="color: hsl(120, 100%, 40%);">+ rate_ctr_group_alloc(ctx, &mgcp_general_ctr_group_desc, general_rate_ctr_index);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ratectr->mgcp_general_ctr_group)</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_set_destructor(ratectr->mgcp_general_ctr_group, free_rate_counter_group);</span><br><span style="color: hsl(120, 100%, 40%);">+ general_rate_ctr_index++;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! allocate trunk specific rate counters into a given rate counter struct</span><br><span style="color: hsl(120, 100%, 40%);">+ * (called once on trunk initialization)</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ctx talloc context.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] ratectr struct that holds the counters</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns 0 on success, -EINVAL on failure */</span><br><span style="color: hsl(120, 100%, 40%);">+int mgcp_ratectr_trunk_alloc(void *ctx, struct mgcp_ratectr_trunk *ratectr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ /* FIXME: see comment in mgcp_ratectr_global_alloc() */</span><br><span style="color: hsl(120, 100%, 40%);">+ static unsigned int crcx_rate_ctr_index = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ static unsigned int mdcx_rate_ctr_index = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ static unsigned int dlcx_rate_ctr_index = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ static unsigned int all_rtp_conn_rate_ctr_index = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ratectr->mgcp_crcx_ctr_group == NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ratectr->mgcp_crcx_ctr_group = rate_ctr_group_alloc(ctx, &mgcp_crcx_ctr_group_desc, crcx_rate_ctr_index);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ratectr->mgcp_crcx_ctr_group)</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_set_destructor(ratectr->mgcp_crcx_ctr_group, free_rate_counter_group);</span><br><span style="color: hsl(120, 100%, 40%);">+ crcx_rate_ctr_index++;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ratectr->mgcp_mdcx_ctr_group == NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ratectr->mgcp_mdcx_ctr_group = rate_ctr_group_alloc(ctx, &mgcp_mdcx_ctr_group_desc, mdcx_rate_ctr_index);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ratectr->mgcp_mdcx_ctr_group)</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_set_destructor(ratectr->mgcp_mdcx_ctr_group, free_rate_counter_group);</span><br><span style="color: hsl(120, 100%, 40%);">+ mdcx_rate_ctr_index++;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ratectr->mgcp_dlcx_ctr_group == NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ratectr->mgcp_dlcx_ctr_group = rate_ctr_group_alloc(ctx, &mgcp_dlcx_ctr_group_desc, dlcx_rate_ctr_index);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ratectr->mgcp_dlcx_ctr_group)</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_set_destructor(ratectr->mgcp_dlcx_ctr_group, free_rate_counter_group);</span><br><span style="color: hsl(120, 100%, 40%);">+ dlcx_rate_ctr_index++;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ratectr->all_rtp_conn_stats == NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ratectr->all_rtp_conn_stats = rate_ctr_group_alloc(ctx, &all_rtp_conn_rate_ctr_group_desc,</span><br><span style="color: hsl(120, 100%, 40%);">+ all_rtp_conn_rate_ctr_index);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ratectr->all_rtp_conn_stats)</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_set_destructor(ratectr->all_rtp_conn_stats, free_rate_counter_group);</span><br><span style="color: hsl(120, 100%, 40%);">+ all_rtp_conn_rate_ctr_index++;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/libosmo-mgcp/mgcp_sdp.c b/src/libosmo-mgcp/mgcp_sdp.c</span><br><span>index 428bde6..f80ebb8 100644</span><br><span>--- a/src/libosmo-mgcp/mgcp_sdp.c</span><br><span>+++ b/src/libosmo-mgcp/mgcp_sdp.c</span><br><span>@@ -25,6 +25,7 @@</span><br><span> #include <osmocom/mgcp/mgcp_internal.h></span><br><span> #include <osmocom/mgcp/mgcp_msg.h></span><br><span> #include <osmocom/mgcp/mgcp_endp.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/mgcp/mgcp_trunk.h></span><br><span> #include <osmocom/mgcp/mgcp_codec.h></span><br><span> #include <osmocom/mgcp/mgcp_sdp.h></span><br><span> </span><br><span>@@ -358,10 +359,11 @@</span><br><span> break;</span><br><span> default:</span><br><span> if (p->endp)</span><br><span style="color: hsl(120, 100%, 40%);">+ /* TODO: Check spec: We used the bare endpoint number before,</span><br><span style="color: hsl(120, 100%, 40%);">+ * now we use the endpoint name as a whole? Is this allowed? */</span><br><span> LOGP(DLMGCP, LOGL_NOTICE,</span><br><span style="color: hsl(0, 100%, 40%);">- "Unhandled SDP option: '%c'/%d on 0x%x\n",</span><br><span style="color: hsl(0, 100%, 40%);">- line[0], line[0],</span><br><span style="color: hsl(0, 100%, 40%);">- ENDPOINT_NUMBER(p->endp));</span><br><span style="color: hsl(120, 100%, 40%);">+ "Unhandled SDP option: '%c'/%d on %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ line[0], line[0], endp->name);</span><br><span> else</span><br><span> LOGP(DLMGCP, LOGL_NOTICE,</span><br><span> "Unhandled SDP option: '%c'/%d\n",</span><br><span>@@ -381,7 +383,7 @@</span><br><span> codec_param = param_by_pt(codecs[i].payload_type, fmtp_params, fmtp_used);</span><br><span> rc = mgcp_codec_add(conn, codecs[i].payload_type, codecs[i].map_line, codec_param);</span><br><span> if (rc < 0)</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DLMGCP, LOGL_NOTICE, "endpoint:0x%x, failed to add codec\n", ENDPOINT_NUMBER(p->endp));</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPENDP(endp, DLMGCP, LOGL_NOTICE, "failed to add codec\n");</span><br><span> }</span><br><span> </span><br><span> talloc_free(tmp_ctx);</span><br><span>diff --git a/src/libosmo-mgcp/mgcp_trunk.c b/src/libosmo-mgcp/mgcp_trunk.c</span><br><span>new file mode 100644</span><br><span>index 0000000..96c5318</span><br><span>--- /dev/null</span><br><span>+++ b/src/libosmo-mgcp/mgcp_trunk.c</span><br><span>@@ -0,0 +1,183 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Trunk handling */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org></span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2009-2012 by On-Waves</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2017-2020 by sysmocom s.f.m.c. GmbH <info@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU Affero General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 3 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU Affero General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU Affero General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program. If not, see <http://www.gnu.org/licenses/>.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/mgcp/mgcp_internal.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/mgcp/mgcp_endp.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/mgcp/mgcp_trunk.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! allocate trunk and add it (if required) to the trunk list</span><br><span style="color: hsl(120, 100%, 40%);">+ * (called once at startup by VTY)</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] cfg mgcp configuration</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] nr trunk number</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ttype trunk type</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns pointer to allocated trunk, NULL on failure */</span><br><span style="color: hsl(120, 100%, 40%);">+struct mgcp_trunk *mgcp_trunk_alloc(struct mgcp_config *cfg, enum mgcp_trunk_type ttype, int nr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_trunk *trunk;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk = talloc_zero(cfg, struct mgcp_trunk);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!trunk) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DLMGCP, LOGL_ERROR, "Failed to allocate.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk->cfg = cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk->trunk_type = ttype;</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk->trunk_nr = nr;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk->audio_send_ptime = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk->audio_send_name = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk->vty_number_endpoints = 33;</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk->omit_rtcp = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Note: Trunk Nr.0 is reserved as "virtual trunk",</span><br><span style="color: hsl(120, 100%, 40%);">+ * it is not stored using a separate pointer and</span><br><span style="color: hsl(120, 100%, 40%);">+ * not in the trunk list. */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (nr > 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_add_tail(&trunk->entry, &cfg->trunks);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_ratectr_trunk_alloc(cfg, &trunk->ratectr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return trunk;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! allocate endpoints and set default values.</span><br><span style="color: hsl(120, 100%, 40%);">+ * (called once at startup by VTY)</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] trunk trunk configuration</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns 0 on success, -1 on failure */</span><br><span style="color: hsl(120, 100%, 40%);">+int mgcp_trunk_alloc_endpts(struct mgcp_trunk *trunk)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</span><br><span style="color: hsl(120, 100%, 40%);">+ char ep_name_buf[MGCP_ENDPOINT_MAXLEN];</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_endpoint *endp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Make sure the amount of requested endpoints does not execeed</span><br><span style="color: hsl(120, 100%, 40%);">+ * sane limits. The VTY already limits the possible amount,</span><br><span style="color: hsl(120, 100%, 40%);">+ * however miss-initalation of the struct or memory corruption</span><br><span style="color: hsl(120, 100%, 40%);">+ * could still lead to an excessive allocation of endpoints, so</span><br><span style="color: hsl(120, 100%, 40%);">+ * better stop early if that is the case. */</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(trunk->vty_number_endpoints < 65534);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* This function is called once on startup by the VTY to allocate the</span><br><span style="color: hsl(120, 100%, 40%);">+ * endpoints. The number of endpoints must not change througout the</span><br><span style="color: hsl(120, 100%, 40%);">+ * runtime of the MGW */</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(trunk->number_endpoints == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(trunk->endpoints == NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* allocate pointer array for the endpoints */</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk->endpoints = _talloc_zero_array(trunk->cfg,</span><br><span style="color: hsl(120, 100%, 40%);">+ sizeof(struct mgcp_endpoint *), trunk->vty_number_endpoints, "endpoints");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!trunk->endpoints)</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* create endpoints */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < trunk->vty_number_endpoints; ++i) {</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (trunk->trunk_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case MGCP_TRUNK_VIRTUAL:</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(ep_name_buf, sizeof(ep_name_buf), "%s%x@%s", MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK, i,</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk->cfg->domain);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case MGCP_TRUNK_E1:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* FIXME: E1 trunk implementation is work in progress, this endpoint</span><br><span style="color: hsl(120, 100%, 40%);">+ * name is incomplete (subslots) */</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(ep_name_buf, sizeof(ep_name_buf), "%s-1/%x", MGCP_ENDPOINT_PREFIX_E1_TRUNK, i);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_panic("Cannot allocate unimplemented trunk type %d! %s:%d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk->trunk_type, __FILE__, __LINE__);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = mgcp_endp_alloc(trunk, ep_name_buf);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!endp) {</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(trunk->endpoints);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk->endpoints[i] = endp;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* make the endpoints we just created available to the MGW code */</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk->number_endpoints = trunk->vty_number_endpoints;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! get trunk configuration by trunk number (index).</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] cfg mgcp configuration</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] index trunk number</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns pointer to trunk configuration, NULL on error */</span><br><span style="color: hsl(120, 100%, 40%);">+struct mgcp_trunk *mgcp_trunk_by_num(const struct mgcp_config *cfg, int index)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_trunk *trunk;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry(trunk, &cfg->trunks, entry)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (trunk->trunk_nr == index)</span><br><span style="color: hsl(120, 100%, 40%);">+ return trunk;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Find a trunk by the trunk prefix in the endpoint name.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] epname endpoint name with trunk prefix to look up.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] cfg that contains the trunks where the endpoint is located.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns trunk or NULL if trunk was not found. */</span><br><span style="color: hsl(120, 100%, 40%);">+struct mgcp_trunk *mgcp_trunk_by_name(const struct mgcp_config *cfg, const char *epname)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t prefix_len;</span><br><span style="color: hsl(120, 100%, 40%);">+ char epname_lc[MGCP_ENDPOINT_MAXLEN];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_str_tolower_buf(epname_lc, sizeof(epname_lc), epname);</span><br><span style="color: hsl(120, 100%, 40%);">+ epname = epname_lc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ prefix_len = sizeof(MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK) - 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strncmp(epname, MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK, prefix_len) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return cfg->virt_trunk;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* E1 trunks are not implemented yet, so we deny any request for an</span><br><span style="color: hsl(120, 100%, 40%);">+ * e1 trunk for now. */</span><br><span style="color: hsl(120, 100%, 40%);">+ prefix_len = sizeof(MGCP_ENDPOINT_PREFIX_E1_TRUNK) - 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strncmp(epname, MGCP_ENDPOINT_PREFIX_E1_TRUNK, prefix_len) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DLMGCP, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+ "endpoint name \"%s\" suggests an E1 trunk, but E1 trunks are not implemented in this version of osmo-mgw!\n", epname);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Earlier versions of osmo-mgw were accepting endpoint names</span><br><span style="color: hsl(120, 100%, 40%);">+ * without trunk prefix. This is normally not allowed, each MGCP</span><br><span style="color: hsl(120, 100%, 40%);">+ * request should supply an endpoint name with trunk prefix.</span><br><span style="color: hsl(120, 100%, 40%);">+ * However in order to stay compatible with old versions of</span><br><span style="color: hsl(120, 100%, 40%);">+ * osmo-bsc and osmo-msc we still accept endpoint names without</span><br><span style="color: hsl(120, 100%, 40%);">+ * trunk prefix and just assume that the virtual trunk should</span><br><span style="color: hsl(120, 100%, 40%);">+ * be selected. There is even a TTCN3 test for this, see also:</span><br><span style="color: hsl(120, 100%, 40%);">+ * MGCP_Test.TC_crcx_noprefix */</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((epname[0] >= '0' && epname[0] <= '9') || (epname[0] >= 'a' && epname[0] <= 'f')) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DLMGCP, LOGL_ERROR, "missing trunk prefix in endpoint name \"%s\", assuming trunk \"%s\"!\n", epname,</span><br><span style="color: hsl(120, 100%, 40%);">+ MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK);</span><br><span style="color: hsl(120, 100%, 40%);">+ return cfg->virt_trunk;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DLMGCP, LOGL_ERROR, "unable to find trunk for endpoint name \"%s\"!\n", epname);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/libosmo-mgcp/mgcp_vty.c b/src/libosmo-mgcp/mgcp_vty.c</span><br><span>index 7278c1c..54b139a 100644</span><br><span>--- a/src/libosmo-mgcp/mgcp_vty.c</span><br><span>+++ b/src/libosmo-mgcp/mgcp_vty.c</span><br><span>@@ -29,6 +29,7 @@</span><br><span> #include <osmocom/mgcp/vty.h></span><br><span> #include <osmocom/mgcp/mgcp_conn.h></span><br><span> #include <osmocom/mgcp/mgcp_endp.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/mgcp/mgcp_trunk.h></span><br><span> </span><br><span> #include <string.h></span><br><span> #include <inttypes.h></span><br><span>@@ -49,7 +50,7 @@</span><br><span> if (nr == 0)</span><br><span> trunk = cfg->virt_trunk;</span><br><span> else</span><br><span style="color: hsl(0, 100%, 40%);">- trunk = mgcp_trunk_num(cfg, nr);</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk = mgcp_trunk_by_num(cfg, nr);</span><br><span> </span><br><span> return trunk;</span><br><span> }</span><br><span>@@ -208,15 +209,13 @@</span><br><span> end->force_output_ptime, VTY_NEWLINE);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void dump_endpoint(struct vty *vty, struct mgcp_endpoint *endp, int epidx,</span><br><span style="color: hsl(120, 100%, 40%);">+static void dump_endpoint(struct vty *vty, struct mgcp_endpoint *endp,</span><br><span> int trunk_nr, enum mgcp_trunk_type trunk_type, int show_stats)</span><br><span> {</span><br><span> struct mgcp_conn *conn;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, "%s trunk %d endpoint %s%.2x:%s",</span><br><span style="color: hsl(0, 100%, 40%);">- trunk_type == MGCP_TRUNK_VIRTUAL ? "Virtual" : "E1", trunk_nr,</span><br><span style="color: hsl(0, 100%, 40%);">- trunk_type == MGCP_TRUNK_VIRTUAL ? MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK : "",</span><br><span style="color: hsl(0, 100%, 40%);">- epidx, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, "%s trunk %d endpoint %s:%s",</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk_type == MGCP_TRUNK_VIRTUAL ? "Virtual" : "E1", trunk_nr, endp->name, VTY_NEWLINE);</span><br><span> </span><br><span> if (llist_empty(&endp->conns)) {</span><br><span> vty_out(vty, " No active connections%s", VTY_NEWLINE);</span><br><span>@@ -244,50 +243,84 @@</span><br><span> }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void dump_trunk(struct vty *vty, struct mgcp_trunk *cfg, int show_stats)</span><br><span style="color: hsl(120, 100%, 40%);">+static void dump_ratectr_global(struct vty *vty, struct mgcp_ratectr_global *ratectr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, "%s", VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, "Rate counters (global):%s", VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ratectr->mgcp_general_ctr_group) {</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, " %s:%s",</span><br><span style="color: hsl(120, 100%, 40%);">+ ratectr->mgcp_general_ctr_group->desc-></span><br><span style="color: hsl(120, 100%, 40%);">+ group_description, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out_rate_ctr_group_fmt(vty,</span><br><span style="color: hsl(120, 100%, 40%);">+ " %25n: %10c (%S/s %M/m %H/h %D/d) %d",</span><br><span style="color: hsl(120, 100%, 40%);">+ ratectr->mgcp_general_ctr_group);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dump_ratectr_trunk(struct vty *vty, struct mgcp_ratectr_trunk *ratectr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, "%s", VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, "Rate counters (trunk):%s", VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ratectr->mgcp_crcx_ctr_group) {</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, " %s:%s",</span><br><span style="color: hsl(120, 100%, 40%);">+ ratectr->mgcp_crcx_ctr_group->desc->group_description,</span><br><span style="color: hsl(120, 100%, 40%);">+ VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out_rate_ctr_group_fmt(vty,</span><br><span style="color: hsl(120, 100%, 40%);">+ " %25n: %10c (%S/s %M/m %H/h %D/d) %d",</span><br><span style="color: hsl(120, 100%, 40%);">+ ratectr->mgcp_crcx_ctr_group);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ratectr->mgcp_dlcx_ctr_group) {</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, " %s:%s",</span><br><span style="color: hsl(120, 100%, 40%);">+ ratectr->mgcp_dlcx_ctr_group->desc->group_description,</span><br><span style="color: hsl(120, 100%, 40%);">+ VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out_rate_ctr_group_fmt(vty,</span><br><span style="color: hsl(120, 100%, 40%);">+ " %25n: %10c (%S/s %M/m %H/h %D/d) %d",</span><br><span style="color: hsl(120, 100%, 40%);">+ ratectr->mgcp_dlcx_ctr_group);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ratectr->mgcp_mdcx_ctr_group) {</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, " %s:%s",</span><br><span style="color: hsl(120, 100%, 40%);">+ ratectr->mgcp_mdcx_ctr_group->desc->group_description,</span><br><span style="color: hsl(120, 100%, 40%);">+ VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out_rate_ctr_group_fmt(vty,</span><br><span style="color: hsl(120, 100%, 40%);">+ " %25n: %10c (%S/s %M/m %H/h %D/d) %d",</span><br><span style="color: hsl(120, 100%, 40%);">+ ratectr->mgcp_mdcx_ctr_group);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ratectr->all_rtp_conn_stats) {</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, " %s:%s",</span><br><span style="color: hsl(120, 100%, 40%);">+ ratectr->all_rtp_conn_stats->desc->group_description,</span><br><span style="color: hsl(120, 100%, 40%);">+ VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out_rate_ctr_group_fmt(vty,</span><br><span style="color: hsl(120, 100%, 40%);">+ " %25n: %10c (%S/s %M/m %H/h %D/d) %d",</span><br><span style="color: hsl(120, 100%, 40%);">+ ratectr->all_rtp_conn_stats);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dump_trunk(struct vty *vty, struct mgcp_trunk *trunk, int show_stats)</span><br><span> {</span><br><span> int i;</span><br><span> </span><br><span> vty_out(vty, "%s trunk %d with %d endpoints:%s",</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->trunk_type == MGCP_TRUNK_VIRTUAL ? "Virtual" : "E1",</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->trunk_nr, cfg->number_endpoints - 1, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk->trunk_type == MGCP_TRUNK_VIRTUAL ? "Virtual" : "E1",</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk->trunk_nr, trunk->number_endpoints - 1, VTY_NEWLINE);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (!cfg->endpoints) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!trunk->endpoints) {</span><br><span> vty_out(vty, "No endpoints allocated yet.%s", VTY_NEWLINE);</span><br><span> return;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- for (i = 0; i < cfg->number_endpoints; ++i) {</span><br><span style="color: hsl(0, 100%, 40%);">- struct mgcp_endpoint *endp = &cfg->endpoints[i];</span><br><span style="color: hsl(0, 100%, 40%);">- dump_endpoint(vty, endp, i, cfg->trunk_nr, cfg->trunk_type, show_stats);</span><br><span style="color: hsl(0, 100%, 40%);">- if (i < cfg->number_endpoints - 1)</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < trunk->number_endpoints; ++i) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_endpoint *endp = trunk->endpoints[i];</span><br><span style="color: hsl(120, 100%, 40%);">+ dump_endpoint(vty, endp, trunk->trunk_nr, trunk->trunk_type,</span><br><span style="color: hsl(120, 100%, 40%);">+ show_stats);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (i < trunk->number_endpoints - 1)</span><br><span> vty_out(vty, "%s", VTY_NEWLINE);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (show_stats) {</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, "%s", VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, "Rate counters:%s", VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (show_stats && cfg->mgcp_general_ctr_group) {</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, " %s:%s", cfg->mgcp_general_ctr_group->desc->group_description, VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out_rate_ctr_group_fmt(vty, " %25n: %10c (%S/s %M/m %H/h %D/d) %d", cfg->mgcp_general_ctr_group);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (show_stats && cfg->mgcp_crcx_ctr_group) {</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, " %s:%s", cfg->mgcp_crcx_ctr_group->desc->group_description, VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out_rate_ctr_group_fmt(vty, " %25n: %10c (%S/s %M/m %H/h %D/d) %d", cfg->mgcp_crcx_ctr_group);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (show_stats && cfg->mgcp_dlcx_ctr_group) {</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, " %s:%s", cfg->mgcp_dlcx_ctr_group->desc->group_description, VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out_rate_ctr_group_fmt(vty, " %25n: %10c (%S/s %M/m %H/h %D/d) %d", cfg->mgcp_dlcx_ctr_group);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (show_stats && cfg->mgcp_mdcx_ctr_group) {</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, " %s:%s", cfg->mgcp_mdcx_ctr_group->desc->group_description, VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out_rate_ctr_group_fmt(vty, " %25n: %10c (%S/s %M/m %H/h %D/d) %d", cfg->mgcp_mdcx_ctr_group);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (show_stats && cfg->all_rtp_conn_stats) {</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, " %s:%s", cfg->all_rtp_conn_stats->desc->group_description, VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out_rate_ctr_group_fmt(vty, " %25n: %10c (%S/s %M/m %H/h %D/d) %d", cfg->all_rtp_conn_stats);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (show_stats)</span><br><span style="color: hsl(120, 100%, 40%);">+ dump_ratectr_trunk(vty, &trunk->ratectr);</span><br><span> }</span><br><span> </span><br><span> #define SHOW_MGCP_STR "Display information about the MGCP Media Gateway\n"</span><br><span>@@ -304,44 +337,41 @@</span><br><span> dump_trunk(vty, g_cfg->virt_trunk, show_stats);</span><br><span> </span><br><span> llist_for_each_entry(trunk, &g_cfg->trunks, entry)</span><br><span style="color: hsl(0, 100%, 40%);">- dump_trunk(vty, trunk, show_stats);</span><br><span style="color: hsl(120, 100%, 40%);">+ dump_trunk(vty, trunk, show_stats);</span><br><span> </span><br><span> if (g_cfg->osmux)</span><br><span> vty_out(vty, "Osmux used CID: %d%s", osmux_cid_pool_count_used(),</span><br><span> VTY_NEWLINE);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ if (show_stats)</span><br><span style="color: hsl(120, 100%, 40%);">+ dump_ratectr_global(vty, &g_cfg->ratectr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> return CMD_SUCCESS;</span><br><span> }</span><br><span> </span><br><span> static void</span><br><span> dump_mgcp_endpoint(struct vty *vty, struct mgcp_trunk *trunk, const char *epname)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- const size_t virt_prefix_len = sizeof(MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK) - 1;</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned long epidx;</span><br><span style="color: hsl(0, 100%, 40%);">- char *endp;</span><br><span style="color: hsl(0, 100%, 40%);">- int i;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_endpoint *endp;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (strncmp(epname, MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK, virt_prefix_len) == 0)</span><br><span style="color: hsl(0, 100%, 40%);">- epname += virt_prefix_len;</span><br><span style="color: hsl(0, 100%, 40%);">- errno = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- epidx = strtoul(epname, &endp, 16);</span><br><span style="color: hsl(0, 100%, 40%);">- if (epname[0] == '\0' || *endp != '\0') {</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, "endpoint name '%s' is not a hex number%s", epname, VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if ((errno == ERANGE && epidx == ULONG_MAX) /* parsed value out of range */</span><br><span style="color: hsl(0, 100%, 40%);">- || epidx >= trunk->number_endpoints) {</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, "endpoint %.2lx not configured on trunk %d%s", epidx, trunk->trunk_nr, VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- for (i = 0; i < trunk->number_endpoints; ++i) {</span><br><span style="color: hsl(0, 100%, 40%);">- struct mgcp_endpoint *endp = &trunk->endpoints[i];</span><br><span style="color: hsl(0, 100%, 40%);">- if (i == epidx) {</span><br><span style="color: hsl(0, 100%, 40%);">- dump_endpoint(vty, endp, i, trunk->trunk_nr, trunk->trunk_type, true);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (trunk) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* If a trunk is given, search on that specific trunk only */</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = mgcp_endp_by_name_trunk(NULL, epname, trunk);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!endp) {</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, "endpoint %s not configured on trunk %d%s", epname, trunk->trunk_nr, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* If no trunk is given, search on all possible trunks */</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = mgcp_endp_by_name(NULL, epname, g_cfg);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!endp) {</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, "endpoint %s not configured%s", epname, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span> }</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk = endp->trunk;</span><br><span style="color: hsl(120, 100%, 40%);">+ dump_endpoint(vty, endp, trunk->trunk_nr, trunk->trunk_type, true);</span><br><span> }</span><br><span> </span><br><span> DEFUN(show_mcgp_endpoint, show_mgcp_endpoint_cmd,</span><br><span>@@ -350,12 +380,7 @@</span><br><span> SHOW_MGCP_STR</span><br><span> "Display information about an endpoint\n" "The name of the endpoint\n")</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct mgcp_trunk *trunk;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- dump_mgcp_endpoint(vty, g_cfg->virt_trunk, argv[0]);</span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry(trunk, &g_cfg->trunks, entry)</span><br><span style="color: hsl(0, 100%, 40%);">- dump_mgcp_endpoint(vty, trunk, argv[0]);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+ dump_mgcp_endpoint(vty, NULL, argv[0]);</span><br><span> return CMD_SUCCESS;</span><br><span> }</span><br><span> </span><br><span>@@ -810,7 +835,7 @@</span><br><span> struct mgcp_trunk *trunk;</span><br><span> int index = atoi(argv[0]);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- trunk = mgcp_trunk_num(g_cfg, index);</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk = mgcp_trunk_by_num(g_cfg, index);</span><br><span> if (!trunk) {</span><br><span> trunk = mgcp_trunk_alloc(g_cfg, MGCP_TRUNK_E1, index);</span><br><span> if (!trunk) {</span><br><span>@@ -1138,7 +1163,7 @@</span><br><span> return CMD_WARNING;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- endp = &trunk->endpoints[endp_no];</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = trunk->endpoints[endp_no];</span><br><span> int loop = atoi(argv[2]);</span><br><span> llist_for_each_entry(conn, &endp->conns, entry) {</span><br><span> if (conn->type == MGCP_CONN_TYPE_RTP)</span><br><span>@@ -1197,7 +1222,7 @@</span><br><span> return CMD_WARNING;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- endp = &trunk->endpoints[endp_no];</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = trunk->endpoints[endp_no];</span><br><span> </span><br><span> conn_id = argv[2];</span><br><span> conn = mgcp_conn_get_rtp(endp, conn_id);</span><br><span>@@ -1250,7 +1275,7 @@</span><br><span> return CMD_WARNING;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- endp = &trunk->endpoints[endp_no];</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = trunk->endpoints[endp_no];</span><br><span> mgcp_endp_release(endp);</span><br><span> return CMD_SUCCESS;</span><br><span> }</span><br><span>@@ -1283,8 +1308,8 @@</span><br><span> return CMD_WARNING;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- endp = &trunk->endpoints[endp_no];</span><br><span style="color: hsl(0, 100%, 40%);">- rc = mgcp_send_reset_ep(endp, ENDPOINT_NUMBER(endp));</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = trunk->endpoints[endp_no];</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = mgcp_send_reset_ep(endp);</span><br><span> if (rc < 0) {</span><br><span> vty_out(vty, "Error %d sending reset.%s", rc, VTY_NEWLINE);</span><br><span> return CMD_WARNING;</span><br><span>@@ -1521,7 +1546,7 @@</span><br><span> return -1;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (mgcp_endpoints_allocate(g_cfg->virt_trunk) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (mgcp_trunk_alloc_endpts(g_cfg->virt_trunk) != 0) {</span><br><span> LOGP(DLMGCP, LOGL_ERROR,</span><br><span> "Failed to initialize the virtual trunk (%d endpoints)\n",</span><br><span> g_cfg->virt_trunk->number_endpoints);</span><br><span>@@ -1529,7 +1554,7 @@</span><br><span> }</span><br><span> </span><br><span> llist_for_each_entry(trunk, &g_cfg->trunks, entry) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (mgcp_endpoints_allocate(trunk) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (mgcp_trunk_alloc_endpts(trunk) != 0) {</span><br><span> LOGP(DLMGCP, LOGL_ERROR,</span><br><span> "Failed to initialize trunk %d (%d endpoints)\n",</span><br><span> trunk->trunk_nr, trunk->number_endpoints);</span><br><span>diff --git a/src/osmo-mgw/mgw_main.c b/src/osmo-mgw/mgw_main.c</span><br><span>index 22f2ab8..99e2499 100644</span><br><span>--- a/src/osmo-mgw/mgw_main.c</span><br><span>+++ b/src/osmo-mgw/mgw_main.c</span><br><span>@@ -38,6 +38,7 @@</span><br><span> #include <osmocom/mgcp/vty.h></span><br><span> #include <osmocom/mgcp/debug.h></span><br><span> #include <osmocom/mgcp/mgcp_endp.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/mgcp/mgcp_trunk.h></span><br><span> #include <osmocom/mgcp/mgcp_ctrl.h></span><br><span> </span><br><span> #include <osmocom/core/application.h></span><br><span>@@ -203,7 +204,7 @@</span><br><span> /* Walk over all endpoints and trigger a release, this will release all</span><br><span> * endpoints, possible open connections are forcefully dropped */</span><br><span> for (i = 1; i < reset_trunk->number_endpoints; ++i)</span><br><span style="color: hsl(0, 100%, 40%);">- mgcp_endp_release(&reset_trunk->endpoints[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_endp_release(reset_trunk->endpoints[i]);</span><br><span> }</span><br><span> </span><br><span> return 0;</span><br><span>diff --git a/tests/mgcp/mgcp_test.c b/tests/mgcp/mgcp_test.c</span><br><span>index fa38296..ed0fda0 100644</span><br><span>--- a/tests/mgcp/mgcp_test.c</span><br><span>+++ b/tests/mgcp/mgcp_test.c</span><br><span>@@ -26,6 +26,7 @@</span><br><span> #include <osmocom/mgcp/mgcp_stat.h></span><br><span> #include <osmocom/mgcp/mgcp_msg.h></span><br><span> #include <osmocom/mgcp/mgcp_endp.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/mgcp/mgcp_trunk.h></span><br><span> #include <osmocom/mgcp/mgcp_sdp.h></span><br><span> #include <osmocom/mgcp/mgcp_codec.h></span><br><span> </span><br><span>@@ -70,7 +71,7 @@</span><br><span> }</span><br><span> </span><br><span> #define AUEP1 "AUEP 158663169 ds/e1-1/2@mgw MGCP 1.0\r\n"</span><br><span style="color: hsl(0, 100%, 40%);">-#define AUEP1_RET "200 158663169 OK\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+#define AUEP1_RET "500 158663169 FAIL\r\n"</span><br><span> #define AUEP2 "AUEP 18983213 ds/e1-2/1@mgw MGCP 1.0\r\n"</span><br><span> #define AUEP2_RET "500 18983213 FAIL\r\n"</span><br><span> #define EMPTY "\r\n"</span><br><span>@@ -81,7 +82,7 @@</span><br><span> #define MDCX_WRONG_EP "MDCX 18983213 ds/e1-3/1@mgw MGCP 1.0\r\n"</span><br><span> #define MDCX_ERR_RET "500 18983213 FAIL\r\n"</span><br><span> #define MDCX_UNALLOCATED "MDCX 18983214 ds/e1-1/2@mgw MGCP 1.0\r\n"</span><br><span style="color: hsl(0, 100%, 40%);">-#define MDCX_RET "400 18983214 FAIL\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+#define MDCX_RET "500 18983214 FAIL\r\n"</span><br><span> </span><br><span> #define MDCX3 \</span><br><span> "MDCX 18983215 1@mgw MGCP 1.0\r\n" \</span><br><span>@@ -593,12 +594,22 @@</span><br><span> </span><br><span> static int last_endpoint = -1;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int mgcp_test_policy_cb(struct mgcp_trunk *cfg, int endpoint,</span><br><span style="color: hsl(0, 100%, 40%);">- int state, const char *transactio_id)</span><br><span style="color: hsl(120, 100%, 40%);">+static int mgcp_test_policy_cb(struct mgcp_endpoint *endp,</span><br><span style="color: hsl(120, 100%, 40%);">+ int state, const char *transaction_id)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "Policy CB got state %d on endpoint 0x%x\n",</span><br><span style="color: hsl(0, 100%, 40%);">- state, endpoint);</span><br><span style="color: hsl(0, 100%, 40%);">- last_endpoint = endpoint;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_trunk *trunk;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "Policy CB got state %d on endpoint %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ state, endp->name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk = endp->trunk;</span><br><span style="color: hsl(120, 100%, 40%);">+ last_endpoint = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < trunk->vty_number_endpoints; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strcmp(endp->name, trunk->endpoints[i]->name) == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ last_endpoint = i;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> return MGCP_POLICY_CONT;</span><br><span> }</span><br><span> </span><br><span>@@ -645,7 +656,7 @@</span><br><span> {</span><br><span> int i;</span><br><span> for (i = 1; i < trunk->number_endpoints; i++)</span><br><span style="color: hsl(0, 100%, 40%);">- mgcp_endp_release(&trunk->endpoints[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_endp_release(trunk->endpoints[i]);</span><br><span> }</span><br><span> </span><br><span> #define CONN_UNMODIFIED (0x1000)</span><br><span>@@ -758,13 +769,13 @@</span><br><span> cfg = mgcp_config_alloc();</span><br><span> </span><br><span> cfg->virt_trunk->vty_number_endpoints = 64;</span><br><span style="color: hsl(0, 100%, 40%);">- mgcp_endpoints_allocate(cfg->virt_trunk);</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_trunk_alloc_endpts(cfg->virt_trunk);</span><br><span> cfg->policy_cb = mgcp_test_policy_cb;</span><br><span> </span><br><span> memset(last_conn_id, 0, sizeof(last_conn_id));</span><br><span> </span><br><span> trunk2 = mgcp_trunk_alloc(cfg, MGCP_TRUNK_E1, 1);</span><br><span style="color: hsl(0, 100%, 40%);">- mgcp_endpoints_allocate(trunk2);</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_trunk_alloc_endpts(trunk2);</span><br><span> </span><br><span> for (i = 0; i < ARRAY_SIZE(tests); i++) {</span><br><span> const struct mgcp_test *t = &tests[i];</span><br><span>@@ -810,7 +821,7 @@</span><br><span> printf("Dummy packets: %d\n", dummy_packets);</span><br><span> </span><br><span> if (last_endpoint != -1) {</span><br><span style="color: hsl(0, 100%, 40%);">- endp = &cfg->virt_trunk->endpoints[last_endpoint];</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = cfg->virt_trunk->endpoints[last_endpoint];</span><br><span> </span><br><span> conn = mgcp_conn_get_rtp(endp, "1");</span><br><span> if (conn) {</span><br><span>@@ -866,7 +877,7 @@</span><br><span> /* Check detected payload type */</span><br><span> if (conn && t->ptype != PTYPE_IGNORE) {</span><br><span> OSMO_ASSERT(last_endpoint != -1);</span><br><span style="color: hsl(0, 100%, 40%);">- endp = &cfg->virt_trunk->endpoints[last_endpoint];</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = cfg->virt_trunk->endpoints[last_endpoint];</span><br><span> </span><br><span> fprintf(stderr, "endpoint 0x%x: "</span><br><span> "payload type %d (expected %d)\n",</span><br><span>@@ -898,12 +909,12 @@</span><br><span> cfg = mgcp_config_alloc();</span><br><span> </span><br><span> cfg->virt_trunk->vty_number_endpoints = 64;</span><br><span style="color: hsl(0, 100%, 40%);">- mgcp_endpoints_allocate(cfg->virt_trunk);</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_trunk_alloc_endpts(cfg->virt_trunk);</span><br><span> </span><br><span> memset(last_conn_id, 0, sizeof(last_conn_id));</span><br><span> </span><br><span> trunk2 = mgcp_trunk_alloc(cfg, MGCP_TRUNK_E1, 1);</span><br><span style="color: hsl(0, 100%, 40%);">- mgcp_endpoints_allocate(trunk2);</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_trunk_alloc_endpts(trunk2);</span><br><span> </span><br><span> for (i = 0; i < ARRAY_SIZE(retransmit); i++) {</span><br><span> const struct mgcp_test *t = &retransmit[i];</span><br><span>@@ -966,10 +977,10 @@</span><br><span> cfg->rqnt_cb = rqnt_cb;</span><br><span> </span><br><span> cfg->virt_trunk->vty_number_endpoints = 64;</span><br><span style="color: hsl(0, 100%, 40%);">- mgcp_endpoints_allocate(cfg->virt_trunk);</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_trunk_alloc_endpts(cfg->virt_trunk);</span><br><span> </span><br><span> trunk2 = mgcp_trunk_alloc(cfg, MGCP_TRUNK_E1, 1);</span><br><span style="color: hsl(0, 100%, 40%);">- mgcp_endpoints_allocate(trunk2);</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_trunk_alloc_endpts(trunk2);</span><br><span> </span><br><span> inp = create_msg(CRCX, NULL);</span><br><span> msg = mgcp_handle_message(cfg, inp);</span><br><span>@@ -1035,6 +1046,7 @@</span><br><span> {</span><br><span> int i;</span><br><span> struct mgcp_endpoint endp;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_endpoint *endpoints[1];</span><br><span> struct mgcp_config cfg = {0};</span><br><span> struct mgcp_trunk trunk;</span><br><span> </span><br><span>@@ -1046,7 +1058,8 @@</span><br><span> endp.cfg = &cfg;</span><br><span> endp.type = &ep_typeset.rtp;</span><br><span> trunk.vty_number_endpoints = 1;</span><br><span style="color: hsl(0, 100%, 40%);">- trunk.endpoints = &endp;</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk.endpoints = endpoints;</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk.endpoints[0] = &endp;</span><br><span> endp.trunk = &trunk;</span><br><span> INIT_LLIST_HEAD(&endp.conns);</span><br><span> </span><br><span>@@ -1264,6 +1277,7 @@</span><br><span> </span><br><span> struct mgcp_trunk trunk;</span><br><span> struct mgcp_endpoint endp;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_endpoint *endpoints[1];</span><br><span> struct mgcp_config cfg = {0};</span><br><span> struct mgcp_rtp_state state;</span><br><span> struct mgcp_rtp_end *rtp;</span><br><span>@@ -1296,7 +1310,8 @@</span><br><span> endp.type = &ep_typeset.rtp;</span><br><span> </span><br><span> trunk.vty_number_endpoints = 1;</span><br><span style="color: hsl(0, 100%, 40%);">- trunk.endpoints = &endp;</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk.endpoints = endpoints;</span><br><span style="color: hsl(120, 100%, 40%);">+ trunk.endpoints[0] = &endp;</span><br><span> trunk.force_constant_ssrc = patch_ssrc;</span><br><span> trunk.force_aligned_timing = patch_ts;</span><br><span> </span><br><span>@@ -1372,11 +1387,11 @@</span><br><span> </span><br><span> cfg = mgcp_config_alloc();</span><br><span> cfg->virt_trunk->vty_number_endpoints = 64;</span><br><span style="color: hsl(0, 100%, 40%);">- mgcp_endpoints_allocate(cfg->virt_trunk);</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_trunk_alloc_endpts(cfg->virt_trunk);</span><br><span> cfg->policy_cb = mgcp_test_policy_cb;</span><br><span> </span><br><span> trunk2 = mgcp_trunk_alloc(cfg, MGCP_TRUNK_E1, 1);</span><br><span style="color: hsl(0, 100%, 40%);">- mgcp_endpoints_allocate(trunk2);</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_trunk_alloc_endpts(trunk2);</span><br><span> </span><br><span> /* Allocate endpoint 1@mgw with two codecs */</span><br><span> last_endpoint = -1;</span><br><span>@@ -1388,7 +1403,7 @@</span><br><span> msgb_free(resp);</span><br><span> </span><br><span> OSMO_ASSERT(last_endpoint == 1);</span><br><span style="color: hsl(0, 100%, 40%);">- endp = &cfg->virt_trunk->endpoints[last_endpoint];</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = cfg->virt_trunk->endpoints[last_endpoint];</span><br><span> conn = mgcp_conn_get_rtp(endp, conn_id);</span><br><span> OSMO_ASSERT(conn);</span><br><span> OSMO_ASSERT(conn->end.codec->payload_type == 18);</span><br><span>@@ -1403,7 +1418,7 @@</span><br><span> msgb_free(resp);</span><br><span> </span><br><span> OSMO_ASSERT(last_endpoint == 2);</span><br><span style="color: hsl(0, 100%, 40%);">- endp = &cfg->virt_trunk->endpoints[last_endpoint];</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = cfg->virt_trunk->endpoints[last_endpoint];</span><br><span> conn = mgcp_conn_get_rtp(endp, conn_id);</span><br><span> OSMO_ASSERT(conn);</span><br><span> OSMO_ASSERT(conn->end.codec->payload_type == 18);</span><br><span>@@ -1423,7 +1438,7 @@</span><br><span> msgb_free(resp);</span><br><span> </span><br><span> OSMO_ASSERT(last_endpoint == 3);</span><br><span style="color: hsl(0, 100%, 40%);">- endp = &cfg->virt_trunk->endpoints[last_endpoint];</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = cfg->virt_trunk->endpoints[last_endpoint];</span><br><span> conn = mgcp_conn_get_rtp(endp, conn_id);</span><br><span> OSMO_ASSERT(conn);</span><br><span> OSMO_ASSERT(conn->end.codec->payload_type == 0);</span><br><span>@@ -1438,7 +1453,7 @@</span><br><span> msgb_free(resp);</span><br><span> </span><br><span> OSMO_ASSERT(last_endpoint == 4);</span><br><span style="color: hsl(0, 100%, 40%);">- endp = &cfg->virt_trunk->endpoints[last_endpoint];</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = cfg->virt_trunk->endpoints[last_endpoint];</span><br><span> conn = mgcp_conn_get_rtp(endp, conn_id);</span><br><span> OSMO_ASSERT(conn);</span><br><span> OSMO_ASSERT(conn->end.codec->payload_type == 18);</span><br><span>@@ -1456,7 +1471,7 @@</span><br><span> msgb_free(resp);</span><br><span> </span><br><span> OSMO_ASSERT(last_endpoint == 5);</span><br><span style="color: hsl(0, 100%, 40%);">- endp = &cfg->virt_trunk->endpoints[last_endpoint];</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = cfg->virt_trunk->endpoints[last_endpoint];</span><br><span> conn = mgcp_conn_get_rtp(endp, conn_id);</span><br><span> OSMO_ASSERT(conn);</span><br><span> OSMO_ASSERT(conn->end.codec->payload_type == 3);</span><br><span>@@ -1467,7 +1482,7 @@</span><br><span> msgb_free(inp);</span><br><span> msgb_free(resp);</span><br><span> OSMO_ASSERT(last_endpoint == 5);</span><br><span style="color: hsl(0, 100%, 40%);">- endp = &cfg->virt_trunk->endpoints[last_endpoint];</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = cfg->virt_trunk->endpoints[last_endpoint];</span><br><span> conn = mgcp_conn_get_rtp(endp, conn_id);</span><br><span> OSMO_ASSERT(conn);</span><br><span> OSMO_ASSERT(conn->end.codec->payload_type == 3);</span><br><span>@@ -1497,7 +1512,7 @@</span><br><span> msgb_free(resp);</span><br><span> </span><br><span> OSMO_ASSERT(last_endpoint == 5);</span><br><span style="color: hsl(0, 100%, 40%);">- endp = &cfg->virt_trunk->endpoints[last_endpoint];</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = cfg->virt_trunk->endpoints[last_endpoint];</span><br><span> conn = mgcp_conn_get_rtp(endp, conn_id);</span><br><span> OSMO_ASSERT(conn);</span><br><span> OSMO_ASSERT(conn->end.codec->payload_type == 0);</span><br><span>@@ -1518,9 +1533,9 @@</span><br><span> </span><br><span> cfg = mgcp_config_alloc();</span><br><span> cfg->virt_trunk->vty_number_endpoints = 64;</span><br><span style="color: hsl(0, 100%, 40%);">- mgcp_endpoints_allocate(cfg->virt_trunk);</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_trunk_alloc_endpts(cfg->virt_trunk);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- endp = &cfg->virt_trunk->endpoints[1];</span><br><span style="color: hsl(120, 100%, 40%);">+ endp = cfg->virt_trunk->endpoints[1];</span><br><span> </span><br><span> _conn = mgcp_conn_alloc(NULL, endp, MGCP_CONN_TYPE_RTP,</span><br><span> "test-connection");</span><br><span>@@ -1567,12 +1582,12 @@</span><br><span> </span><br><span> cfg->virt_trunk->vty_number_endpoints = 64;</span><br><span> cfg->virt_trunk->audio_send_name = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- mgcp_endpoints_allocate(cfg->virt_trunk);</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_trunk_alloc_endpts(cfg->virt_trunk);</span><br><span> </span><br><span> cfg->policy_cb = mgcp_test_policy_cb;</span><br><span> </span><br><span> trunk2 = mgcp_trunk_alloc(cfg, MGCP_TRUNK_E1, 1);</span><br><span style="color: hsl(0, 100%, 40%);">- mgcp_endpoints_allocate(trunk2);</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_trunk_alloc_endpts(trunk2);</span><br><span> </span><br><span> inp = create_msg(CRCX, NULL);</span><br><span> msg = mgcp_handle_message(cfg, inp);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-mgw/+/18644">change 18644</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-mgw/+/18644"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: osmo-mgw </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Ia8cf4d6caf05a4e13f1f507dc68cbabb7e6239aa </div>
<div style="display:none"> Gerrit-Change-Number: 18644 </div>
<div style="display:none"> Gerrit-PatchSet: 7 </div>
<div style="display:none"> Gerrit-Owner: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>