mgcp_e1: finish E1 support, add E1 support from libosmoabis

Currently only the endpoint handling for E1 exists, but there is no
actual code behind it that handles the E1 traffic.

Change-Id: I6b93809b5ac7d01af55888347dd787b0bc997ae1
Related: OS#2659
diff --git a/include/osmocom/mgcp/Makefile.am b/include/osmocom/mgcp/Makefile.am
index fb7654f..549ba87 100644
--- a/include/osmocom/mgcp/Makefile.am
+++ b/include/osmocom/mgcp/Makefile.am
@@ -10,4 +10,5 @@
 	mgcp_trunk.h \
 	debug.h \
 	mgcp_ratectr.h \
+	mgcp_e1.h \
 	$(NULL)
diff --git a/include/osmocom/mgcp/debug.h b/include/osmocom/mgcp/debug.h
index ddeb0dc..7044c1e 100644
--- a/include/osmocom/mgcp/debug.h
+++ b/include/osmocom/mgcp/debug.h
@@ -29,6 +29,7 @@
 /* Debug Areas of the code */
 enum {
 	DRTP,
+	DE1,
 	Debug_LastEntry,
 };
 
diff --git a/include/osmocom/mgcp/mgcp_conn.h b/include/osmocom/mgcp/mgcp_conn.h
index ff5a779..78d5ea8 100644
--- a/include/osmocom/mgcp/mgcp_conn.h
+++ b/include/osmocom/mgcp/mgcp_conn.h
@@ -124,3 +124,4 @@
 void mgcp_conn_free_all(struct mgcp_endpoint *endp);
 char *mgcp_conn_dump(struct mgcp_conn *conn);
 struct mgcp_conn *mgcp_find_dst_conn(struct mgcp_conn *conn);
+struct mgcp_conn *mgcp_conn_get_oldest(struct mgcp_endpoint *endp);
diff --git a/include/osmocom/mgcp/mgcp_e1.h b/include/osmocom/mgcp/mgcp_e1.h
new file mode 100644
index 0000000..a4ae854
--- /dev/null
+++ b/include/osmocom/mgcp/mgcp_e1.h
@@ -0,0 +1,28 @@
+#pragma once
+
+/* A 64k timeslot on an E1 line can be subdevied into the following
+ * subslot combinations:
+ *
+ * subslot:                                          offset:
+ * [          ][          ][   16k    ][8k_subslot]  0
+ * [          ][   32k    ][_subslot__][8k_subslot]  1
+ * [          ][ subslot  ][   16k    ][8k_subslot]  2
+ * [   64k    ][__________][_subslot__][8k_subslot]  3
+ * [ timeslot ][          ][   16k    ][8k_subslot]  4
+ * [          ][   32K    ][_subslot__][8k_subslot]  5
+ * [          ][ subslot  ][   16k    ][8k_subslot]  6
+ * [          ][          ][ subslot  ][8k_subslot]  7
+ *
+ * Since overlapping assignment of subslots is not possible there is a limited
+ * set of subslot assignments possible. The e1_rates array lists the possible
+ * assignments as depicted above. Also each subslot assignment comes along with
+ * a bit offset in the E1 bitstream. The e1_offsets arrays lists the bit
+ * offsets. */
+static const uint8_t e1_rates[] = { 64, 32, 32, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 8, 8 };
+static const uint8_t e1_offsets[] = { 0, 0, 4, 0, 2, 4, 6, 0, 1, 2, 3, 4, 5, 6, 7 };
+
+int mgcp_e1_init(struct mgcp_trunk *trunk, uint8_t ts_nr);
+int mgcp_e1_endp_equip(struct mgcp_endpoint *endp, uint8_t ts, uint8_t ss, uint8_t offs);
+void mgcp_e1_endp_update(struct mgcp_endpoint *endp);
+void mgcp_e1_endp_release(struct mgcp_endpoint *endp);
+int mgcp_e1_send_rtp(struct mgcp_endpoint *endp, struct mgcp_rtp_codec *codec, struct msgb *msg);
diff --git a/include/osmocom/mgcp/mgcp_endp.h b/include/osmocom/mgcp/mgcp_endp.h
index c16ea4b..065494f 100644
--- a/include/osmocom/mgcp/mgcp_endp.h
+++ b/include/osmocom/mgcp/mgcp_endp.h
@@ -24,6 +24,7 @@
 #pragma once
 
 #include <osmocom/core/msgb.h>
+#include <osmocom/gsm/i460_mux.h>
 
 struct sockaddr_in;
 struct mgcp_conn;
@@ -116,10 +117,23 @@
 
 	/*! MGCP_X_OSMO_IGN_* flags from 'X-Osmo-IGN:' header */
 	uint32_t x_osmo_ign;
+
+	/* E1 specific */
+	struct {
+		struct osmo_i460_schan_desc scd;
+		struct osmo_i460_subchan *schan;
+		struct osmo_fsm_inst *trau_sync_fi;
+		struct osmo_trau2rtp_state *trau_rtp_st;
+		uint8_t last_amr_ft;
+		struct mgcp_rtp_codec *last_codec;
+	} e1;
+
 };
 
 struct mgcp_endpoint *mgcp_endp_alloc(struct mgcp_trunk *trunk, unsigned int index);
 void mgcp_endp_release(struct mgcp_endpoint *endp);
