osmo-mgw: refactor endpoint and trunk handling

The trunk and endpoint handling in osmo-mgw is still very complex and
implemented in various places (mostly mgcp_protocol.c). Also we use
still integers for endpoint identification, which is not flexible enough
to address timeslots/subslots on an E1 trunk. Some refactoring is needed.

  - get rid of integers as endpoint identifiers, use strings instead and
    find the endpoint based on its string name on the trunk.

  - identify the trunk based on the trunk prefix given in the endpoint
    name.

  - refactor trunk and endpoint allocation. Aggregate functionality in
    in mgcp_endp.c and mgcp_trunk.c. Also remove non-reusable code that
    relates to the still exisiting, but unfinished E1 trunk support.

  - refactor rate counters, put them into a separate module and do no
    longer allocate them per trunk. Allocate them globally instead.

Change-Id: Ia8cf4d6caf05a4e13f1f507dc68cbabb7e6239aa
Related: OS#2659
diff --git a/include/osmocom/mgcp/Makefile.am b/include/osmocom/mgcp/Makefile.am
index 036b4ca..fb7654f 100644
--- a/include/osmocom/mgcp/Makefile.am
+++ b/include/osmocom/mgcp/Makefile.am
@@ -7,5 +7,7 @@
 	mgcp_sdp.h \
 	mgcp_codec.h \
 	mgcp_ctrl.h \
+	mgcp_trunk.h \
 	debug.h \
+	mgcp_ratectr.h \
 	$(NULL)
diff --git a/include/osmocom/mgcp/mgcp.h b/include/osmocom/mgcp/mgcp.h
index 538c907..3811991 100644
--- a/include/osmocom/mgcp/mgcp.h
+++ b/include/osmocom/mgcp/mgcp.h
@@ -34,6 +34,8 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 
+#include "mgcp_ratectr.h"
+
 #define RTP_PORT_DEFAULT_RANGE_START 16002
 #define RTP_PORT_DEFAULT_RANGE_END RTP_PORT_DEFAULT_RANGE_START + 64
 
@@ -59,8 +61,8 @@
 #define MGCP_POLICY_REJECT	5
 #define MGCP_POLICY_DEFER	6
 
-typedef int (*mgcp_change)(struct mgcp_trunk *cfg, int endpoint, int state);
-typedef int (*mgcp_policy)(struct mgcp_trunk *cfg, int endpoint, int state, const char *transactio_id);
+typedef int (*mgcp_change)(struct mgcp_endpoint *endp, int state);
+typedef int (*mgcp_policy)(struct mgcp_endpoint *endp, int state, const char *transaction_id);
 typedef int (*mgcp_reset)(struct mgcp_trunk *cfg);
 typedef int (*mgcp_rqnt)(struct mgcp_endpoint *endp, char tone);
 
@@ -177,57 +179,6 @@
 	MGCP_DLCX_DEFERRED_BY_POLICY,
 };
 
-struct mgcp_trunk {
-	struct llist_head entry;
-
-	struct mgcp_config *cfg;
-
-	int trunk_nr;
-	int trunk_type;
-
-	char *audio_fmtp_extra;
-	char *audio_name;
-	int audio_payload;
-	int audio_send_ptime;
-	int audio_send_name;
-	int audio_loop;
-
-	int no_audio_transcoding;
-
-	int omit_rtcp;
-	int keepalive_interval;
-
-	/* RTP patching */
-	int force_constant_ssrc; /* 0: don't, 1: once */
-	int force_aligned_timing;
-	bool rfc5993_hr_convert;
-
-	/* spec handling */
-	int force_realloc;
-
-	/* timer */
-	struct osmo_timer_list keepalive_timer;
-
-	/* When set, incoming RTP packets are not filtered
-	 * when ports and ip-address do not match (debug) */
-	int rtp_accept_all;
-
-	unsigned int number_endpoints;
-	int vty_number_endpoints;
-	struct mgcp_endpoint *endpoints;
-
-	/* Rate counter group which contains stats for generic MGCP events. */
-	struct rate_ctr_group *mgcp_general_ctr_group;
-	/* Rate counter group which contains stats for processed CRCX commands. */
-	struct rate_ctr_group *mgcp_crcx_ctr_group;
-	/* Rate counter group which contains stats for processed MDCX commands. */
-	struct rate_ctr_group *mgcp_mdcx_ctr_group;
-	/* Rate counter group which contains stats for processed DLCX commands. */
-	struct rate_ctr_group *mgcp_dlcx_ctr_group;
-	/* Rate counter group which aggregates stats of individual RTP connections. */
-	struct rate_ctr_group *all_rtp_conn_stats;
-};
-
 enum mgcp_role {
 	MGCP_BSC = 0,
 	MGCP_BSC_NAT,
@@ -295,6 +246,10 @@
 
 	/* osmocom CTRL interface */
 	struct ctrl_handle *ctrl;
+
+	/* global rate counters to measure the MGWs overall performance and
+	 * health */
+	struct mgcp_ratectr_global ratectr;
 };
 
 /* config management */
