aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Smith <osmith@sysmocom.de>2023-02-21 17:17:33 +0100
committerOliver Smith <osmith@sysmocom.de>2023-03-06 10:23:30 +0100
commit2150b307c2578165261cffa964e14f71db7f6629 (patch)
treea4b1bb187b4c170852c94c26a144ed43294b1a19
parent0361b0161422bb711ac972e3a0fedffe3e1501cf (diff)
assignment_fsm: chan mode check: support CSD
Replace check_requires_voice_stream, which used to iterate over ch_mode_rate_list and verify that all entries are either for speech or signalling. Instead verify in check_chan_mode_rate_against_ch_indctr, that all entries of ch_mode_rate_list have a chan_mode that matches the ch_indctr (data, speech, signalling; called "speech / data indicator" in 3GPP TS 48.008 § 3.2.2.11). This ensures that all of them are either data, speech or signalling and not mixed. Related: OS#4393 Change-Id: Iee5cbfee84d7f2ad59ee2d5a19891a2b59bbafff
-rw-r--r--include/osmocom/bsc/gsm_data.h3
-rw-r--r--src/osmo-bsc/assignment_fsm.c56
-rw-r--r--src/osmo-bsc/osmo_bsc_bssap.c2
3 files changed, 29 insertions, 32 deletions
diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h
index cf66a041f..d4615b2d5 100644
--- a/include/osmocom/bsc/gsm_data.h
+++ b/include/osmocom/bsc/gsm_data.h
@@ -163,6 +163,9 @@ struct assignment_request {
/* The TSC to use if 'use' is true, otherwise automatically determine the TSC value to use. Valid range is 0 to
* 7, as described in 3GPP TS 45.002. */
struct optional_val tsc;
+
+ /* The "speech / data indicator" from 3GPP TS 48.008 § 3.2.2.11 Channel Type (speech/data/signalling). */
+ enum gsm0808_chan_indicator ch_indctr;
};
/* State of an ongoing Assignment, while the assignment_fsm is still busy. This serves as state separation to keep the
diff --git a/src/osmo-bsc/assignment_fsm.c b/src/osmo-bsc/assignment_fsm.c
index 7f6a7ea85..6dc09c6fa 100644
--- a/src/osmo-bsc/assignment_fsm.c
+++ b/src/osmo-bsc/assignment_fsm.c
@@ -370,62 +370,53 @@ static __attribute__((constructor)) void assignment_fsm_init(void)
OSMO_ASSERT(osmo_fsm_register(&assignment_fsm) == 0);
}
-static int check_requires_voice(bool *requires_voice, enum gsm48_chan_mode chan_mode)
+static int chan_mode_to_ch_indctr(enum gsm48_chan_mode chan_mode)
{
- *requires_voice = false;
-
switch (gsm48_chan_mode_to_non_vamos(chan_mode)) {
+ case GSM48_CMODE_DATA_14k5:
+ case GSM48_CMODE_DATA_12k0:
+ case GSM48_CMODE_DATA_6k0:
+ case GSM48_CMODE_DATA_3k6:
+ return GSM0808_CHAN_DATA;
case GSM48_CMODE_SPEECH_V1:
case GSM48_CMODE_SPEECH_EFR:
case GSM48_CMODE_SPEECH_AMR:
- *requires_voice = true;
- break;
+ return GSM0808_CHAN_SPEECH;
case GSM48_CMODE_SIGN:
- *requires_voice = false;
- break;
+ return GSM0808_CHAN_SIGN;
default:
return -EINVAL;
}
-
- return 0;
}
-/* Check if the incoming assignment request requires a voice stream or not,
- * we will look at the preferred and the alternate channel mode and also make
- * sure that both are consistent. */
-static int check_requires_voice_stream(struct gsm_subscriber_connection *conn)
+/* Check if the incoming assignment request has a channel mode that is
+ * inconsistent with ch_indctr, e.g. GSM48_CMODE_DATA_14k5 and
+ * GSM0808_CHAN_SPEECH */
+static int check_chan_mode_rate_against_ch_indctr(struct gsm_subscriber_connection *conn)
{
- bool requires_voice_pref = false, requires_voice_alt;
struct assignment_request *req = &conn->assignment.req;
struct osmo_fsm_inst *fi = conn->fi;
- int i, rc;
-
- /* When the assignment request indicates that there is an alternate
- * rate available (e.g. "Full or Half rate channel, Half rate
- * preferred..."), then both must be either voice or either signalling,
- * a mismatch is not permitted */
+ int i;
+ uint8_t ch_indctr;
for (i = 0; i < req->n_ch_mode_rate; i++) {
- rc = check_requires_voice(&requires_voice_alt, req->ch_mode_rate_list[i].chan_mode);
- if (rc < 0) {
+ ch_indctr = chan_mode_to_ch_indctr(req->ch_mode_rate_list[i].chan_mode);
+ if (ch_indctr < 0) {
assignment_fail(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_NOT_SUPP,
"Channel mode not supported (prev level %d): %s", i,
gsm48_chan_mode_name(req->ch_mode_rate_list[i].chan_mode));
return -EINVAL;
}
- if (i==0)
- requires_voice_pref = requires_voice_alt;
- else if (requires_voice_alt != requires_voice_pref) {
+ if (ch_indctr != req->ch_indctr) {
assignment_fail(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_NOT_SUPP,
- "Requested a mix of Signalling and non-Signalling channel modes: %s != %s",
- gsm48_chan_mode_name(req->ch_mode_rate_list[0].chan_mode),
- gsm48_chan_mode_name(req->ch_mode_rate_list[i].chan_mode));
+ "Channel mode %s has ch_indctr %d, channel type has ch_indctr %d",
+ gsm48_chan_mode_name(req->ch_mode_rate_list[i].chan_mode),
+ ch_indctr, req->ch_indctr);
return -EINVAL;
}
}
- conn->assignment.requires_voice_stream = requires_voice_pref;
return 0;
}
@@ -471,6 +462,8 @@ static int _reassignment_request(enum assign_for assign_for, struct gsm_lchan *l
.present = (tsc >= 0),
.val = tsc,
},
+
+ .ch_indctr = chan_mode_to_ch_indctr(lchan->current_ch_mode_rate.chan_mode),
};
if (to_lchan)
@@ -529,10 +522,9 @@ void assignment_fsm_start(struct gsm_subscriber_connection *conn, struct gsm_bts
assignment_count(CTR_ASSIGNMENT_ATTEMPTED);
- /* Check if we need a voice stream. If yes, set the appropriate struct
- * members in conn */
- if (check_requires_voice_stream(conn) < 0)
+ if (check_chan_mode_rate_against_ch_indctr(conn) < 0)
return;
+ conn->assignment.requires_voice_stream = (req->ch_indctr != GSM0808_CHAN_SIGN);
if (!req->target_lchan && reuse_existing_lchan(conn)) {
/* The already existing lchan is suitable for this mode */
diff --git a/src/osmo-bsc/osmo_bsc_bssap.c b/src/osmo-bsc/osmo_bsc_bssap.c
index e38a9759c..916e3b8ad 100644
--- a/src/osmo-bsc/osmo_bsc_bssap.c
+++ b/src/osmo-bsc/osmo_bsc_bssap.c
@@ -1136,6 +1136,8 @@ static int bssmap_handle_assignm_req(struct gsm_subscriber_connection *conn,
goto reject;
}
+ req.ch_indctr = ct.ch_indctr;
+
return osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_ASSIGNMENT_START, &req);
reject: