<p>dexter has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-mgw/+/18644">View Change</a></p><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, 901 insertions(+), 629 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-mgw refs/changes/44/18644/1</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..4c122e7 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 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..1fe8266 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%);">+                                          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..82e5b11</span><br><span>--- /dev/null</span><br><span>+++ b/include/osmocom/mgcp/mgcp_ratectr.h</span><br><span>@@ -0,0 +1,16 @@</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_ratectr {</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%);">+        /* 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_alloc(void *ctx, struct mgcp_ratectr *ratecntr);</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..71d89ac</span><br><span>--- /dev/null</span><br><span>+++ b/include/osmocom/mgcp/mgcp_trunk.h</span><br><span>@@ -0,0 +1,46 @@</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%);">+</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(struct mgcp_config *cfg, int index);</span><br><span style="color: hsl(120, 100%, 40%);">+struct mgcp_trunk *mgcp_trunk_by_name(const char *epname, struct mgcp_config *cfg);</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..1b15e14 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_config *cfg, 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 = cfg->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->cfg, &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..9d5681c 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,38 @@</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%);">+ *  \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 +86,217 @@</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 chop it off, if it exists (per trunk the prefix is</span><br><span style="color: hsl(120, 100%, 40%);">+ * the same for all endpoints, so no ambiguity is introduced) */</span><br><span style="color: hsl(120, 100%, 40%);">+static void chop_epname_prefix(char *epname, 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%);">+       }</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 chop</span><br><span style="color: hsl(120, 100%, 40%);">+ * it off */</span><br><span style="color: hsl(120, 100%, 40%);">+static void chop_epname_suffix(char *epname, 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%);">+/* Strip the endpoint name from all information that is already evaluated</span><br><span style="color: hsl(120, 100%, 40%);">+ * and not needed to identify the endpoint on the trunk */</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%);">+                     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, strlen(epname), 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(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%);">+                        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%);">+</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%);">+static struct mgcp_endpoint *find_specific_endpoint(const char *epname,</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%);">+      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%);">+                     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%);">+</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%);">+                                         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%);">+                  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%);">+          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(epname, cfg);</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..7651486 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->cfg->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..f62b581 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,8 @@</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 mgcp_config *cfg = endp->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct rate_ctr_group *rate_ctrs = cfg->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 +946,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 +968,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 +990,9 @@</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 mgcp_config *cfg = endp->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct rate_ctr_group *rate_ctrs = cfg->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 +1159,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 +1188,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 +1214,9 @@</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 mgcp_config *cfg = endp->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct rate_ctr_group *rate_ctrs = cfg->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 +1277,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 +1341,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 +1446,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 +1472,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 +1501,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_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 +1546,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..beb5d5a</span><br><span>--- /dev/null</span><br><span>+++ b/src/libosmo-mgcp/mgcp_ratectr.c</span><br><span>@@ -0,0 +1,192 @@</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 rate counters into a given rate counter struct</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] 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_alloc(void *ctx, struct mgcp_ratectr *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%);">+       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_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%);">+     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..76d2e97</span><br><span>--- /dev/null</span><br><span>+++ b/src/libosmo-mgcp/mgcp_trunk.c</span><br><span>@@ -0,0 +1,181 @@</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%);">+  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(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 endpoint was not found. */</span><br><span style="color: hsl(120, 100%, 40%);">+struct mgcp_trunk *mgcp_trunk_by_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%);">+ 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..d332d75 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,73 @@</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(struct vty *vty, struct mgcp_ratectr *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:%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%);">+     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%);">+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 style="color: hsl(0, 100%, 40%);">-</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> }</span><br><span> </span><br><span> #define SHOW_MGCP_STR "Display information about the MGCP Media Gateway\n"</span><br><span>@@ -304,44 +326,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(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 +369,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 +824,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 +1152,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 +1211,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 +1264,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 +1297,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 +1535,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 +1543,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: 1 </div>
<div style="display:none"> Gerrit-Owner: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>