fixeria has submitted this change. ( https://gerrit.osmocom.org/c/osmo-bsc/+/42590?usp=email )
Change subject: assignment_fsm: check ipaccess channel mode support ......................................................................
assignment_fsm: check ipaccess channel mode support
Add ipacc_chan_mode_supported(), which checks the NM_IPAC_F_CHANM_* flags stored in the Baseband Transceiver's MO state (populated during OML bring-up) to decide whether the BTS can handle a requested channel mode. If the IE containing supported channel modes was never received, the function returns true as if the given mode was supported.
Without this change, requesting a channel mode not supported by the BTS results in a NACK to the RSL Channel Activation, which causes the lchan to be marked as BROKEN and thus unavailable.
Change-Id: I680ba7993786f5486d671f931e75df4543670a37 Related: OS#6324 --- M src/osmo-bsc/assignment_fsm.c 1 file changed, 102 insertions(+), 3 deletions(-)
Approvals: jolly: Looks good to me, but someone else must approve Jenkins Builder: Verified laforge: Looks good to me, approved
diff --git a/src/osmo-bsc/assignment_fsm.c b/src/osmo-bsc/assignment_fsm.c index 11408d6..54a57aa 100644 --- a/src/osmo-bsc/assignment_fsm.c +++ b/src/osmo-bsc/assignment_fsm.c @@ -365,6 +365,86 @@ new_lchan->ts->max_primary_lchans : 0)); }
+/* Check whether the ipaccess BTS supports the requested channel mode. + * Returns false if the BTS has reported its supported channel modes and the + * requested mode is absent from that list. Returns true if the Supported + * Features IE was never received (older osmo-bts versions do not send it). */ +static bool ipacc_chan_mode_supported(const struct gsm_lchan *lchan, + const struct channel_mode_and_rate *ch_mode_rate) +{ + const struct ipacc_supp_feat *feat = + &lchan->ts->trx->bb_transc.mo.ipaccess.chan_modes; + uint32_t flag = 0; + + /* Supported Features IE was not received */ + if (!feat->present) + return true; + + switch (gsm48_chan_mode_to_non_vamos(ch_mode_rate->chan_mode)) { + case GSM48_CMODE_SPEECH_V1: + flag = (lchan->type == GSM_LCHAN_TCH_H) + ? NM_IPAC_F_CHANM_SPEECH_HS : NM_IPAC_F_CHANM_SPEECH_FS; + break; + case GSM48_CMODE_SPEECH_EFR: + flag = NM_IPAC_F_CHANM_SPEECH_EFS; + break; + case GSM48_CMODE_SPEECH_AMR: + flag = (lchan->type == GSM_LCHAN_TCH_H) + ? NM_IPAC_F_CHANM_SPEECH_AHS : NM_IPAC_F_CHANM_SPEECH_AFS; + break; + case GSM48_CMODE_DATA_3k6: + case GSM48_CMODE_DATA_6k0: + case GSM48_CMODE_DATA_12k0: + case GSM48_CMODE_DATA_14k5: + if (ch_mode_rate->data_transparent) { + switch (ch_mode_rate->data_rate.t) { + case RSL_CMOD_CSD_T_1200_75: + flag = NM_IPAC_F_CHANM_CSD_T_1200_75; + break; + case RSL_CMOD_CSD_T_600: + flag = NM_IPAC_F_CHANM_CSD_T_600; + break; + case RSL_CMOD_CSD_T_1k2: + flag = NM_IPAC_F_CHANM_CSD_T_1k2; + break; + case RSL_CMOD_CSD_T_2k4: + flag = NM_IPAC_F_CHANM_CSD_T_2k4; + break; + case RSL_CMOD_CSD_T_4k8: + flag = NM_IPAC_F_CHANM_CSD_T_4k8; + break; + case RSL_CMOD_CSD_T_9k6: + flag = NM_IPAC_F_CHANM_CSD_T_9k6; + break; + case RSL_CMOD_CSD_T_14k4: + flag = NM_IPAC_F_CHANM_CSD_T_14k4; + break; + default: + return true; /* unhandled T rate */ + } + } else { + switch (ch_mode_rate->data_rate.nt) { + case RSL_CMOD_CSD_NT_6k0: + flag = NM_IPAC_F_CHANM_CSD_NT_4k8; + break; + case RSL_CMOD_CSD_NT_12k0: + flag = NM_IPAC_F_CHANM_CSD_NT_9k6; + break; + case RSL_CMOD_CSD_NT_14k5: + flag = NM_IPAC_F_CHANM_CSD_NT_14k4; + break; + default: + return true; /* unhandled NT rate */ + } + } + break; + default: + return true; /* unknown channel mode */ + } + + return (feat->val & flag) != 0; +} + static bool lchan_type_compat_with_mode(const struct gsm_lchan *lchan, const struct channel_mode_and_rate *ch_mode_rate) { @@ -373,6 +453,8 @@
switch (gsm48_chan_mode_to_non_vamos(chan_mode)) { case GSM48_CMODE_SIGN: + /* Signalling does not require a specific channel mode on the BTS, + * so skip the ipaccess feature check (below) and return directly. */ switch (lchan->type) { case GSM_LCHAN_TCH_F: return chan_rate == CH_RATE_FULL; case GSM_LCHAN_TCH_H: return chan_rate == CH_RATE_HALF; @@ -388,22 +470,39 @@ * an explicit override by the 'chan_rate' argument */ switch (lchan->type) { case GSM_LCHAN_TCH_F: - return chan_rate == CH_RATE_FULL; + if (chan_rate != CH_RATE_FULL) + return false; + break; case GSM_LCHAN_TCH_H: - return chan_rate == CH_RATE_HALF; + if (chan_rate != CH_RATE_HALF) + return false; + break; default: return false; } + break;
case GSM48_CMODE_DATA_12k0: case GSM48_CMODE_DATA_14k5: case GSM48_CMODE_SPEECH_EFR: /* these services all explicitly require a TCH/F */ - return lchan->type == GSM_LCHAN_TCH_F; + if (lchan->type != GSM_LCHAN_TCH_F) + return false; + break;
default: return false; } + + switch (lchan->ts->trx->bts->type) { + case GSM_BTS_TYPE_NANOBTS: + case GSM_BTS_TYPE_OSMOBTS: + /* osmo-bts and nanoBTS report supported channel modes during + * the OML bring-up - additionally check them */ + return ipacc_chan_mode_supported(lchan, ch_mode_rate); + default: + return true; + } }
static __attribute__((constructor)) void assignment_fsm_init(void)