+int mgcp_endp_claim(struct mgcp_endpoint *endp, const char *callid);
+void mgcp_endp_update(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,
diff --git a/include/osmocom/mgcp/mgcp_internal.h b/include/osmocom/mgcp/mgcp_internal.h
index 3d7224e..86b2a57 100644
--- a/include/osmocom/mgcp/mgcp_internal.h
+++ b/include/osmocom/mgcp/mgcp_internal.h
@@ -71,6 +71,10 @@
 	/* duration of a packet (FIXME: in which unit?) */
 	uint32_t packet_duration;
 
+	/* Note: These states are not continuously updated, they serve as an
+	 * information source to patch certain values in the RTP header. Do
+	 * not use this state if constantly updated data about the RTP stream
+	 * is needed. (see also mgcp_patch_and_count() */
 	struct mgcp_rtp_stream_state in_stream;
 	struct mgcp_rtp_stream_state out_stream;
 
@@ -85,6 +89,13 @@
 		int cycles;
 	} stats;
 
+	/* Alternative values for RTP tx, in case no sufficient header
+	 * information is available so the header needs to be generated
+	 * locally (when just forwarding packets, the header of incoming
+	 * data is just re-used) */
+	uint16_t alt_rtp_tx_sequence;
+	uint32_t alt_rtp_tx_ssrc;
+
 	bool patched_first_rtp_payload; /* FIXME: drop this, see OS#2459 */
 };
 
@@ -296,3 +307,5 @@
 			  struct mgcp_rtp_state *state,
 			  struct mgcp_rtp_end *rtp_end,
 			  struct sockaddr_in *addr, struct msgb *msg);
+
+#define RTP_BUF_SIZE		4096
diff --git a/include/osmocom/mgcp/mgcp_ratectr.h b/include/osmocom/mgcp/mgcp_ratectr.h
index d0bc628..ff59ea4 100644
--- a/include/osmocom/mgcp/mgcp_ratectr.h
+++ b/include/osmocom/mgcp/mgcp_ratectr.h
@@ -29,6 +29,7 @@
 	MGCP_CRCX_FAIL_CODEC_NEGOTIATION,
 	MGCP_CRCX_FAIL_BIND_PORT,
 	MGCP_CRCX_FAIL_AVAIL,
+	MGCP_CRCX_FAIL_CLAIM,
 };
 
 /* Global MCGP MDCX related rate counters */
@@ -63,6 +64,13 @@
 	MGCP_DLCX_FAIL_AVAIL,
 };
 
+/* Trunk-global E1 related counters */
+enum {
+        E1_I460_TRAU_RX_FAIL_CTR,
+        E1_I460_TRAU_TX_FAIL_CTR,
+        E1_I460_TRAU_MUX_EMPTY_CTR,
+};
+
 /* NOTE: When adding counters, also the dump_ratectr_* routines in vty.c must be updated. */
 
 struct mgcp_ratectr_global {
@@ -79,6 +87,8 @@
 	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;
+	/* Rate counter group which contains stats for E1 events (only valid for E1 trunks) */
+	struct rate_ctr_group *e1_stats;
 };
 
 int mgcp_ratectr_global_alloc(void *ctx, struct mgcp_ratectr_global *ratectr);
diff --git a/include/osmocom/mgcp/mgcp_trunk.h b/include/osmocom/mgcp/mgcp_trunk.h
index aa6dd29..d99f801 100644
--- a/include/osmocom/mgcp/mgcp_trunk.h
+++ b/include/osmocom/mgcp/mgcp_trunk.h
@@ -1,5 +1,13 @@
 #pragma once
 
+#include <osmocom/gsm/i460_mux.h>
+
+#define LOGPTRUNK(trunk, cat, level, fmt, args...) \
+LOGP(cat, level, "trunk:%u " fmt, \
+     trunk ? trunk->trunk_nr : 0, \
+     ## args)
+
+
 enum mgcp_trunk_type {
 	MGCP_TRUNK_VIRTUAL,
 	MGCP_TRUNK_E1,
@@ -39,18 +47,32 @@
 	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;
+
+	union {
+		/* Virtual trunk specific */
+		struct {
+			unsigned int vty_number_endpoints;
+		} v;
+		/* E1 specific */
+		struct {
+			unsigned int vty_line_nr;
+			struct e1inp_line *line;
+			bool ts_in_use[31];
+			struct osmo_i460_timeslot i460_ts[31];
+		} e1;
+	};
 };
 
 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);
+int mgcp_trunk_equip(struct mgcp_trunk *trunk);
 struct mgcp_trunk *mgcp_trunk_by_num(const struct mgcp_config *cfg, enum mgcp_trunk_type ttype, int nr);
 struct mgcp_trunk *mgcp_trunk_by_name(const struct mgcp_config *cfg, const char *epname);
 int e1_trunk_nr_from_epname(const char *epname);
+struct mgcp_trunk *mgcp_trunk_by_line_num(const struct mgcp_config *cfg, unsigned int num);
 
 /* The virtual trunk is always created on trunk id 0 for historical reasons,
  * use this define constant as ID when allocating a virtual trunk. Other