@@ -302,7 +257,6 @@
 int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
 		      enum mgcp_role role);
 int mgcp_vty_init(void);
-int mgcp_endpoints_allocate(struct mgcp_trunk *cfg);
 void mgcp_trunk_set_keepalive(struct mgcp_trunk *trunk, int interval);
 
 /*
@@ -311,7 +265,7 @@
 struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg);
 
 
-int mgcp_send_reset_ep(struct mgcp_endpoint *endp, int endpoint);
+int mgcp_send_reset_ep(struct mgcp_endpoint *endp);
 int mgcp_send_reset_all(struct mgcp_config *cfg);
 
 
diff --git a/include/osmocom/mgcp/mgcp_common.h b/include/osmocom/mgcp/mgcp_common.h
index a1bbb19..07d8d37 100644
--- a/include/osmocom/mgcp/mgcp_common.h
+++ b/include/osmocom/mgcp/mgcp_common.h
@@ -100,6 +100,10 @@
 /* A prefix to denote the virtual trunk (RTP on both ends) */
 #define MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK "rtpbridge/"
 
+/* A prefix to denote the e1 trunk
+ * (see also RFC3435 section E.2) */
+#define MGCP_ENDPOINT_PREFIX_E1_TRUNK "ds/e1-"
+
 /* Maximal number of payload types / codecs that can be negotiated via SDP at
  * at once. */
 #define MGCP_MAX_CODECS 10
diff --git a/include/osmocom/mgcp/mgcp_endp.h b/include/osmocom/mgcp/mgcp_endp.h
index 8fa8390..5737cd2 100644
--- a/include/osmocom/mgcp/mgcp_endp.h
+++ b/include/osmocom/mgcp/mgcp_endp.h
@@ -28,8 +28,8 @@
 struct mgcp_endpoint;
 
 #define LOGPENDP(endp, cat, level, fmt, args...) \
