aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2018-03-21 22:11:32 +0100
committerHarald Welte <laforge@gnumonks.org>2018-03-22 15:15:12 +0000
commitead291aaf2bbbea3a853ef02008f88fe4c001db0 (patch)
tree69095987a9cfc7a3daa3a873794f58f8af59c039
parent6900f8123611fc4667ba42c25a03abf96e697aa7 (diff)
bssmap: State correct speech codec in ASSIGNMENT COMPLETE
Correctly compute the TS 48.008 "speech mode" (codec) for AMR on TCH/F. There are way too many different ways how to express a given voice codec. There are two different schemes in TS 48.008 alone, plus one on TS 48.058 and one in 04.08 / 44.018. Let's avoid unneeded conversion (that we might get wrong) and avoid storing information in a sub-struct of the lchan if we can simply derive it from the lchan at the time we need it. Also, move BSSAP related encoding/conversion functions closer to the user (osmo_bsc_bssap), rather than in libbsc. Without this patch, TCH/F with AMR was erroneously reported as TCH/H with AMR in the BSSMAP ASSIGNMENT COMPLETE. After this patch, it's reported correctly. Change-Id: I6feebfae77fdc93a7ce333a25dd9b9267c5a4a2e Related: OS#3094 Related: OS#3095 Related: OS#3096
-rw-r--r--include/osmocom/bsc/bsc_api.h7
-rw-r--r--include/osmocom/bsc/gsm_data.h3
-rw-r--r--src/libbsc/bsc_api.c93
-rw-r--r--src/libbsc/bsc_subscr_conn_fsm.c91
-rw-r--r--src/osmo-bsc/osmo_bsc_api.c7
5 files changed, 91 insertions, 110 deletions
diff --git a/include/osmocom/bsc/bsc_api.h b/include/osmocom/bsc/bsc_api.h
index 01f90b158..06f80937f 100644
--- a/include/osmocom/bsc/bsc_api.h
+++ b/include/osmocom/bsc/bsc_api.h
@@ -21,9 +21,7 @@ struct bsc_api {
void (*dtap)(struct gsm_subscriber_connection *conn, uint8_t link_id,
struct msgb *msg);
/*! \brief BSC->MSC: Assignment of lchan successful */
- void (*assign_compl)(struct gsm_subscriber_connection *conn,
- uint8_t rr_cause, uint8_t chosen_channel,
- uint8_t encr_alg_id, uint8_t speech_mode);
+ void (*assign_compl)(struct gsm_subscriber_connection *conn, uint8_t rr_cause);
/*! \brief BSC->MSC: Assignment of lchan failed */
void (*assign_fail)(struct gsm_subscriber_connection *conn,
uint8_t cause, uint8_t *rr_cause);
@@ -46,9 +44,6 @@ struct bsc_api {
void (*conn_cleanup)(struct gsm_subscriber_connection *conn);
};
-uint8_t lchan_to_chosen_channel(struct gsm_lchan *lchan);
-uint8_t chan_mode_to_speech(struct gsm_lchan *lchan);
-
int bsc_api_init(struct gsm_network *network, struct bsc_api *api);
int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg, int link_id, int allow_sacch);
int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_mode, int full_rate);
diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h
index fa65ab973..8caedff36 100644
--- a/include/osmocom/bsc/gsm_data.h
+++ b/include/osmocom/bsc/gsm_data.h
@@ -416,9 +416,6 @@ struct gsm_lchan {
* assignment completed message */
struct {
uint8_t rr_cause;
- uint8_t chosen_channel;
- uint8_t encr_alg_id;
- uint8_t speech_mode;
bool valid;
} ass_compl;
} abis_ip;
diff --git a/src/libbsc/bsc_api.c b/src/libbsc/bsc_api.c
index 748245342..142efef02 100644
--- a/src/libbsc/bsc_api.c
+++ b/src/libbsc/bsc_api.c
@@ -50,89 +50,6 @@ static void handle_release(struct gsm_subscriber_connection *conn, struct bsc_ap
static void handle_chan_ack(struct gsm_subscriber_connection *conn, struct bsc_api *bsc, struct gsm_lchan *lchan);
static void handle_chan_nack(struct gsm_subscriber_connection *conn, struct bsc_api *bsc, struct gsm_lchan *lchan);
-/* GSM 08.08 3.2.2.33 */
-uint8_t lchan_to_chosen_channel(struct gsm_lchan *lchan)
-{
- uint8_t channel_mode = 0, channel = 0;
-
- switch (lchan->tch_mode) {
- case GSM48_CMODE_SPEECH_V1:
- case GSM48_CMODE_SPEECH_EFR:
- case GSM48_CMODE_SPEECH_AMR:
- channel_mode = 0x9;
- break;
- case GSM48_CMODE_SIGN:
- channel_mode = 0x8;
- break;
- case GSM48_CMODE_DATA_14k5:
- channel_mode = 0xe;
- break;
- case GSM48_CMODE_DATA_12k0:
- channel_mode = 0xb;
- break;
- case GSM48_CMODE_DATA_6k0:
- channel_mode = 0xc;
- break;
- case GSM48_CMODE_DATA_3k6:
- channel_mode = 0xd;
- break;
- }
-
- switch (lchan->type) {
- case GSM_LCHAN_NONE:
- channel = 0x0;
- break;
- case GSM_LCHAN_SDCCH:
- channel = 0x1;
- break;
- case GSM_LCHAN_TCH_F:
- channel = 0x8;
- break;
- case GSM_LCHAN_TCH_H:
- channel = 0x9;
- break;
- case GSM_LCHAN_UNKNOWN:
- default:
- LOGP(DMSC, LOGL_ERROR, "Unknown lchan type: %p\n", lchan);
- break;
- }
-
- return channel_mode << 4 | channel;
-}
-
-uint8_t chan_mode_to_speech(struct gsm_lchan *lchan)
-{
- int mode = 0;
-
- switch (lchan->tch_mode) {
- case GSM48_CMODE_SPEECH_V1:
- mode = 1;
- break;
- case GSM48_CMODE_SPEECH_EFR:
- mode = 0x11;
- break;
- case GSM48_CMODE_SPEECH_AMR:
- mode = 0x21;
- break;
- case GSM48_CMODE_SIGN:
- case GSM48_CMODE_DATA_14k5:
- case GSM48_CMODE_DATA_12k0:
- case GSM48_CMODE_DATA_6k0:
- case GSM48_CMODE_DATA_3k6:
- default:
- LOGP(DMSC, LOGL_ERROR, "Using non speech mode: %d\n", mode);
- return 0;
- break;
- }
-
- /* assume to always do AMR HR on any TCH type */
- if (lchan->type == GSM_LCHAN_TCH_H ||
- lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)
- mode |= 0x4;
-
- return mode;
-}
-
/*! \brief Determine and apply AMR multi-rate configuration to lchan
* Determine which AMR multi-rate configuration to use and apply it to
* the lchan (so it can be communicated to BTS and MS during channel
@@ -470,10 +387,7 @@ static void handle_ass_compl(struct gsm_subscriber_connection *conn,
if (is_ipaccess_bts(conn_get_bts(conn)) && conn->lchan->tch_mode != GSM48_CMODE_SIGN)
rsl_ipacc_crcx(conn->lchan);
- api->assign_compl(conn, gh->data[0],
- lchan_to_chosen_channel(conn->lchan),
- conn->lchan->encr.alg_id,
- chan_mode_to_speech(conn->lchan));
+ api->assign_compl(conn, gh->data[0]);
}
static void handle_ass_fail(struct gsm_subscriber_connection *conn,
@@ -673,10 +587,7 @@ static void dispatch_dtap(struct gsm_subscriber_connection *conn,
GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE,
NULL);
} else if (rc >= 0) {
- api->assign_compl(conn, 0,
- lchan_to_chosen_channel(conn->lchan),
- conn->lchan->encr.alg_id,
- chan_mode_to_speech(conn->lchan));
+ api->assign_compl(conn, 0);
}
break;
case GSM48_MT_RR_CLSM_CHG:
diff --git a/src/libbsc/bsc_subscr_conn_fsm.c b/src/libbsc/bsc_subscr_conn_fsm.c
index 9d23dd55f..03eec3f39 100644
--- a/src/libbsc/bsc_subscr_conn_fsm.c
+++ b/src/libbsc/bsc_subscr_conn_fsm.c
@@ -143,12 +143,95 @@ static void sigtran_send(struct gsm_subscriber_connection *conn, struct msgb *ms
LOGPFSML(fi, LOGL_ERROR, "Unable to deliver SCCP message!\n");
}
+
+/* See TS 48.008 3.2.2.11 Channel Type Octet 5 */
+static int bssap_speech_from_lchan(const struct gsm_lchan *lchan)
+{
+ switch (lchan->type) {
+ case GSM_LCHAN_TCH_H:
+ switch (lchan->tch_mode) {
+ case GSM48_CMODE_SPEECH_V1:
+ return 0x05;
+ case GSM48_CMODE_SPEECH_AMR:
+ return 0x25;
+ default:
+ return -1;
+ }
+ break;
+ case GSM_LCHAN_TCH_F:
+ switch (lchan->tch_mode) {
+ case GSM48_CMODE_SPEECH_V1:
+ return 0x01;
+ case GSM48_CMODE_SPEECH_EFR:
+ return 0x11;
+ case GSM48_CMODE_SPEECH_AMR:
+ return 0x21;
+ default:
+ return -1;
+ }
+ break;
+ default:
+ return -1;
+ }
+}
+
+/* GSM 08.08 3.2.2.33 */
+static uint8_t lchan_to_chosen_channel(struct gsm_lchan *lchan)
+{
+ uint8_t channel_mode = 0, channel = 0;
+
+ switch (lchan->tch_mode) {
+ case GSM48_CMODE_SPEECH_V1:
+ case GSM48_CMODE_SPEECH_EFR:
+ case GSM48_CMODE_SPEECH_AMR:
+ channel_mode = 0x9;
+ break;
+ case GSM48_CMODE_SIGN:
+ channel_mode = 0x8;
+ break;
+ case GSM48_CMODE_DATA_14k5:
+ channel_mode = 0xe;
+ break;
+ case GSM48_CMODE_DATA_12k0:
+ channel_mode = 0xb;
+ break;
+ case GSM48_CMODE_DATA_6k0:
+ channel_mode = 0xc;
+ break;
+ case GSM48_CMODE_DATA_3k6:
+ channel_mode = 0xd;
+ break;
+ }
+
+ switch (lchan->type) {
+ case GSM_LCHAN_NONE:
+ channel = 0x0;
+ break;
+ case GSM_LCHAN_SDCCH:
+ channel = 0x1;
+ break;
+ case GSM_LCHAN_TCH_F:
+ channel = 0x8;
+ break;
+ case GSM_LCHAN_TCH_H:
+ channel = 0x9;
+ break;
+ case GSM_LCHAN_UNKNOWN:
+ default:
+ LOGP(DMSC, LOGL_ERROR, "Unknown lchan type: %p\n", lchan);
+ break;
+ }
+
+ return channel_mode << 4 | channel;
+}
+
/* Generate and send assignment complete message */
static void send_ass_compl(struct gsm_lchan *lchan, struct osmo_fsm_inst *fi)
{
struct msgb *resp;
struct gsm0808_speech_codec sc;
struct gsm_subscriber_connection *conn;
+ int perm_spch = bssap_speech_from_lchan(lchan);
conn = lchan->conn;
@@ -158,13 +241,13 @@ static void send_ass_compl(struct gsm_lchan *lchan, struct osmo_fsm_inst *fi)
LOGPFSML(fi, LOGL_DEBUG, "Sending assignment complete message... (id=%i)\n", conn->sccp.conn_id);
/* Extrapolate speech codec from speech mode */
- gsm0808_speech_codec_from_chan_type(&sc, lchan->abis_ip.ass_compl.speech_mode);
+ gsm0808_speech_codec_from_chan_type(&sc, perm_spch);
+ /* FIXME: AMR codec configuration must be derived from lchan1! */
/* Generate message */
resp = gsm0808_create_ass_compl(lchan->abis_ip.ass_compl.rr_cause,
- lchan->abis_ip.ass_compl.chosen_channel,
- lchan->abis_ip.ass_compl.encr_alg_id,
- lchan->abis_ip.ass_compl.speech_mode,
+ lchan_to_chosen_channel(lchan),
+ lchan->encr.alg_id, perm_spch,
&conn->user_plane.aoip_rtp_addr_local, &sc, NULL);
if (!resp) {
diff --git a/src/osmo-bsc/osmo_bsc_api.c b/src/osmo-bsc/osmo_bsc_api.c
index 7a42f3c17..b80eb584c 100644
--- a/src/osmo-bsc/osmo_bsc_api.c
+++ b/src/osmo-bsc/osmo_bsc_api.c
@@ -408,17 +408,12 @@ static void bsc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, st
osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_MO_DTAP, msg);
}
-static void bsc_assign_compl(struct gsm_subscriber_connection *conn, uint8_t rr_cause,
- uint8_t chosen_channel, uint8_t encr_alg_id,
- uint8_t speech_model)
+static void bsc_assign_compl(struct gsm_subscriber_connection *conn, uint8_t rr_cause)
{
if (!msc_connected(conn))
return;
conn->lchan->abis_ip.ass_compl.rr_cause = rr_cause;
- conn->lchan->abis_ip.ass_compl.chosen_channel = chosen_channel;
- conn->lchan->abis_ip.ass_compl.encr_alg_id = encr_alg_id;
- conn->lchan->abis_ip.ass_compl.speech_mode = speech_model;
if (is_ipaccess_bts(conn_get_bts(conn)) && conn->user_plane.rtp_ip) {
/* NOTE: In a network that makes use of an IPA base station