implement Channel Mode Modify to VAMOS mode

Put a (primary) lchan in VAMOS speech mode.
This is not yet about activating shadow lchans, this merely puts any
lchan in a VAMOS capable channel- and speech mode.

Protocol:

In RR Channel Mode Modify, send a spec conforming VAMOS channel mode as
well as an Extended TSC Set, wich adds the TSC Set to the training
sequence code value.

In RSL MODE MODIFY, send Osmocom specific extensions to indicate the TSC
Set and TSC, as well as the VAMOS channel mode; only to OsmoBTS type
cells.
- Set the Channel Mode's Channel Rate to Osmocom specific
  RSL_CMOD_CRT_OSMO_TCH_VAMOS_Bm / RSL_CMOD_CRT_OSMO_TCH_VAMOS_Lm
- Add the Osmocom specific Training Sequence IE containing both TSC Set
  and TSC.
(These are documented in the Abis manual.)

Implementation:

The internal API to request a Mode Modify is lchan_modify(info). Add to
this info the 'vamos' bool, set to true when the modification should put
the lchan in VAMOS channel mode or not.

When info.vamos == true, make sure the channel mode value is a VAMOS
one: in the copy of info->ch_mode_rate at lchan->modify.ch_mode_rate,
convert to the right VAMOS/non-VAMOS equivalent channel mode.

When the modification is through, set lchan->vamos.enabled
appropriately.

This patch also builds on Ic665125255d7354f5499d10dda1dd866ab243d24
'allow explixit TSC Set and TSC on chan activ / modif / assignment'
placing tsc_set and tsc values in the TSC related IEs.

Related: SYS#5315 OS#4940
Change-Id: Ibf53f4797d7491b17a33946fd7d920f038362b4c
This commit is contained in:
Neels Hofmeyr 2021-04-19 22:01:14 +00:00
parent a56b94ce0f
commit e3e317242c
4 changed files with 53 additions and 6 deletions

View File

@ -626,6 +626,8 @@ struct lchan_modify_info {
/* TSC to use, or -1 for automatically determining the TSC to use. Valid range is 0 to 7, as described in 3GPP
* TS 45.002. */
int tsc;
bool vamos;
};
struct gsm_lchan {
@ -741,6 +743,11 @@ struct gsm_lchan {
int tsc_set;
/* Training Sequence Code in use. The valid range is 0-7 as described in the spec 3GPP TS 45.002. */
uint8_t tsc;
struct {
/* Whether this lchan is activated/modified into a mode that allows VAMOS multiplexing at this moment */
bool enabled;
} vamos;
};
/* One Timeslot in a TRX */

View File

@ -353,7 +353,8 @@ int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan)
static int channel_mode_from_lchan(struct rsl_ie_chan_mode *cm,
struct gsm_lchan *lchan,
const struct channel_mode_and_rate *ch_mode_rate)
const struct channel_mode_and_rate *ch_mode_rate,
bool vamos)
{
int rc;
memset(cm, 0, sizeof(*cm));
@ -378,10 +379,10 @@ static int channel_mode_from_lchan(struct rsl_ie_chan_mode *cm,
cm->chan_rt = RSL_CMOD_CRT_SDCCH;
break;
case GSM_LCHAN_TCH_F:
cm->chan_rt = RSL_CMOD_CRT_TCH_Bm;
cm->chan_rt = vamos ? RSL_CMOD_CRT_OSMO_TCH_VAMOS_Bm : RSL_CMOD_CRT_TCH_Bm;
break;
case GSM_LCHAN_TCH_H:
cm->chan_rt = RSL_CMOD_CRT_TCH_Lm;
cm->chan_rt = vamos ? RSL_CMOD_CRT_OSMO_TCH_VAMOS_Lm : RSL_CMOD_CRT_TCH_Lm;
break;
case GSM_LCHAN_NONE:
case GSM_LCHAN_UNKNOWN:
@ -502,6 +503,17 @@ static void rep_acch_cap_for_bts(struct gsm_lchan *lchan,
}
}
/* Write RSL_IE_OSMO_TRAINING_SEQUENCE to msgb. The tsc_set argument's range is 1-4, tsc argument range is 0-7. */
static void put_osmo_training_sequence_ie(struct msgb *msg, uint8_t tsc_set, uint8_t tsc)
{
uint8_t *len = msgb_tl_put(msg, RSL_IE_OSMO_TRAINING_SEQUENCE);
*len = 2;
/* Convert from spec conforming "human readable" TSC Set 1-4 to 0-3 on the wire */
msgb_put_u8(msg, tsc_set - 1);
/* TSC is 0-7 both on the wire and in spec descriptions */
msgb_put_u8(msg, tsc);
}
/* Chapter 8.4.1 */
int rsl_tx_chan_activ(struct gsm_lchan *lchan, uint8_t act_type, uint8_t ho_ref)
{
@ -522,7 +534,7 @@ int rsl_tx_chan_activ(struct gsm_lchan *lchan, uint8_t act_type, uint8_t ho_ref)
/* PDCH activation is a job for rsl_tx_dyn_ts_pdch_act_deact(); */
OSMO_ASSERT(act_type != RSL_ACT_OSMO_PDCH);
rc = channel_mode_from_lchan(&cm, lchan, &lchan->activate.info.ch_mode_rate);
rc = channel_mode_from_lchan(&cm, lchan, &lchan->activate.info.ch_mode_rate, false);
if (rc < 0) {
LOGP(DRSL, LOGL_ERROR,
"%s Cannot find channel mode from lchan type\n",
@ -637,7 +649,7 @@ int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
struct rsl_ie_chan_mode cm;
struct gsm_bts *bts = lchan->ts->trx->bts;
rc = channel_mode_from_lchan(&cm, lchan, &lchan->modify.ch_mode_rate);
rc = channel_mode_from_lchan(&cm, lchan, &lchan->modify.ch_mode_rate, lchan->modify.info.vamos);
if (rc < 0)
return rc;
@ -668,6 +680,11 @@ int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
rep_acch_cap_for_bts(lchan, msg);
/* Selecting a specific TSC Set is only applicable to VAMOS mode. Send this Osmocom specific IE only to OsmoBTS
* types. */
if (lchan->modify.info.vamos && lchan->modify.tsc_set >= 1 && bts->model->type == GSM_BTS_TYPE_OSMOBTS)
put_osmo_training_sequence_ie(msg, lchan->modify.tsc_set, lchan->modify.tsc);
msg->dst = rsl_chan_link(lchan);
return abis_rsl_sendmsg(msg);

View File

@ -702,6 +702,12 @@ int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t mode)
}
}
if (lchan->modify.info.vamos && lchan->modify.tsc_set > 0) {
/* Add the Extended TSC Set IE. So far we only need a TSC Set sent for VAMOS.
* Convert from spec conforming "human readable" TSC Set 1-4 to 0-3 on the wire */
msgb_tv_put(msg, GSM48_IE_EXTENDED_TSC_SET, (lchan->modify.tsc_set - 1) & 0x3);
}
return gsm48_sendmsg(msg);
}

View File

@ -382,6 +382,16 @@ void lchan_mode_modify(struct gsm_lchan *lchan, struct lchan_modify_info *info)
{
OSMO_ASSERT(lchan && info);
if (info->vamos && !osmo_bts_has_feature(&lchan->ts->trx->bts->features, BTS_FEAT_VAMOS)) {
lchan->last_error = talloc_strdup(lchan->ts->trx, "VAMOS related Channel Mode Modify requested,"
" but BTS does not support VAMOS");
LOG_LCHAN(lchan, LOGL_ERROR,
"VAMOS related Channel Mode Modify requested, but BTS %u does not support VAMOS\n",
lchan->ts->trx->bts->nr);
lchan_on_mode_modify_failure(lchan, info->modify_for, lchan->conn);
return;
}
/* To make sure that the lchan is actually allowed to initiate Mode Modify, feed through an FSM event. */
if (osmo_fsm_inst_dispatch(lchan->fi, LCHAN_EV_REQUEST_MODE_MODIFY, info)) {
LOG_LCHAN(lchan, LOGL_ERROR,
@ -973,6 +983,7 @@ static void lchan_fsm_wait_rsl_chan_mode_modify_ack(struct osmo_fsm_inst *fi, ui
lchan->current_mr_conf = lchan->modify.mr_conf_filtered;
lchan->tsc_set = lchan->modify.tsc_set;
lchan->tsc = lchan->modify.tsc;
lchan->vamos.enabled = lchan->modify.info.vamos;
if (lchan->modify.info.requires_voice_stream
&& !lchan->fi_rtp) {
@ -1118,7 +1129,13 @@ static void lchan_fsm_established(struct osmo_fsm_inst *fi, uint32_t event, void
use_mgwep_ci = lchan_use_mgw_endpoint_ci_bts(lchan);
lchan->modify.ch_mode_rate = lchan->modify.info.ch_mode_rate;
/* future: automatically adjust chan_mode in lchan->modify.ch_mode_rate */
lchan->modify.ch_mode_rate.chan_mode = (lchan->modify.info.vamos
? gsm48_chan_mode_to_vamos(lchan->modify.info.ch_mode_rate.chan_mode)
: gsm48_chan_mode_to_non_vamos(lchan->modify.info.ch_mode_rate.chan_mode));
if (lchan->modify.ch_mode_rate.chan_mode < 0) {
lchan_fail("Invalid chan_mode: %s", gsm48_chan_mode_name(lchan->modify.info.ch_mode_rate.chan_mode));
return;
}
if (gsm48_chan_mode_to_non_vamos(modif_info->ch_mode_rate.chan_mode) == GSM48_CMODE_SPEECH_AMR) {
if (lchan_mr_config(&lchan->modify.mr_conf_filtered, lchan, modif_info->ch_mode_rate.s15_s0)