-LOGP(cat, level, "endpoint:0x%x " fmt, \
-     endp ? ENDPOINT_NUMBER(endp) : -1, \
+LOGP(cat, level, "endpoint:%s " fmt, \
+     endp ? endp->name : "none", \
      ## args)
 
 /* Callback type for RTP dispatcher functions
@@ -68,6 +68,9 @@
 /*! MGCP endpoint model */
 struct mgcp_endpoint {
 
+	/*! Unique endpoint name, used for addressing via MGCP */
+	char *name;
+
 	/*! Call identifier string (as supplied by the call agant) */
 	char *callid;
 
@@ -80,7 +83,7 @@
 	/*! Backpointer to the MGW configuration */
 	struct mgcp_config *cfg;
 
-	/*! Backpointer to the Trunk specific configuration */
+	/*! Backpointer to the trunk this endpoint belongs to */
 	struct mgcp_trunk *trunk;
 
 	/*! Endpoint properties (see above) */
@@ -100,7 +103,9 @@
 	uint32_t x_osmo_ign;
 };
 
-/*! Extract endpoint number for a given endpoint */
-#define ENDPOINT_NUMBER(endp) abs((int)(endp - endp->trunk->endpoints))
-
+struct mgcp_endpoint *mgcp_endp_alloc(struct mgcp_trunk *trunk, char *name);
 void mgcp_endp_release(struct mgcp_endpoint *endp);
+struct mgcp_endpoint *mgcp_endp_by_name_trunk(int *cause, const char *epname,
+					      const struct mgcp_trunk *trunk);
+struct mgcp_endpoint *mgcp_endp_by_name(int *cause, const char *epname,
+					struct mgcp_config *cfg);
diff --git a/include/osmocom/mgcp/mgcp_internal.h b/include/osmocom/mgcp/mgcp_internal.h
index b2e2210..174bfd9 100644
--- a/include/osmocom/mgcp/mgcp_internal.h
+++ b/include/osmocom/mgcp/mgcp_internal.h
@@ -282,9 +282,6 @@
 	return endpoint + 60;
 }
 
-struct mgcp_trunk *mgcp_trunk_alloc(struct mgcp_config *cfg, enum mgcp_trunk_type ttype, int index);
-struct mgcp_trunk *mgcp_trunk_num(struct mgcp_config *cfg, int index);
-
 char *get_lco_identifier(const char *options);
 int check_local_cx_options(void *ctx, const char *options);
 void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change,
diff --git a/include/osmocom/mgcp/mgcp_ratectr.h b/include/osmocom/mgcp/mgcp_ratectr.h
new file mode 100644
index 0000000..e05b70c
--- /dev/null
+++ b/include/osmocom/mgcp/mgcp_ratectr.h
@@ -0,0 +1,22 @@
+#pragma once
+
+/* NOTE: When adding counters, also the dump_ratectr_* routines in vty.c must be updated. */
+
+struct mgcp_ratectr_global {
+	/* Rate counter group which contains stats for generic MGCP events. */
+	struct rate_ctr_group *mgcp_general_ctr_group;
+};
+
+struct mgcp_ratectr_trunk {
+	/* Rate counter group which contains stats for processed CRCX commands. */
+	struct rate_ctr_group *mgcp_crcx_ctr_group;
+	/* Rate counter group which contains stats for processed MDCX commands. */
+	struct rate_ctr_group *mgcp_mdcx_ctr_group;
+	/* Rate counter group which contains stats for processed DLCX commands. */
+	struct rate_ctr_group *mgcp_dlcx_ctr_group;
+	/* Rate counter group which aggregates stats of individual RTP connections. */
+	struct rate_ctr_group *all_rtp_conn_stats;
+};
+
+int mgcp_ratectr_global_alloc(void *ctx, struct mgcp_ratectr_global *ratectr);
+int mgcp_ratectr_trunk_alloc(void *ctx, struct mgcp_ratectr_trunk *ratectr);
diff --git a/include/osmocom/mgcp/mgcp_trunk.h b/include/osmocom/mgcp/mgcp_trunk.h
new file mode 100644
index 0000000..436e39a
--- /dev/null
+++ b/include/osmocom/mgcp/mgcp_trunk.h
@@ -0,0 +1,49 @@
+#pragma once
+
+struct mgcp_trunk {
+	struct llist_head entry;
+
+	struct mgcp_config *cfg;
+
+	int trunk_nr;
+	int trunk_type;
+
+	char *audio_fmtp_extra;
+	char *audio_name;
+	int audio_payload;
+	int audio_send_ptime;
+	int audio_send_name;
+	int audio_loop;
+
+	int no_audio_transcoding;
+
+	int omit_rtcp;
+	int keepalive_interval;
+
+	/* RTP patching */
+	int force_constant_ssrc; /* 0: don't, 1: once */
+	int force_aligned_timing;
+	bool rfc5993_hr_convert;
+
+	/* spec handling */
+	int force_realloc;
+
+	/* timer */
+	struct osmo_timer_list keepalive_timer;
+
+	/* When set, incoming RTP packets are not filtered
+	 * when ports and ip-address do not match (debug) */
+	int rtp_accept_all;
+
+	unsigned int number_endpoints;
+	unsigned int vty_number_endpoints;
+	struct mgcp_endpoint **endpoints;
+
+	/* global rate counters to measure the trunks overall performance and health */
+	struct mgcp_ratectr_trunk ratectr;
+};
+
+struct mgcp_trunk *mgcp_trunk_alloc(struct mgcp_config *cfg, enum mgcp_trunk_type ttype, int nr);
+int mgcp_trunk_alloc_endpts(struct mgcp_trunk *tcfg);
+struct mgcp_trunk *mgcp_trunk_by_num(const struct mgcp_config *cfg, int index);
+struct mgcp_trunk *mgcp_trunk_by_name(const struct mgcp_config *cfg, const char *epname);