aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bsc/osmo_bsc_bssap.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2018-05-30 01:39:43 +0200
committerHarald Welte <laforge@gnumonks.org>2018-06-02 20:56:17 +0200
commitc997ceb750a67baef1a05590febe1c678b287d8f (patch)
treee50b2bf3fe565546316577aa18096bffb9bb3497 /src/osmo-bsc/osmo_bsc_bssap.c
parent00965dca2bd78cc57ddb3989b365226908ff1c31 (diff)
Add initial 3GPP LCLS support to OsmoBSC
This code contains the following code: * receive/parse/interpret LCLS specific BSSMAP IEs and PDUs * osmo_fsm handling the various states and their transitions * call leg correlation (finding the other subscr_conn with same GCR) * communication between the two call-leg LCLS FSMs * detection of supported / unsupported LCLS configurations * display of GCR / LCLS information in "show conns" * switch the media streams locally using MDCX to the MGW Closes: OS#1602 Change-Id: I614fade62834def5cafc94c4d2578cd747a3f9f7
Diffstat (limited to 'src/osmo-bsc/osmo_bsc_bssap.c')
-rw-r--r--src/osmo-bsc/osmo_bsc_bssap.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/src/osmo-bsc/osmo_bsc_bssap.c b/src/osmo-bsc/osmo_bsc_bssap.c
index f7f99fa30..24a5e3a3e 100644
--- a/src/osmo-bsc/osmo_bsc_bssap.c
+++ b/src/osmo-bsc/osmo_bsc_bssap.c
@@ -34,8 +34,10 @@
#include <osmocom/gsm/gsm0808_utils.h>
#include <osmocom/gsm/gsm48.h>
#include <osmocom/bsc/osmo_bsc_sigtran.h>
+#include <osmocom/bsc/osmo_bsc_lcls.h>
#include <osmocom/bsc/a_reset.h>
#include <osmocom/core/byteswap.h>
+#include <osmocom/core/fsm.h>
#define IP_V4_ADDR_LEN 4
@@ -634,6 +636,83 @@ reject:
return -1;
}
+/* handle LCLS specific IES in BSSMAP ASS REQ */
+static void bssmap_handle_ass_req_lcls(struct gsm_subscriber_connection *conn,
+ const struct tlv_parsed *tp)
+{
+ const struct tlv_p_entry *tlv;
+ const uint8_t *config, *control;
+
+ tlv = TLVP_GET(tp, GSM0808_IE_GLOBAL_CALL_REF);
+ if (tlv) {
+ if (tlv->len > sizeof(conn->lcls.global_call_ref))
+ LOGPFSML(conn->fi, LOGL_ERROR, "Global Call Ref IE of %u bytes is too long\n",
+ tlv->len);
+ else {
+ LOGPFSM(conn->fi, "Setting GCR to %s\n", osmo_hexdump_nospc(tlv->val, tlv->len));
+ memcpy(&conn->lcls.global_call_ref, tlv->val, tlv->len);
+ conn->lcls.global_call_ref_len = tlv->len;
+ }
+ }
+
+ config = TLVP_VAL_MINLEN(tp, GSM0808_IE_LCLS_CONFIG, 1);
+ control = TLVP_VAL_MINLEN(tp, GSM0808_IE_LCLS_CONN_STATUS_CTRL, 1);
+
+ if (config || control) {
+ LOGPFSM(conn->fi, "BSSMAP ASS REQ contains LCLS (%s / %s)\n",
+ config ? gsm0808_lcls_config_name(*config) : "NULL",
+ control ? gsm0808_lcls_control_name(*control) : "NULL");
+ }
+
+ /* Update the LCLS state with Config + CSC (if any) */
+ lcls_update_config(conn, config, control);
+
+ /* Do not attempt to perform correlation yet, as during processing of the ASS REQ
+ * we don't have the MGCP/MGW connections yet, and hence couldn't enable LS. */
+}
+
+/* TS 48.008 3.2.1.91 */
+static int bssmap_handle_lcls_connect_ctrl(struct gsm_subscriber_connection *conn,
+ struct msgb *msg, unsigned int length)
+{
+ struct msgb *resp;
+ struct tlv_parsed tp;
+ const uint8_t *config, *control;
+ int rc;
+
+ OSMO_ASSERT(conn);
+
+ rc = tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, length - 1, 0, 0);
+ if (rc < 0) {
+ LOGPFSML(conn->fi, LOGL_ERROR, "Error parsing TLVs of LCLS CONNT CTRL: %s\n",
+ msgb_hexdump(msg));
+ return rc;
+ }
+ config = TLVP_VAL_MINLEN(&tp, GSM0808_IE_LCLS_CONFIG, 1);
+ control = TLVP_VAL_MINLEN(&tp, GSM0808_IE_LCLS_CONN_STATUS_CTRL, 1);
+
+ LOGPFSM(conn->fi, "Rx LCLS CONNECT CTRL (%s / %s)\n",
+ config ? gsm0808_lcls_config_name(*config) : "NULL",
+ control ? gsm0808_lcls_control_name(*control) : "NULL");
+
+ if (conn->lcls.global_call_ref_len == 0) {
+ LOGPFSML(conn->fi, LOGL_ERROR, "Ignoring LCLS as no GCR was set before\n");
+ return 0;
+ }
+ /* Update the LCLS state with Config + CSC (if any) */
+ lcls_update_config(conn, TLVP_VAL_MINLEN(&tp, GSM0808_IE_LCLS_CONFIG, 1),
+ TLVP_VAL_MINLEN(&tp, GSM0808_IE_LCLS_CONN_STATUS_CTRL, 1));
+ lcls_apply_config(conn);
+
+ LOGPFSM(conn->fi, "Tx LCLS CONNECT CTRL ACK (%s)\n",
+ gsm0808_lcls_status_name(lcls_get_status(conn)));
+ resp = gsm0808_create_lcls_conn_ctrl_ack(lcls_get_status(conn));
+ osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_TX_SCCP, resp);
+
+ return 0;
+}
+
+
/*
* Handle the assignment request message.
*
@@ -682,6 +761,8 @@ static int bssmap_handle_assignm_req(struct gsm_subscriber_connection *conn,
goto reject;
}
+ bssmap_handle_ass_req_lcls(conn, &tp);
+
/* Currently we only support a limited subset of all
* possible channel types, such as multi-slot or CSD */
switch (ct.ch_indctr) {
@@ -852,6 +933,9 @@ static int bssmap_rcvmsg_dt1(struct gsm_subscriber_connection *conn,
case BSS_MAP_MSG_ASSIGMENT_RQST:
ret = bssmap_handle_assignm_req(conn, msg, length);
break;
+ case BSS_MAP_MSG_LCLS_CONNECT_CTRL:
+ ret = bssmap_handle_lcls_connect_ctrl(conn, msg, length);
+ break;
default:
LOGP(DMSC, LOGL_NOTICE, "Unimplemented msg type: %s\n",
gsm0808_bssmap_name(msg->l4h[0]));