diff options
author | Harald Welte <laforge@gnumonks.org> | 2018-05-30 01:39:43 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2018-06-02 20:56:17 +0200 |
commit | c997ceb750a67baef1a05590febe1c678b287d8f (patch) | |
tree | e50b2bf3fe565546316577aa18096bffb9bb3497 /src/osmo-bsc/osmo_bsc_bssap.c | |
parent | 00965dca2bd78cc57ddb3989b365226908ff1c31 (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.c | 84 |
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])); |